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