1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*8975f5c5SAndroid Build Coastguard Worker# Copyright 2016 The Chromium Authors 3*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 4*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 5*8975f5c5SAndroid Build Coastguard Worker 6*8975f5c5SAndroid Build Coastguard Worker"""Generates an Android Studio project from a GN target.""" 7*8975f5c5SAndroid Build Coastguard Worker 8*8975f5c5SAndroid Build Coastguard Workerimport argparse 9*8975f5c5SAndroid Build Coastguard Workerimport codecs 10*8975f5c5SAndroid Build Coastguard Workerimport collections 11*8975f5c5SAndroid Build Coastguard Workerimport glob 12*8975f5c5SAndroid Build Coastguard Workerimport json 13*8975f5c5SAndroid Build Coastguard Workerimport logging 14*8975f5c5SAndroid Build Coastguard Workerimport os 15*8975f5c5SAndroid Build Coastguard Workerimport pathlib 16*8975f5c5SAndroid Build Coastguard Workerimport re 17*8975f5c5SAndroid Build Coastguard Workerimport shlex 18*8975f5c5SAndroid Build Coastguard Workerimport shutil 19*8975f5c5SAndroid Build Coastguard Workerimport subprocess 20*8975f5c5SAndroid Build Coastguard Workerimport sys 21*8975f5c5SAndroid Build Coastguard Worker 22*8975f5c5SAndroid Build Coastguard Worker_BUILD_ANDROID = os.path.join(os.path.dirname(__file__), os.pardir) 23*8975f5c5SAndroid Build Coastguard Workersys.path.append(_BUILD_ANDROID) 24*8975f5c5SAndroid Build Coastguard Workerimport devil_chromium 25*8975f5c5SAndroid Build Coastguard Workerfrom devil.utils import run_tests_helper 26*8975f5c5SAndroid Build Coastguard Workerfrom pylib import constants 27*8975f5c5SAndroid Build Coastguard Workerfrom pylib.constants import host_paths 28*8975f5c5SAndroid Build Coastguard Worker 29*8975f5c5SAndroid Build Coastguard Workersys.path.append(os.path.join(_BUILD_ANDROID, 'gyp')) 30*8975f5c5SAndroid Build Coastguard Workerimport jinja_template 31*8975f5c5SAndroid Build Coastguard Workerfrom util import build_utils 32*8975f5c5SAndroid Build Coastguard Workerfrom util import resource_utils 33*8975f5c5SAndroid Build Coastguard Worker 34*8975f5c5SAndroid Build Coastguard Workersys.path.append(os.path.dirname(_BUILD_ANDROID)) 35*8975f5c5SAndroid Build Coastguard Workerimport gn_helpers 36*8975f5c5SAndroid Build Coastguard Worker 37*8975f5c5SAndroid Build Coastguard Worker# Typically these should track the versions that works on the slowest release 38*8975f5c5SAndroid Build Coastguard Worker# channel, i.e. Android Studio stable. 39*8975f5c5SAndroid Build Coastguard Worker_DEFAULT_ANDROID_GRADLE_PLUGIN_VERSION = '7.3.1' 40*8975f5c5SAndroid Build Coastguard Worker_DEFAULT_KOTLIN_GRADLE_PLUGIN_VERSION = '1.8.0' 41*8975f5c5SAndroid Build Coastguard Worker_DEFAULT_GRADLE_WRAPPER_VERSION = '7.4' 42*8975f5c5SAndroid Build Coastguard Worker 43*8975f5c5SAndroid Build Coastguard Worker_DEPOT_TOOLS_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party', 44*8975f5c5SAndroid Build Coastguard Worker 'depot_tools') 45*8975f5c5SAndroid Build Coastguard Worker_DEFAULT_ANDROID_MANIFEST_PATH = os.path.join( 46*8975f5c5SAndroid Build Coastguard Worker host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'gradle', 47*8975f5c5SAndroid Build Coastguard Worker 'AndroidManifest.xml') 48*8975f5c5SAndroid Build Coastguard Worker_FILE_DIR = os.path.dirname(__file__) 49*8975f5c5SAndroid Build Coastguard Worker_GENERATED_JAVA_SUBDIR = 'generated_java' 50*8975f5c5SAndroid Build Coastguard Worker_JNI_LIBS_SUBDIR = 'symlinked-libs' 51*8975f5c5SAndroid Build Coastguard Worker_ARMEABI_SUBDIR = 'armeabi' 52*8975f5c5SAndroid Build Coastguard Worker_GRADLE_BUILD_FILE = 'build.gradle' 53*8975f5c5SAndroid Build Coastguard Worker_CMAKE_FILE = 'CMakeLists.txt' 54*8975f5c5SAndroid Build Coastguard Worker# This needs to come first alphabetically among all modules. 55*8975f5c5SAndroid Build Coastguard Worker_MODULE_ALL = '_all' 56*8975f5c5SAndroid Build Coastguard Worker_INSTRUMENTATION_TARGET_SUFFIX = '_test_apk__test_apk' 57*8975f5c5SAndroid Build Coastguard Worker 58*8975f5c5SAndroid Build Coastguard Worker_DEFAULT_TARGETS = [ 59*8975f5c5SAndroid Build Coastguard Worker '//android_webview/test/embedded_test_server:aw_net_test_support_apk', 60*8975f5c5SAndroid Build Coastguard Worker '//android_webview/test:webview_instrumentation_apk', 61*8975f5c5SAndroid Build Coastguard Worker '//android_webview/test:webview_instrumentation_test_apk', 62*8975f5c5SAndroid Build Coastguard Worker '//base:base_junit_tests', 63*8975f5c5SAndroid Build Coastguard Worker '//chrome/android:chrome_junit_tests', 64*8975f5c5SAndroid Build Coastguard Worker '//chrome/android:chrome_public_apk', 65*8975f5c5SAndroid Build Coastguard Worker '//chrome/android:chrome_public_test_apk', 66*8975f5c5SAndroid Build Coastguard Worker '//chrome/android:chrome_public_unit_test_apk', 67*8975f5c5SAndroid Build Coastguard Worker '//content/public/android:content_junit_tests', 68*8975f5c5SAndroid Build Coastguard Worker '//content/shell/android:content_shell_apk', 69*8975f5c5SAndroid Build Coastguard Worker # Below must be included even with --all since they are libraries. 70*8975f5c5SAndroid Build Coastguard Worker '//base/android/jni_generator:jni_processor', 71*8975f5c5SAndroid Build Coastguard Worker '//tools/android/errorprone_plugin:errorprone_plugin_java', 72*8975f5c5SAndroid Build Coastguard Worker] 73*8975f5c5SAndroid Build Coastguard Worker 74*8975f5c5SAndroid Build Coastguard Worker 75*8975f5c5SAndroid Build Coastguard Workerdef _TemplatePath(name): 76*8975f5c5SAndroid Build Coastguard Worker return os.path.join(_FILE_DIR, '{}.jinja'.format(name)) 77*8975f5c5SAndroid Build Coastguard Worker 78*8975f5c5SAndroid Build Coastguard Worker 79*8975f5c5SAndroid Build Coastguard Workerdef _RebasePath(path_or_list, new_cwd=None, old_cwd=None): 80*8975f5c5SAndroid Build Coastguard Worker """Makes the given path(s) relative to new_cwd, or absolute if not specified. 81*8975f5c5SAndroid Build Coastguard Worker 82*8975f5c5SAndroid Build Coastguard Worker If new_cwd is not specified, absolute paths are returned. 83*8975f5c5SAndroid Build Coastguard Worker If old_cwd is not specified, constants.GetOutDirectory() is assumed. 84*8975f5c5SAndroid Build Coastguard Worker """ 85*8975f5c5SAndroid Build Coastguard Worker if path_or_list is None: 86*8975f5c5SAndroid Build Coastguard Worker return [] 87*8975f5c5SAndroid Build Coastguard Worker if not isinstance(path_or_list, str): 88*8975f5c5SAndroid Build Coastguard Worker return [_RebasePath(p, new_cwd, old_cwd) for p in path_or_list] 89*8975f5c5SAndroid Build Coastguard Worker if old_cwd is None: 90*8975f5c5SAndroid Build Coastguard Worker old_cwd = constants.GetOutDirectory() 91*8975f5c5SAndroid Build Coastguard Worker old_cwd = os.path.abspath(old_cwd) 92*8975f5c5SAndroid Build Coastguard Worker if new_cwd: 93*8975f5c5SAndroid Build Coastguard Worker new_cwd = os.path.abspath(new_cwd) 94*8975f5c5SAndroid Build Coastguard Worker return os.path.relpath(os.path.join(old_cwd, path_or_list), new_cwd) 95*8975f5c5SAndroid Build Coastguard Worker return os.path.abspath(os.path.join(old_cwd, path_or_list)) 96*8975f5c5SAndroid Build Coastguard Worker 97*8975f5c5SAndroid Build Coastguard Worker 98*8975f5c5SAndroid Build Coastguard Workerdef _WriteFile(path, data): 99*8975f5c5SAndroid Build Coastguard Worker """Writes |data| to |path|, constucting parent directories if necessary.""" 100*8975f5c5SAndroid Build Coastguard Worker logging.info('Writing %s', path) 101*8975f5c5SAndroid Build Coastguard Worker dirname = os.path.dirname(path) 102*8975f5c5SAndroid Build Coastguard Worker if not os.path.exists(dirname): 103*8975f5c5SAndroid Build Coastguard Worker os.makedirs(dirname) 104*8975f5c5SAndroid Build Coastguard Worker with codecs.open(path, 'w', 'utf-8') as output_file: 105*8975f5c5SAndroid Build Coastguard Worker output_file.write(data) 106*8975f5c5SAndroid Build Coastguard Worker 107*8975f5c5SAndroid Build Coastguard Worker 108*8975f5c5SAndroid Build Coastguard Workerdef _RunGnGen(output_dir, args=None): 109*8975f5c5SAndroid Build Coastguard Worker cmd = [os.path.join(_DEPOT_TOOLS_PATH, 'gn'), 'gen', output_dir] 110*8975f5c5SAndroid Build Coastguard Worker if args: 111*8975f5c5SAndroid Build Coastguard Worker cmd.extend(args) 112*8975f5c5SAndroid Build Coastguard Worker logging.info('Running: %r', cmd) 113*8975f5c5SAndroid Build Coastguard Worker subprocess.check_call(cmd) 114*8975f5c5SAndroid Build Coastguard Worker 115*8975f5c5SAndroid Build Coastguard Worker 116*8975f5c5SAndroid Build Coastguard Workerdef _BuildTargets(output_dir, args): 117*8975f5c5SAndroid Build Coastguard Worker cmd = gn_helpers.CreateBuildCommand(output_dir) 118*8975f5c5SAndroid Build Coastguard Worker cmd.extend(args) 119*8975f5c5SAndroid Build Coastguard Worker logging.info('Running: %s', shlex.join(cmd)) 120*8975f5c5SAndroid Build Coastguard Worker subprocess.check_call(cmd) 121*8975f5c5SAndroid Build Coastguard Worker 122*8975f5c5SAndroid Build Coastguard Worker 123*8975f5c5SAndroid Build Coastguard Workerdef _QueryForAllGnTargets(output_dir): 124*8975f5c5SAndroid Build Coastguard Worker cmd = [ 125*8975f5c5SAndroid Build Coastguard Worker os.path.join(_BUILD_ANDROID, 'list_java_targets.py'), '--gn-labels', 126*8975f5c5SAndroid Build Coastguard Worker '--nested', '--build', '--output-directory', output_dir 127*8975f5c5SAndroid Build Coastguard Worker ] 128*8975f5c5SAndroid Build Coastguard Worker logging.info('Running: %r', cmd) 129*8975f5c5SAndroid Build Coastguard Worker return subprocess.check_output(cmd, encoding='UTF-8').splitlines() 130*8975f5c5SAndroid Build Coastguard Worker 131*8975f5c5SAndroid Build Coastguard Worker 132*8975f5c5SAndroid Build Coastguard Workerclass _ProjectEntry: 133*8975f5c5SAndroid Build Coastguard Worker """Helper class for project entries.""" 134*8975f5c5SAndroid Build Coastguard Worker 135*8975f5c5SAndroid Build Coastguard Worker _cached_entries = {} 136*8975f5c5SAndroid Build Coastguard Worker 137*8975f5c5SAndroid Build Coastguard Worker def __init__(self, gn_target): 138*8975f5c5SAndroid Build Coastguard Worker # Use _ProjectEntry.FromGnTarget instead for caching. 139*8975f5c5SAndroid Build Coastguard Worker self._gn_target = gn_target 140*8975f5c5SAndroid Build Coastguard Worker self._build_config = None 141*8975f5c5SAndroid Build Coastguard Worker self._java_files = None 142*8975f5c5SAndroid Build Coastguard Worker self._all_entries = None 143*8975f5c5SAndroid Build Coastguard Worker self.android_test_entries = [] 144*8975f5c5SAndroid Build Coastguard Worker 145*8975f5c5SAndroid Build Coastguard Worker @classmethod 146*8975f5c5SAndroid Build Coastguard Worker def FromGnTarget(cls, gn_target): 147*8975f5c5SAndroid Build Coastguard Worker assert gn_target.startswith('//'), gn_target 148*8975f5c5SAndroid Build Coastguard Worker if ':' not in gn_target: 149*8975f5c5SAndroid Build Coastguard Worker gn_target = '%s:%s' % (gn_target, os.path.basename(gn_target)) 150*8975f5c5SAndroid Build Coastguard Worker if gn_target not in cls._cached_entries: 151*8975f5c5SAndroid Build Coastguard Worker cls._cached_entries[gn_target] = cls(gn_target) 152*8975f5c5SAndroid Build Coastguard Worker return cls._cached_entries[gn_target] 153*8975f5c5SAndroid Build Coastguard Worker 154*8975f5c5SAndroid Build Coastguard Worker @classmethod 155*8975f5c5SAndroid Build Coastguard Worker def FromBuildConfigPath(cls, path): 156*8975f5c5SAndroid Build Coastguard Worker prefix = 'gen/' 157*8975f5c5SAndroid Build Coastguard Worker suffix = '.build_config.json' 158*8975f5c5SAndroid Build Coastguard Worker assert path.startswith(prefix) and path.endswith(suffix), path 159*8975f5c5SAndroid Build Coastguard Worker subdir = path[len(prefix):-len(suffix)] 160*8975f5c5SAndroid Build Coastguard Worker gn_target = '//%s:%s' % (os.path.split(subdir)) 161*8975f5c5SAndroid Build Coastguard Worker return cls.FromGnTarget(gn_target) 162*8975f5c5SAndroid Build Coastguard Worker 163*8975f5c5SAndroid Build Coastguard Worker def __hash__(self): 164*8975f5c5SAndroid Build Coastguard Worker return hash(self._gn_target) 165*8975f5c5SAndroid Build Coastguard Worker 166*8975f5c5SAndroid Build Coastguard Worker def __eq__(self, other): 167*8975f5c5SAndroid Build Coastguard Worker return self._gn_target == other.GnTarget() 168*8975f5c5SAndroid Build Coastguard Worker 169*8975f5c5SAndroid Build Coastguard Worker def GnTarget(self): 170*8975f5c5SAndroid Build Coastguard Worker return self._gn_target 171*8975f5c5SAndroid Build Coastguard Worker 172*8975f5c5SAndroid Build Coastguard Worker def NinjaTarget(self): 173*8975f5c5SAndroid Build Coastguard Worker return self._gn_target[2:] 174*8975f5c5SAndroid Build Coastguard Worker 175*8975f5c5SAndroid Build Coastguard Worker def BuildConfigPath(self): 176*8975f5c5SAndroid Build Coastguard Worker return os.path.join('gen', self.GradleSubdir() + '.build_config.json') 177*8975f5c5SAndroid Build Coastguard Worker 178*8975f5c5SAndroid Build Coastguard Worker def GradleSubdir(self): 179*8975f5c5SAndroid Build Coastguard Worker """Returns the output subdirectory.""" 180*8975f5c5SAndroid Build Coastguard Worker ninja_target = self.NinjaTarget() 181*8975f5c5SAndroid Build Coastguard Worker # Support targets at the root level. e.g. //:foo 182*8975f5c5SAndroid Build Coastguard Worker if ninja_target[0] == ':': 183*8975f5c5SAndroid Build Coastguard Worker ninja_target = ninja_target[1:] 184*8975f5c5SAndroid Build Coastguard Worker return ninja_target.replace(':', os.path.sep) 185*8975f5c5SAndroid Build Coastguard Worker 186*8975f5c5SAndroid Build Coastguard Worker def GeneratedJavaSubdir(self): 187*8975f5c5SAndroid Build Coastguard Worker return _RebasePath( 188*8975f5c5SAndroid Build Coastguard Worker os.path.join('gen', self.GradleSubdir(), _GENERATED_JAVA_SUBDIR)) 189*8975f5c5SAndroid Build Coastguard Worker 190*8975f5c5SAndroid Build Coastguard Worker def ProjectName(self): 191*8975f5c5SAndroid Build Coastguard Worker """Returns the Gradle project name.""" 192*8975f5c5SAndroid Build Coastguard Worker return self.GradleSubdir().replace(os.path.sep, '.') 193*8975f5c5SAndroid Build Coastguard Worker 194*8975f5c5SAndroid Build Coastguard Worker def BuildConfig(self): 195*8975f5c5SAndroid Build Coastguard Worker """Reads and returns the project's .build_config.json JSON.""" 196*8975f5c5SAndroid Build Coastguard Worker if not self._build_config: 197*8975f5c5SAndroid Build Coastguard Worker with open(_RebasePath(self.BuildConfigPath())) as jsonfile: 198*8975f5c5SAndroid Build Coastguard Worker self._build_config = json.load(jsonfile) 199*8975f5c5SAndroid Build Coastguard Worker return self._build_config 200*8975f5c5SAndroid Build Coastguard Worker 201*8975f5c5SAndroid Build Coastguard Worker def DepsInfo(self): 202*8975f5c5SAndroid Build Coastguard Worker return self.BuildConfig()['deps_info'] 203*8975f5c5SAndroid Build Coastguard Worker 204*8975f5c5SAndroid Build Coastguard Worker def Gradle(self): 205*8975f5c5SAndroid Build Coastguard Worker return self.BuildConfig()['gradle'] 206*8975f5c5SAndroid Build Coastguard Worker 207*8975f5c5SAndroid Build Coastguard Worker def Javac(self): 208*8975f5c5SAndroid Build Coastguard Worker return self.BuildConfig()['javac'] 209*8975f5c5SAndroid Build Coastguard Worker 210*8975f5c5SAndroid Build Coastguard Worker def GetType(self): 211*8975f5c5SAndroid Build Coastguard Worker """Returns the target type from its .build_config.""" 212*8975f5c5SAndroid Build Coastguard Worker return self.DepsInfo()['type'] 213*8975f5c5SAndroid Build Coastguard Worker 214*8975f5c5SAndroid Build Coastguard Worker def IsValid(self): 215*8975f5c5SAndroid Build Coastguard Worker return self.GetType() in ( 216*8975f5c5SAndroid Build Coastguard Worker 'android_apk', 217*8975f5c5SAndroid Build Coastguard Worker 'android_app_bundle_module', 218*8975f5c5SAndroid Build Coastguard Worker 'java_library', 219*8975f5c5SAndroid Build Coastguard Worker "java_annotation_processor", 220*8975f5c5SAndroid Build Coastguard Worker 'java_binary', 221*8975f5c5SAndroid Build Coastguard Worker 'robolectric_binary', 222*8975f5c5SAndroid Build Coastguard Worker ) 223*8975f5c5SAndroid Build Coastguard Worker 224*8975f5c5SAndroid Build Coastguard Worker def ResSources(self): 225*8975f5c5SAndroid Build Coastguard Worker return self.DepsInfo().get('lint_resource_sources', []) 226*8975f5c5SAndroid Build Coastguard Worker 227*8975f5c5SAndroid Build Coastguard Worker def JavaFiles(self): 228*8975f5c5SAndroid Build Coastguard Worker if self._java_files is None: 229*8975f5c5SAndroid Build Coastguard Worker target_sources_file = self.DepsInfo().get('target_sources_file') 230*8975f5c5SAndroid Build Coastguard Worker java_files = [] 231*8975f5c5SAndroid Build Coastguard Worker if target_sources_file: 232*8975f5c5SAndroid Build Coastguard Worker target_sources_file = _RebasePath(target_sources_file) 233*8975f5c5SAndroid Build Coastguard Worker java_files = build_utils.ReadSourcesList(target_sources_file) 234*8975f5c5SAndroid Build Coastguard Worker self._java_files = java_files 235*8975f5c5SAndroid Build Coastguard Worker return self._java_files 236*8975f5c5SAndroid Build Coastguard Worker 237*8975f5c5SAndroid Build Coastguard Worker def PrebuiltJars(self): 238*8975f5c5SAndroid Build Coastguard Worker return self.Gradle().get('dependent_prebuilt_jars', []) 239*8975f5c5SAndroid Build Coastguard Worker 240*8975f5c5SAndroid Build Coastguard Worker def AllEntries(self): 241*8975f5c5SAndroid Build Coastguard Worker """Returns a list of all entries that the current entry depends on. 242*8975f5c5SAndroid Build Coastguard Worker 243*8975f5c5SAndroid Build Coastguard Worker This includes the entry itself to make iterating simpler.""" 244*8975f5c5SAndroid Build Coastguard Worker if self._all_entries is None: 245*8975f5c5SAndroid Build Coastguard Worker logging.debug('Generating entries for %s', self.GnTarget()) 246*8975f5c5SAndroid Build Coastguard Worker deps = [_ProjectEntry.FromBuildConfigPath(p) 247*8975f5c5SAndroid Build Coastguard Worker for p in self.Gradle()['dependent_android_projects']] 248*8975f5c5SAndroid Build Coastguard Worker deps.extend(_ProjectEntry.FromBuildConfigPath(p) 249*8975f5c5SAndroid Build Coastguard Worker for p in self.Gradle()['dependent_java_projects']) 250*8975f5c5SAndroid Build Coastguard Worker all_entries = set() 251*8975f5c5SAndroid Build Coastguard Worker for dep in deps: 252*8975f5c5SAndroid Build Coastguard Worker all_entries.update(dep.AllEntries()) 253*8975f5c5SAndroid Build Coastguard Worker all_entries.add(self) 254*8975f5c5SAndroid Build Coastguard Worker self._all_entries = list(all_entries) 255*8975f5c5SAndroid Build Coastguard Worker return self._all_entries 256*8975f5c5SAndroid Build Coastguard Worker 257*8975f5c5SAndroid Build Coastguard Worker 258*8975f5c5SAndroid Build Coastguard Workerclass _ProjectContextGenerator: 259*8975f5c5SAndroid Build Coastguard Worker """Helper class to generate gradle build files""" 260*8975f5c5SAndroid Build Coastguard Worker def __init__(self, project_dir, build_vars, use_gradle_process_resources, 261*8975f5c5SAndroid Build Coastguard Worker jinja_processor, split_projects): 262*8975f5c5SAndroid Build Coastguard Worker self.project_dir = project_dir 263*8975f5c5SAndroid Build Coastguard Worker self.build_vars = build_vars 264*8975f5c5SAndroid Build Coastguard Worker self.use_gradle_process_resources = use_gradle_process_resources 265*8975f5c5SAndroid Build Coastguard Worker self.jinja_processor = jinja_processor 266*8975f5c5SAndroid Build Coastguard Worker self.split_projects = split_projects 267*8975f5c5SAndroid Build Coastguard Worker self.processed_java_dirs = set() 268*8975f5c5SAndroid Build Coastguard Worker self.processed_prebuilts = set() 269*8975f5c5SAndroid Build Coastguard Worker self.processed_res_dirs = set() 270*8975f5c5SAndroid Build Coastguard Worker 271*8975f5c5SAndroid Build Coastguard Worker def _GenJniLibs(self, root_entry): 272*8975f5c5SAndroid Build Coastguard Worker libraries = [] 273*8975f5c5SAndroid Build Coastguard Worker for entry in self._GetEntries(root_entry): 274*8975f5c5SAndroid Build Coastguard Worker libraries += entry.BuildConfig().get('native', {}).get('libraries', []) 275*8975f5c5SAndroid Build Coastguard Worker if libraries: 276*8975f5c5SAndroid Build Coastguard Worker return _CreateJniLibsDir(constants.GetOutDirectory(), 277*8975f5c5SAndroid Build Coastguard Worker self.EntryOutputDir(root_entry), libraries) 278*8975f5c5SAndroid Build Coastguard Worker return [] 279*8975f5c5SAndroid Build Coastguard Worker 280*8975f5c5SAndroid Build Coastguard Worker def _GenJavaDirs(self, root_entry): 281*8975f5c5SAndroid Build Coastguard Worker java_files = [] 282*8975f5c5SAndroid Build Coastguard Worker for entry in self._GetEntries(root_entry): 283*8975f5c5SAndroid Build Coastguard Worker java_files += entry.JavaFiles() 284*8975f5c5SAndroid Build Coastguard Worker java_dirs, excludes = _ComputeJavaSourceDirsAndExcludes( 285*8975f5c5SAndroid Build Coastguard Worker constants.GetOutDirectory(), java_files) 286*8975f5c5SAndroid Build Coastguard Worker return java_dirs, excludes 287*8975f5c5SAndroid Build Coastguard Worker 288*8975f5c5SAndroid Build Coastguard Worker def _GenCustomManifest(self, entry): 289*8975f5c5SAndroid Build Coastguard Worker """Returns the path to the generated AndroidManifest.xml. 290*8975f5c5SAndroid Build Coastguard Worker 291*8975f5c5SAndroid Build Coastguard Worker Gradle uses package id from manifest when generating R.class. So, we need 292*8975f5c5SAndroid Build Coastguard Worker to generate a custom manifest if we let gradle process resources. We cannot 293*8975f5c5SAndroid Build Coastguard Worker simply set android.defaultConfig.applicationId because it is not supported 294*8975f5c5SAndroid Build Coastguard Worker for library targets.""" 295*8975f5c5SAndroid Build Coastguard Worker resource_packages = entry.Javac().get('resource_packages') 296*8975f5c5SAndroid Build Coastguard Worker if not resource_packages: 297*8975f5c5SAndroid Build Coastguard Worker logging.debug( 298*8975f5c5SAndroid Build Coastguard Worker 'Target %s includes resources from unknown package. ' 299*8975f5c5SAndroid Build Coastguard Worker 'Unable to process with gradle.', entry.GnTarget()) 300*8975f5c5SAndroid Build Coastguard Worker return _DEFAULT_ANDROID_MANIFEST_PATH 301*8975f5c5SAndroid Build Coastguard Worker if len(resource_packages) > 1: 302*8975f5c5SAndroid Build Coastguard Worker logging.debug( 303*8975f5c5SAndroid Build Coastguard Worker 'Target %s includes resources from multiple packages. ' 304*8975f5c5SAndroid Build Coastguard Worker 'Unable to process with gradle.', entry.GnTarget()) 305*8975f5c5SAndroid Build Coastguard Worker return _DEFAULT_ANDROID_MANIFEST_PATH 306*8975f5c5SAndroid Build Coastguard Worker 307*8975f5c5SAndroid Build Coastguard Worker variables = {'package': resource_packages[0]} 308*8975f5c5SAndroid Build Coastguard Worker data = self.jinja_processor.Render(_TemplatePath('manifest'), variables) 309*8975f5c5SAndroid Build Coastguard Worker output_file = os.path.join( 310*8975f5c5SAndroid Build Coastguard Worker self.EntryOutputDir(entry), 'AndroidManifest.xml') 311*8975f5c5SAndroid Build Coastguard Worker _WriteFile(output_file, data) 312*8975f5c5SAndroid Build Coastguard Worker 313*8975f5c5SAndroid Build Coastguard Worker return output_file 314*8975f5c5SAndroid Build Coastguard Worker 315*8975f5c5SAndroid Build Coastguard Worker def _Relativize(self, entry, paths): 316*8975f5c5SAndroid Build Coastguard Worker return _RebasePath(paths, self.EntryOutputDir(entry)) 317*8975f5c5SAndroid Build Coastguard Worker 318*8975f5c5SAndroid Build Coastguard Worker def _GetEntries(self, entry): 319*8975f5c5SAndroid Build Coastguard Worker if self.split_projects: 320*8975f5c5SAndroid Build Coastguard Worker return [entry] 321*8975f5c5SAndroid Build Coastguard Worker return entry.AllEntries() 322*8975f5c5SAndroid Build Coastguard Worker 323*8975f5c5SAndroid Build Coastguard Worker def EntryOutputDir(self, entry): 324*8975f5c5SAndroid Build Coastguard Worker return os.path.join(self.project_dir, entry.GradleSubdir()) 325*8975f5c5SAndroid Build Coastguard Worker 326*8975f5c5SAndroid Build Coastguard Worker def GeneratedInputs(self, root_entry): 327*8975f5c5SAndroid Build Coastguard Worker generated_inputs = set() 328*8975f5c5SAndroid Build Coastguard Worker for entry in self._GetEntries(root_entry): 329*8975f5c5SAndroid Build Coastguard Worker generated_inputs.update(entry.PrebuiltJars()) 330*8975f5c5SAndroid Build Coastguard Worker return generated_inputs 331*8975f5c5SAndroid Build Coastguard Worker 332*8975f5c5SAndroid Build Coastguard Worker def GenerateManifest(self, root_entry): 333*8975f5c5SAndroid Build Coastguard Worker android_manifest = root_entry.DepsInfo().get('android_manifest') 334*8975f5c5SAndroid Build Coastguard Worker if not android_manifest: 335*8975f5c5SAndroid Build Coastguard Worker android_manifest = self._GenCustomManifest(root_entry) 336*8975f5c5SAndroid Build Coastguard Worker return self._Relativize(root_entry, android_manifest) 337*8975f5c5SAndroid Build Coastguard Worker 338*8975f5c5SAndroid Build Coastguard Worker def Generate(self, root_entry): 339*8975f5c5SAndroid Build Coastguard Worker # TODO(agrieve): Add an option to use interface jars and see if that speeds 340*8975f5c5SAndroid Build Coastguard Worker # things up at all. 341*8975f5c5SAndroid Build Coastguard Worker variables = {} 342*8975f5c5SAndroid Build Coastguard Worker java_dirs, excludes = self._GenJavaDirs(root_entry) 343*8975f5c5SAndroid Build Coastguard Worker java_dirs.extend( 344*8975f5c5SAndroid Build Coastguard Worker e.GeneratedJavaSubdir() for e in self._GetEntries(root_entry)) 345*8975f5c5SAndroid Build Coastguard Worker self.processed_java_dirs.update(java_dirs) 346*8975f5c5SAndroid Build Coastguard Worker java_dirs.sort() 347*8975f5c5SAndroid Build Coastguard Worker variables['java_dirs'] = self._Relativize(root_entry, java_dirs) 348*8975f5c5SAndroid Build Coastguard Worker variables['java_excludes'] = excludes 349*8975f5c5SAndroid Build Coastguard Worker variables['jni_libs'] = self._Relativize( 350*8975f5c5SAndroid Build Coastguard Worker root_entry, set(self._GenJniLibs(root_entry))) 351*8975f5c5SAndroid Build Coastguard Worker prebuilts = set( 352*8975f5c5SAndroid Build Coastguard Worker p for e in self._GetEntries(root_entry) for p in e.PrebuiltJars()) 353*8975f5c5SAndroid Build Coastguard Worker self.processed_prebuilts.update(prebuilts) 354*8975f5c5SAndroid Build Coastguard Worker variables['prebuilts'] = self._Relativize(root_entry, prebuilts) 355*8975f5c5SAndroid Build Coastguard Worker res_sources_files = _RebasePath( 356*8975f5c5SAndroid Build Coastguard Worker set(p for e in self._GetEntries(root_entry) for p in e.ResSources())) 357*8975f5c5SAndroid Build Coastguard Worker res_sources = [] 358*8975f5c5SAndroid Build Coastguard Worker for res_sources_file in res_sources_files: 359*8975f5c5SAndroid Build Coastguard Worker res_sources.extend(build_utils.ReadSourcesList(res_sources_file)) 360*8975f5c5SAndroid Build Coastguard Worker res_dirs = resource_utils.DeduceResourceDirsFromFileList(res_sources) 361*8975f5c5SAndroid Build Coastguard Worker # Do not add generated resources for the all module since it creates many 362*8975f5c5SAndroid Build Coastguard Worker # duplicates, and currently resources are only used for editing. 363*8975f5c5SAndroid Build Coastguard Worker self.processed_res_dirs.update(res_dirs) 364*8975f5c5SAndroid Build Coastguard Worker variables['res_dirs'] = self._Relativize(root_entry, res_dirs) 365*8975f5c5SAndroid Build Coastguard Worker if self.split_projects: 366*8975f5c5SAndroid Build Coastguard Worker deps = [_ProjectEntry.FromBuildConfigPath(p) 367*8975f5c5SAndroid Build Coastguard Worker for p in root_entry.Gradle()['dependent_android_projects']] 368*8975f5c5SAndroid Build Coastguard Worker variables['android_project_deps'] = [d.ProjectName() for d in deps] 369*8975f5c5SAndroid Build Coastguard Worker deps = [_ProjectEntry.FromBuildConfigPath(p) 370*8975f5c5SAndroid Build Coastguard Worker for p in root_entry.Gradle()['dependent_java_projects']] 371*8975f5c5SAndroid Build Coastguard Worker variables['java_project_deps'] = [d.ProjectName() for d in deps] 372*8975f5c5SAndroid Build Coastguard Worker return variables 373*8975f5c5SAndroid Build Coastguard Worker 374*8975f5c5SAndroid Build Coastguard Worker 375*8975f5c5SAndroid Build Coastguard Workerdef _ComputeJavaSourceDirs(java_files): 376*8975f5c5SAndroid Build Coastguard Worker """Returns a dictionary of source dirs with each given files in one.""" 377*8975f5c5SAndroid Build Coastguard Worker found_roots = {} 378*8975f5c5SAndroid Build Coastguard Worker for path in java_files: 379*8975f5c5SAndroid Build Coastguard Worker path_root = path 380*8975f5c5SAndroid Build Coastguard Worker # Recognize these tokens as top-level. 381*8975f5c5SAndroid Build Coastguard Worker while True: 382*8975f5c5SAndroid Build Coastguard Worker path_root = os.path.dirname(path_root) 383*8975f5c5SAndroid Build Coastguard Worker basename = os.path.basename(path_root) 384*8975f5c5SAndroid Build Coastguard Worker assert basename, 'Failed to find source dir for ' + path 385*8975f5c5SAndroid Build Coastguard Worker if basename in ('java', 'src'): 386*8975f5c5SAndroid Build Coastguard Worker break 387*8975f5c5SAndroid Build Coastguard Worker if basename in ('javax', 'org', 'com'): 388*8975f5c5SAndroid Build Coastguard Worker path_root = os.path.dirname(path_root) 389*8975f5c5SAndroid Build Coastguard Worker break 390*8975f5c5SAndroid Build Coastguard Worker if path_root not in found_roots: 391*8975f5c5SAndroid Build Coastguard Worker found_roots[path_root] = [] 392*8975f5c5SAndroid Build Coastguard Worker found_roots[path_root].append(path) 393*8975f5c5SAndroid Build Coastguard Worker return found_roots 394*8975f5c5SAndroid Build Coastguard Worker 395*8975f5c5SAndroid Build Coastguard Worker 396*8975f5c5SAndroid Build Coastguard Workerdef _ComputeExcludeFilters(wanted_files, unwanted_files, parent_dir): 397*8975f5c5SAndroid Build Coastguard Worker """Returns exclude patters to exclude unwanted files but keep wanted files. 398*8975f5c5SAndroid Build Coastguard Worker 399*8975f5c5SAndroid Build Coastguard Worker - Shortens exclude list by globbing if possible. 400*8975f5c5SAndroid Build Coastguard Worker - Exclude patterns are relative paths from the parent directory. 401*8975f5c5SAndroid Build Coastguard Worker """ 402*8975f5c5SAndroid Build Coastguard Worker excludes = [] 403*8975f5c5SAndroid Build Coastguard Worker files_to_include = set(wanted_files) 404*8975f5c5SAndroid Build Coastguard Worker files_to_exclude = set(unwanted_files) 405*8975f5c5SAndroid Build Coastguard Worker while files_to_exclude: 406*8975f5c5SAndroid Build Coastguard Worker unwanted_file = files_to_exclude.pop() 407*8975f5c5SAndroid Build Coastguard Worker target_exclude = os.path.join( 408*8975f5c5SAndroid Build Coastguard Worker os.path.dirname(unwanted_file), '*.java') 409*8975f5c5SAndroid Build Coastguard Worker found_files = set(glob.glob(target_exclude)) 410*8975f5c5SAndroid Build Coastguard Worker valid_files = found_files & files_to_include 411*8975f5c5SAndroid Build Coastguard Worker if valid_files: 412*8975f5c5SAndroid Build Coastguard Worker excludes.append(os.path.relpath(unwanted_file, parent_dir)) 413*8975f5c5SAndroid Build Coastguard Worker else: 414*8975f5c5SAndroid Build Coastguard Worker excludes.append(os.path.relpath(target_exclude, parent_dir)) 415*8975f5c5SAndroid Build Coastguard Worker files_to_exclude -= found_files 416*8975f5c5SAndroid Build Coastguard Worker return excludes 417*8975f5c5SAndroid Build Coastguard Worker 418*8975f5c5SAndroid Build Coastguard Worker 419*8975f5c5SAndroid Build Coastguard Workerdef _ComputeJavaSourceDirsAndExcludes(output_dir, source_files): 420*8975f5c5SAndroid Build Coastguard Worker """Computes the list of java source directories and exclude patterns. 421*8975f5c5SAndroid Build Coastguard Worker 422*8975f5c5SAndroid Build Coastguard Worker This includes both Java and Kotlin files since both are listed in the same 423*8975f5c5SAndroid Build Coastguard Worker "java" section for gradle. 424*8975f5c5SAndroid Build Coastguard Worker 425*8975f5c5SAndroid Build Coastguard Worker 1. Computes the root source directories from the list of files. 426*8975f5c5SAndroid Build Coastguard Worker 2. Compute exclude patterns that exclude all extra files only. 427*8975f5c5SAndroid Build Coastguard Worker 3. Returns the list of source directories and exclude patterns. 428*8975f5c5SAndroid Build Coastguard Worker """ 429*8975f5c5SAndroid Build Coastguard Worker java_dirs = [] 430*8975f5c5SAndroid Build Coastguard Worker excludes = [] 431*8975f5c5SAndroid Build Coastguard Worker if source_files: 432*8975f5c5SAndroid Build Coastguard Worker source_files = _RebasePath(source_files) 433*8975f5c5SAndroid Build Coastguard Worker computed_dirs = _ComputeJavaSourceDirs(source_files) 434*8975f5c5SAndroid Build Coastguard Worker java_dirs = list(computed_dirs.keys()) 435*8975f5c5SAndroid Build Coastguard Worker all_found_source_files = set() 436*8975f5c5SAndroid Build Coastguard Worker 437*8975f5c5SAndroid Build Coastguard Worker for directory, files in computed_dirs.items(): 438*8975f5c5SAndroid Build Coastguard Worker found_source_files = (build_utils.FindInDirectory(directory, '*.java') + 439*8975f5c5SAndroid Build Coastguard Worker build_utils.FindInDirectory(directory, '*.kt')) 440*8975f5c5SAndroid Build Coastguard Worker all_found_source_files.update(found_source_files) 441*8975f5c5SAndroid Build Coastguard Worker unwanted_source_files = set(found_source_files) - set(files) 442*8975f5c5SAndroid Build Coastguard Worker if unwanted_source_files: 443*8975f5c5SAndroid Build Coastguard Worker logging.debug('Directory requires excludes: %s', directory) 444*8975f5c5SAndroid Build Coastguard Worker excludes.extend( 445*8975f5c5SAndroid Build Coastguard Worker _ComputeExcludeFilters(files, unwanted_source_files, directory)) 446*8975f5c5SAndroid Build Coastguard Worker 447*8975f5c5SAndroid Build Coastguard Worker missing_source_files = set(source_files) - all_found_source_files 448*8975f5c5SAndroid Build Coastguard Worker # Warn only about non-generated files that are missing. 449*8975f5c5SAndroid Build Coastguard Worker missing_source_files = [ 450*8975f5c5SAndroid Build Coastguard Worker p for p in missing_source_files if not p.startswith(output_dir) 451*8975f5c5SAndroid Build Coastguard Worker ] 452*8975f5c5SAndroid Build Coastguard Worker if missing_source_files: 453*8975f5c5SAndroid Build Coastguard Worker logging.warning('Some source files were not found: %s', 454*8975f5c5SAndroid Build Coastguard Worker missing_source_files) 455*8975f5c5SAndroid Build Coastguard Worker 456*8975f5c5SAndroid Build Coastguard Worker return java_dirs, excludes 457*8975f5c5SAndroid Build Coastguard Worker 458*8975f5c5SAndroid Build Coastguard Worker 459*8975f5c5SAndroid Build Coastguard Workerdef _CreateRelativeSymlink(target_path, link_path): 460*8975f5c5SAndroid Build Coastguard Worker link_dir = os.path.dirname(link_path) 461*8975f5c5SAndroid Build Coastguard Worker relpath = os.path.relpath(target_path, link_dir) 462*8975f5c5SAndroid Build Coastguard Worker logging.debug('Creating symlink %s -> %s', link_path, relpath) 463*8975f5c5SAndroid Build Coastguard Worker os.symlink(relpath, link_path) 464*8975f5c5SAndroid Build Coastguard Worker 465*8975f5c5SAndroid Build Coastguard Worker 466*8975f5c5SAndroid Build Coastguard Workerdef _CreateJniLibsDir(output_dir, entry_output_dir, so_files): 467*8975f5c5SAndroid Build Coastguard Worker """Creates directory with symlinked .so files if necessary. 468*8975f5c5SAndroid Build Coastguard Worker 469*8975f5c5SAndroid Build Coastguard Worker Returns list of JNI libs directories.""" 470*8975f5c5SAndroid Build Coastguard Worker 471*8975f5c5SAndroid Build Coastguard Worker if so_files: 472*8975f5c5SAndroid Build Coastguard Worker symlink_dir = os.path.join(entry_output_dir, _JNI_LIBS_SUBDIR) 473*8975f5c5SAndroid Build Coastguard Worker shutil.rmtree(symlink_dir, True) 474*8975f5c5SAndroid Build Coastguard Worker abi_dir = os.path.join(symlink_dir, _ARMEABI_SUBDIR) 475*8975f5c5SAndroid Build Coastguard Worker if not os.path.exists(abi_dir): 476*8975f5c5SAndroid Build Coastguard Worker os.makedirs(abi_dir) 477*8975f5c5SAndroid Build Coastguard Worker for so_file in so_files: 478*8975f5c5SAndroid Build Coastguard Worker target_path = os.path.join(output_dir, so_file) 479*8975f5c5SAndroid Build Coastguard Worker symlinked_path = os.path.join(abi_dir, so_file) 480*8975f5c5SAndroid Build Coastguard Worker _CreateRelativeSymlink(target_path, symlinked_path) 481*8975f5c5SAndroid Build Coastguard Worker 482*8975f5c5SAndroid Build Coastguard Worker return [symlink_dir] 483*8975f5c5SAndroid Build Coastguard Worker 484*8975f5c5SAndroid Build Coastguard Worker return [] 485*8975f5c5SAndroid Build Coastguard Worker 486*8975f5c5SAndroid Build Coastguard Worker 487*8975f5c5SAndroid Build Coastguard Workerdef _ParseVersionFromFile(file_path, version_regex_string, default_version): 488*8975f5c5SAndroid Build Coastguard Worker if os.path.exists(file_path): 489*8975f5c5SAndroid Build Coastguard Worker content = pathlib.Path(file_path).read_text() 490*8975f5c5SAndroid Build Coastguard Worker match = re.search(version_regex_string, content) 491*8975f5c5SAndroid Build Coastguard Worker if match: 492*8975f5c5SAndroid Build Coastguard Worker version = match.group(1) 493*8975f5c5SAndroid Build Coastguard Worker logging.info('Using existing version %s in %s.', version, file_path) 494*8975f5c5SAndroid Build Coastguard Worker return version 495*8975f5c5SAndroid Build Coastguard Worker logging.warning('Unable to find %s in %s:\n%s', version_regex_string, 496*8975f5c5SAndroid Build Coastguard Worker file_path, content) 497*8975f5c5SAndroid Build Coastguard Worker return default_version 498*8975f5c5SAndroid Build Coastguard Worker 499*8975f5c5SAndroid Build Coastguard Worker 500*8975f5c5SAndroid Build Coastguard Workerdef _GenerateLocalProperties(sdk_dir): 501*8975f5c5SAndroid Build Coastguard Worker """Returns the data for local.properties as a string.""" 502*8975f5c5SAndroid Build Coastguard Worker return '\n'.join([ 503*8975f5c5SAndroid Build Coastguard Worker '# Generated by //build/android/gradle/generate_gradle.py', 504*8975f5c5SAndroid Build Coastguard Worker 'sdk.dir=%s' % sdk_dir, 505*8975f5c5SAndroid Build Coastguard Worker '', 506*8975f5c5SAndroid Build Coastguard Worker ]) 507*8975f5c5SAndroid Build Coastguard Worker 508*8975f5c5SAndroid Build Coastguard Worker 509*8975f5c5SAndroid Build Coastguard Workerdef _GenerateGradleWrapperProperties(file_path): 510*8975f5c5SAndroid Build Coastguard Worker """Returns the data for gradle-wrapper.properties as a string.""" 511*8975f5c5SAndroid Build Coastguard Worker 512*8975f5c5SAndroid Build Coastguard Worker version = _ParseVersionFromFile(file_path, 513*8975f5c5SAndroid Build Coastguard Worker r'/distributions/gradle-([\d.]+)-all.zip', 514*8975f5c5SAndroid Build Coastguard Worker _DEFAULT_GRADLE_WRAPPER_VERSION) 515*8975f5c5SAndroid Build Coastguard Worker 516*8975f5c5SAndroid Build Coastguard Worker return '\n'.join([ 517*8975f5c5SAndroid Build Coastguard Worker '# Generated by //build/android/gradle/generate_gradle.py', 518*8975f5c5SAndroid Build Coastguard Worker ('distributionUrl=https\\://services.gradle.org' 519*8975f5c5SAndroid Build Coastguard Worker f'/distributions/gradle-{version}-all.zip'), 520*8975f5c5SAndroid Build Coastguard Worker '', 521*8975f5c5SAndroid Build Coastguard Worker ]) 522*8975f5c5SAndroid Build Coastguard Worker 523*8975f5c5SAndroid Build Coastguard Worker 524*8975f5c5SAndroid Build Coastguard Workerdef _GenerateGradleProperties(): 525*8975f5c5SAndroid Build Coastguard Worker """Returns the data for gradle.properties as a string.""" 526*8975f5c5SAndroid Build Coastguard Worker return '\n'.join([ 527*8975f5c5SAndroid Build Coastguard Worker '# Generated by //build/android/gradle/generate_gradle.py', 528*8975f5c5SAndroid Build Coastguard Worker '', 529*8975f5c5SAndroid Build Coastguard Worker '# Tells Gradle to show warnings during project sync.', 530*8975f5c5SAndroid Build Coastguard Worker 'org.gradle.warning.mode=all', 531*8975f5c5SAndroid Build Coastguard Worker '', 532*8975f5c5SAndroid Build Coastguard Worker ]) 533*8975f5c5SAndroid Build Coastguard Worker 534*8975f5c5SAndroid Build Coastguard Worker 535*8975f5c5SAndroid Build Coastguard Workerdef _GenerateBaseVars(generator, build_vars): 536*8975f5c5SAndroid Build Coastguard Worker variables = {} 537*8975f5c5SAndroid Build Coastguard Worker # Avoid pre-release SDKs since Studio might not know how to download them. 538*8975f5c5SAndroid Build Coastguard Worker variables['compile_sdk_version'] = ( 539*8975f5c5SAndroid Build Coastguard Worker 'android-%s' % build_vars['android_sdk_platform_version']) 540*8975f5c5SAndroid Build Coastguard Worker target_sdk_version = build_vars['android_sdk_platform_version'] 541*8975f5c5SAndroid Build Coastguard Worker if str(target_sdk_version).isalpha(): 542*8975f5c5SAndroid Build Coastguard Worker target_sdk_version = '"{}"'.format(target_sdk_version) 543*8975f5c5SAndroid Build Coastguard Worker variables['target_sdk_version'] = target_sdk_version 544*8975f5c5SAndroid Build Coastguard Worker variables['min_sdk_version'] = build_vars['default_min_sdk_version'] 545*8975f5c5SAndroid Build Coastguard Worker variables['use_gradle_process_resources'] = ( 546*8975f5c5SAndroid Build Coastguard Worker generator.use_gradle_process_resources) 547*8975f5c5SAndroid Build Coastguard Worker return variables 548*8975f5c5SAndroid Build Coastguard Worker 549*8975f5c5SAndroid Build Coastguard Worker 550*8975f5c5SAndroid Build Coastguard Workerdef _GenerateGradleFile(entry, generator, build_vars, jinja_processor): 551*8975f5c5SAndroid Build Coastguard Worker """Returns the data for a project's build.gradle.""" 552*8975f5c5SAndroid Build Coastguard Worker deps_info = entry.DepsInfo() 553*8975f5c5SAndroid Build Coastguard Worker variables = _GenerateBaseVars(generator, build_vars) 554*8975f5c5SAndroid Build Coastguard Worker sourceSetName = 'main' 555*8975f5c5SAndroid Build Coastguard Worker 556*8975f5c5SAndroid Build Coastguard Worker if deps_info['type'] == 'android_apk': 557*8975f5c5SAndroid Build Coastguard Worker target_type = 'android_apk' 558*8975f5c5SAndroid Build Coastguard Worker elif deps_info['type'] in ('java_library', 'java_annotation_processor'): 559*8975f5c5SAndroid Build Coastguard Worker is_prebuilt = deps_info.get('is_prebuilt', False) 560*8975f5c5SAndroid Build Coastguard Worker gradle_treat_as_prebuilt = deps_info.get('gradle_treat_as_prebuilt', False) 561*8975f5c5SAndroid Build Coastguard Worker if is_prebuilt or gradle_treat_as_prebuilt: 562*8975f5c5SAndroid Build Coastguard Worker return None 563*8975f5c5SAndroid Build Coastguard Worker if deps_info['requires_android']: 564*8975f5c5SAndroid Build Coastguard Worker target_type = 'android_library' 565*8975f5c5SAndroid Build Coastguard Worker else: 566*8975f5c5SAndroid Build Coastguard Worker target_type = 'java_library' 567*8975f5c5SAndroid Build Coastguard Worker elif deps_info['type'] == 'java_binary': 568*8975f5c5SAndroid Build Coastguard Worker target_type = 'java_binary' 569*8975f5c5SAndroid Build Coastguard Worker variables['main_class'] = deps_info.get('main_class') 570*8975f5c5SAndroid Build Coastguard Worker elif deps_info['type'] == 'robolectric_binary': 571*8975f5c5SAndroid Build Coastguard Worker target_type = 'android_junit' 572*8975f5c5SAndroid Build Coastguard Worker sourceSetName = 'test' 573*8975f5c5SAndroid Build Coastguard Worker else: 574*8975f5c5SAndroid Build Coastguard Worker return None 575*8975f5c5SAndroid Build Coastguard Worker 576*8975f5c5SAndroid Build Coastguard Worker variables['target_name'] = os.path.splitext(deps_info['name'])[0] 577*8975f5c5SAndroid Build Coastguard Worker variables['template_type'] = target_type 578*8975f5c5SAndroid Build Coastguard Worker variables['main'] = {} 579*8975f5c5SAndroid Build Coastguard Worker variables[sourceSetName] = generator.Generate(entry) 580*8975f5c5SAndroid Build Coastguard Worker variables['main']['android_manifest'] = generator.GenerateManifest(entry) 581*8975f5c5SAndroid Build Coastguard Worker 582*8975f5c5SAndroid Build Coastguard Worker if entry.android_test_entries: 583*8975f5c5SAndroid Build Coastguard Worker variables['android_test'] = [] 584*8975f5c5SAndroid Build Coastguard Worker for e in entry.android_test_entries: 585*8975f5c5SAndroid Build Coastguard Worker test_entry = generator.Generate(e) 586*8975f5c5SAndroid Build Coastguard Worker test_entry['android_manifest'] = generator.GenerateManifest(e) 587*8975f5c5SAndroid Build Coastguard Worker variables['android_test'].append(test_entry) 588*8975f5c5SAndroid Build Coastguard Worker for key, value in test_entry.items(): 589*8975f5c5SAndroid Build Coastguard Worker if isinstance(value, list): 590*8975f5c5SAndroid Build Coastguard Worker test_entry[key] = sorted(set(value) - set(variables['main'][key])) 591*8975f5c5SAndroid Build Coastguard Worker 592*8975f5c5SAndroid Build Coastguard Worker return jinja_processor.Render( 593*8975f5c5SAndroid Build Coastguard Worker _TemplatePath(target_type.split('_')[0]), variables) 594*8975f5c5SAndroid Build Coastguard Worker 595*8975f5c5SAndroid Build Coastguard Worker 596*8975f5c5SAndroid Build Coastguard Worker# Example: //chrome/android:monochrome 597*8975f5c5SAndroid Build Coastguard Workerdef _GetNative(relative_func, target_names): 598*8975f5c5SAndroid Build Coastguard Worker """Returns an object containing native c++ sources list and its included path 599*8975f5c5SAndroid Build Coastguard Worker 600*8975f5c5SAndroid Build Coastguard Worker Iterate through all target_names and their deps to get the list of included 601*8975f5c5SAndroid Build Coastguard Worker paths and sources.""" 602*8975f5c5SAndroid Build Coastguard Worker out_dir = constants.GetOutDirectory() 603*8975f5c5SAndroid Build Coastguard Worker with open(os.path.join(out_dir, 'project.json'), 'r') as project_file: 604*8975f5c5SAndroid Build Coastguard Worker projects = json.load(project_file) 605*8975f5c5SAndroid Build Coastguard Worker project_targets = projects['targets'] 606*8975f5c5SAndroid Build Coastguard Worker root_dir = projects['build_settings']['root_path'] 607*8975f5c5SAndroid Build Coastguard Worker includes = set() 608*8975f5c5SAndroid Build Coastguard Worker processed_target = set() 609*8975f5c5SAndroid Build Coastguard Worker targets_stack = list(target_names) 610*8975f5c5SAndroid Build Coastguard Worker sources = [] 611*8975f5c5SAndroid Build Coastguard Worker 612*8975f5c5SAndroid Build Coastguard Worker while targets_stack: 613*8975f5c5SAndroid Build Coastguard Worker target_name = targets_stack.pop() 614*8975f5c5SAndroid Build Coastguard Worker if target_name in processed_target: 615*8975f5c5SAndroid Build Coastguard Worker continue 616*8975f5c5SAndroid Build Coastguard Worker processed_target.add(target_name) 617*8975f5c5SAndroid Build Coastguard Worker target = project_targets[target_name] 618*8975f5c5SAndroid Build Coastguard Worker includes.update(target.get('include_dirs', [])) 619*8975f5c5SAndroid Build Coastguard Worker targets_stack.extend(target.get('deps', [])) 620*8975f5c5SAndroid Build Coastguard Worker # Ignore generated files 621*8975f5c5SAndroid Build Coastguard Worker sources.extend(f for f in target.get('sources', []) 622*8975f5c5SAndroid Build Coastguard Worker if f.endswith('.cc') and not f.startswith('//out')) 623*8975f5c5SAndroid Build Coastguard Worker 624*8975f5c5SAndroid Build Coastguard Worker def process_paths(paths): 625*8975f5c5SAndroid Build Coastguard Worker # Ignores leading // 626*8975f5c5SAndroid Build Coastguard Worker return relative_func( 627*8975f5c5SAndroid Build Coastguard Worker sorted(os.path.join(root_dir, path[2:]) for path in paths)) 628*8975f5c5SAndroid Build Coastguard Worker 629*8975f5c5SAndroid Build Coastguard Worker return { 630*8975f5c5SAndroid Build Coastguard Worker 'sources': process_paths(sources), 631*8975f5c5SAndroid Build Coastguard Worker 'includes': process_paths(includes), 632*8975f5c5SAndroid Build Coastguard Worker } 633*8975f5c5SAndroid Build Coastguard Worker 634*8975f5c5SAndroid Build Coastguard Worker 635*8975f5c5SAndroid Build Coastguard Workerdef _GenerateModuleAll(gradle_output_dir, generator, build_vars, 636*8975f5c5SAndroid Build Coastguard Worker jinja_processor, native_targets): 637*8975f5c5SAndroid Build Coastguard Worker """Returns the data for a pseudo build.gradle of all dirs. 638*8975f5c5SAndroid Build Coastguard Worker 639*8975f5c5SAndroid Build Coastguard Worker See //docs/android_studio.md for more details.""" 640*8975f5c5SAndroid Build Coastguard Worker variables = _GenerateBaseVars(generator, build_vars) 641*8975f5c5SAndroid Build Coastguard Worker target_type = 'android_apk' 642*8975f5c5SAndroid Build Coastguard Worker variables['target_name'] = _MODULE_ALL 643*8975f5c5SAndroid Build Coastguard Worker variables['template_type'] = target_type 644*8975f5c5SAndroid Build Coastguard Worker java_dirs = sorted(generator.processed_java_dirs) 645*8975f5c5SAndroid Build Coastguard Worker prebuilts = sorted(generator.processed_prebuilts) 646*8975f5c5SAndroid Build Coastguard Worker res_dirs = sorted(generator.processed_res_dirs) 647*8975f5c5SAndroid Build Coastguard Worker def Relativize(paths): 648*8975f5c5SAndroid Build Coastguard Worker return _RebasePath(paths, os.path.join(gradle_output_dir, _MODULE_ALL)) 649*8975f5c5SAndroid Build Coastguard Worker 650*8975f5c5SAndroid Build Coastguard Worker # As after clank modularization, the java and javatests code will live side by 651*8975f5c5SAndroid Build Coastguard Worker # side in the same module, we will list both of them in the main target here. 652*8975f5c5SAndroid Build Coastguard Worker main_java_dirs = [d for d in java_dirs if 'junit/' not in d] 653*8975f5c5SAndroid Build Coastguard Worker junit_test_java_dirs = [d for d in java_dirs if 'junit/' in d] 654*8975f5c5SAndroid Build Coastguard Worker variables['main'] = { 655*8975f5c5SAndroid Build Coastguard Worker 'android_manifest': Relativize(_DEFAULT_ANDROID_MANIFEST_PATH), 656*8975f5c5SAndroid Build Coastguard Worker 'java_dirs': Relativize(main_java_dirs), 657*8975f5c5SAndroid Build Coastguard Worker 'prebuilts': Relativize(prebuilts), 658*8975f5c5SAndroid Build Coastguard Worker 'java_excludes': ['**/*.java', '**/*.kt'], 659*8975f5c5SAndroid Build Coastguard Worker 'res_dirs': Relativize(res_dirs), 660*8975f5c5SAndroid Build Coastguard Worker } 661*8975f5c5SAndroid Build Coastguard Worker variables['android_test'] = [{ 662*8975f5c5SAndroid Build Coastguard Worker 'java_dirs': Relativize(junit_test_java_dirs), 663*8975f5c5SAndroid Build Coastguard Worker 'java_excludes': ['**/*.java', '**/*.kt'], 664*8975f5c5SAndroid Build Coastguard Worker }] 665*8975f5c5SAndroid Build Coastguard Worker if native_targets: 666*8975f5c5SAndroid Build Coastguard Worker variables['native'] = _GetNative( 667*8975f5c5SAndroid Build Coastguard Worker relative_func=Relativize, target_names=native_targets) 668*8975f5c5SAndroid Build Coastguard Worker data = jinja_processor.Render( 669*8975f5c5SAndroid Build Coastguard Worker _TemplatePath(target_type.split('_')[0]), variables) 670*8975f5c5SAndroid Build Coastguard Worker _WriteFile( 671*8975f5c5SAndroid Build Coastguard Worker os.path.join(gradle_output_dir, _MODULE_ALL, _GRADLE_BUILD_FILE), data) 672*8975f5c5SAndroid Build Coastguard Worker if native_targets: 673*8975f5c5SAndroid Build Coastguard Worker cmake_data = jinja_processor.Render(_TemplatePath('cmake'), variables) 674*8975f5c5SAndroid Build Coastguard Worker _WriteFile( 675*8975f5c5SAndroid Build Coastguard Worker os.path.join(gradle_output_dir, _MODULE_ALL, _CMAKE_FILE), cmake_data) 676*8975f5c5SAndroid Build Coastguard Worker 677*8975f5c5SAndroid Build Coastguard Worker 678*8975f5c5SAndroid Build Coastguard Workerdef _GenerateRootGradle(jinja_processor, file_path): 679*8975f5c5SAndroid Build Coastguard Worker """Returns the data for the root project's build.gradle.""" 680*8975f5c5SAndroid Build Coastguard Worker android_gradle_plugin_version = _ParseVersionFromFile( 681*8975f5c5SAndroid Build Coastguard Worker file_path, r'com.android.tools.build:gradle:([\d.]+)', 682*8975f5c5SAndroid Build Coastguard Worker _DEFAULT_ANDROID_GRADLE_PLUGIN_VERSION) 683*8975f5c5SAndroid Build Coastguard Worker kotlin_gradle_plugin_version = _ParseVersionFromFile( 684*8975f5c5SAndroid Build Coastguard Worker file_path, r'org.jetbrains.kotlin:kotlin-gradle-plugin:([\d.]+)', 685*8975f5c5SAndroid Build Coastguard Worker _DEFAULT_KOTLIN_GRADLE_PLUGIN_VERSION) 686*8975f5c5SAndroid Build Coastguard Worker 687*8975f5c5SAndroid Build Coastguard Worker return jinja_processor.Render( 688*8975f5c5SAndroid Build Coastguard Worker _TemplatePath('root'), { 689*8975f5c5SAndroid Build Coastguard Worker 'android_gradle_plugin_version': android_gradle_plugin_version, 690*8975f5c5SAndroid Build Coastguard Worker 'kotlin_gradle_plugin_version': kotlin_gradle_plugin_version, 691*8975f5c5SAndroid Build Coastguard Worker }) 692*8975f5c5SAndroid Build Coastguard Worker 693*8975f5c5SAndroid Build Coastguard Worker 694*8975f5c5SAndroid Build Coastguard Workerdef _GenerateSettingsGradle(project_entries): 695*8975f5c5SAndroid Build Coastguard Worker """Returns the data for settings.gradle.""" 696*8975f5c5SAndroid Build Coastguard Worker project_name = os.path.basename(os.path.dirname(host_paths.DIR_SOURCE_ROOT)) 697*8975f5c5SAndroid Build Coastguard Worker lines = [] 698*8975f5c5SAndroid Build Coastguard Worker lines.append('// Generated by //build/android/gradle/generate_gradle.py') 699*8975f5c5SAndroid Build Coastguard Worker lines.append('rootProject.name = "%s"' % project_name) 700*8975f5c5SAndroid Build Coastguard Worker lines.append('rootProject.projectDir = settingsDir') 701*8975f5c5SAndroid Build Coastguard Worker lines.append('') 702*8975f5c5SAndroid Build Coastguard Worker for name, subdir in project_entries: 703*8975f5c5SAndroid Build Coastguard Worker # Example target: 704*8975f5c5SAndroid Build Coastguard Worker # android_webview:android_webview_java__build_config_crbug_908819 705*8975f5c5SAndroid Build Coastguard Worker lines.append('include ":%s"' % name) 706*8975f5c5SAndroid Build Coastguard Worker lines.append('project(":%s").projectDir = new File(settingsDir, "%s")' % 707*8975f5c5SAndroid Build Coastguard Worker (name, subdir)) 708*8975f5c5SAndroid Build Coastguard Worker return '\n'.join(lines) 709*8975f5c5SAndroid Build Coastguard Worker 710*8975f5c5SAndroid Build Coastguard Worker 711*8975f5c5SAndroid Build Coastguard Workerdef _FindAllProjectEntries(main_entries): 712*8975f5c5SAndroid Build Coastguard Worker """Returns the list of all _ProjectEntry instances given the root project.""" 713*8975f5c5SAndroid Build Coastguard Worker found = set() 714*8975f5c5SAndroid Build Coastguard Worker to_scan = list(main_entries) 715*8975f5c5SAndroid Build Coastguard Worker while to_scan: 716*8975f5c5SAndroid Build Coastguard Worker cur_entry = to_scan.pop() 717*8975f5c5SAndroid Build Coastguard Worker if cur_entry in found: 718*8975f5c5SAndroid Build Coastguard Worker continue 719*8975f5c5SAndroid Build Coastguard Worker found.add(cur_entry) 720*8975f5c5SAndroid Build Coastguard Worker sub_config_paths = cur_entry.DepsInfo()['deps_configs'] 721*8975f5c5SAndroid Build Coastguard Worker to_scan.extend( 722*8975f5c5SAndroid Build Coastguard Worker _ProjectEntry.FromBuildConfigPath(p) for p in sub_config_paths) 723*8975f5c5SAndroid Build Coastguard Worker return list(found) 724*8975f5c5SAndroid Build Coastguard Worker 725*8975f5c5SAndroid Build Coastguard Worker 726*8975f5c5SAndroid Build Coastguard Workerdef _CombineTestEntries(entries): 727*8975f5c5SAndroid Build Coastguard Worker """Combines test apks into the androidTest source set of their target. 728*8975f5c5SAndroid Build Coastguard Worker 729*8975f5c5SAndroid Build Coastguard Worker - Speeds up android studio 730*8975f5c5SAndroid Build Coastguard Worker - Adds proper dependency between test and apk_under_test 731*8975f5c5SAndroid Build Coastguard Worker - Doesn't work for junit yet due to resulting circular dependencies 732*8975f5c5SAndroid Build Coastguard Worker - e.g. base_junit_tests > base_junit_test_support > base_java 733*8975f5c5SAndroid Build Coastguard Worker """ 734*8975f5c5SAndroid Build Coastguard Worker combined_entries = [] 735*8975f5c5SAndroid Build Coastguard Worker android_test_entries = collections.defaultdict(list) 736*8975f5c5SAndroid Build Coastguard Worker for entry in entries: 737*8975f5c5SAndroid Build Coastguard Worker target_name = entry.GnTarget() 738*8975f5c5SAndroid Build Coastguard Worker if (target_name.endswith(_INSTRUMENTATION_TARGET_SUFFIX) 739*8975f5c5SAndroid Build Coastguard Worker and 'apk_under_test' in entry.Gradle()): 740*8975f5c5SAndroid Build Coastguard Worker apk_name = entry.Gradle()['apk_under_test'] 741*8975f5c5SAndroid Build Coastguard Worker android_test_entries[apk_name].append(entry) 742*8975f5c5SAndroid Build Coastguard Worker else: 743*8975f5c5SAndroid Build Coastguard Worker combined_entries.append(entry) 744*8975f5c5SAndroid Build Coastguard Worker for entry in combined_entries: 745*8975f5c5SAndroid Build Coastguard Worker target_name = entry.DepsInfo()['name'] 746*8975f5c5SAndroid Build Coastguard Worker if target_name in android_test_entries: 747*8975f5c5SAndroid Build Coastguard Worker entry.android_test_entries = android_test_entries[target_name] 748*8975f5c5SAndroid Build Coastguard Worker del android_test_entries[target_name] 749*8975f5c5SAndroid Build Coastguard Worker # Add unmatched test entries as individual targets. 750*8975f5c5SAndroid Build Coastguard Worker combined_entries.extend(e for l in android_test_entries.values() for e in l) 751*8975f5c5SAndroid Build Coastguard Worker return combined_entries 752*8975f5c5SAndroid Build Coastguard Worker 753*8975f5c5SAndroid Build Coastguard Worker 754*8975f5c5SAndroid Build Coastguard Workerdef main(): 755*8975f5c5SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 756*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--output-directory', 757*8975f5c5SAndroid Build Coastguard Worker help='Path to the root build directory.') 758*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-v', 759*8975f5c5SAndroid Build Coastguard Worker '--verbose', 760*8975f5c5SAndroid Build Coastguard Worker dest='verbose_count', 761*8975f5c5SAndroid Build Coastguard Worker default=0, 762*8975f5c5SAndroid Build Coastguard Worker action='count', 763*8975f5c5SAndroid Build Coastguard Worker help='Verbose level') 764*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--target', 765*8975f5c5SAndroid Build Coastguard Worker dest='targets', 766*8975f5c5SAndroid Build Coastguard Worker action='append', 767*8975f5c5SAndroid Build Coastguard Worker help='GN target to generate project for. Replaces set of ' 768*8975f5c5SAndroid Build Coastguard Worker 'default targets. May be repeated.') 769*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--extra-target', 770*8975f5c5SAndroid Build Coastguard Worker dest='extra_targets', 771*8975f5c5SAndroid Build Coastguard Worker action='append', 772*8975f5c5SAndroid Build Coastguard Worker help='GN target to generate project for, in addition to ' 773*8975f5c5SAndroid Build Coastguard Worker 'the default ones. May be repeated.') 774*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--project-dir', 775*8975f5c5SAndroid Build Coastguard Worker help='Root of the output project.', 776*8975f5c5SAndroid Build Coastguard Worker default=os.path.join('$CHROMIUM_OUTPUT_DIR', 'gradle')) 777*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--all', 778*8975f5c5SAndroid Build Coastguard Worker action='store_true', 779*8975f5c5SAndroid Build Coastguard Worker help='Include all .java files reachable from any ' 780*8975f5c5SAndroid Build Coastguard Worker 'apk/test/binary target. On by default unless ' 781*8975f5c5SAndroid Build Coastguard Worker '--split-projects is used (--split-projects can ' 782*8975f5c5SAndroid Build Coastguard Worker 'slow down Studio given too many targets).') 783*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--use-gradle-process-resources', 784*8975f5c5SAndroid Build Coastguard Worker action='store_true', 785*8975f5c5SAndroid Build Coastguard Worker help='Have gradle generate R.java rather than ninja') 786*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--split-projects', 787*8975f5c5SAndroid Build Coastguard Worker action='store_true', 788*8975f5c5SAndroid Build Coastguard Worker help='Split projects by their gn deps rather than ' 789*8975f5c5SAndroid Build Coastguard Worker 'combining all the dependencies of each target') 790*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--native-target', 791*8975f5c5SAndroid Build Coastguard Worker dest='native_targets', 792*8975f5c5SAndroid Build Coastguard Worker action='append', 793*8975f5c5SAndroid Build Coastguard Worker help='GN native targets to generate for. May be ' 794*8975f5c5SAndroid Build Coastguard Worker 'repeated.') 795*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 796*8975f5c5SAndroid Build Coastguard Worker '--sdk-path', 797*8975f5c5SAndroid Build Coastguard Worker default=os.path.expanduser('~/Android/Sdk'), 798*8975f5c5SAndroid Build Coastguard Worker help='The path to use as the SDK root, overrides the ' 799*8975f5c5SAndroid Build Coastguard Worker 'default at ~/Android/Sdk.') 800*8975f5c5SAndroid Build Coastguard Worker args = parser.parse_args() 801*8975f5c5SAndroid Build Coastguard Worker if args.output_directory: 802*8975f5c5SAndroid Build Coastguard Worker constants.SetOutputDirectory(args.output_directory) 803*8975f5c5SAndroid Build Coastguard Worker constants.CheckOutputDirectory() 804*8975f5c5SAndroid Build Coastguard Worker output_dir = constants.GetOutDirectory() 805*8975f5c5SAndroid Build Coastguard Worker devil_chromium.Initialize(output_directory=output_dir) 806*8975f5c5SAndroid Build Coastguard Worker run_tests_helper.SetLogLevel(args.verbose_count) 807*8975f5c5SAndroid Build Coastguard Worker 808*8975f5c5SAndroid Build Coastguard Worker if args.use_gradle_process_resources: 809*8975f5c5SAndroid Build Coastguard Worker assert args.split_projects, ( 810*8975f5c5SAndroid Build Coastguard Worker 'Gradle resources does not work without --split-projects.') 811*8975f5c5SAndroid Build Coastguard Worker 812*8975f5c5SAndroid Build Coastguard Worker _gradle_output_dir = os.path.abspath( 813*8975f5c5SAndroid Build Coastguard Worker args.project_dir.replace('$CHROMIUM_OUTPUT_DIR', output_dir)) 814*8975f5c5SAndroid Build Coastguard Worker logging.warning('Creating project at: %s', _gradle_output_dir) 815*8975f5c5SAndroid Build Coastguard Worker 816*8975f5c5SAndroid Build Coastguard Worker # Generate for "all targets" by default when not using --split-projects (too 817*8975f5c5SAndroid Build Coastguard Worker # slow), and when no --target has been explicitly set. "all targets" means all 818*8975f5c5SAndroid Build Coastguard Worker # java targets that are depended on by an apk or java_binary (leaf 819*8975f5c5SAndroid Build Coastguard Worker # java_library targets will not be included). 820*8975f5c5SAndroid Build Coastguard Worker args.all = args.all or (not args.split_projects and not args.targets) 821*8975f5c5SAndroid Build Coastguard Worker 822*8975f5c5SAndroid Build Coastguard Worker targets_from_args = set(args.targets or _DEFAULT_TARGETS) 823*8975f5c5SAndroid Build Coastguard Worker if args.extra_targets: 824*8975f5c5SAndroid Build Coastguard Worker targets_from_args.update(args.extra_targets) 825*8975f5c5SAndroid Build Coastguard Worker 826*8975f5c5SAndroid Build Coastguard Worker if args.all: 827*8975f5c5SAndroid Build Coastguard Worker if args.native_targets: 828*8975f5c5SAndroid Build Coastguard Worker _RunGnGen(output_dir, ['--ide=json']) 829*8975f5c5SAndroid Build Coastguard Worker elif not os.path.exists(os.path.join(output_dir, 'build.ninja')): 830*8975f5c5SAndroid Build Coastguard Worker _RunGnGen(output_dir) 831*8975f5c5SAndroid Build Coastguard Worker else: 832*8975f5c5SAndroid Build Coastguard Worker # Faster than running "gn gen" in the no-op case. 833*8975f5c5SAndroid Build Coastguard Worker _BuildTargets(output_dir, ['build.ninja']) 834*8975f5c5SAndroid Build Coastguard Worker # Query ninja for all __build_config_crbug_908819 targets. 835*8975f5c5SAndroid Build Coastguard Worker targets = _QueryForAllGnTargets(output_dir) 836*8975f5c5SAndroid Build Coastguard Worker else: 837*8975f5c5SAndroid Build Coastguard Worker assert not args.native_targets, 'Native editing requires --all.' 838*8975f5c5SAndroid Build Coastguard Worker targets = [ 839*8975f5c5SAndroid Build Coastguard Worker re.sub(r'_test_apk$', _INSTRUMENTATION_TARGET_SUFFIX, t) 840*8975f5c5SAndroid Build Coastguard Worker for t in targets_from_args 841*8975f5c5SAndroid Build Coastguard Worker ] 842*8975f5c5SAndroid Build Coastguard Worker # Necessary after "gn clean" 843*8975f5c5SAndroid Build Coastguard Worker if not os.path.exists( 844*8975f5c5SAndroid Build Coastguard Worker os.path.join(output_dir, gn_helpers.BUILD_VARS_FILENAME)): 845*8975f5c5SAndroid Build Coastguard Worker _RunGnGen(output_dir) 846*8975f5c5SAndroid Build Coastguard Worker 847*8975f5c5SAndroid Build Coastguard Worker main_entries = [_ProjectEntry.FromGnTarget(t) for t in targets] 848*8975f5c5SAndroid Build Coastguard Worker if not args.all: 849*8975f5c5SAndroid Build Coastguard Worker # list_java_targets.py takes care of building .build_config.json in the 850*8975f5c5SAndroid Build Coastguard Worker # --all case. 851*8975f5c5SAndroid Build Coastguard Worker _BuildTargets(output_dir, [t.BuildConfigPath() for t in main_entries]) 852*8975f5c5SAndroid Build Coastguard Worker 853*8975f5c5SAndroid Build Coastguard Worker build_vars = gn_helpers.ReadBuildVars(output_dir) 854*8975f5c5SAndroid Build Coastguard Worker jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) 855*8975f5c5SAndroid Build Coastguard Worker generator = _ProjectContextGenerator(_gradle_output_dir, build_vars, 856*8975f5c5SAndroid Build Coastguard Worker args.use_gradle_process_resources, 857*8975f5c5SAndroid Build Coastguard Worker jinja_processor, args.split_projects) 858*8975f5c5SAndroid Build Coastguard Worker 859*8975f5c5SAndroid Build Coastguard Worker if args.all: 860*8975f5c5SAndroid Build Coastguard Worker # There are many unused libraries, so restrict to those that are actually 861*8975f5c5SAndroid Build Coastguard Worker # used by apks/bundles/binaries/tests or that are explicitly mentioned in 862*8975f5c5SAndroid Build Coastguard Worker # --targets. 863*8975f5c5SAndroid Build Coastguard Worker BASE_TYPES = ('android_apk', 'android_app_bundle_module', 'java_binary', 864*8975f5c5SAndroid Build Coastguard Worker 'robolectric_binary') 865*8975f5c5SAndroid Build Coastguard Worker main_entries = [ 866*8975f5c5SAndroid Build Coastguard Worker e for e in main_entries 867*8975f5c5SAndroid Build Coastguard Worker if (e.GetType() in BASE_TYPES or e.GnTarget() in targets_from_args 868*8975f5c5SAndroid Build Coastguard Worker or e.GnTarget().endswith(_INSTRUMENTATION_TARGET_SUFFIX)) 869*8975f5c5SAndroid Build Coastguard Worker ] 870*8975f5c5SAndroid Build Coastguard Worker 871*8975f5c5SAndroid Build Coastguard Worker if args.split_projects: 872*8975f5c5SAndroid Build Coastguard Worker main_entries = _FindAllProjectEntries(main_entries) 873*8975f5c5SAndroid Build Coastguard Worker 874*8975f5c5SAndroid Build Coastguard Worker logging.info('Generating for %d targets.', len(main_entries)) 875*8975f5c5SAndroid Build Coastguard Worker 876*8975f5c5SAndroid Build Coastguard Worker entries = [e for e in _CombineTestEntries(main_entries) if e.IsValid()] 877*8975f5c5SAndroid Build Coastguard Worker logging.info('Creating %d projects for targets.', len(entries)) 878*8975f5c5SAndroid Build Coastguard Worker 879*8975f5c5SAndroid Build Coastguard Worker logging.warning('Writing .gradle files...') 880*8975f5c5SAndroid Build Coastguard Worker project_entries = [] 881*8975f5c5SAndroid Build Coastguard Worker # When only one entry will be generated we want it to have a valid 882*8975f5c5SAndroid Build Coastguard Worker # build.gradle file with its own AndroidManifest. 883*8975f5c5SAndroid Build Coastguard Worker for entry in entries: 884*8975f5c5SAndroid Build Coastguard Worker data = _GenerateGradleFile(entry, generator, build_vars, jinja_processor) 885*8975f5c5SAndroid Build Coastguard Worker if data and not args.all: 886*8975f5c5SAndroid Build Coastguard Worker project_entries.append((entry.ProjectName(), entry.GradleSubdir())) 887*8975f5c5SAndroid Build Coastguard Worker _WriteFile( 888*8975f5c5SAndroid Build Coastguard Worker os.path.join(generator.EntryOutputDir(entry), _GRADLE_BUILD_FILE), 889*8975f5c5SAndroid Build Coastguard Worker data) 890*8975f5c5SAndroid Build Coastguard Worker if args.all: 891*8975f5c5SAndroid Build Coastguard Worker project_entries.append((_MODULE_ALL, _MODULE_ALL)) 892*8975f5c5SAndroid Build Coastguard Worker _GenerateModuleAll(_gradle_output_dir, generator, build_vars, 893*8975f5c5SAndroid Build Coastguard Worker jinja_processor, args.native_targets) 894*8975f5c5SAndroid Build Coastguard Worker 895*8975f5c5SAndroid Build Coastguard Worker root_gradle_path = os.path.join(generator.project_dir, _GRADLE_BUILD_FILE) 896*8975f5c5SAndroid Build Coastguard Worker _WriteFile(root_gradle_path, 897*8975f5c5SAndroid Build Coastguard Worker _GenerateRootGradle(jinja_processor, root_gradle_path)) 898*8975f5c5SAndroid Build Coastguard Worker 899*8975f5c5SAndroid Build Coastguard Worker _WriteFile(os.path.join(generator.project_dir, 'settings.gradle'), 900*8975f5c5SAndroid Build Coastguard Worker _GenerateSettingsGradle(project_entries)) 901*8975f5c5SAndroid Build Coastguard Worker 902*8975f5c5SAndroid Build Coastguard Worker # Ensure the Android Studio sdk is correctly initialized. 903*8975f5c5SAndroid Build Coastguard Worker if not os.path.exists(args.sdk_path): 904*8975f5c5SAndroid Build Coastguard Worker # Help first-time users avoid Android Studio forcibly changing back to 905*8975f5c5SAndroid Build Coastguard Worker # the previous default due to not finding a valid sdk under this dir. 906*8975f5c5SAndroid Build Coastguard Worker shutil.copytree(_RebasePath(build_vars['android_sdk_root']), args.sdk_path) 907*8975f5c5SAndroid Build Coastguard Worker _WriteFile( 908*8975f5c5SAndroid Build Coastguard Worker os.path.join(generator.project_dir, 'local.properties'), 909*8975f5c5SAndroid Build Coastguard Worker _GenerateLocalProperties(args.sdk_path)) 910*8975f5c5SAndroid Build Coastguard Worker _WriteFile(os.path.join(generator.project_dir, 'gradle.properties'), 911*8975f5c5SAndroid Build Coastguard Worker _GenerateGradleProperties()) 912*8975f5c5SAndroid Build Coastguard Worker 913*8975f5c5SAndroid Build Coastguard Worker wrapper_properties = os.path.join(generator.project_dir, 'gradle', 'wrapper', 914*8975f5c5SAndroid Build Coastguard Worker 'gradle-wrapper.properties') 915*8975f5c5SAndroid Build Coastguard Worker _WriteFile(wrapper_properties, 916*8975f5c5SAndroid Build Coastguard Worker _GenerateGradleWrapperProperties(wrapper_properties)) 917*8975f5c5SAndroid Build Coastguard Worker 918*8975f5c5SAndroid Build Coastguard Worker generated_inputs = set() 919*8975f5c5SAndroid Build Coastguard Worker for entry in entries: 920*8975f5c5SAndroid Build Coastguard Worker entries_to_gen = [entry] 921*8975f5c5SAndroid Build Coastguard Worker entries_to_gen.extend(entry.android_test_entries) 922*8975f5c5SAndroid Build Coastguard Worker for entry_to_gen in entries_to_gen: 923*8975f5c5SAndroid Build Coastguard Worker # Build all paths references by .gradle that exist within output_dir. 924*8975f5c5SAndroid Build Coastguard Worker generated_inputs.update(generator.GeneratedInputs(entry_to_gen)) 925*8975f5c5SAndroid Build Coastguard Worker if generated_inputs: 926*8975f5c5SAndroid Build Coastguard Worker # Skip targets outside the output_dir since those are not generated. 927*8975f5c5SAndroid Build Coastguard Worker targets = [ 928*8975f5c5SAndroid Build Coastguard Worker p for p in _RebasePath(generated_inputs, output_dir) 929*8975f5c5SAndroid Build Coastguard Worker if not p.startswith(os.pardir) 930*8975f5c5SAndroid Build Coastguard Worker ] 931*8975f5c5SAndroid Build Coastguard Worker _BuildTargets(output_dir, targets) 932*8975f5c5SAndroid Build Coastguard Worker 933*8975f5c5SAndroid Build Coastguard Worker print('Generated projects for Android Studio.') 934*8975f5c5SAndroid Build Coastguard Worker print('** Building using Android Studio / Gradle does not work.') 935*8975f5c5SAndroid Build Coastguard Worker print('** This project is only for IDE editing & tools.') 936*8975f5c5SAndroid Build Coastguard Worker print('Note: Generated files will appear only if they have been built') 937*8975f5c5SAndroid Build Coastguard Worker print('For more tips: https://chromium.googlesource.com/chromium/src.git/' 938*8975f5c5SAndroid Build Coastguard Worker '+/main/docs/android_studio.md') 939*8975f5c5SAndroid Build Coastguard Worker 940*8975f5c5SAndroid Build Coastguard Worker 941*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 942*8975f5c5SAndroid Build Coastguard Worker main() 943