| #!/usr/bin/env python3 |
| # |
| # Copyright 2019 - The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| """It is an AIDEGen sub task: generate the CLion project file. |
| |
| Usage example: |
| json_path = common_util.get_blueprint_json_path( |
| constant.BLUEPRINT_CC_JSONFILE_NAME) |
| json_dict = common_util.get_soong_build_json_dict(json_path) |
| if 'modules' not in json_dict: |
| return |
| mod_info = json_dict['modules'].get('libui', {}) |
| if not mod_info: |
| return |
| CLionProjectFileGenerator(mod_info).generate_cmakelists_file() |
| """ |
| |
| import logging |
| import os |
| |
| from io import StringIO |
| from io import TextIOWrapper |
| |
| from aidegen import constant |
| from aidegen import templates |
| from aidegen.lib import common_util |
| from aidegen.lib import errors |
| from aidegen.lib import native_module_info |
| |
| # Flags for writing to CMakeLists.txt section. |
| _GLOBAL_COMMON_FLAGS = '\n# GLOBAL ALL FLAGS:\n' |
| _LOCAL_COMMON_FLAGS = '\n# LOCAL ALL FLAGS:\n' |
| _GLOBAL_CFLAGS = '\n# GLOBAL CFLAGS:\n' |
| _LOCAL_CFLAGS = '\n# LOCAL CFLAGS:\n' |
| _GLOBAL_C_ONLY_FLAGS = '\n# GLOBAL C ONLY FLAGS:\n' |
| _LOCAL_C_ONLY_FLAGS = '\n# LOCAL C ONLY FLAGS:\n' |
| _GLOBAL_CPP_FLAGS = '\n# GLOBAL CPP FLAGS:\n' |
| _LOCAL_CPP_FLAGS = '\n# LOCAL CPP FLAGS:\n' |
| _SYSTEM_INCLUDE_FLAGS = '\n# GLOBAL SYSTEM INCLUDE FLAGS:\n' |
| |
| # Keys for writing in module_bp_cc_deps.json |
| _KEY_GLOBAL_COMMON_FLAGS = 'global_common_flags' |
| _KEY_LOCAL_COMMON_FLAGS = 'local_common_flags' |
| _KEY_GLOBAL_CFLAGS = 'global_c_flags' |
| _KEY_LOCAL_CFLAGS = 'local_c_flags' |
| _KEY_GLOBAL_C_ONLY_FLAGS = 'global_c_only_flags' |
| _KEY_LOCAL_C_ONLY_FLAGS = 'local_c_only_flags' |
| _KEY_GLOBAL_CPP_FLAGS = 'global_cpp_flags' |
| _KEY_LOCAL_CPP_FLAGS = 'local_cpp_flags' |
| _KEY_SYSTEM_INCLUDE_FLAGS = 'system_include_flags' |
| |
| # Dictionary maps keys to sections. |
| _FLAGS_DICT = { |
| _KEY_GLOBAL_COMMON_FLAGS: _GLOBAL_COMMON_FLAGS, |
| _KEY_LOCAL_COMMON_FLAGS: _LOCAL_COMMON_FLAGS, |
| _KEY_GLOBAL_CFLAGS: _GLOBAL_CFLAGS, |
| _KEY_LOCAL_CFLAGS: _LOCAL_CFLAGS, |
| _KEY_GLOBAL_C_ONLY_FLAGS: _GLOBAL_C_ONLY_FLAGS, |
| _KEY_LOCAL_C_ONLY_FLAGS: _LOCAL_C_ONLY_FLAGS, |
| _KEY_GLOBAL_CPP_FLAGS: _GLOBAL_CPP_FLAGS, |
| _KEY_LOCAL_CPP_FLAGS: _LOCAL_CPP_FLAGS, |
| _KEY_SYSTEM_INCLUDE_FLAGS: _SYSTEM_INCLUDE_FLAGS |
| } |
| |
| # Keys for parameter types. |
| _KEY_FLAG = 'flag' |
| _KEY_SYSTEM_ROOT = 'system_root' |
| _KEY_RELATIVE = 'relative_file_path' |
| |
| # Constants for CMakeLists.txt. |
| _MIN_VERSION_TOKEN = '@MINVERSION@' |
| _PROJECT_NAME_TOKEN = '@PROJNAME@' |
| _ANDROID_ROOT_TOKEN = '@ANDROIDROOT@' |
| _MINI_VERSION_SUPPORT = 'cmake_minimum_required(VERSION {})\n' |
| _MINI_VERSION = '3.5' |
| _KEY_CLANG = 'clang' |
| _KEY_CPPLANG = 'clang++' |
| _SET_C_COMPILER = 'set(CMAKE_C_COMPILER \"{}\")\n' |
| _SET_CXX_COMPILER = 'set(CMAKE_CXX_COMPILER \"{}\")\n' |
| _LIST_APPEND_HEADER = 'list(APPEND\n' |
| _SOURCE_FILES_HEADER = 'SOURCE_FILES' |
| _SOURCE_FILES_LINE = ' SOURCE_FILES\n' |
| _END_WITH_ONE_BLANK_LINE = ')\n' |
| _END_WITH_TWO_BLANK_LINES = ')\n\n' |
| _SET_RELATIVE_PATH = 'set({} "{} {}={}")\n' |
| _SET_ALL_FLAGS = 'set({} "{} {}")\n' |
| _ANDROID_ROOT_SYMBOL = '${ANDROID_ROOT}' |
| _SYSTEM = 'SYSTEM' |
| _INCLUDE_DIR = 'include_directories({} \n' |
| _SET_INCLUDE_FORMAT = ' "{}"\n' |
| _CMAKE_C_FLAGS = 'CMAKE_C_FLAGS' |
| _CMAKE_CXX_FLAGS = 'CMAKE_CXX_FLAGS' |
| _USR = 'usr' |
| _INCLUDE = 'include' |
| _INCLUDE_SYSTEM = 'include_directories(SYSTEM "{}")\n' |
| _GLOB_RECURSE_TMP_HEADERS = 'file (GLOB_RECURSE TMP_HEADERS\n' |
| _ALL_HEADER_FILES = ' "{}/**/*.h"\n' |
| _APPEND_SOURCE_FILES = "list (APPEND SOURCE_FILES ${TMP_HEADERS})\n\n" |
| _ADD_EXECUTABLE_HEADER = '\nadd_executable({} {})' |
| _PROJECT = 'project({})\n' |
| _ADD_SUB = 'add_subdirectory({})\n' |
| _DICT_EMPTY = 'mod_info is empty.' |
| _DICT_NO_MOD_NAME_KEY = "mod_info does not contain 'module_name' key." |
| _DICT_NO_PATH_KEY = "mod_info does not contain 'path' key." |
| _MODULE_INFO_EMPTY = 'The module info dictionary is empty.' |
| |
| |
| class CLionProjectFileGenerator: |
| """CLion project file generator. |
| |
| Attributes: |
| mod_info: A dictionary of the target module's info. |
| mod_name: A string of module name. |
| mod_path: A string of module's path. |
| cc_dir: A string of generated CLion project file's directory. |
| cc_path: A string of generated CLion project file's path. |
| """ |
| |
| def __init__(self, mod_info, parent_dir=None): |
| """ProjectFileGenerator initialize. |
| |
| Args: |
| mod_info: A dictionary of native module's info. |
| parent_dir: The parent directory of this native module. The default |
| value is None. |
| """ |
| if not mod_info: |
| raise errors.ModuleInfoEmptyError(_MODULE_INFO_EMPTY) |
| self.mod_info = mod_info |
| self.mod_name = self._get_module_name() |
| self.mod_path = CLionProjectFileGenerator.get_module_path( |
| mod_info, parent_dir) |
| self.cc_dir = CLionProjectFileGenerator.get_cmakelists_file_dir( |
| os.path.join(self.mod_path, self.mod_name)) |
| if not os.path.exists(self.cc_dir): |
| os.makedirs(self.cc_dir) |
| self.cc_path = os.path.join(self.cc_dir, |
| constant.CLION_PROJECT_FILE_NAME) |
| |
| def _get_module_name(self): |
| """Gets the value of the 'module_name' key if it exists. |
| |
| Returns: |
| A string of the module's name. |
| |
| Raises: |
| NoModuleNameDefinedInModuleInfoError if no 'module_name' key in |
| mod_info. |
| """ |
| mod_name = self.mod_info.get(constant.KEY_MODULE_NAME, '') |
| if not mod_name: |
| raise errors.NoModuleNameDefinedInModuleInfoError( |
| _DICT_NO_MOD_NAME_KEY) |
| return mod_name |
| |
| @staticmethod |
| def get_module_path(mod_info, parent_dir=None): |
| """Gets the correct value of the 'path' key if it exists. |
| |
| When a module with different paths, e.g., |
| 'libqcomvoiceprocessingdescriptors': { |
| 'path': [ |
| 'device/google/bonito/voice_processing', |
| 'device/google/coral/voice_processing', |
| 'device/google/crosshatch/voice_processing', |
| 'device/google/muskie/voice_processing', |
| 'device/google/taimen/voice_processing' |
| ], |
| ... |
| } |
| it might be wrong if we always choose the first path. For example, in |
| this case if users command 'aidegen -i c device/google/coral' the |
| correct path they need should be the second one. |
| |
| Args: |
| mod_info: A module's info dictionary. |
| parent_dir: The parent directory of this native module. The default |
| value is None. |
| |
| Returns: |
| A string of the module's path. |
| |
| Raises: |
| NoPathDefinedInModuleInfoError if no 'path' key in mod_info. |
| """ |
| mod_paths = mod_info.get(constant.KEY_PATH, []) |
| if not mod_paths: |
| raise errors.NoPathDefinedInModuleInfoError(_DICT_NO_PATH_KEY) |
| mod_path = mod_paths[0] |
| if parent_dir and len(mod_paths) > 1: |
| for path in mod_paths: |
| if common_util.is_source_under_relative_path(path, parent_dir): |
| mod_path = path |
| return mod_path |
| |
| @staticmethod |
| @common_util.check_args(cc_path=str) |
| def get_cmakelists_file_dir(cc_path): |
| """Gets module's CMakeLists.txt file path to be created. |
| |
| Return a string of $OUT/development/ide/clion/${cc_path}. |
| For example, if module name is 'libui'. The return path string would be: |
| out/development/ide/clion/frameworks/native/libs/ui/libui |
| |
| Args: |
| cc_path: A string of absolute path of module's Android.bp file. |
| |
| Returns: |
| A string of absolute path of module's CMakeLists.txt file to be |
| created. |
| """ |
| return os.path.join(common_util.get_android_root_dir(), |
| common_util.get_android_out_dir(), |
| constant.RELATIVE_NATIVE_PATH, cc_path) |
| |
| def generate_cmakelists_file(self): |
| """Generates CLion project file from the target module's info.""" |
| with open(self.cc_path, 'w', encoding='utf-8') as hfile: |
| self._write_cmakelists_file(hfile) |
| |
| @common_util.check_args(hfile=(TextIOWrapper, StringIO)) |
| @common_util.io_error_handle |
| def _write_cmakelists_file(self, hfile): |
| """Writes CLion project file content with necessary info. |
| |
| Args: |
| hfile: A file handler instance. |
| """ |
| self._write_header(hfile) |
| self._write_c_compiler_paths(hfile) |
| self._write_source_files(hfile) |
| self._write_cmakelists_flags(hfile) |
| self._write_tail(hfile) |
| |
| @common_util.check_args(hfile=(TextIOWrapper, StringIO)) |
| @common_util.io_error_handle |
| def _write_header(self, hfile): |
| """Writes CLion project file's header messages. |
| |
| Args: |
| hfile: A file handler instance. |
| """ |
| content = templates.CMAKELISTS_HEADER.replace( |
| _MIN_VERSION_TOKEN, _MINI_VERSION) |
| content = content.replace(_PROJECT_NAME_TOKEN, self.mod_name) |
| content = content.replace( |
| _ANDROID_ROOT_TOKEN, common_util.get_android_root_dir()) |
| hfile.write(content) |
| |
| @common_util.check_args(hfile=(TextIOWrapper, StringIO)) |
| @common_util.io_error_handle |
| def _write_c_compiler_paths(self, hfile): |
| """Writes CMake compiler paths for C and Cpp to CLion project file. |
| |
| Args: |
| hfile: A file handler instance. |
| """ |
| hfile.write(_SET_C_COMPILER.format( |
| native_module_info.NativeModuleInfo.c_lang_path)) |
| hfile.write(_SET_CXX_COMPILER.format( |
| native_module_info.NativeModuleInfo.cpp_lang_path)) |
| |
| @common_util.check_args(hfile=(TextIOWrapper, StringIO)) |
| @common_util.io_error_handle |
| def _write_source_files(self, hfile): |
| """Writes source files' paths to CLion project file. |
| |
| Args: |
| hfile: A file handler instance. |
| """ |
| if constant.KEY_SRCS not in self.mod_info: |
| logging.warning("No source files in %s's module info.", |
| self.mod_name) |
| return |
| root = common_util.get_android_root_dir() |
| source_files = self.mod_info[constant.KEY_SRCS] |
| hfile.write(_LIST_APPEND_HEADER) |
| hfile.write(_SOURCE_FILES_LINE) |
| for src in source_files: |
| if not os.path.exists(os.path.join(root, src)): |
| continue |
| hfile.write(''.join([_build_cmake_path(src, ' '), '\n'])) |
| hfile.write(_END_WITH_ONE_BLANK_LINE) |
| |
| @common_util.check_args(hfile=(TextIOWrapper, StringIO)) |
| @common_util.io_error_handle |
| def _write_cmakelists_flags(self, hfile): |
| """Writes all kinds of flags in CLion project file. |
| |
| Args: |
| hfile: A file handler instance. |
| """ |
| self._write_flags(hfile, _KEY_GLOBAL_COMMON_FLAGS, True, True) |
| self._write_flags(hfile, _KEY_LOCAL_COMMON_FLAGS, True, True) |
| self._write_flags(hfile, _KEY_GLOBAL_CFLAGS, True, True) |
| self._write_flags(hfile, _KEY_LOCAL_CFLAGS, True, True) |
| self._write_flags(hfile, _KEY_GLOBAL_C_ONLY_FLAGS, True, False) |
| self._write_flags(hfile, _KEY_LOCAL_C_ONLY_FLAGS, True, False) |
| self._write_flags(hfile, _KEY_GLOBAL_CPP_FLAGS, False, True) |
| self._write_flags(hfile, _KEY_LOCAL_CPP_FLAGS, False, True) |
| self._write_flags(hfile, _KEY_SYSTEM_INCLUDE_FLAGS, True, True) |
| |
| @common_util.check_args(hfile=(TextIOWrapper, StringIO)) |
| @common_util.io_error_handle |
| def _write_tail(self, hfile): |
| """Writes CLion project file content with necessary info. |
| |
| Args: |
| hfile: A file handler instance. |
| """ |
| hfile.write( |
| _ADD_EXECUTABLE_HEADER.format( |
| _cleanup_executable_name(self.mod_name), |
| _add_dollar_sign(_SOURCE_FILES_HEADER))) |
| |
| @common_util.check_args( |
| hfile=(TextIOWrapper, StringIO), key=str, cflags=bool, cppflags=bool) |
| @common_util.io_error_handle |
| def _write_flags(self, hfile, key, cflags, cppflags): |
| """Writes CMake compiler paths of C, Cpp for different kinds of flags. |
| |
| Args: |
| hfile: A file handler instance. |
| key: A string of flag type, e.g., 'global_common_flags' flag. |
| cflags: A boolean for setting 'CMAKE_C_FLAGS' flag. |
| cppflags: A boolean for setting 'CMAKE_CXX_FLAGS' flag. |
| """ |
| if key not in _FLAGS_DICT: |
| return |
| hfile.write(_FLAGS_DICT[key]) |
| params_dict = self._parse_compiler_parameters(key) |
| if params_dict: |
| _translate_to_cmake(hfile, params_dict, cflags, cppflags) |
| |
| @common_util.check_args(flag=str) |
| def _parse_compiler_parameters(self, flag): |
| """Parses the specific flag data from a module_info dictionary. |
| |
| Args: |
| flag: The string of key flag, e.g.: _KEY_GLOBAL_COMMON_FLAGS. |
| |
| Returns: |
| A dictionary with compiled parameters. |
| """ |
| params = self.mod_info.get(flag, {}) |
| if not params: |
| return None |
| params_dict = { |
| constant.KEY_HEADER: [], |
| constant.KEY_SYSTEM: [], |
| _KEY_FLAG: [], |
| _KEY_SYSTEM_ROOT: '', |
| _KEY_RELATIVE: {} |
| } |
| for key, value in params.items(): |
| params_dict[key] = value |
| return params_dict |
| |
| |
| @common_util.check_args(rel_project_path=str, mod_names=list) |
| @common_util.io_error_handle |
| def generate_base_cmakelists_file(cc_module_info, rel_project_path, mod_names): |
| """Generates base CLion project file for multiple CLion projects. |
| |
| We create a multiple native project file: |
| {android_root}/development/ide/clion/{rel_project_path}/CMakeLists.txt |
| and use this project file to generate a link: |
| {android_root}/out/development/ide/clion/{rel_project_path}/CMakeLists.txt |
| |
| Args: |
| cc_module_info: An instance of native_module_info.NativeModuleInfo. |
| rel_project_path: A string of the base project relative path. For |
| example: frameworks/native/libs/ui. |
| mod_names: A list of module names whose project were created under |
| rel_project_path. |
| |
| Returns: |
| A symbolic link CLion project file path. |
| """ |
| root_dir = common_util.get_android_root_dir() |
| cc_dir = os.path.join(root_dir, constant.RELATIVE_NATIVE_PATH, |
| rel_project_path) |
| cc_out_dir = os.path.join(root_dir, common_util.get_android_out_dir(), |
| constant.RELATIVE_NATIVE_PATH, rel_project_path) |
| if not os.path.exists(cc_dir): |
| os.makedirs(cc_dir) |
| dst_path = os.path.join(cc_out_dir, constant.CLION_PROJECT_FILE_NAME) |
| if os.path.islink(dst_path): |
| os.unlink(dst_path) |
| src_path = os.path.join(cc_dir, constant.CLION_PROJECT_FILE_NAME) |
| if os.path.isfile(src_path): |
| os.remove(src_path) |
| with open(src_path, 'w', encoding='utf-8') as hfile: |
| _write_base_cmakelists_file(hfile, cc_module_info, src_path, mod_names) |
| os.symlink(src_path, dst_path) |
| return dst_path |
| |
| |
| @common_util.check_args( |
| hfile=(TextIOWrapper, StringIO), abs_project_path=str, mod_names=list) |
| @common_util.io_error_handle |
| def _write_base_cmakelists_file(hfile, cc_module_info, abs_project_path, |
| mod_names): |
| """Writes base CLion project file content. |
| |
| When we write module info into base CLion project file, first check if the |
| module's CMakeLists.txt exists. If file exists, write content, |
| add_subdirectory({'relative_module_path'}) |
| |
| Args: |
| hfile: A file handler instance. |
| cc_module_info: An instance of native_module_info.NativeModuleInfo. |
| abs_project_path: A string of the base project absolute path. |
| For example, |
| ${ANDROID_BUILD_TOP}/frameworks/native/libs/ui. |
| mod_names: A list of module names whose project were created under |
| abs_project_path. |
| """ |
| hfile.write(_MINI_VERSION_SUPPORT.format(_MINI_VERSION)) |
| project_dir = os.path.dirname(abs_project_path) |
| hfile.write(_PROJECT.format(os.path.basename(project_dir))) |
| root_dir = common_util.get_android_root_dir() |
| parent_dir = os.path.relpath(abs_project_path, root_dir) |
| for mod_name in mod_names: |
| mod_info = cc_module_info.get_module_info(mod_name) |
| mod_path = CLionProjectFileGenerator.get_module_path( |
| mod_info, parent_dir) |
| file_dir = CLionProjectFileGenerator.get_cmakelists_file_dir( |
| os.path.join(mod_path, mod_name)) |
| file_path = os.path.join(file_dir, constant.CLION_PROJECT_FILE_NAME) |
| if not os.path.isfile(file_path): |
| logging.warning("%s the project file %s doesn't exist.", |
| common_util.COLORED_INFO('Warning:'), file_path) |
| continue |
| link_project_dir = os.path.join(root_dir, |
| common_util.get_android_out_dir(), |
| os.path.relpath(project_dir, root_dir)) |
| rel_mod_path = os.path.relpath(file_dir, link_project_dir) |
| hfile.write(_ADD_SUB.format(rel_mod_path)) |
| |
| |
| @common_util.check_args( |
| hfile=(TextIOWrapper, StringIO), params_dict=dict, cflags=bool, |
| cppflags=bool) |
| def _translate_to_cmake(hfile, params_dict, cflags, cppflags): |
| """Translates parameter dict's contents into CLion project file format. |
| |
| Args: |
| hfile: A file handler instance. |
| params_dict: A dict contains data to be translated into CLion |
| project file format. |
| cflags: A boolean is to set 'CMAKE_C_FLAGS' flag. |
| cppflags: A boolean is to set 'CMAKE_CXX_FLAGS' flag. |
| """ |
| _write_all_include_directories( |
| hfile, params_dict[constant.KEY_SYSTEM], True) |
| _write_all_include_directories( |
| hfile, params_dict[constant.KEY_HEADER], False) |
| |
| if cflags: |
| _write_all_relative_file_path_flags(hfile, params_dict[_KEY_RELATIVE], |
| _CMAKE_C_FLAGS) |
| _write_all_flags(hfile, params_dict[_KEY_FLAG], _CMAKE_C_FLAGS) |
| |
| if cppflags: |
| _write_all_relative_file_path_flags(hfile, params_dict[_KEY_RELATIVE], |
| _CMAKE_CXX_FLAGS) |
| _write_all_flags(hfile, params_dict[_KEY_FLAG], _CMAKE_CXX_FLAGS) |
| |
| if params_dict[_KEY_SYSTEM_ROOT]: |
| path = os.path.join(params_dict[_KEY_SYSTEM_ROOT], _USR, _INCLUDE) |
| hfile.write(_INCLUDE_SYSTEM.format(_build_cmake_path(path))) |
| |
| |
| @common_util.check_args(hfile=(TextIOWrapper, StringIO), is_system=bool) |
| @common_util.io_error_handle |
| def _write_all_include_directories(hfile, includes, is_system): |
| """Writes all included directories' paths to the CLion project file. |
| |
| Args: |
| hfile: A file handler instance. |
| includes: A list of included file paths. |
| is_system: A boolean of whether it's a system flag. |
| """ |
| if not includes: |
| return |
| _write_all_includes(hfile, includes, is_system) |
| _write_all_headers(hfile, includes) |
| |
| |
| @common_util.check_args( |
| hfile=(TextIOWrapper, StringIO), rel_paths_dict=dict, tag=str) |
| @common_util.io_error_handle |
| def _write_all_relative_file_path_flags(hfile, rel_paths_dict, tag): |
| """Writes all relative file path flags' parameters. |
| |
| Args: |
| hfile: A file handler instance. |
| rel_paths_dict: A dict contains data of flag as a key and the relative |
| path string as its value. |
| tag: A string of tag, such as 'CMAKE_C_FLAGS'. |
| """ |
| for flag, path in rel_paths_dict.items(): |
| hfile.write( |
| _SET_RELATIVE_PATH.format(tag, _add_dollar_sign(tag), flag, |
| _build_cmake_path(path))) |
| |
| |
| @common_util.check_args(hfile=(TextIOWrapper, StringIO), flags=list, tag=str) |
| @common_util.io_error_handle |
| def _write_all_flags(hfile, flags, tag): |
| """Writes all flags to the project file. |
| |
| Args: |
| hfile: A file handler instance. |
| flags: A list of flag strings to be added. |
| tag: A string to be added a dollar sign. |
| """ |
| for flag in flags: |
| hfile.write(_SET_ALL_FLAGS.format(tag, _add_dollar_sign(tag), flag)) |
| |
| |
| def _add_dollar_sign(tag): |
| """Adds dollar sign to a string, e.g.: 'ANDROID_ROOT' -> '${ANDROID_ROOT}'. |
| |
| Args: |
| tag: A string to be added a dollar sign. |
| |
| Returns: |
| A dollar sign added string. |
| """ |
| return ''.join(['${', tag, '}']) |
| |
| |
| def _build_cmake_path(path, tag=''): |
| """Joins tag, '${ANDROID_ROOT}' and path into a new string. |
| |
| Args: |
| path: A string of a path. |
| tag: A string to be added in front of a dollar sign |
| |
| Returns: |
| The composed string. |
| """ |
| return ''.join([tag, _ANDROID_ROOT_SYMBOL, os.path.sep, path]) |
| |
| |
| @common_util.check_args(hfile=(TextIOWrapper, StringIO), is_system=bool) |
| @common_util.io_error_handle |
| def _write_all_includes(hfile, includes, is_system): |
| """Writes all included directories' paths to the CLion project file. |
| |
| Args: |
| hfile: A file handler instance. |
| includes: A list of included file paths. |
| is_system: A boolean of whether it's a system flag. |
| """ |
| if not includes: |
| return |
| system = '' |
| if is_system: |
| system = _SYSTEM |
| hfile.write(_INCLUDE_DIR.format(system)) |
| for include in includes: |
| hfile.write(_SET_INCLUDE_FORMAT.format(_build_cmake_path(include))) |
| hfile.write(_END_WITH_TWO_BLANK_LINES) |
| |
| |
| @common_util.check_args(hfile=(TextIOWrapper, StringIO)) |
| @common_util.io_error_handle |
| def _write_all_headers(hfile, includes): |
| """Writes all header directories' paths to the CLion project file. |
| |
| Args: |
| hfile: A file handler instance. |
| includes: A list of included file paths. |
| """ |
| if not includes: |
| return |
| hfile.write(_GLOB_RECURSE_TMP_HEADERS) |
| for include in includes: |
| hfile.write(_ALL_HEADER_FILES.format(_build_cmake_path(include))) |
| hfile.write(_END_WITH_ONE_BLANK_LINE) |
| hfile.write(_APPEND_SOURCE_FILES) |
| |
| |
| def _cleanup_executable_name(mod_name): |
| """Clean up an executable name to be suitable for CMake. |
| |
| Replace the last '@' of a module name with '-' and make it become a suitable |
| executable name for CMake. |
| |
| Args: |
| mod_name: A string of module name to be cleaned up. |
| |
| Returns: |
| A string of the executable name. |
| """ |
| return mod_name[::-1].replace('@', '-', 1)[::-1] |