1#!/usr/bin/env python3 2# 3# Copyright 2020 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17"""It is an AIDEGen sub task: generate VSCode related config files.""" 18 19import logging 20import os 21 22from aidegen import constant 23from aidegen.lib import common_util 24from aidegen.lib import native_module_info 25from atest import constants 26 27_C_CPP_PROPERTIES_CONFIG_FILE_NAME = 'c_cpp_properties.json' 28_ENV = 'env' 29_MY_DEFAULT_INCLUDE_PATH = 'myDefaultIncludePath' 30_MY_COMPILER_PATH = 'myCompilerPath' 31_CONFIG = 'configurations' 32_NAME = 'name' 33_LINUX = 'Linux' 34_INTELL_SENSE = 'intelliSenseMode' 35_GCC_X64 = 'clang-x64' 36_INC_PATH = 'includePath' 37_SYS_INC_PATH = 'systemIncludePath' 38_COMPILE_PATH = 'compilerPath' 39_C_STANDARD = 'cStandard' 40_C_11 = 'c11' 41_CPP_STANDARD = 'cppStandard' 42_CPP_17 = 'c++17' 43_COMPILE_CMD = 'compileCommands' 44_COMPILE_COMMANDS_FILE_DIR = 'out/soong/development/ide/compdb' 45_COMPILE_COMMANDS_FILE_NAME = 'compile_commands.json' 46_BROWSE = 'browse' 47_PATH = 'path' 48_WORKSPACE_DIR = 'workspaceFolder' 49_LIMIT_SYM = 'limitSymbolsToIncludedHeaders' 50_DB_FILE_NAME = 'databaseFilename' 51_COMPILER_PATH = '/usr/bin/gcc' 52_COMPILER_EMPTY = '"compilerPath" is empty and will skip querying a compiler.' 53_FALSE = 'false' 54_INTELI_SENSE_ENGINE = 'C_Cpp.intelliSenseEngine' 55_DEFAULT = 'Default' 56 57 58class VSCodeNativeProjectFileGenerator: 59 """VSCode native project file generator. 60 61 Attributes: 62 mod_dir: A string of native project path. 63 config_dir: A string of native project's configuration path. 64 """ 65 66 def __init__(self, mod_dir): 67 """VSCodeNativeProjectFileGenerator initialize. 68 69 Args: 70 mod_dir: An absolute path of native project directory. 71 """ 72 self.mod_dir = mod_dir 73 config_dir = os.path.join(mod_dir, constant.VSCODE_CONFIG_DIR) 74 if not os.path.isdir(config_dir): 75 os.mkdir(config_dir) 76 self.config_dir = config_dir 77 78 def generate_c_cpp_properties_json_file(self): 79 """Generates c_cpp_properties.json file for VSCode project.""" 80 native_mod_info = native_module_info.NativeModuleInfo() 81 root_dir = common_util.get_android_root_dir() 82 mod_names = native_mod_info.get_module_names_in_targets_paths( 83 [os.path.relpath(self.mod_dir, root_dir)]) 84 data = self._create_c_cpp_properties_dict(native_mod_info, mod_names) 85 common_util.dump_json_dict( 86 os.path.join(self.config_dir, _C_CPP_PROPERTIES_CONFIG_FILE_NAME), 87 data) 88 89 def _create_c_cpp_properties_dict(self, native_mod_info, mod_names): 90 """Creates the dictionary of 'c_cpp_properties.json' file. 91 92 Args: 93 native_mod_info: An instance of native_module_info.NativeModuleInfo 94 class. 95 mod_names: A list of module names. 96 97 Returns: 98 A dictionary contains the formats of c_cpp_properties.json file. 99 """ 100 configs = {} 101 configs[_NAME] = _LINUX 102 includes = set() 103 for mod_name in mod_names: 104 includes.update(native_mod_info.get_module_includes(mod_name)) 105 browse = {_LIMIT_SYM: _FALSE, _INTELI_SENSE_ENGINE: _DEFAULT} 106 if includes: 107 paths = _make_header_file_paths(includes) 108 configs[_INC_PATH] = paths 109 browse[_PATH] = paths 110 configs[_COMPILE_PATH] = '' 111 if os.path.isfile(_COMPILER_PATH): 112 configs[_COMPILE_PATH] = _COMPILER_PATH 113 if not configs[_COMPILE_PATH]: 114 logging.warning(_COMPILER_EMPTY) 115 configs[_C_STANDARD] = _C_11 116 configs[_CPP_STANDARD] = _CPP_17 117 root_var = _make_var(constants.ANDROID_BUILD_TOP) 118 configs[_COMPILE_CMD] = os.path.join( 119 root_var, _COMPILE_COMMANDS_FILE_DIR, _COMPILE_COMMANDS_FILE_NAME) 120 configs[_BROWSE] = browse 121 configs[_INTELL_SENSE] = _GCC_X64 122 data = {} 123 data[_CONFIG] = [configs] 124 return data 125 126 127def _make_var(text): 128 """Adds '${}' to make the text become a variable. 129 130 Args: 131 text: A string of text to be added '${}'. 132 133 Returns: 134 A string after adding '${}'. 135 """ 136 return ''.join(['${', text, '}']) 137 138 139def _make_header_file_paths(paths): 140 """Adds prefix '${ANDROID_BUILD_TOP}' and suffix '**/*.h' to a path. 141 142 Args: 143 paths: An iterative set of relative paths' strings. 144 145 Returns: 146 A list of new paths after adding prefix and suffix. 147 """ 148 header_list = [] 149 for path in paths: 150 header_list.append(os.path.join( 151 _make_var(constants.ANDROID_BUILD_TOP), path)) 152 return header_list 153