1""" 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14""" 15 16""" 17gn gen --ide=json 181. modifty at ./build/core/build_scripts/make_main.sh 19 20${BUILD_TOOLS_DIR}/gn gen ${TARGET_OUT_DIR} --> ${BUILD_TOOLS_DIR}/gn gen --ide=json ${TARGET_OUT_DIR} 21 222. build object --> generate project.json at out/ohos-arm-release/project.json 23 243. python3 gn_project_to_cmake.py root_path_of_project(eg. home/xxxx/code/openharmony) 25 26to generate CMakeLists.txt at home/xxxx/code/openharmony 27""" 28 29import datetime 30import json 31import os 32import re 33import sys 34from pathlib import Path, PureWindowsPath 35from typing import List 36 37def to_abs_path(path: str) -> str: 38 if path.startswith("//"): 39 path = path[2:] 40 return path 41 42 43class GnTarget(object): 44 def __init__(self, full_name: str, content: object): 45 self.full_name = full_name 46 self.content = content 47 self.resolved = False 48 49 @property 50 def dep_names(self) -> set: 51 return set(self.content.get('deps', [])) 52 53 @property 54 def inputs_field(self) -> set: 55 return set(self.content.get('inputs', set())) 56 57 @property 58 def sources_field(self) -> set: 59 return set(self.content.get('sources', set())) 60 61 @property 62 def include_dirs_field(self) -> set: 63 return set(self.content.get('include_dirs', set())) 64 65 def __filter_src_dirs(self, files) -> set: 66 return set(f.split("/src/")[0] + "/src" for f in files) 67 68 @property 69 def cpp_src_files(self) -> set: 70 return set(to_abs_path(jf) for jf in self.sources_field 71 if 72 jf.endswith(".cpp") or jf.endswith(".h") or jf.endswith(".c++") or jf.endswith(".cc")) 73 74 @property 75 def cpp_hdr_dirs(self) -> set: 76 return set(to_abs_path(x) for x in self.include_dirs_field if x != "//" and not x.startswith("//out")) 77 78 79class ProjectJson(object): 80 def __init__(self, path: str): 81 self.path = path 82 with open(path, 'r') as project_file: 83 self.jobj = json.load(project_file) 84 85 self.gn_targets_cache = dict() 86 project_targets = self.jobj['targets'] 87 for k, v in project_targets.items(): 88 if (k.find("rosen") < 0): 89 continue 90 print(k) 91 self.gn_targets_cache[k] = GnTarget(full_name=k, content=v) 92 93 @property 94 def targets(self): 95 return self.gn_targets_cache.values() 96 97 @property 98 def target_names(self): 99 return set([x.full_name for x in self.targets]) 100 101 def find_targets_startswith(self, prefix: str) -> List[GnTarget]: 102 return [x for x in self.targets if x.full_name.startswith(prefix)] 103 104 def get_target(self, name: str) -> GnTarget: 105 return next(x for x in self.targets if x.full_name == name) 106 107 108class CMakeCreator(object): 109 def __init__(self, project_json: ProjectJson, project_root_dir: str): 110 self.project_json = project_json 111 self.project_root_dir = project_root_dir 112 self.project_name = os.path.basename(self.project_root_dir) 113 114 @property 115 def project_cpp_srcs(self): 116 ret = set() 117 for x in self.project_json.targets: 118 for f in x.cpp_src_files: 119 f = os.path.join(self.project_root_dir, f) 120 if os.path.isfile(f): 121 ret.add(f) 122 print(f) 123 124 return sorted(ret) 125 126 @property 127 def project_cpp_hdrs(self): 128 ret = set() 129 for x in self.project_json.targets: 130 ret.update([_ for _ in x.cpp_hdr_dirs if os.path.isdir(self.project_root_dir + "/" + _)]) 131 return sorted(ret) 132 133 @property 134 def jar_deps(self): 135 ret = set() 136 for x in self.project_json.targets: 137 ret.update([_ for _ in x.jar_files if os.path.isfile(self.project_root_dir + "/" + _)]) 138 return sorted(ret) 139 140 def write_cmakelist(self): 141 hdr_list_str = "\n ".join(self.project_cpp_hdrs) 142 src_list_str = "\n ".join(self.project_cpp_srcs) 143 144 project_name = self.project_name + "clion" 145 146 with open(os.path.join(self.project_root_dir, 'CMakeLists.txt'), "w") as f: 147 f.write("""cmake_minimum_required(VERSION 3.15)\n""") 148 f.write("project(" + project_name + ")\n""") 149 f.write("set(CMAKE_CXX_STANDARD 17)\n") 150 f.write("include_directories(" + hdr_list_str + ")\n") 151 f.write("add_executable(" + project_name + " " + src_list_str + ")\n") 152 153 with open(os.path.join(self.project_root_dir, 'CMakeLists.txt'), "w") as f: 154 f.write('# Generated by gn_project_to_cmake.py.\n') 155 f.write("""cmake_minimum_required(VERSION 3.15) 156project({}clion) 157set(CMAKE_CXX_STANDARD 17) 158include_directories({}) 159add_executable({}clion {}) 160 """.format(self.project_name, hdr_list_str, self.project_name, src_list_str)) 161 162 def write(self): 163 self.write_cmakelist() 164 165 166if __name__ == "__main__": 167 # 168 # read args 169 # 170 if len(sys.argv) < 2: 171 print("""Usage: {} <project_root_dir>, 172eg. {} /home/xxxxxx/codes/openharmony""".format(sys.argv[0], sys.argv[0])) 173 sys.exit(1) 174 175 project_root_dir = sys.argv[1] 176 if not os.path.isdir(project_root_dir): 177 print(project_root_dir + " not exist!") 178 sys.exit(1) 179 180 # 181 # parse project.json 182 # 183 project_json = ProjectJson(path=os.path.join(*[project_root_dir, "out", "ohos-arm-release", "project.json"])) 184 print(project_json) 185 186 # 187 # write CMakeLists.txt 188 # 189 CMakeCreator(project_json=project_json, project_root_dir=project_root_dir).write() 190 191