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 25 26_C_CPP_PROPERTIES_CONFIG_FILE_NAME = 'c_cpp_properties.json' 27_ENV = 'env' 28_MY_DEFAULT_INCLUDE_PATH = 'myDefaultIncludePath' 29_MY_COMPILER_PATH = 'myCompilerPath' 30_CONFIG = 'configurations' 31_NAME = 'name' 32_LINUX = 'Linux' 33_INTELLI_SENSE = 'intelliSenseMode' 34_GCC_X64 = 'clang-x64' 35_INC_PATH = 'includePath' 36_SYS_INC_PATH = 'systemIncludePath' 37_COMPILE_PATH = 'compilerPath' 38_C_STANDARD = 'cStandard' 39_C_11 = 'c11' 40_CPP_STANDARD = 'cppStandard' 41_CPP_17 = 'c++17' 42_COMPILE_CMD = 'compileCommands' 43_COMPILE_COMMANDS_FILE_DIR = 'out/soong/development/ide/compdb' 44_COMPILE_COMMANDS_FILE_NAME = 'compile_commands.json' 45_BROWSE = 'browse' 46_PATH = 'path' 47_WORKSPACE_DIR = 'workspaceFolder' 48_LIMIT_SYM = 'limitSymbolsToIncludedHeaders' 49_DB_FILE_NAME = 'databaseFilename' 50_COMPILER_PATH = '/usr/bin/gcc' 51_COMPILER_EMPTY = '"compilerPath" is empty and will skip querying a compiler.' 52_FALSE = 'false' 53_INTELLI_SENSE_ENGINE = 'C_Cpp.intelliSenseEngine' 54_DEFAULT = 'Default' 55 56 57class VSCodeNativeProjectFileGenerator: 58 """VSCode native project file generator. 59 60 Attributes: 61 mod_dir: A string of native project path. 62 config_dir: A string of native project's configuration path. 63 """ 64 65 def __init__(self, mod_dir): 66 """VSCodeNativeProjectFileGenerator initialize. 67 68 Args: 69 mod_dir: An absolute path of native project directory. 70 """ 71 self.mod_dir = mod_dir 72 config_dir = os.path.join(mod_dir, constant.VSCODE_CONFIG_DIR) 73 if not os.path.isdir(config_dir): 74 os.mkdir(config_dir) 75 self.config_dir = config_dir 76 77 def generate_c_cpp_properties_json_file(self): 78 """Generates c_cpp_properties.json file for VSCode project.""" 79 native_mod_info = native_module_info.NativeModuleInfo() 80 root_dir = common_util.get_android_root_dir() 81 mod_names = native_mod_info.get_module_names_in_targets_paths( 82 [os.path.relpath(self.mod_dir, root_dir)]) 83 data = self._create_c_cpp_properties_dict(native_mod_info, mod_names) 84 common_util.dump_json_dict( 85 os.path.join(self.config_dir, _C_CPP_PROPERTIES_CONFIG_FILE_NAME), 86 data) 87 88 @staticmethod 89 def _create_c_cpp_properties_dict(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 = {_NAME: _LINUX} 101 includes = set() 102 for mod_name in mod_names: 103 includes.update(native_mod_info.get_module_includes(mod_name)) 104 browse = {_LIMIT_SYM: _FALSE, _INTELLI_SENSE_ENGINE: _DEFAULT} 105 if includes: 106 paths = _make_header_file_paths(includes) 107 configs[_INC_PATH] = paths 108 browse[_PATH] = paths 109 configs[_COMPILE_PATH] = '' 110 if os.path.isfile(_COMPILER_PATH): 111 configs[_COMPILE_PATH] = _COMPILER_PATH 112 if not configs[_COMPILE_PATH]: 113 logging.warning(_COMPILER_EMPTY) 114 configs[_C_STANDARD] = _C_11 115 configs[_CPP_STANDARD] = _CPP_17 116 root_dir = common_util.get_android_root_dir() 117 configs[_COMPILE_CMD] = os.path.join( 118 root_dir, _COMPILE_COMMANDS_FILE_DIR, _COMPILE_COMMANDS_FILE_NAME) 119 configs[_BROWSE] = browse 120 configs[_INTELLI_SENSE] = _GCC_X64 121 data = {_CONFIG: [configs]} 122 return data 123 124 125def _make_header_file_paths(paths): 126 """Adds the Android root directory and suffix '**/*.h' to a path. 127 128 Args: 129 paths: An iterative set of relative paths' strings. 130 131 Returns: 132 A list of new paths after adding prefix and suffix. 133 """ 134 root_dir = common_util.get_android_root_dir() 135 header_list = [] 136 for path in paths: 137 header_list.append(os.path.join(root_dir, path)) 138 return header_list 139