1*c2e18aaaSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*c2e18aaaSAndroid Build Coastguard Worker# 3*c2e18aaaSAndroid Build Coastguard Worker# Copyright 2018 - 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 information.""" 18*c2e18aaaSAndroid Build Coastguard Worker 19*c2e18aaaSAndroid Build Coastguard Workerfrom __future__ import absolute_import 20*c2e18aaaSAndroid Build Coastguard Worker 21*c2e18aaaSAndroid Build Coastguard Workerimport logging 22*c2e18aaaSAndroid Build Coastguard Workerimport os 23*c2e18aaaSAndroid Build Coastguard Workerimport time 24*c2e18aaaSAndroid Build Coastguard Worker 25*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen import constant 26*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import aidegen_metrics 27*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import common_util 28*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import errors 29*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import module_info 30*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import project_config 31*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import source_locator 32*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.idea import iml 33*c2e18aaaSAndroid Build Coastguard Worker 34*c2e18aaaSAndroid Build Coastguard Workerfrom atest import atest_utils 35*c2e18aaaSAndroid Build Coastguard Worker 36*c2e18aaaSAndroid Build Coastguard Worker_CONVERT_MK_URL = ('https://android.googlesource.com/platform/build/soong/' 37*c2e18aaaSAndroid Build Coastguard Worker '#convert-android_mk-files') 38*c2e18aaaSAndroid Build Coastguard Worker_ROBOLECTRIC_MODULE = 'Robolectric_all' 39*c2e18aaaSAndroid Build Coastguard Worker_NOT_TARGET = ('The module %s does not contain any Java or Kotlin file, ' 40*c2e18aaaSAndroid Build Coastguard Worker 'therefore we skip this module in the project.') 41*c2e18aaaSAndroid Build Coastguard Worker# The module fake-framework have the same package name with framework but empty 42*c2e18aaaSAndroid Build Coastguard Worker# content. It will impact the dependency for framework when referencing the 43*c2e18aaaSAndroid Build Coastguard Worker# package from fake-framework in IntelliJ. 44*c2e18aaaSAndroid Build Coastguard Worker_EXCLUDE_MODULES = ['fake-framework'] 45*c2e18aaaSAndroid Build Coastguard Worker# When we use atest_utils.build(), there is a command length limit on 46*c2e18aaaSAndroid Build Coastguard Worker# soong_ui.bash. We reserve 5000 characters for rewriting the command line 47*c2e18aaaSAndroid Build Coastguard Worker# in soong_ui.bash. 48*c2e18aaaSAndroid Build Coastguard Worker_CMD_LENGTH_BUFFER = 5000 49*c2e18aaaSAndroid Build Coastguard Worker# For each argument, it needs a space to separate following argument. 50*c2e18aaaSAndroid Build Coastguard Worker_BLANK_SIZE = 1 51*c2e18aaaSAndroid Build Coastguard Worker_CORE_MODULES = [constant.FRAMEWORK_ALL, constant.CORE_ALL, 52*c2e18aaaSAndroid Build Coastguard Worker 'org.apache.http.legacy.stubs.system'] 53*c2e18aaaSAndroid Build Coastguard Worker_BUILD_BP_JSON_ENV_ON = { 54*c2e18aaaSAndroid Build Coastguard Worker constant.GEN_JAVA_DEPS: 'true', 55*c2e18aaaSAndroid Build Coastguard Worker constant.GEN_CC_DEPS: 'true', 56*c2e18aaaSAndroid Build Coastguard Worker constant.GEN_COMPDB: 'true', 57*c2e18aaaSAndroid Build Coastguard Worker constant.GEN_RUST: 'true' 58*c2e18aaaSAndroid Build Coastguard Worker} 59*c2e18aaaSAndroid Build Coastguard Worker 60*c2e18aaaSAndroid Build Coastguard Worker 61*c2e18aaaSAndroid Build Coastguard Workerclass ProjectInfo: 62*c2e18aaaSAndroid Build Coastguard Worker """Project information. 63*c2e18aaaSAndroid Build Coastguard Worker 64*c2e18aaaSAndroid Build Coastguard Worker Users should call config_project first before starting using ProjectInfo. 65*c2e18aaaSAndroid Build Coastguard Worker 66*c2e18aaaSAndroid Build Coastguard Worker Class attributes: 67*c2e18aaaSAndroid Build Coastguard Worker modules_info: An AidegenModuleInfo instance whose name_to_module_info is 68*c2e18aaaSAndroid Build Coastguard Worker combining module-info.json with module_bp_java_deps.json. 69*c2e18aaaSAndroid Build Coastguard Worker projects: A list of instances of ProjectInfo that are generated in an 70*c2e18aaaSAndroid Build Coastguard Worker AIDEGen command. 71*c2e18aaaSAndroid Build Coastguard Worker 72*c2e18aaaSAndroid Build Coastguard Worker Attributes: 73*c2e18aaaSAndroid Build Coastguard Worker project_absolute_path: The absolute path of the project. 74*c2e18aaaSAndroid Build Coastguard Worker project_relative_path: The relative path of the project to 75*c2e18aaaSAndroid Build Coastguard Worker common_util.get_android_root_dir(). 76*c2e18aaaSAndroid Build Coastguard Worker project_module_names: A set of module names under project_absolute_path 77*c2e18aaaSAndroid Build Coastguard Worker directory or it's subdirectories. 78*c2e18aaaSAndroid Build Coastguard Worker dep_modules: A dict has recursively dependent modules of 79*c2e18aaaSAndroid Build Coastguard Worker project_module_names. 80*c2e18aaaSAndroid Build Coastguard Worker iml_path: The project's iml file path. 81*c2e18aaaSAndroid Build Coastguard Worker source_path: A dictionary to keep following data: 82*c2e18aaaSAndroid Build Coastguard Worker source_folder_path: A set contains the source folder 83*c2e18aaaSAndroid Build Coastguard Worker relative paths. 84*c2e18aaaSAndroid Build Coastguard Worker test_folder_path: A set contains the test folder relative 85*c2e18aaaSAndroid Build Coastguard Worker paths. 86*c2e18aaaSAndroid Build Coastguard Worker jar_path: A set contains the jar file paths. 87*c2e18aaaSAndroid Build Coastguard Worker jar_module_path: A dictionary contains the jar file and 88*c2e18aaaSAndroid Build Coastguard Worker the module's path mapping, only used in 89*c2e18aaaSAndroid Build Coastguard Worker Eclipse. 90*c2e18aaaSAndroid Build Coastguard Worker r_java_path: A set contains the relative path to the 91*c2e18aaaSAndroid Build Coastguard Worker R.java files, only used in Eclipse. 92*c2e18aaaSAndroid Build Coastguard Worker srcjar_path: A source content descriptor only used in 93*c2e18aaaSAndroid Build Coastguard Worker IntelliJ. 94*c2e18aaaSAndroid Build Coastguard Worker e.g. out/.../aapt2.srcjar!/ 95*c2e18aaaSAndroid Build Coastguard Worker The "!/" is a content descriptor for 96*c2e18aaaSAndroid Build Coastguard Worker compressed files in IntelliJ. 97*c2e18aaaSAndroid Build Coastguard Worker is_main_project: A boolean to verify the project is main project. 98*c2e18aaaSAndroid Build Coastguard Worker dependencies: A list of dependency projects' iml file names, e.g. base, 99*c2e18aaaSAndroid Build Coastguard Worker framework-all. 100*c2e18aaaSAndroid Build Coastguard Worker iml_name: The iml project file name of this project. 101*c2e18aaaSAndroid Build Coastguard Worker rel_out_soong_jar_path: A string of relative project path in the 102*c2e18aaaSAndroid Build Coastguard Worker 'out/soong/.intermediates' directory, e.g., if 103*c2e18aaaSAndroid Build Coastguard Worker self.project_relative_path = 'frameworks/base' 104*c2e18aaaSAndroid Build Coastguard Worker the rel_out_soong_jar_path should be 105*c2e18aaaSAndroid Build Coastguard Worker 'out/soong/.intermediates/frameworks/base/'. 106*c2e18aaaSAndroid Build Coastguard Worker """ 107*c2e18aaaSAndroid Build Coastguard Worker 108*c2e18aaaSAndroid Build Coastguard Worker modules_info = None 109*c2e18aaaSAndroid Build Coastguard Worker projects = [] 110*c2e18aaaSAndroid Build Coastguard Worker 111*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, target=None, is_main_project=False): 112*c2e18aaaSAndroid Build Coastguard Worker """ProjectInfo initialize. 113*c2e18aaaSAndroid Build Coastguard Worker 114*c2e18aaaSAndroid Build Coastguard Worker Args: 115*c2e18aaaSAndroid Build Coastguard Worker target: Includes target module or project path from user input, when 116*c2e18aaaSAndroid Build Coastguard Worker locating the target, project with matching module name of 117*c2e18aaaSAndroid Build Coastguard Worker the given target has a higher priority than project path. 118*c2e18aaaSAndroid Build Coastguard Worker is_main_project: A boolean, default is False. True if the target is 119*c2e18aaaSAndroid Build Coastguard Worker the main project, otherwise False. 120*c2e18aaaSAndroid Build Coastguard Worker """ 121*c2e18aaaSAndroid Build Coastguard Worker rel_path, abs_path = common_util.get_related_paths( 122*c2e18aaaSAndroid Build Coastguard Worker self.modules_info, target) 123*c2e18aaaSAndroid Build Coastguard Worker self.module_name = self.get_target_name(target, abs_path) 124*c2e18aaaSAndroid Build Coastguard Worker self.is_main_project = is_main_project 125*c2e18aaaSAndroid Build Coastguard Worker self.project_module_names = set( 126*c2e18aaaSAndroid Build Coastguard Worker self.modules_info.get_module_names(rel_path)) 127*c2e18aaaSAndroid Build Coastguard Worker self.project_relative_path = rel_path 128*c2e18aaaSAndroid Build Coastguard Worker self.project_absolute_path = abs_path 129*c2e18aaaSAndroid Build Coastguard Worker self.iml_path = '' 130*c2e18aaaSAndroid Build Coastguard Worker self._set_default_modules() 131*c2e18aaaSAndroid Build Coastguard Worker self._init_source_path() 132*c2e18aaaSAndroid Build Coastguard Worker if target == constant.FRAMEWORK_ALL: 133*c2e18aaaSAndroid Build Coastguard Worker self.dep_modules = self.get_dep_modules([target]) 134*c2e18aaaSAndroid Build Coastguard Worker else: 135*c2e18aaaSAndroid Build Coastguard Worker self.dep_modules = self.get_dep_modules() 136*c2e18aaaSAndroid Build Coastguard Worker self._filter_out_modules() 137*c2e18aaaSAndroid Build Coastguard Worker self.dependencies = [] 138*c2e18aaaSAndroid Build Coastguard Worker self.iml_name = iml.IMLGenerator.get_unique_iml_name(abs_path) 139*c2e18aaaSAndroid Build Coastguard Worker self.rel_out_soong_jar_path = self._get_rel_project_out_soong_jar_path() 140*c2e18aaaSAndroid Build Coastguard Worker 141*c2e18aaaSAndroid Build Coastguard Worker def _set_default_modules(self): 142*c2e18aaaSAndroid Build Coastguard Worker """Append default hard-code modules, source paths and jar files. 143*c2e18aaaSAndroid Build Coastguard Worker 144*c2e18aaaSAndroid Build Coastguard Worker 1. framework: Framework module is always needed for dependencies, but it 145*c2e18aaaSAndroid Build Coastguard Worker might not always be located by module dependency. 146*c2e18aaaSAndroid Build Coastguard Worker 2. org.apache.http.legacy.stubs.system: The module can't be located 147*c2e18aaaSAndroid Build Coastguard Worker through module dependency. Without it, a lot of java files will have 148*c2e18aaaSAndroid Build Coastguard Worker error of "cannot resolve symbol" in IntelliJ since they import 149*c2e18aaaSAndroid Build Coastguard Worker packages android.Manifest and com.android.internal.R. 150*c2e18aaaSAndroid Build Coastguard Worker """ 151*c2e18aaaSAndroid Build Coastguard Worker # Set the default modules framework-all and core-all as the core 152*c2e18aaaSAndroid Build Coastguard Worker # dependency modules. 153*c2e18aaaSAndroid Build Coastguard Worker self.project_module_names.update(_CORE_MODULES) 154*c2e18aaaSAndroid Build Coastguard Worker 155*c2e18aaaSAndroid Build Coastguard Worker def _init_source_path(self): 156*c2e18aaaSAndroid Build Coastguard Worker """Initialize source_path dictionary.""" 157*c2e18aaaSAndroid Build Coastguard Worker self.source_path = { 158*c2e18aaaSAndroid Build Coastguard Worker 'source_folder_path': set(), 159*c2e18aaaSAndroid Build Coastguard Worker 'test_folder_path': set(), 160*c2e18aaaSAndroid Build Coastguard Worker 'jar_path': set(), 161*c2e18aaaSAndroid Build Coastguard Worker 'jar_module_path': {}, 162*c2e18aaaSAndroid Build Coastguard Worker 'r_java_path': set(), 163*c2e18aaaSAndroid Build Coastguard Worker 'srcjar_path': set() 164*c2e18aaaSAndroid Build Coastguard Worker } 165*c2e18aaaSAndroid Build Coastguard Worker 166*c2e18aaaSAndroid Build Coastguard Worker def _search_android_make_files(self): 167*c2e18aaaSAndroid Build Coastguard Worker """Search project and dependency modules contain Android.mk files. 168*c2e18aaaSAndroid Build Coastguard Worker 169*c2e18aaaSAndroid Build Coastguard Worker If there is only Android.mk but no Android.bp, we'll show the warning 170*c2e18aaaSAndroid Build Coastguard Worker message, otherwise we won't. 171*c2e18aaaSAndroid Build Coastguard Worker 172*c2e18aaaSAndroid Build Coastguard Worker Yields: 173*c2e18aaaSAndroid Build Coastguard Worker A string: the relative path of Android.mk. 174*c2e18aaaSAndroid Build Coastguard Worker """ 175*c2e18aaaSAndroid Build Coastguard Worker if (common_util.exist_android_mk(self.project_absolute_path) and 176*c2e18aaaSAndroid Build Coastguard Worker not common_util.exist_android_bp(self.project_absolute_path)): 177*c2e18aaaSAndroid Build Coastguard Worker yield '\t' + os.path.join(self.project_relative_path, 178*c2e18aaaSAndroid Build Coastguard Worker constant.ANDROID_MK) 179*c2e18aaaSAndroid Build Coastguard Worker for mod_name in self.dep_modules: 180*c2e18aaaSAndroid Build Coastguard Worker rel_path, abs_path = common_util.get_related_paths( 181*c2e18aaaSAndroid Build Coastguard Worker self.modules_info, mod_name) 182*c2e18aaaSAndroid Build Coastguard Worker if rel_path and abs_path: 183*c2e18aaaSAndroid Build Coastguard Worker if (common_util.exist_android_mk(abs_path) 184*c2e18aaaSAndroid Build Coastguard Worker and not common_util.exist_android_bp(abs_path)): 185*c2e18aaaSAndroid Build Coastguard Worker yield '\t' + os.path.join(rel_path, constant.ANDROID_MK) 186*c2e18aaaSAndroid Build Coastguard Worker 187*c2e18aaaSAndroid Build Coastguard Worker def _get_modules_under_project_path(self, rel_path): 188*c2e18aaaSAndroid Build Coastguard Worker """Find qualified modules under the rel_path. 189*c2e18aaaSAndroid Build Coastguard Worker 190*c2e18aaaSAndroid Build Coastguard Worker Find modules which contain any Java or Kotlin file as a target module. 191*c2e18aaaSAndroid Build Coastguard Worker If it's the whole source tree project, add all modules into it. 192*c2e18aaaSAndroid Build Coastguard Worker 193*c2e18aaaSAndroid Build Coastguard Worker Args: 194*c2e18aaaSAndroid Build Coastguard Worker rel_path: A string, the project's relative path. 195*c2e18aaaSAndroid Build Coastguard Worker 196*c2e18aaaSAndroid Build Coastguard Worker Returns: 197*c2e18aaaSAndroid Build Coastguard Worker A set of module names. 198*c2e18aaaSAndroid Build Coastguard Worker """ 199*c2e18aaaSAndroid Build Coastguard Worker logging.info('Find modules contain any Java or Kotlin file under %s.', 200*c2e18aaaSAndroid Build Coastguard Worker rel_path) 201*c2e18aaaSAndroid Build Coastguard Worker if rel_path == '': 202*c2e18aaaSAndroid Build Coastguard Worker return self.modules_info.name_to_module_info.keys() 203*c2e18aaaSAndroid Build Coastguard Worker modules = set() 204*c2e18aaaSAndroid Build Coastguard Worker root_dir = common_util.get_android_root_dir() 205*c2e18aaaSAndroid Build Coastguard Worker for name, data in self.modules_info.name_to_module_info.items(): 206*c2e18aaaSAndroid Build Coastguard Worker if module_info.AidegenModuleInfo.is_project_path_relative_module( 207*c2e18aaaSAndroid Build Coastguard Worker data, rel_path): 208*c2e18aaaSAndroid Build Coastguard Worker if common_util.check_java_or_kotlin_file_exists( 209*c2e18aaaSAndroid Build Coastguard Worker os.path.join(root_dir, data[constant.KEY_PATH][0])): 210*c2e18aaaSAndroid Build Coastguard Worker modules.add(name) 211*c2e18aaaSAndroid Build Coastguard Worker else: 212*c2e18aaaSAndroid Build Coastguard Worker logging.debug(_NOT_TARGET, name) 213*c2e18aaaSAndroid Build Coastguard Worker return modules 214*c2e18aaaSAndroid Build Coastguard Worker 215*c2e18aaaSAndroid Build Coastguard Worker def _get_robolectric_dep_module(self, modules): 216*c2e18aaaSAndroid Build Coastguard Worker """Return the robolectric module set as dependency if any module is a 217*c2e18aaaSAndroid Build Coastguard Worker robolectric test. 218*c2e18aaaSAndroid Build Coastguard Worker 219*c2e18aaaSAndroid Build Coastguard Worker Args: 220*c2e18aaaSAndroid Build Coastguard Worker modules: A set of modules. 221*c2e18aaaSAndroid Build Coastguard Worker 222*c2e18aaaSAndroid Build Coastguard Worker Returns: 223*c2e18aaaSAndroid Build Coastguard Worker A set with a robolectric_all module name if one of the modules 224*c2e18aaaSAndroid Build Coastguard Worker needs the robolectric test module. Otherwise return empty list. 225*c2e18aaaSAndroid Build Coastguard Worker """ 226*c2e18aaaSAndroid Build Coastguard Worker for module in modules: 227*c2e18aaaSAndroid Build Coastguard Worker if self.modules_info.is_robolectric_test(module): 228*c2e18aaaSAndroid Build Coastguard Worker return {_ROBOLECTRIC_MODULE} 229*c2e18aaaSAndroid Build Coastguard Worker return set() 230*c2e18aaaSAndroid Build Coastguard Worker 231*c2e18aaaSAndroid Build Coastguard Worker def _filter_out_modules(self): 232*c2e18aaaSAndroid Build Coastguard Worker """Filter out unnecessary modules.""" 233*c2e18aaaSAndroid Build Coastguard Worker for module in _EXCLUDE_MODULES: 234*c2e18aaaSAndroid Build Coastguard Worker self.dep_modules.pop(module, None) 235*c2e18aaaSAndroid Build Coastguard Worker 236*c2e18aaaSAndroid Build Coastguard Worker def get_dep_modules(self, module_names=None, depth=0): 237*c2e18aaaSAndroid Build Coastguard Worker """Recursively find dependent modules of the project. 238*c2e18aaaSAndroid Build Coastguard Worker 239*c2e18aaaSAndroid Build Coastguard Worker Find dependent modules by dependencies parameter of each module. 240*c2e18aaaSAndroid Build Coastguard Worker For example: 241*c2e18aaaSAndroid Build Coastguard Worker The module_names is ['m1']. 242*c2e18aaaSAndroid Build Coastguard Worker The modules_info is 243*c2e18aaaSAndroid Build Coastguard Worker { 244*c2e18aaaSAndroid Build Coastguard Worker 'm1': {'dependencies': ['m2'], 'path': ['path_to_m1']}, 245*c2e18aaaSAndroid Build Coastguard Worker 'm2': {'path': ['path_to_m4']}, 246*c2e18aaaSAndroid Build Coastguard Worker 'm3': {'path': ['path_to_m1']} 247*c2e18aaaSAndroid Build Coastguard Worker 'm4': {'path': []} 248*c2e18aaaSAndroid Build Coastguard Worker } 249*c2e18aaaSAndroid Build Coastguard Worker The result dependent modules are: 250*c2e18aaaSAndroid Build Coastguard Worker { 251*c2e18aaaSAndroid Build Coastguard Worker 'm1': {'dependencies': ['m2'], 'path': ['path_to_m1'] 252*c2e18aaaSAndroid Build Coastguard Worker 'depth': 0}, 253*c2e18aaaSAndroid Build Coastguard Worker 'm2': {'path': ['path_to_m4'], 'depth': 1}, 254*c2e18aaaSAndroid Build Coastguard Worker 'm3': {'path': ['path_to_m1'], 'depth': 0} 255*c2e18aaaSAndroid Build Coastguard Worker } 256*c2e18aaaSAndroid Build Coastguard Worker Note that: 257*c2e18aaaSAndroid Build Coastguard Worker 1. m4 is not in the result as it's not among dependent modules. 258*c2e18aaaSAndroid Build Coastguard Worker 2. m3 is in the result as it has the same path to m1. 259*c2e18aaaSAndroid Build Coastguard Worker 260*c2e18aaaSAndroid Build Coastguard Worker Args: 261*c2e18aaaSAndroid Build Coastguard Worker module_names: A set of module names. 262*c2e18aaaSAndroid Build Coastguard Worker depth: An integer shows the depth of module dependency referenced by 263*c2e18aaaSAndroid Build Coastguard Worker source. Zero means the max module depth. 264*c2e18aaaSAndroid Build Coastguard Worker 265*c2e18aaaSAndroid Build Coastguard Worker Returns: 266*c2e18aaaSAndroid Build Coastguard Worker deps: A dict contains all dependent modules data of given modules. 267*c2e18aaaSAndroid Build Coastguard Worker """ 268*c2e18aaaSAndroid Build Coastguard Worker dep = {} 269*c2e18aaaSAndroid Build Coastguard Worker children = set() 270*c2e18aaaSAndroid Build Coastguard Worker if not module_names: 271*c2e18aaaSAndroid Build Coastguard Worker module_names = self.project_module_names 272*c2e18aaaSAndroid Build Coastguard Worker module_names.update( 273*c2e18aaaSAndroid Build Coastguard Worker self._get_modules_under_project_path( 274*c2e18aaaSAndroid Build Coastguard Worker self.project_relative_path)) 275*c2e18aaaSAndroid Build Coastguard Worker module_names.update(self._get_robolectric_dep_module(module_names)) 276*c2e18aaaSAndroid Build Coastguard Worker self.project_module_names = set() 277*c2e18aaaSAndroid Build Coastguard Worker for name in module_names: 278*c2e18aaaSAndroid Build Coastguard Worker if (name in self.modules_info.name_to_module_info 279*c2e18aaaSAndroid Build Coastguard Worker and name not in self.project_module_names): 280*c2e18aaaSAndroid Build Coastguard Worker dep[name] = self.modules_info.name_to_module_info[name] 281*c2e18aaaSAndroid Build Coastguard Worker dep[name][constant.KEY_DEPTH] = depth 282*c2e18aaaSAndroid Build Coastguard Worker self.project_module_names.add(name) 283*c2e18aaaSAndroid Build Coastguard Worker if (constant.KEY_DEPENDENCIES in dep[name] 284*c2e18aaaSAndroid Build Coastguard Worker and dep[name][constant.KEY_DEPENDENCIES]): 285*c2e18aaaSAndroid Build Coastguard Worker children.update(dep[name][constant.KEY_DEPENDENCIES]) 286*c2e18aaaSAndroid Build Coastguard Worker if children: 287*c2e18aaaSAndroid Build Coastguard Worker dep.update(self.get_dep_modules(children, depth + 1)) 288*c2e18aaaSAndroid Build Coastguard Worker return dep 289*c2e18aaaSAndroid Build Coastguard Worker 290*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 291*c2e18aaaSAndroid Build Coastguard Worker def generate_projects(targets): 292*c2e18aaaSAndroid Build Coastguard Worker """Generate a list of projects in one time by a list of module names. 293*c2e18aaaSAndroid Build Coastguard Worker 294*c2e18aaaSAndroid Build Coastguard Worker Args: 295*c2e18aaaSAndroid Build Coastguard Worker targets: A list of target modules or project paths from user input, 296*c2e18aaaSAndroid Build Coastguard Worker when locating the target, project with matched module name 297*c2e18aaaSAndroid Build Coastguard Worker of the target has a higher priority than project path. 298*c2e18aaaSAndroid Build Coastguard Worker 299*c2e18aaaSAndroid Build Coastguard Worker Returns: 300*c2e18aaaSAndroid Build Coastguard Worker List: A list of ProjectInfo instances. 301*c2e18aaaSAndroid Build Coastguard Worker """ 302*c2e18aaaSAndroid Build Coastguard Worker return [ProjectInfo(target, i == 0) for i, target in enumerate(targets)] 303*c2e18aaaSAndroid Build Coastguard Worker 304*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 305*c2e18aaaSAndroid Build Coastguard Worker def get_target_name(target, abs_path): 306*c2e18aaaSAndroid Build Coastguard Worker """Get target name from target's absolute path. 307*c2e18aaaSAndroid Build Coastguard Worker 308*c2e18aaaSAndroid Build Coastguard Worker If the project is for entire Android source tree, change the target to 309*c2e18aaaSAndroid Build Coastguard Worker source tree's root folder name. In this way, we give IDE project file 310*c2e18aaaSAndroid Build Coastguard Worker a more specific name. e.g, master.iml. 311*c2e18aaaSAndroid Build Coastguard Worker 312*c2e18aaaSAndroid Build Coastguard Worker Args: 313*c2e18aaaSAndroid Build Coastguard Worker target: Includes target module or project path from user input, when 314*c2e18aaaSAndroid Build Coastguard Worker locating the target, project with matching module name of 315*c2e18aaaSAndroid Build Coastguard Worker the given target has a higher priority than project path. 316*c2e18aaaSAndroid Build Coastguard Worker abs_path: A string, target's absolute path. 317*c2e18aaaSAndroid Build Coastguard Worker 318*c2e18aaaSAndroid Build Coastguard Worker Returns: 319*c2e18aaaSAndroid Build Coastguard Worker A string, the target name. 320*c2e18aaaSAndroid Build Coastguard Worker """ 321*c2e18aaaSAndroid Build Coastguard Worker if abs_path == common_util.get_android_root_dir(): 322*c2e18aaaSAndroid Build Coastguard Worker return os.path.basename(abs_path) 323*c2e18aaaSAndroid Build Coastguard Worker return target 324*c2e18aaaSAndroid Build Coastguard Worker 325*c2e18aaaSAndroid Build Coastguard Worker def locate_source(self, build=True): 326*c2e18aaaSAndroid Build Coastguard Worker """Locate the paths of dependent source folders and jar files. 327*c2e18aaaSAndroid Build Coastguard Worker 328*c2e18aaaSAndroid Build Coastguard Worker Try to reference source folder path as dependent module unless the 329*c2e18aaaSAndroid Build Coastguard Worker dependent module should be referenced to a jar file, such as modules 330*c2e18aaaSAndroid Build Coastguard Worker have jars and jarjar_rules parameter. 331*c2e18aaaSAndroid Build Coastguard Worker For example: 332*c2e18aaaSAndroid Build Coastguard Worker Module: asm-6.0 333*c2e18aaaSAndroid Build Coastguard Worker java_import { 334*c2e18aaaSAndroid Build Coastguard Worker name: 'asm-6.0', 335*c2e18aaaSAndroid Build Coastguard Worker host_supported: true, 336*c2e18aaaSAndroid Build Coastguard Worker jars: ['asm-6.0.jar'], 337*c2e18aaaSAndroid Build Coastguard Worker } 338*c2e18aaaSAndroid Build Coastguard Worker Module: bouncycastle 339*c2e18aaaSAndroid Build Coastguard Worker java_library { 340*c2e18aaaSAndroid Build Coastguard Worker name: 'bouncycastle', 341*c2e18aaaSAndroid Build Coastguard Worker ... 342*c2e18aaaSAndroid Build Coastguard Worker target: { 343*c2e18aaaSAndroid Build Coastguard Worker android: { 344*c2e18aaaSAndroid Build Coastguard Worker jarjar_rules: 'jarjar-rules.txt', 345*c2e18aaaSAndroid Build Coastguard Worker }, 346*c2e18aaaSAndroid Build Coastguard Worker }, 347*c2e18aaaSAndroid Build Coastguard Worker } 348*c2e18aaaSAndroid Build Coastguard Worker 349*c2e18aaaSAndroid Build Coastguard Worker Args: 350*c2e18aaaSAndroid Build Coastguard Worker build: A boolean default to true. If false, skip building jar and 351*c2e18aaaSAndroid Build Coastguard Worker srcjar files, otherwise build them. 352*c2e18aaaSAndroid Build Coastguard Worker 353*c2e18aaaSAndroid Build Coastguard Worker Example usage: 354*c2e18aaaSAndroid Build Coastguard Worker project.source_path = project.locate_source() 355*c2e18aaaSAndroid Build Coastguard Worker E.g. 356*c2e18aaaSAndroid Build Coastguard Worker project.source_path = { 357*c2e18aaaSAndroid Build Coastguard Worker 'source_folder_path': ['path/to/source/folder1', 358*c2e18aaaSAndroid Build Coastguard Worker 'path/to/source/folder2', ...], 359*c2e18aaaSAndroid Build Coastguard Worker 'test_folder_path': ['path/to/test/folder', ...], 360*c2e18aaaSAndroid Build Coastguard Worker 'jar_path': ['path/to/jar/file1', 'path/to/jar/file2', ...] 361*c2e18aaaSAndroid Build Coastguard Worker } 362*c2e18aaaSAndroid Build Coastguard Worker """ 363*c2e18aaaSAndroid Build Coastguard Worker if not hasattr(self, 'dep_modules') or not self.dep_modules: 364*c2e18aaaSAndroid Build Coastguard Worker raise errors.EmptyModuleDependencyError( 365*c2e18aaaSAndroid Build Coastguard Worker 'Dependent modules dictionary is empty.') 366*c2e18aaaSAndroid Build Coastguard Worker rebuild_targets = set() 367*c2e18aaaSAndroid Build Coastguard Worker for module_name, module_data in self.dep_modules.items(): 368*c2e18aaaSAndroid Build Coastguard Worker module = self._generate_moduledata(module_name, module_data) 369*c2e18aaaSAndroid Build Coastguard Worker module.locate_sources_path() 370*c2e18aaaSAndroid Build Coastguard Worker self.source_path['source_folder_path'].update(set(module.src_dirs)) 371*c2e18aaaSAndroid Build Coastguard Worker self.source_path['test_folder_path'].update(set(module.test_dirs)) 372*c2e18aaaSAndroid Build Coastguard Worker self.source_path['r_java_path'].update(set(module.r_java_paths)) 373*c2e18aaaSAndroid Build Coastguard Worker self.source_path['srcjar_path'].update(set(module.srcjar_paths)) 374*c2e18aaaSAndroid Build Coastguard Worker self._append_jars_as_dependencies(module) 375*c2e18aaaSAndroid Build Coastguard Worker rebuild_targets.update(module.build_targets) 376*c2e18aaaSAndroid Build Coastguard Worker config = project_config.ProjectConfig.get_instance() 377*c2e18aaaSAndroid Build Coastguard Worker if config.is_skip_build: 378*c2e18aaaSAndroid Build Coastguard Worker return 379*c2e18aaaSAndroid Build Coastguard Worker if rebuild_targets: 380*c2e18aaaSAndroid Build Coastguard Worker if build: 381*c2e18aaaSAndroid Build Coastguard Worker logging.info('\nThe batch_build_dependencies function is ' 382*c2e18aaaSAndroid Build Coastguard Worker 'called by ProjectInfo\'s locate_source method.') 383*c2e18aaaSAndroid Build Coastguard Worker batch_build_dependencies(rebuild_targets) 384*c2e18aaaSAndroid Build Coastguard Worker self.locate_source(build=False) 385*c2e18aaaSAndroid Build Coastguard Worker else: 386*c2e18aaaSAndroid Build Coastguard Worker logging.warning('Jar or srcjar files build skipped:\n\t%s.', 387*c2e18aaaSAndroid Build Coastguard Worker '\n\t'.join(rebuild_targets)) 388*c2e18aaaSAndroid Build Coastguard Worker 389*c2e18aaaSAndroid Build Coastguard Worker def _generate_moduledata(self, module_name, module_data): 390*c2e18aaaSAndroid Build Coastguard Worker """Generate a module class to collect dependencies in IDE. 391*c2e18aaaSAndroid Build Coastguard Worker 392*c2e18aaaSAndroid Build Coastguard Worker The rules of initialize a module data instance: if ide_object isn't None 393*c2e18aaaSAndroid Build Coastguard Worker and its ide_name is 'eclipse', we'll create an EclipseModuleData 394*c2e18aaaSAndroid Build Coastguard Worker instance otherwise create a ModuleData instance. 395*c2e18aaaSAndroid Build Coastguard Worker 396*c2e18aaaSAndroid Build Coastguard Worker Args: 397*c2e18aaaSAndroid Build Coastguard Worker module_name: Name of the module. 398*c2e18aaaSAndroid Build Coastguard Worker module_data: A dictionary holding a module information. 399*c2e18aaaSAndroid Build Coastguard Worker 400*c2e18aaaSAndroid Build Coastguard Worker Returns: 401*c2e18aaaSAndroid Build Coastguard Worker A ModuleData class. 402*c2e18aaaSAndroid Build Coastguard Worker """ 403*c2e18aaaSAndroid Build Coastguard Worker ide_name = project_config.ProjectConfig.get_instance().ide_name 404*c2e18aaaSAndroid Build Coastguard Worker if ide_name == constant.IDE_ECLIPSE: 405*c2e18aaaSAndroid Build Coastguard Worker return source_locator.EclipseModuleData( 406*c2e18aaaSAndroid Build Coastguard Worker module_name, module_data, self.project_relative_path) 407*c2e18aaaSAndroid Build Coastguard Worker depth = project_config.ProjectConfig.get_instance().depth 408*c2e18aaaSAndroid Build Coastguard Worker return source_locator.ModuleData(module_name, module_data, depth) 409*c2e18aaaSAndroid Build Coastguard Worker 410*c2e18aaaSAndroid Build Coastguard Worker def _append_jars_as_dependencies(self, module): 411*c2e18aaaSAndroid Build Coastguard Worker """Add given module's jar files into dependent_data as dependencies. 412*c2e18aaaSAndroid Build Coastguard Worker 413*c2e18aaaSAndroid Build Coastguard Worker Args: 414*c2e18aaaSAndroid Build Coastguard Worker module: A ModuleData instance. 415*c2e18aaaSAndroid Build Coastguard Worker """ 416*c2e18aaaSAndroid Build Coastguard Worker if module.jar_files: 417*c2e18aaaSAndroid Build Coastguard Worker self.source_path['jar_path'].update(module.jar_files) 418*c2e18aaaSAndroid Build Coastguard Worker for jar in list(module.jar_files): 419*c2e18aaaSAndroid Build Coastguard Worker self.source_path['jar_module_path'].update({ 420*c2e18aaaSAndroid Build Coastguard Worker jar: 421*c2e18aaaSAndroid Build Coastguard Worker module.module_path 422*c2e18aaaSAndroid Build Coastguard Worker }) 423*c2e18aaaSAndroid Build Coastguard Worker # Collecting the jar files of default core modules as dependencies. 424*c2e18aaaSAndroid Build Coastguard Worker if constant.KEY_DEPENDENCIES in module.module_data: 425*c2e18aaaSAndroid Build Coastguard Worker self.source_path['jar_path'].update([ 426*c2e18aaaSAndroid Build Coastguard Worker x for x in module.module_data[constant.KEY_DEPENDENCIES] 427*c2e18aaaSAndroid Build Coastguard Worker if common_util.is_target(x, constant.TARGET_LIBS) 428*c2e18aaaSAndroid Build Coastguard Worker ]) 429*c2e18aaaSAndroid Build Coastguard Worker 430*c2e18aaaSAndroid Build Coastguard Worker def _get_rel_project_out_soong_jar_path(self): 431*c2e18aaaSAndroid Build Coastguard Worker """Gets the projects' jar path in 'out/soong/.intermediates' folder. 432*c2e18aaaSAndroid Build Coastguard Worker 433*c2e18aaaSAndroid Build Coastguard Worker Gets the relative project's jar path in the 'out/soong/.intermediates' 434*c2e18aaaSAndroid Build Coastguard Worker directory. For example, if the self.project_relative_path is 435*c2e18aaaSAndroid Build Coastguard Worker 'frameworks/base', the returned value should be 436*c2e18aaaSAndroid Build Coastguard Worker 'out/soong/.intermediates/frameworks/base/'. 437*c2e18aaaSAndroid Build Coastguard Worker 438*c2e18aaaSAndroid Build Coastguard Worker Returns: 439*c2e18aaaSAndroid Build Coastguard Worker A string of relative project path in out/soong/.intermediates/ 440*c2e18aaaSAndroid Build Coastguard Worker directory, e.g. 'out/soong/.intermediates/frameworks/base/'. 441*c2e18aaaSAndroid Build Coastguard Worker """ 442*c2e18aaaSAndroid Build Coastguard Worker rdir = os.path.relpath(common_util.get_soong_out_path(), 443*c2e18aaaSAndroid Build Coastguard Worker common_util.get_android_root_dir()) 444*c2e18aaaSAndroid Build Coastguard Worker return os.sep.join( 445*c2e18aaaSAndroid Build Coastguard Worker [rdir, constant.INTERMEDIATES, self.project_relative_path]) + os.sep 446*c2e18aaaSAndroid Build Coastguard Worker 447*c2e18aaaSAndroid Build Coastguard Worker @classmethod 448*c2e18aaaSAndroid Build Coastguard Worker def multi_projects_locate_source(cls, projects): 449*c2e18aaaSAndroid Build Coastguard Worker """Locate the paths of dependent source folders and jar files. 450*c2e18aaaSAndroid Build Coastguard Worker 451*c2e18aaaSAndroid Build Coastguard Worker Args: 452*c2e18aaaSAndroid Build Coastguard Worker projects: A list of ProjectInfo instances. Information of a project 453*c2e18aaaSAndroid Build Coastguard Worker such as project relative path, project real path, project 454*c2e18aaaSAndroid Build Coastguard Worker dependencies. 455*c2e18aaaSAndroid Build Coastguard Worker """ 456*c2e18aaaSAndroid Build Coastguard Worker cls.projects = projects 457*c2e18aaaSAndroid Build Coastguard Worker for project in projects: 458*c2e18aaaSAndroid Build Coastguard Worker project.locate_source() 459*c2e18aaaSAndroid Build Coastguard Worker _update_iml_dep_modules(project) 460*c2e18aaaSAndroid Build Coastguard Worker 461*c2e18aaaSAndroid Build Coastguard Worker 462*c2e18aaaSAndroid Build Coastguard Workerclass MultiProjectsInfo(ProjectInfo): 463*c2e18aaaSAndroid Build Coastguard Worker """Multiple projects info. 464*c2e18aaaSAndroid Build Coastguard Worker 465*c2e18aaaSAndroid Build Coastguard Worker Usage example: 466*c2e18aaaSAndroid Build Coastguard Worker if folder_base: 467*c2e18aaaSAndroid Build Coastguard Worker project = MultiProjectsInfo(['module_name']) 468*c2e18aaaSAndroid Build Coastguard Worker project.collect_all_dep_modules() 469*c2e18aaaSAndroid Build Coastguard Worker project.gen_folder_base_dependencies() 470*c2e18aaaSAndroid Build Coastguard Worker else: 471*c2e18aaaSAndroid Build Coastguard Worker ProjectInfo.generate_projects(['module_name']) 472*c2e18aaaSAndroid Build Coastguard Worker 473*c2e18aaaSAndroid Build Coastguard Worker Attributes: 474*c2e18aaaSAndroid Build Coastguard Worker _targets: A list of module names or project paths. 475*c2e18aaaSAndroid Build Coastguard Worker path_to_sources: A dictionary of modules' sources, the module's path 476*c2e18aaaSAndroid Build Coastguard Worker as key and the sources as value. 477*c2e18aaaSAndroid Build Coastguard Worker e.g. 478*c2e18aaaSAndroid Build Coastguard Worker { 479*c2e18aaaSAndroid Build Coastguard Worker 'frameworks/base': { 480*c2e18aaaSAndroid Build Coastguard Worker 'src_dirs': [], 481*c2e18aaaSAndroid Build Coastguard Worker 'test_dirs': [], 482*c2e18aaaSAndroid Build Coastguard Worker 'r_java_paths': [], 483*c2e18aaaSAndroid Build Coastguard Worker 'srcjar_paths': [], 484*c2e18aaaSAndroid Build Coastguard Worker 'jar_files': [], 485*c2e18aaaSAndroid Build Coastguard Worker 'dep_paths': [], 486*c2e18aaaSAndroid Build Coastguard Worker } 487*c2e18aaaSAndroid Build Coastguard Worker } 488*c2e18aaaSAndroid Build Coastguard Worker """ 489*c2e18aaaSAndroid Build Coastguard Worker 490*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, targets=None): 491*c2e18aaaSAndroid Build Coastguard Worker """MultiProjectsInfo initialize. 492*c2e18aaaSAndroid Build Coastguard Worker 493*c2e18aaaSAndroid Build Coastguard Worker Args: 494*c2e18aaaSAndroid Build Coastguard Worker targets: A list of module names or project paths from user's input. 495*c2e18aaaSAndroid Build Coastguard Worker """ 496*c2e18aaaSAndroid Build Coastguard Worker super().__init__(targets[0], True) 497*c2e18aaaSAndroid Build Coastguard Worker self._targets = targets 498*c2e18aaaSAndroid Build Coastguard Worker self.path_to_sources = {} 499*c2e18aaaSAndroid Build Coastguard Worker 500*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 501*c2e18aaaSAndroid Build Coastguard Worker def _clear_srcjar_paths(module): 502*c2e18aaaSAndroid Build Coastguard Worker """Clears the srcjar_paths. 503*c2e18aaaSAndroid Build Coastguard Worker 504*c2e18aaaSAndroid Build Coastguard Worker Args: 505*c2e18aaaSAndroid Build Coastguard Worker module: A ModuleData instance. 506*c2e18aaaSAndroid Build Coastguard Worker """ 507*c2e18aaaSAndroid Build Coastguard Worker module.srcjar_paths = [] 508*c2e18aaaSAndroid Build Coastguard Worker 509*c2e18aaaSAndroid Build Coastguard Worker def _collect_framework_srcjar_info(self, module): 510*c2e18aaaSAndroid Build Coastguard Worker """Clears the framework's srcjars. 511*c2e18aaaSAndroid Build Coastguard Worker 512*c2e18aaaSAndroid Build Coastguard Worker Args: 513*c2e18aaaSAndroid Build Coastguard Worker module: A ModuleData instance. 514*c2e18aaaSAndroid Build Coastguard Worker """ 515*c2e18aaaSAndroid Build Coastguard Worker if module.module_path == constant.FRAMEWORK_PATH: 516*c2e18aaaSAndroid Build Coastguard Worker framework_srcjar_path = os.path.join(constant.FRAMEWORK_PATH, 517*c2e18aaaSAndroid Build Coastguard Worker constant.FRAMEWORK_SRCJARS) 518*c2e18aaaSAndroid Build Coastguard Worker if module.module_name == constant.FRAMEWORK_ALL: 519*c2e18aaaSAndroid Build Coastguard Worker self.path_to_sources[framework_srcjar_path] = { 520*c2e18aaaSAndroid Build Coastguard Worker 'src_dirs': [], 521*c2e18aaaSAndroid Build Coastguard Worker 'test_dirs': [], 522*c2e18aaaSAndroid Build Coastguard Worker 'r_java_paths': [], 523*c2e18aaaSAndroid Build Coastguard Worker 'srcjar_paths': module.srcjar_paths, 524*c2e18aaaSAndroid Build Coastguard Worker 'jar_files': [], 525*c2e18aaaSAndroid Build Coastguard Worker 'dep_paths': [constant.FRAMEWORK_PATH], 526*c2e18aaaSAndroid Build Coastguard Worker } 527*c2e18aaaSAndroid Build Coastguard Worker # In the folder base case, AIDEGen has to ignore all module's srcjar 528*c2e18aaaSAndroid Build Coastguard Worker # files under the frameworks/base except the framework-all. Because 529*c2e18aaaSAndroid Build Coastguard Worker # there are too many duplicate srcjars of modules under the 530*c2e18aaaSAndroid Build Coastguard Worker # frameworks/base. So that AIDEGen keeps the srcjar files only from 531*c2e18aaaSAndroid Build Coastguard Worker # the framework-all module. Other modules' srcjar files will be 532*c2e18aaaSAndroid Build Coastguard Worker # removed. However, when users choose the module base case, srcjar 533*c2e18aaaSAndroid Build Coastguard Worker # files will be collected by the ProjectInfo class, so that the 534*c2e18aaaSAndroid Build Coastguard Worker # removing srcjar_paths in this class does not impact the 535*c2e18aaaSAndroid Build Coastguard Worker # srcjar_paths collection of modules in the ProjectInfo class. 536*c2e18aaaSAndroid Build Coastguard Worker self._clear_srcjar_paths(module) 537*c2e18aaaSAndroid Build Coastguard Worker 538*c2e18aaaSAndroid Build Coastguard Worker def collect_all_dep_modules(self): 539*c2e18aaaSAndroid Build Coastguard Worker """Collects all dependency modules for the projects.""" 540*c2e18aaaSAndroid Build Coastguard Worker self.project_module_names.clear() 541*c2e18aaaSAndroid Build Coastguard Worker module_names = set(_CORE_MODULES) 542*c2e18aaaSAndroid Build Coastguard Worker for target in self._targets: 543*c2e18aaaSAndroid Build Coastguard Worker relpath, _ = common_util.get_related_paths(self.modules_info, 544*c2e18aaaSAndroid Build Coastguard Worker target) 545*c2e18aaaSAndroid Build Coastguard Worker module_names.update(self._get_modules_under_project_path(relpath)) 546*c2e18aaaSAndroid Build Coastguard Worker module_names.update(self._get_robolectric_dep_module(module_names)) 547*c2e18aaaSAndroid Build Coastguard Worker self.dep_modules = self.get_dep_modules(module_names) 548*c2e18aaaSAndroid Build Coastguard Worker 549*c2e18aaaSAndroid Build Coastguard Worker def gen_folder_base_dependencies(self, module): 550*c2e18aaaSAndroid Build Coastguard Worker """Generates the folder base dependencies dictionary. 551*c2e18aaaSAndroid Build Coastguard Worker 552*c2e18aaaSAndroid Build Coastguard Worker Args: 553*c2e18aaaSAndroid Build Coastguard Worker module: A ModuleData instance. 554*c2e18aaaSAndroid Build Coastguard Worker """ 555*c2e18aaaSAndroid Build Coastguard Worker mod_path = module.module_path 556*c2e18aaaSAndroid Build Coastguard Worker if not mod_path: 557*c2e18aaaSAndroid Build Coastguard Worker logging.debug('The %s\'s path is empty.', module.module_name) 558*c2e18aaaSAndroid Build Coastguard Worker return 559*c2e18aaaSAndroid Build Coastguard Worker self._collect_framework_srcjar_info(module) 560*c2e18aaaSAndroid Build Coastguard Worker if mod_path not in self.path_to_sources: 561*c2e18aaaSAndroid Build Coastguard Worker self.path_to_sources[mod_path] = { 562*c2e18aaaSAndroid Build Coastguard Worker 'src_dirs': module.src_dirs, 563*c2e18aaaSAndroid Build Coastguard Worker 'test_dirs': module.test_dirs, 564*c2e18aaaSAndroid Build Coastguard Worker 'r_java_paths': module.r_java_paths, 565*c2e18aaaSAndroid Build Coastguard Worker 'srcjar_paths': module.srcjar_paths, 566*c2e18aaaSAndroid Build Coastguard Worker 'jar_files': module.jar_files, 567*c2e18aaaSAndroid Build Coastguard Worker 'dep_paths': module.dep_paths, 568*c2e18aaaSAndroid Build Coastguard Worker } 569*c2e18aaaSAndroid Build Coastguard Worker else: 570*c2e18aaaSAndroid Build Coastguard Worker for key, val in self.path_to_sources[mod_path].items(): 571*c2e18aaaSAndroid Build Coastguard Worker val.extend([v for v in getattr(module, key) if v not in val]) 572*c2e18aaaSAndroid Build Coastguard Worker 573*c2e18aaaSAndroid Build Coastguard Worker 574*c2e18aaaSAndroid Build Coastguard Workerdef batch_build_dependencies(rebuild_targets): 575*c2e18aaaSAndroid Build Coastguard Worker """Batch build the jar or srcjar files of the modules if they don't exist. 576*c2e18aaaSAndroid Build Coastguard Worker 577*c2e18aaaSAndroid Build Coastguard Worker Command line has the max length limit, MAX_ARG_STRLEN, and 578*c2e18aaaSAndroid Build Coastguard Worker MAX_ARG_STRLEN = (PAGE_SIZE * 32). 579*c2e18aaaSAndroid Build Coastguard Worker If the build command is longer than MAX_ARG_STRLEN, this function will 580*c2e18aaaSAndroid Build Coastguard Worker separate the rebuild_targets into chunks with size less or equal to 581*c2e18aaaSAndroid Build Coastguard Worker MAX_ARG_STRLEN to make sure it can be built successfully. 582*c2e18aaaSAndroid Build Coastguard Worker 583*c2e18aaaSAndroid Build Coastguard Worker Args: 584*c2e18aaaSAndroid Build Coastguard Worker rebuild_targets: A set of jar or srcjar files which do not exist. 585*c2e18aaaSAndroid Build Coastguard Worker """ 586*c2e18aaaSAndroid Build Coastguard Worker start_time = time.time() 587*c2e18aaaSAndroid Build Coastguard Worker logging.info('Ready to build the jar or srcjar files. Files count = %s', 588*c2e18aaaSAndroid Build Coastguard Worker str(len(rebuild_targets))) 589*c2e18aaaSAndroid Build Coastguard Worker arg_max = os.sysconf('SC_PAGE_SIZE') * 32 - _CMD_LENGTH_BUFFER 590*c2e18aaaSAndroid Build Coastguard Worker rebuild_targets = list(rebuild_targets) 591*c2e18aaaSAndroid Build Coastguard Worker for start, end in iter(_separate_build_targets(rebuild_targets, arg_max)): 592*c2e18aaaSAndroid Build Coastguard Worker _build_target(rebuild_targets[start:end]) 593*c2e18aaaSAndroid Build Coastguard Worker duration = time.time() - start_time 594*c2e18aaaSAndroid Build Coastguard Worker logging.debug('Build Time, duration = %s', str(duration)) 595*c2e18aaaSAndroid Build Coastguard Worker aidegen_metrics.performance_metrics(constant.TYPE_AIDEGEN_BUILD_TIME, 596*c2e18aaaSAndroid Build Coastguard Worker duration) 597*c2e18aaaSAndroid Build Coastguard Worker 598*c2e18aaaSAndroid Build Coastguard Worker 599*c2e18aaaSAndroid Build Coastguard Workerdef _build_target(targets): 600*c2e18aaaSAndroid Build Coastguard Worker """Build the jar or srcjar files. 601*c2e18aaaSAndroid Build Coastguard Worker 602*c2e18aaaSAndroid Build Coastguard Worker Use -k to keep going when some targets can't be built or build failed. 603*c2e18aaaSAndroid Build Coastguard Worker Use -j to speed up building. 604*c2e18aaaSAndroid Build Coastguard Worker 605*c2e18aaaSAndroid Build Coastguard Worker Args: 606*c2e18aaaSAndroid Build Coastguard Worker targets: A list of jar or srcjar files which need to build. 607*c2e18aaaSAndroid Build Coastguard Worker """ 608*c2e18aaaSAndroid Build Coastguard Worker build_cmd = ['-k', '-j'] 609*c2e18aaaSAndroid Build Coastguard Worker build_cmd.extend(list(targets)) 610*c2e18aaaSAndroid Build Coastguard Worker atest_utils.update_build_env(_BUILD_BP_JSON_ENV_ON) 611*c2e18aaaSAndroid Build Coastguard Worker if not atest_utils.build(build_cmd): 612*c2e18aaaSAndroid Build Coastguard Worker message = ('Build failed!\n{}\nAIDEGen will proceed but dependency ' 613*c2e18aaaSAndroid Build Coastguard Worker 'correctness is not guaranteed if not all targets being ' 614*c2e18aaaSAndroid Build Coastguard Worker 'built successfully.'.format('\n'.join(targets))) 615*c2e18aaaSAndroid Build Coastguard Worker print('\n{} {}\n'.format(common_util.COLORED_INFO('Warning:'), message)) 616*c2e18aaaSAndroid Build Coastguard Worker 617*c2e18aaaSAndroid Build Coastguard Worker 618*c2e18aaaSAndroid Build Coastguard Workerdef _separate_build_targets(build_targets, max_length): 619*c2e18aaaSAndroid Build Coastguard Worker """Separate the build_targets by limit the command size to max command 620*c2e18aaaSAndroid Build Coastguard Worker length. 621*c2e18aaaSAndroid Build Coastguard Worker 622*c2e18aaaSAndroid Build Coastguard Worker Args: 623*c2e18aaaSAndroid Build Coastguard Worker build_targets: A list to be separated. 624*c2e18aaaSAndroid Build Coastguard Worker max_length: The max number of each build command length. 625*c2e18aaaSAndroid Build Coastguard Worker 626*c2e18aaaSAndroid Build Coastguard Worker Yields: 627*c2e18aaaSAndroid Build Coastguard Worker The start index and end index of build_targets. 628*c2e18aaaSAndroid Build Coastguard Worker """ 629*c2e18aaaSAndroid Build Coastguard Worker arg_len = 0 630*c2e18aaaSAndroid Build Coastguard Worker first_item_index = 0 631*c2e18aaaSAndroid Build Coastguard Worker for i, item in enumerate(build_targets): 632*c2e18aaaSAndroid Build Coastguard Worker arg_len = arg_len + len(item) + _BLANK_SIZE 633*c2e18aaaSAndroid Build Coastguard Worker if arg_len > max_length: 634*c2e18aaaSAndroid Build Coastguard Worker yield first_item_index, i 635*c2e18aaaSAndroid Build Coastguard Worker first_item_index = i 636*c2e18aaaSAndroid Build Coastguard Worker arg_len = len(item) + _BLANK_SIZE 637*c2e18aaaSAndroid Build Coastguard Worker if first_item_index < len(build_targets): 638*c2e18aaaSAndroid Build Coastguard Worker yield first_item_index, len(build_targets) 639*c2e18aaaSAndroid Build Coastguard Worker 640*c2e18aaaSAndroid Build Coastguard Worker 641*c2e18aaaSAndroid Build Coastguard Workerdef _update_iml_dep_modules(project): 642*c2e18aaaSAndroid Build Coastguard Worker """Gets the dependent modules in the project's iml file. 643*c2e18aaaSAndroid Build Coastguard Worker 644*c2e18aaaSAndroid Build Coastguard Worker The jar files which have the same source codes as cls.projects' source files 645*c2e18aaaSAndroid Build Coastguard Worker should be removed from the dependencies.iml file's jar paths. The codes are 646*c2e18aaaSAndroid Build Coastguard Worker written in aidegen.project.project_splitter.py. 647*c2e18aaaSAndroid Build Coastguard Worker We should also add the jar project's unique iml name into self.dependencies 648*c2e18aaaSAndroid Build Coastguard Worker which later will be written into its own iml project file. If we don't 649*c2e18aaaSAndroid Build Coastguard Worker remove these files in dependencies.iml, it will cause the duplicated codes 650*c2e18aaaSAndroid Build Coastguard Worker in IDE and raise issues. For example, when users do 'refactor' and rename a 651*c2e18aaaSAndroid Build Coastguard Worker class in the IDE, it will search all sources and dependencies' jar paths and 652*c2e18aaaSAndroid Build Coastguard Worker lead to the error. 653*c2e18aaaSAndroid Build Coastguard Worker """ 654*c2e18aaaSAndroid Build Coastguard Worker keys = ('source_folder_path', 'test_folder_path', 'r_java_path', 655*c2e18aaaSAndroid Build Coastguard Worker 'srcjar_path', 'jar_path') 656*c2e18aaaSAndroid Build Coastguard Worker for key in keys: 657*c2e18aaaSAndroid Build Coastguard Worker for jar in project.source_path[key]: 658*c2e18aaaSAndroid Build Coastguard Worker for prj in ProjectInfo.projects: 659*c2e18aaaSAndroid Build Coastguard Worker if prj is project: 660*c2e18aaaSAndroid Build Coastguard Worker continue 661*c2e18aaaSAndroid Build Coastguard Worker if (prj.rel_out_soong_jar_path in jar and 662*c2e18aaaSAndroid Build Coastguard Worker jar.endswith(constant.JAR_EXT)): 663*c2e18aaaSAndroid Build Coastguard Worker if prj.iml_name not in project.dependencies: 664*c2e18aaaSAndroid Build Coastguard Worker project.dependencies.append(prj.iml_name) 665*c2e18aaaSAndroid Build Coastguard Worker break 666