1*c2e18aaaSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*c2e18aaaSAndroid Build Coastguard Worker# 3*c2e18aaaSAndroid Build Coastguard Worker# Copyright 2019 - The Android Open Source Project 4*c2e18aaaSAndroid Build Coastguard Worker# 5*c2e18aaaSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*c2e18aaaSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*c2e18aaaSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*c2e18aaaSAndroid Build Coastguard Worker# 9*c2e18aaaSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*c2e18aaaSAndroid Build Coastguard Worker# 11*c2e18aaaSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*c2e18aaaSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*c2e18aaaSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*c2e18aaaSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*c2e18aaaSAndroid Build Coastguard Worker# limitations under the License. 16*c2e18aaaSAndroid Build Coastguard Worker 17*c2e18aaaSAndroid Build Coastguard Worker"""Project config class.""" 18*c2e18aaaSAndroid Build Coastguard Worker 19*c2e18aaaSAndroid Build Coastguard Workerimport os 20*c2e18aaaSAndroid Build Coastguard Worker 21*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen import constant 22*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import common_util 23*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import errors 24*c2e18aaaSAndroid Build Coastguard Worker 25*c2e18aaaSAndroid Build Coastguard WorkerSKIP_BUILD_INFO = ('If you are sure the related modules and dependencies have ' 26*c2e18aaaSAndroid Build Coastguard Worker 'been already built, please try to use command {} to skip ' 27*c2e18aaaSAndroid Build Coastguard Worker 'the building process.') 28*c2e18aaaSAndroid Build Coastguard Worker_SKIP_BUILD_CMD = 'aidegen {} -s' 29*c2e18aaaSAndroid Build Coastguard Worker_SKIP_BUILD_WARN = ( 30*c2e18aaaSAndroid Build Coastguard Worker 'You chose "--skip-build". Skip building jar and module might increase ' 31*c2e18aaaSAndroid Build Coastguard Worker 'the risk of the absence of some jar or R/AIDL/logtags java files and ' 32*c2e18aaaSAndroid Build Coastguard Worker 'cause the red lines to appear in IDE tool.') 33*c2e18aaaSAndroid Build Coastguard Worker_INSTANCE_NOT_EXIST_ERROR = ('The instance of {} does not exist. Please ' 34*c2e18aaaSAndroid Build Coastguard Worker 'initialize it before using.') 35*c2e18aaaSAndroid Build Coastguard Worker 36*c2e18aaaSAndroid Build Coastguard Worker 37*c2e18aaaSAndroid Build Coastguard Workerclass ProjectConfig: 38*c2e18aaaSAndroid Build Coastguard Worker """A singleton class manages AIDEGen's configurations. 39*c2e18aaaSAndroid Build Coastguard Worker 40*c2e18aaaSAndroid Build Coastguard Worker ProjectConfig is a singleton class that can be accessed in other modules. 41*c2e18aaaSAndroid Build Coastguard Worker 42*c2e18aaaSAndroid Build Coastguard Worker Usage: 43*c2e18aaaSAndroid Build Coastguard Worker 1. Main module should do it once by instantiating a ProjectConfig with 44*c2e18aaaSAndroid Build Coastguard Worker users' input arguments and calling init_environment(). 45*c2e18aaaSAndroid Build Coastguard Worker args = aidegen_main.main(sys.argv[1:]) 46*c2e18aaaSAndroid Build Coastguard Worker project_config.ProjectConfig(args).init_environment() 47*c2e18aaaSAndroid Build Coastguard Worker 2. All others can get the ProjectConfig instance by calling 48*c2e18aaaSAndroid Build Coastguard Worker get_instance(). 49*c2e18aaaSAndroid Build Coastguard Worker project_config.ProjectConfig.get_instance() 50*c2e18aaaSAndroid Build Coastguard Worker 51*c2e18aaaSAndroid Build Coastguard Worker Class attributes: 52*c2e18aaaSAndroid Build Coastguard Worker _instance: A singleton instance of ProjectConfig. 53*c2e18aaaSAndroid Build Coastguard Worker 54*c2e18aaaSAndroid Build Coastguard Worker Attributes: 55*c2e18aaaSAndroid Build Coastguard Worker ide_name: The IDE name which users prefer to launch. 56*c2e18aaaSAndroid Build Coastguard Worker is_launch_ide: A boolean for launching IDE in the end of AIDEGen. 57*c2e18aaaSAndroid Build Coastguard Worker depth: The depth of module referenced by source. 58*c2e18aaaSAndroid Build Coastguard Worker full_repo: A boolean decides import whole Android source repo. 59*c2e18aaaSAndroid Build Coastguard Worker is_skip_build: A boolean decides skipping building jars or modules. 60*c2e18aaaSAndroid Build Coastguard Worker targets: A string list with Android module names or paths. 61*c2e18aaaSAndroid Build Coastguard Worker verbose: A boolean. If true, display DEBUG level logs. 62*c2e18aaaSAndroid Build Coastguard Worker ide_installed_path: A string of IDE installed path. 63*c2e18aaaSAndroid Build Coastguard Worker config_reset: A boolean if true to reset all saved configurations. 64*c2e18aaaSAndroid Build Coastguard Worker atest_module_info: A ModuleInfo instance. 65*c2e18aaaSAndroid Build Coastguard Worker language: The programming language users prefer to deal with. 66*c2e18aaaSAndroid Build Coastguard Worker """ 67*c2e18aaaSAndroid Build Coastguard Worker 68*c2e18aaaSAndroid Build Coastguard Worker _instance = None 69*c2e18aaaSAndroid Build Coastguard Worker 70*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, args): 71*c2e18aaaSAndroid Build Coastguard Worker """ProjectConfig initialize. 72*c2e18aaaSAndroid Build Coastguard Worker 73*c2e18aaaSAndroid Build Coastguard Worker Args: 74*c2e18aaaSAndroid Build Coastguard Worker An argparse.Namespace object holds parsed args. 75*c2e18aaaSAndroid Build Coastguard Worker """ 76*c2e18aaaSAndroid Build Coastguard Worker self.language = constant.LANGUAGE_NAME_DICT[args.language[0]] 77*c2e18aaaSAndroid Build Coastguard Worker self.ide_name = constant.IDE_NAME_DICT[args.ide[0]] 78*c2e18aaaSAndroid Build Coastguard Worker self.is_launch_ide = not args.no_launch 79*c2e18aaaSAndroid Build Coastguard Worker self.depth = args.depth 80*c2e18aaaSAndroid Build Coastguard Worker self.full_repo = args.android_tree 81*c2e18aaaSAndroid Build Coastguard Worker self.is_skip_build = args.skip_build 82*c2e18aaaSAndroid Build Coastguard Worker self.targets = args.targets.copy() 83*c2e18aaaSAndroid Build Coastguard Worker self.verbose = args.verbose 84*c2e18aaaSAndroid Build Coastguard Worker self.ide_installed_path = args.ide_installed_path 85*c2e18aaaSAndroid Build Coastguard Worker self.config_reset = args.config_reset 86*c2e18aaaSAndroid Build Coastguard Worker self.exclude_paths = args.exclude_paths 87*c2e18aaaSAndroid Build Coastguard Worker self.atest_module_info = None 88*c2e18aaaSAndroid Build Coastguard Worker ProjectConfig._instance = self 89*c2e18aaaSAndroid Build Coastguard Worker 90*c2e18aaaSAndroid Build Coastguard Worker def init_environment(self): 91*c2e18aaaSAndroid Build Coastguard Worker """Initialize the environment settings for the whole project.""" 92*c2e18aaaSAndroid Build Coastguard Worker self._show_skip_build_msg() 93*c2e18aaaSAndroid Build Coastguard Worker # TODO(b/159078170): Avoid CLion IDE case for now, we should avoid 94*c2e18aaaSAndroid Build Coastguard Worker # Android Studio's native project's case in the future. 95*c2e18aaaSAndroid Build Coastguard Worker targets = self.targets if self.language == constant.JAVA else None 96*c2e18aaaSAndroid Build Coastguard Worker self.atest_module_info = common_util.get_atest_module_info(targets) 97*c2e18aaaSAndroid Build Coastguard Worker self.exclude_paths = _transform_exclusive_paths( 98*c2e18aaaSAndroid Build Coastguard Worker self.atest_module_info, self.exclude_paths) 99*c2e18aaaSAndroid Build Coastguard Worker self.targets = _check_whole_android_tree(self.targets, self.full_repo) 100*c2e18aaaSAndroid Build Coastguard Worker self.full_repo = (self.targets[0] == constant.WHOLE_ANDROID_TREE_TARGET) 101*c2e18aaaSAndroid Build Coastguard Worker 102*c2e18aaaSAndroid Build Coastguard Worker def _show_skip_build_msg(self): 103*c2e18aaaSAndroid Build Coastguard Worker """Display different messages if users skip building targets or not.""" 104*c2e18aaaSAndroid Build Coastguard Worker if self.is_skip_build: 105*c2e18aaaSAndroid Build Coastguard Worker print('\n{} {}\n'.format( 106*c2e18aaaSAndroid Build Coastguard Worker common_util.COLORED_INFO('Warning:'), _SKIP_BUILD_WARN)) 107*c2e18aaaSAndroid Build Coastguard Worker else: 108*c2e18aaaSAndroid Build Coastguard Worker msg = SKIP_BUILD_INFO.format( 109*c2e18aaaSAndroid Build Coastguard Worker common_util.COLORED_INFO( 110*c2e18aaaSAndroid Build Coastguard Worker _SKIP_BUILD_CMD.format(' '.join(self.targets)))) 111*c2e18aaaSAndroid Build Coastguard Worker print('\n{} {}\n'.format(common_util.COLORED_INFO('INFO:'), msg)) 112*c2e18aaaSAndroid Build Coastguard Worker 113*c2e18aaaSAndroid Build Coastguard Worker @classmethod 114*c2e18aaaSAndroid Build Coastguard Worker def get_instance(cls): 115*c2e18aaaSAndroid Build Coastguard Worker """Get a singleton's instance. 116*c2e18aaaSAndroid Build Coastguard Worker 117*c2e18aaaSAndroid Build Coastguard Worker Returns: 118*c2e18aaaSAndroid Build Coastguard Worker A singleton instance of ProjectConfig. 119*c2e18aaaSAndroid Build Coastguard Worker 120*c2e18aaaSAndroid Build Coastguard Worker Raises: 121*c2e18aaaSAndroid Build Coastguard Worker An exception of errors.InstanceNotExistError if users didn't 122*c2e18aaaSAndroid Build Coastguard Worker instantiate a ProjectConfig object before calling this method. 123*c2e18aaaSAndroid Build Coastguard Worker """ 124*c2e18aaaSAndroid Build Coastguard Worker if not cls._instance: 125*c2e18aaaSAndroid Build Coastguard Worker raise errors.InstanceNotExistError( 126*c2e18aaaSAndroid Build Coastguard Worker _INSTANCE_NOT_EXIST_ERROR.format(str(cls))) 127*c2e18aaaSAndroid Build Coastguard Worker return cls._instance 128*c2e18aaaSAndroid Build Coastguard Worker 129*c2e18aaaSAndroid Build Coastguard Worker 130*c2e18aaaSAndroid Build Coastguard Workerdef _check_whole_android_tree(targets, android_tree): 131*c2e18aaaSAndroid Build Coastguard Worker """Check if it's a building project file for the whole Android tree. 132*c2e18aaaSAndroid Build Coastguard Worker 133*c2e18aaaSAndroid Build Coastguard Worker The rules: 134*c2e18aaaSAndroid Build Coastguard Worker 1. If users command aidegen under Android root, e.g., 135*c2e18aaaSAndroid Build Coastguard Worker root$ aidegen 136*c2e18aaaSAndroid Build Coastguard Worker that implies users would like to launch the whole Android tree, AIDEGen 137*c2e18aaaSAndroid Build Coastguard Worker should set the flag android_tree True. 138*c2e18aaaSAndroid Build Coastguard Worker 2. If android_tree is True, add whole Android tree to the project. 139*c2e18aaaSAndroid Build Coastguard Worker 140*c2e18aaaSAndroid Build Coastguard Worker Args: 141*c2e18aaaSAndroid Build Coastguard Worker targets: A list of targets to be imported. 142*c2e18aaaSAndroid Build Coastguard Worker android_tree: A boolean, True if it's a whole Android tree case, 143*c2e18aaaSAndroid Build Coastguard Worker otherwise False. 144*c2e18aaaSAndroid Build Coastguard Worker 145*c2e18aaaSAndroid Build Coastguard Worker Returns: 146*c2e18aaaSAndroid Build Coastguard Worker A list of targets to be built. 147*c2e18aaaSAndroid Build Coastguard Worker """ 148*c2e18aaaSAndroid Build Coastguard Worker if common_util.is_android_root(os.getcwd()) and targets == ['']: 149*c2e18aaaSAndroid Build Coastguard Worker return [constant.WHOLE_ANDROID_TREE_TARGET] 150*c2e18aaaSAndroid Build Coastguard Worker new_targets = targets.copy() 151*c2e18aaaSAndroid Build Coastguard Worker if android_tree: 152*c2e18aaaSAndroid Build Coastguard Worker new_targets.insert(0, constant.WHOLE_ANDROID_TREE_TARGET) 153*c2e18aaaSAndroid Build Coastguard Worker return new_targets 154*c2e18aaaSAndroid Build Coastguard Worker 155*c2e18aaaSAndroid Build Coastguard Worker 156*c2e18aaaSAndroid Build Coastguard Workerdef is_whole_android_tree(targets, android_tree): 157*c2e18aaaSAndroid Build Coastguard Worker """Checks is AIDEGen going to process whole android tree. 158*c2e18aaaSAndroid Build Coastguard Worker 159*c2e18aaaSAndroid Build Coastguard Worker Args: 160*c2e18aaaSAndroid Build Coastguard Worker targets: A list of targets to be imported. 161*c2e18aaaSAndroid Build Coastguard Worker android_tree: A boolean, True if it's a whole Android tree case, 162*c2e18aaaSAndroid Build Coastguard Worker otherwise False. 163*c2e18aaaSAndroid Build Coastguard Worker Returns: 164*c2e18aaaSAndroid Build Coastguard Worker A boolean, True when user is going to import whole Android tree. 165*c2e18aaaSAndroid Build Coastguard Worker """ 166*c2e18aaaSAndroid Build Coastguard Worker return (android_tree or 167*c2e18aaaSAndroid Build Coastguard Worker (common_util.is_android_root(os.getcwd()) and targets == [''])) 168*c2e18aaaSAndroid Build Coastguard Worker 169*c2e18aaaSAndroid Build Coastguard Worker 170*c2e18aaaSAndroid Build Coastguard Workerdef _transform_exclusive_paths(atest_module_info, exclude_paths): 171*c2e18aaaSAndroid Build Coastguard Worker """Transforms exclusive paths to relative paths. 172*c2e18aaaSAndroid Build Coastguard Worker 173*c2e18aaaSAndroid Build Coastguard Worker Args: 174*c2e18aaaSAndroid Build Coastguard Worker exclude_paths: A list of strings of exclusive paths. 175*c2e18aaaSAndroid Build Coastguard Worker 176*c2e18aaaSAndroid Build Coastguard Worker Returns: 177*c2e18aaaSAndroid Build Coastguard Worker A list of relative paths. 178*c2e18aaaSAndroid Build Coastguard Worker """ 179*c2e18aaaSAndroid Build Coastguard Worker if not exclude_paths: 180*c2e18aaaSAndroid Build Coastguard Worker return None 181*c2e18aaaSAndroid Build Coastguard Worker excludes = [] 182*c2e18aaaSAndroid Build Coastguard Worker for path in exclude_paths: 183*c2e18aaaSAndroid Build Coastguard Worker exclude_path, _ = common_util.get_related_paths(atest_module_info, path) 184*c2e18aaaSAndroid Build Coastguard Worker excludes.append(exclude_path) 185*c2e18aaaSAndroid Build Coastguard Worker return excludes 186