def RecordInstallMetadata(device, apk_package, metadata_path): """Records the metadata from the device for apk_package.""" metadata = device.GetInstallMetadata(apk_package, refresh=True) if not metadata: raise Exception('APK install failed unexpectedly.') build_utils.WriteJson(metadata, metadata_path)
def main(): parser = optparse.OptionParser() parser.add_option('--input-libraries', help='A list of top-level input libraries.') parser.add_option('--libraries-dir', help='The directory which contains shared libraries.') parser.add_option('--readelf', help='Path to the readelf binary.') parser.add_option('--output', help='Path to the generated .json file.') parser.add_option('--stamp', help='Path to touch on success.') options, _ = parser.parse_args() SetReadelfPath(options.readelf) SetLibraryDirs(options.libraries_dir.split(',')) libraries = build_utils.ParseGypList(options.input_libraries) if len(libraries): libraries = GetSortedTransitiveDependenciesForBinaries(libraries) # Convert to "base" library names: e.g. libfoo.so -> foo java_libraries_list = ('{%s}' % ','.join(['"%s"' % s[3:-3] for s in libraries])) build_utils.WriteJson( { 'libraries': libraries, 'java_libraries_list': java_libraries_list }, options.output, only_if_changed=True) if options.stamp: build_utils.Touch(options.stamp)
def CheckOutput(self): self.build() # Proguard will skip writing these files if they would be empty. Create # empty versions of them all now so that they are updated as the build # expects. open(self._outjar + '.dump', 'w').close() open(self._outjar + '.seeds', 'w').close() open(self._outjar + '.usage', 'w').close() open(self._outjar + '.mapping', 'w').close() # Warning: and Error: are sent to stderr, but messages and Note: are sent # to stdout. stdout_filter = None stderr_filter = None if not self._verbose: stdout_filter = _ProguardOutputFilter() stderr_filter = _ProguardOutputFilter() build_utils.CheckOutput(self._cmd, print_stdout=True, print_stderr=True, stdout_filter=stdout_filter, stderr_filter=stderr_filter) this_info = { 'inputs': self._injars, 'configs': self._configs, 'mapping': self._outjar + '.mapping', } build_utils.WriteJson(this_info, self._outjar + '.info')
def DoDex(options, paths, dex_args=None): dx_binary = os.path.join(options.android_sdk_tools, 'dx') # See http://crbug.com/272064 for context on --force-jumbo. # See https://github.com/android/platform_dalvik/commit/dd140a22d for # --num-threads. dex_cmd = [dx_binary, '--num-threads=8', '--dex', '--force-jumbo', '--output', options.dex_path] if options.no_locals != '0': dex_cmd.append('--no-locals') if dex_args: dex_cmd += dex_args dex_cmd += paths record_path = '%s.md5.stamp' % options.dex_path md5_check.CallAndRecordIfStale( lambda: build_utils.CheckOutput(dex_cmd, print_stderr=False), record_path=record_path, input_paths=paths, input_strings=dex_cmd, force=not os.path.exists(options.dex_path)) build_utils.WriteJson( [os.path.relpath(p, options.output_directory) for p in paths], options.dex_path + '.inputs')
def main(argv): parser = optparse.OptionParser() parser.add_option('--input-libraries', help='A list of top-level input libraries.') parser.add_option('--libraries-dir', help='The directory which contains shared libraries.') parser.add_option('--readelf', help='Path to the readelf binary.') parser.add_option('--output', help='Path to the generated .json file.') parser.add_option('--stamp', help='Path to touch on success.') global _options _options, _ = parser.parse_args() libraries = build_utils.ParseGypList(_options.input_libraries) if libraries[0].endswith('.so'): libraries = [os.path.basename(lib) for lib in libraries] libraries = GetSortedTransitiveDependencies(libraries) else: libraries = GetSortedTransitiveDependenciesForExecutable(libraries[0]) build_utils.WriteJson(libraries, _options.output, only_if_changed=True) if _options.stamp: build_utils.Touch(_options.stamp)
def main(): parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option('--readelf', help='Path to the readelf binary.') parser.add_option('--runtime-deps', help='A file created for the target using write_runtime_deps.') parser.add_option('--exclude-shared-libraries', help='List of shared libraries to exclude from the output.') parser.add_option('--output', help='Path to the generated .json file.') parser.add_option('--stamp', help='Path to touch on success.') options, _ = parser.parse_args(build_utils.ExpandFileArgs(sys.argv[1:])) SetReadelfPath(options.readelf) unsorted_lib_paths = [] exclude_shared_libraries = [] if options.exclude_shared_libraries: exclude_shared_libraries = options.exclude_shared_libraries.split(',') for f in open(options.runtime_deps): f = f[:-1] if f.endswith('.so'): p = f.replace('lib.unstripped/', '') if os.path.basename(p) in exclude_shared_libraries: continue unsorted_lib_paths.append(p) _library_path_map[os.path.basename(p)] = p lib_paths = GetSortedTransitiveDependencies(unsorted_lib_paths) libraries = [os.path.basename(l) for l in lib_paths] # Convert to "base" library names: e.g. libfoo.so -> foo java_libraries_list = ( '{%s}' % ','.join(['"%s"' % s[3:-3] for s in libraries])) out_json = { 'libraries': libraries, 'lib_paths': lib_paths, 'java_libraries_list': java_libraries_list } build_utils.WriteJson( out_json, options.output, only_if_changed=True) if options.stamp: build_utils.Touch(options.stamp) if options.depfile: build_utils.WriteDepfile(options.depfile, options.output, libraries)
def DoDex(options, paths): d8_binary = os.path.join(options.android_sdk_tools, 'd8') dex_cmd = [d8_binary, '--output', options.dex_path] dex_cmd += paths record_path = '%s.md5.stamp' % options.dex_path md5_check.CallAndRecordIfStale( lambda: build_utils.CheckOutput(dex_cmd, print_stderr=False), record_path=record_path, input_paths=paths, input_strings=dex_cmd, force=not os.path.exists(options.dex_path)) build_utils.WriteJson( [os.path.relpath(p, options.output_directory) for p in paths], options.dex_path + '.inputs')
def DoDex(options, paths): dx_binary = os.path.join(options.android_sdk_tools, 'dx') # See http://crbug.com/272064 for context on --force-jumbo. dex_cmd = [dx_binary, '--dex', '--force-jumbo', '--output', options.dex_path] if options.no_locals != '0': dex_cmd.append('--no-locals') dex_cmd += paths record_path = '%s.md5.stamp' % options.dex_path md5_check.CallAndRecordIfStale( lambda: build_utils.CheckOutput(dex_cmd, print_stderr=False), record_path=record_path, input_paths=paths, input_strings=dex_cmd, force=not os.path.exists(options.dex_path)) build_utils.WriteJson(paths, options.dex_path + '.inputs')
def on_stale_md5_callback(): if is_jar and _NoClassFiles(paths): # Handle case where no classfiles are specified in inputs # by creating an empty JAR with zipfile.ZipFile(options.dex_path, 'w') as outfile: outfile.comment = 'empty' elif is_dex: # .dex files can't specify a name for D8. Instead, we output them to a # temp directory then move them after the command has finished running # (see _MoveTempDexFile). For other files, tmp_dex_dir is None. with build_utils.TempDir() as tmp_dex_dir: _RunD8(dex_cmd, paths, tmp_dex_dir) _MoveTempDexFile(tmp_dex_dir, options.dex_path) else: _RunD8(dex_cmd, paths, options.dex_path) build_utils.WriteJson( [os.path.relpath(p, options.output_directory) for p in paths], options.dex_path + '.inputs')
def CheckOutput(self): self.build() # There are a couple scenarios (.mapping files and switching from no # proguard -> proguard) where GN's copy() target is used on output # paths. These create hardlinks, so we explicitly unlink here to avoid # updating files with multiple links. for path in self.GetOutputs(): if os.path.exists(path): os.unlink(path) with open(self._outjar + '.flags', 'w') as out: self._WriteFlagsFile(out) # Warning: and Error: are sent to stderr, but messages and Note: are sent # to stdout. stdout_filter = None stderr_filter = None if not self._verbose: stdout_filter = _ProguardOutputFilter() stderr_filter = _ProguardOutputFilter() start_time = time.time() build_utils.CheckOutput(self._cmd, print_stdout=True, print_stderr=True, stdout_filter=stdout_filter, stderr_filter=stderr_filter) # Proguard will skip writing -printseeds / -printusage / -printmapping if # the files would be empty, but ninja needs all outputs to exist. open(self._outjar + '.seeds', 'a').close() open(self._outjar + '.usage', 'a').close() open(self._outjar + '.mapping', 'a').close() this_info = { 'inputs': self._injars, 'configs': self._configs, 'mapping': self._outjar + '.mapping', 'elapsed_time': round(time.time() - start_time), } build_utils.WriteJson(this_info, self._outjar + '.info')
def CheckOutput(self): self.build() # Proguard will skip writing these files if they would be empty. Create # empty versions of them all now so that they are updated as the build # expects. open(self._outjar + '.dump', 'w').close() open(self._outjar + '.seeds', 'w').close() open(self._outjar + '.usage', 'w').close() open(self._outjar + '.mapping', 'w').close() build_utils.CheckOutput(self._cmd, print_stdout=True, stdout_filter=FilterProguardOutput) this_info = { 'inputs': self._injars, 'configs': self._configs, 'mapping': self._outjar + '.mapping', } build_utils.WriteJson(this_info, self._outjar + '.info')
def DoProguard(options): proguard = proguard_util.ProguardCmdBuilder(options.proguard_jar_path) proguard.outjar(options.obfuscated_jar_path) library_classpath = [options.android_sdk_jar] input_jars = build_utils.ParseGypList(options.input_jars_paths) exclude_paths = [] configs = build_utils.ParseGypList(options.proguard_configs) if options.tested_apk_obfuscated_jar_path: # configs should only contain the process_resources.py generated config. assert len(configs) == 1, ( 'test apks should not have custom proguard configs: ' + str(configs)) tested_jar_info = build_utils.ReadJson( options.tested_apk_obfuscated_jar_path + '.info') exclude_paths = tested_jar_info['inputs'] configs = tested_jar_info['configs'] proguard.is_test(True) proguard.mapping(options.tested_apk_obfuscated_jar_path + '.mapping') library_classpath.append(options.tested_apk_obfuscated_jar_path) proguard.libraryjars(library_classpath) proguard_injars = [p for p in input_jars if p not in exclude_paths] proguard.injars(proguard_injars) proguard.configs(configs) proguard.CheckOutput() this_info = { 'inputs': proguard_injars, 'configs': configs } build_utils.WriteJson( this_info, options.obfuscated_jar_path + '.info')
def main(argv): parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option('--build-config', help='Path to build_config output.') parser.add_option('--type', help='Type of this target (e.g. android_library).') parser.add_option( '--possible-deps-configs', help='List of paths for dependency\'s build_config files. Some ' 'dependencies may not write build_config files. Missing build_config ' 'files are handled differently based on the type of this target.') # android_resources options parser.add_option('--srcjar', help='Path to target\'s resources srcjar.') parser.add_option('--resources-zip', help='Path to target\'s resources zip.') parser.add_option('--r-text', help='Path to target\'s R.txt file.') parser.add_option('--package-name', help='Java package name for these resources.') parser.add_option('--android-manifest', help='Path to android manifest.') # android_assets options parser.add_option('--asset-sources', help='List of asset sources.') parser.add_option('--asset-renaming-sources', help='List of asset sources with custom destinations.') parser.add_option('--asset-renaming-destinations', help='List of asset custom destinations.') parser.add_option('--disable-asset-compression', action='store_true', help='Whether to disable asset compression.') # java library options parser.add_option('--jar-path', help='Path to target\'s jar output.') parser.add_option( '--supports-android', action='store_true', help='Whether this library supports running on the Android platform.') parser.add_option( '--requires-android', action='store_true', help='Whether this library requires running on the Android platform.') parser.add_option( '--bypass-platform-checks', action='store_true', help='Bypass checks for support/require Android platform.') # android library options parser.add_option('--dex-path', help='Path to target\'s dex output.') # native library options parser.add_option('--native-libs', help='List of top-level native libs.') parser.add_option('--readelf-path', help='Path to toolchain\'s readelf.') # apk options parser.add_option('--apk-path', help='Path to the target\'s apk output.') parser.add_option( '--tested-apk-config', help= 'Path to the build config of the tested apk (for an instrumentation ' 'test apk).') parser.add_option('--proguard-enabled', action='store_true', help='Whether proguard is enabled for this apk.') parser.add_option('--proguard-info', help='Path to the proguard .info output for this apk.') options, args = parser.parse_args(argv) if args: parser.error('No positional arguments should be given.') required_options_map = { 'java_binary': ['build_config', 'jar_path'], 'java_library': ['build_config', 'jar_path'], 'android_assets': ['build_config'], 'android_resources': ['build_config', 'resources_zip'], 'android_apk': ['build_config', 'jar_path', 'dex_path', 'resources_zip'], 'deps_dex': ['build_config', 'dex_path'], 'resource_rewriter': ['build_config'] } required_options = required_options_map.get(options.type) if not required_options: raise Exception('Unknown type: <%s>' % options.type) if options.native_libs: required_options.append('readelf_path') build_utils.CheckOptions(options, parser, required_options) if options.type == 'java_library': if options.supports_android and not options.dex_path: raise Exception( 'java_library that supports Android requires a dex path.') if options.requires_android and not options.supports_android: raise Exception( '--supports-android is required when using --requires-android') possible_deps_config_paths = build_utils.ParseGypList( options.possible_deps_configs) allow_unknown_deps = (options.type in ('android_apk', 'android_assets', 'android_resources')) unknown_deps = [ c for c in possible_deps_config_paths if not os.path.exists(c) ] if unknown_deps and not allow_unknown_deps: raise Exception('Unknown deps: ' + str(unknown_deps)) direct_deps_config_paths = [ c for c in possible_deps_config_paths if not c in unknown_deps ] direct_deps_config_paths = _FilterUnwantedDepsPaths( direct_deps_config_paths, options.type) deps = Deps(direct_deps_config_paths) direct_library_deps = deps.Direct('java_library') all_library_deps = deps.All('java_library') direct_resources_deps = deps.Direct('android_resources') all_resources_deps = deps.All('android_resources') # Resources should be ordered with the highest-level dependency first so that # overrides are done correctly. all_resources_deps.reverse() if options.type == 'android_apk' and options.tested_apk_config: tested_apk_deps = Deps([options.tested_apk_config]) tested_apk_resources_deps = tested_apk_deps.All('android_resources') all_resources_deps = [ d for d in all_resources_deps if not d in tested_apk_resources_deps ] # Initialize some common config. config = { 'deps_info': { 'name': os.path.basename(options.build_config), 'path': options.build_config, 'type': options.type, 'deps_configs': direct_deps_config_paths } } deps_info = config['deps_info'] if (options.type in ('java_binary', 'java_library') and not options.bypass_platform_checks): deps_info['requires_android'] = options.requires_android deps_info['supports_android'] = options.supports_android deps_require_android = ( all_resources_deps + [d['name'] for d in all_library_deps if d['requires_android']]) deps_not_support_android = ([ d['name'] for d in all_library_deps if not d['supports_android'] ]) if deps_require_android and not options.requires_android: raise Exception( 'Some deps require building for the Android platform: ' + str(deps_require_android)) if deps_not_support_android and options.supports_android: raise Exception('Not all deps support the Android platform: ' + str(deps_not_support_android)) if options.type in ('java_binary', 'java_library', 'android_apk'): javac_classpath = [c['jar_path'] for c in direct_library_deps] java_full_classpath = [c['jar_path'] for c in all_library_deps] deps_info['resources_deps'] = [c['path'] for c in all_resources_deps] deps_info['jar_path'] = options.jar_path if options.type == 'android_apk' or options.supports_android: deps_info['dex_path'] = options.dex_path if options.type == 'android_apk': deps_info['apk_path'] = options.apk_path config['javac'] = { 'classpath': javac_classpath, } config['java'] = {'full_classpath': java_full_classpath} if options.type in ('java_binary', 'java_library'): # Only resources might have srcjars (normal srcjar targets are listed in # srcjar_deps). A resource's srcjar contains the R.java file for those # resources, and (like Android's default build system) we allow a library to # refer to the resources in any of its dependents. config['javac']['srcjars'] = [ c['srcjar'] for c in direct_resources_deps if 'srcjar' in c ] if options.type == 'android_apk': # Apks will get their resources srcjar explicitly passed to the java step. config['javac']['srcjars'] = [] if options.type == 'android_assets': all_asset_sources = [] if options.asset_renaming_sources: all_asset_sources.extend( build_utils.ParseGypList(options.asset_renaming_sources)) if options.asset_sources: all_asset_sources.extend( build_utils.ParseGypList(options.asset_sources)) deps_info['assets'] = {'sources': all_asset_sources} if options.asset_renaming_destinations: deps_info['assets']['outputs'] = (build_utils.ParseGypList( options.asset_renaming_destinations)) if options.disable_asset_compression: deps_info['assets']['disable_compression'] = True if options.type == 'android_resources': deps_info['resources_zip'] = options.resources_zip if options.srcjar: deps_info['srcjar'] = options.srcjar if options.android_manifest: manifest = AndroidManifest(options.android_manifest) deps_info['package_name'] = manifest.GetPackageName() if options.package_name: deps_info['package_name'] = options.package_name if options.r_text: deps_info['r_text'] = options.r_text if options.type in ('android_resources', 'android_apk', 'resource_rewriter'): config['resources'] = {} config['resources']['dependency_zips'] = [ c['resources_zip'] for c in all_resources_deps ] config['resources']['extra_package_names'] = [] config['resources']['extra_r_text_files'] = [] if options.type == 'android_apk' or options.type == 'resource_rewriter': config['resources']['extra_package_names'] = [ c['package_name'] for c in all_resources_deps if 'package_name' in c ] config['resources']['extra_r_text_files'] = [ c['r_text'] for c in all_resources_deps if 'r_text' in c ] if options.type in ['android_apk', 'deps_dex']: deps_dex_files = [c['dex_path'] for c in all_library_deps] proguard_enabled = options.proguard_enabled if options.type == 'android_apk': deps_info['proguard_enabled'] = proguard_enabled if proguard_enabled: deps_info['proguard_info'] = options.proguard_info config['proguard'] = {} proguard_config = config['proguard'] proguard_config['input_paths'] = [options.jar_path ] + java_full_classpath proguard_config['tested_apk_info'] = '' # An instrumentation test apk should exclude the dex files that are in the apk # under test. if options.type == 'android_apk' and options.tested_apk_config: tested_apk_deps = Deps([options.tested_apk_config]) tested_apk_library_deps = tested_apk_deps.All('java_library') tested_apk_deps_dex_files = [ c['dex_path'] for c in tested_apk_library_deps ] deps_dex_files = [ p for p in deps_dex_files if not p in tested_apk_deps_dex_files ] tested_apk_config = GetDepConfig(options.tested_apk_config) expected_tested_package = tested_apk_config['package_name'] AndroidManifest(options.android_manifest).CheckInstrumentation( expected_tested_package) if tested_apk_config['proguard_enabled']: assert proguard_enabled, ( 'proguard must be enabled for instrumentation' ' apks if it\'s enabled for the tested apk') proguard_config['tested_apk_info'] = tested_apk_config[ 'proguard_info'] deps_info['tested_apk_path'] = tested_apk_config['apk_path'] # Dependencies for the final dex file of an apk or a 'deps_dex'. if options.type in ['android_apk', 'deps_dex']: config['final_dex'] = {} dex_config = config['final_dex'] dex_config['dependency_dex_files'] = deps_dex_files if options.type == 'android_apk': config['dist_jar'] = { 'dependency_jars': [c['jar_path'] for c in all_library_deps] } manifest = AndroidManifest(options.android_manifest) deps_info['package_name'] = manifest.GetPackageName() if not options.tested_apk_config and manifest.GetInstrumentation(): # This must then have instrumentation only for itself. manifest.CheckInstrumentation(manifest.GetPackageName()) library_paths = [] java_libraries_list_holder = [None] libraries = build_utils.ParseGypList(options.native_libs or '[]') if libraries: def recompute_ordered_libraries(): libraries_dir = os.path.dirname(libraries[0]) write_ordered_libraries.SetReadelfPath(options.readelf_path) write_ordered_libraries.SetLibraryDirs([libraries_dir]) all_deps = ( write_ordered_libraries. GetSortedTransitiveDependenciesForBinaries(libraries)) # Create a java literal array with the "base" library names: # e.g. libfoo.so -> foo java_libraries_list_holder[0] = ( '{%s}' % ','.join(['"%s"' % s[3:-3] for s in all_deps])) library_paths.extend( write_ordered_libraries.FullLibraryPath(x) for x in all_deps) # This step takes about 600ms on a z620 for chrome_apk, so it's worth # caching. md5_check.CallAndRecordIfStale(recompute_ordered_libraries, record_path=options.build_config + '.nativelibs.md5.stamp', input_paths=libraries, output_paths=[options.build_config]) if not library_paths: prev_config = build_utils.ReadJson(options.build_config) java_libraries_list_holder[0] = ( prev_config['native']['java_libraries_list']) library_paths.extend(prev_config['native']['libraries']) config['native'] = { 'libraries': library_paths, 'java_libraries_list': java_libraries_list_holder[0], } config['assets'], config['uncompressed_assets'] = (_MergeAssets( deps.All('android_assets'))) build_utils.WriteJson(config, options.build_config, only_if_changed=True) if options.depfile: build_utils.WriteDepfile( options.depfile, deps.AllConfigPaths() + build_utils.GetPythonDependencies())
def main(argv): parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option('--build-config', help='Path to build_config output.') parser.add_option('--type', help='Type of this target (e.g. android_library).') parser.add_option( '--deps-configs', help='List of paths for dependency\'s build_config files. ') # android_resources options parser.add_option('--srcjar', help='Path to target\'s resources srcjar.') parser.add_option('--resources-zip', help='Path to target\'s resources zip.') parser.add_option('--r-text', help='Path to target\'s R.txt file.') parser.add_option('--package-name', help='Java package name for these resources.') parser.add_option('--android-manifest', help='Path to android manifest.') parser.add_option('--is-locale-resource', action='store_true', help='Whether it is locale resource.') parser.add_option('--resource-dirs', action='append', default=[], help='GYP-list of resource dirs') # android_assets options parser.add_option('--asset-sources', help='List of asset sources.') parser.add_option('--asset-renaming-sources', help='List of asset sources with custom destinations.') parser.add_option('--asset-renaming-destinations', help='List of asset custom destinations.') parser.add_option('--disable-asset-compression', action='store_true', help='Whether to disable asset compression.') # java library options parser.add_option('--jar-path', help='Path to target\'s jar output.') parser.add_option( '--supports-android', action='store_true', help='Whether this library supports running on the Android platform.') parser.add_option( '--requires-android', action='store_true', help='Whether this library requires running on the Android platform.') parser.add_option( '--bypass-platform-checks', action='store_true', help='Bypass checks for support/require Android platform.') # android library options parser.add_option('--dex-path', help='Path to target\'s dex output.') # native library options parser.add_option('--shared-libraries-runtime-deps', help='Path to file containing runtime deps for shared ' 'libraries.') # apk options parser.add_option('--apk-path', help='Path to the target\'s apk output.') parser.add_option('--incremental-apk-path', help="Path to the target's incremental apk output.") parser.add_option( '--incremental-install-script-path', help="Path to the target's generated incremental install " "script.") parser.add_option( '--tested-apk-config', help= 'Path to the build config of the tested apk (for an instrumentation ' 'test apk).') parser.add_option('--proguard-enabled', action='store_true', help='Whether proguard is enabled for this apk.') parser.add_option('--proguard-info', help='Path to the proguard .info output for this apk.') parser.add_option( '--has-alternative-locale-resource', action='store_true', help='Whether there is alternative-locale-resource in direct deps') options, args = parser.parse_args(argv) if args: parser.error('No positional arguments should be given.') required_options_map = { 'java_binary': ['build_config', 'jar_path'], 'java_library': ['build_config', 'jar_path'], 'android_assets': ['build_config'], 'android_resources': ['build_config', 'resources_zip'], 'android_apk': ['build_config', 'jar_path', 'dex_path', 'resources_zip'], 'deps_dex': ['build_config', 'dex_path'], 'resource_rewriter': ['build_config'], 'group': ['build_config'], } required_options = required_options_map.get(options.type) if not required_options: raise Exception('Unknown type: <%s>' % options.type) build_utils.CheckOptions(options, parser, required_options) if options.type == 'java_library': if options.supports_android and not options.dex_path: raise Exception( 'java_library that supports Android requires a dex path.') if options.requires_android and not options.supports_android: raise Exception( '--supports-android is required when using --requires-android') direct_deps_config_paths = build_utils.ParseGypList(options.deps_configs) direct_deps_config_paths = _FilterUnwantedDepsPaths( direct_deps_config_paths, options.type) deps = Deps(direct_deps_config_paths) all_inputs = deps.AllConfigPaths() + build_utils.GetPythonDependencies() # Remove other locale resources if there is alternative_locale_resource in # direct deps. if options.has_alternative_locale_resource: alternative = [ r['path'] for r in deps.Direct('android_resources') if r.get('is_locale_resource') ] # We can only have one locale resources in direct deps. if len(alternative) != 1: raise Exception( 'The number of locale resource in direct deps is wrong %d' % len(alternative)) unwanted = [ r['path'] for r in deps.All('android_resources') if r.get('is_locale_resource') and r['path'] not in alternative ] for p in unwanted: deps.RemoveNonDirectDep(p) direct_library_deps = deps.Direct('java_library') all_library_deps = deps.All('java_library') direct_resources_deps = deps.Direct('android_resources') all_resources_deps = deps.All('android_resources') # Resources should be ordered with the highest-level dependency first so that # overrides are done correctly. all_resources_deps.reverse() if options.type == 'android_apk' and options.tested_apk_config: tested_apk_deps = Deps([options.tested_apk_config]) tested_apk_resources_deps = tested_apk_deps.All('android_resources') all_resources_deps = [ d for d in all_resources_deps if not d in tested_apk_resources_deps ] # Initialize some common config. config = { 'deps_info': { 'name': os.path.basename(options.build_config), 'path': options.build_config, 'type': options.type, 'deps_configs': direct_deps_config_paths } } deps_info = config['deps_info'] if (options.type in ('java_binary', 'java_library') and not options.bypass_platform_checks): deps_info['requires_android'] = options.requires_android deps_info['supports_android'] = options.supports_android deps_require_android = ( all_resources_deps + [d['name'] for d in all_library_deps if d['requires_android']]) deps_not_support_android = ([ d['name'] for d in all_library_deps if not d['supports_android'] ]) if deps_require_android and not options.requires_android: raise Exception( 'Some deps require building for the Android platform: ' + str(deps_require_android)) if deps_not_support_android and options.supports_android: raise Exception('Not all deps support the Android platform: ' + str(deps_not_support_android)) if options.type in ('java_binary', 'java_library', 'android_apk'): deps_info['resources_deps'] = [c['path'] for c in all_resources_deps] deps_info['jar_path'] = options.jar_path if options.type == 'android_apk' or options.supports_android: deps_info['dex_path'] = options.dex_path if options.type == 'android_apk': deps_info['apk_path'] = options.apk_path deps_info['incremental_apk_path'] = options.incremental_apk_path deps_info['incremental_install_script_path'] = ( options.incremental_install_script_path) # Classpath values filled in below (after applying tested_apk_config). config['javac'] = {} if options.type in ('java_binary', 'java_library'): # Only resources might have srcjars (normal srcjar targets are listed in # srcjar_deps). A resource's srcjar contains the R.java file for those # resources, and (like Android's default build system) we allow a library to # refer to the resources in any of its dependents. config['javac']['srcjars'] = [ c['srcjar'] for c in all_resources_deps if 'srcjar' in c ] # Used to strip out R.class for android_prebuilt()s. if options.type == 'java_library': config['javac']['resource_packages'] = [ c['package_name'] for c in all_resources_deps if 'package_name' in c ] if options.type == 'android_apk': # Apks will get their resources srcjar explicitly passed to the java step. config['javac']['srcjars'] = [] if options.type == 'android_assets': all_asset_sources = [] if options.asset_renaming_sources: all_asset_sources.extend( build_utils.ParseGypList(options.asset_renaming_sources)) if options.asset_sources: all_asset_sources.extend( build_utils.ParseGypList(options.asset_sources)) deps_info['assets'] = {'sources': all_asset_sources} if options.asset_renaming_destinations: deps_info['assets']['outputs'] = (build_utils.ParseGypList( options.asset_renaming_destinations)) if options.disable_asset_compression: deps_info['assets']['disable_compression'] = True if options.type == 'android_resources': deps_info['resources_zip'] = options.resources_zip if options.srcjar: deps_info['srcjar'] = options.srcjar if options.android_manifest: manifest = AndroidManifest(options.android_manifest) deps_info['package_name'] = manifest.GetPackageName() if options.package_name: deps_info['package_name'] = options.package_name if options.r_text: deps_info['r_text'] = options.r_text if options.is_locale_resource: deps_info['is_locale_resource'] = True # Record resources_dirs of this target so dependendent libraries can pick up # them and pass to Lint. lint_info = deps_info['lint'] = {} resource_dirs = [] lint_info['resources_zips'] = [] for gyp_list in options.resource_dirs: resource_dirs += build_utils.ParseGypList(gyp_list) if resource_dirs: lint_info['resources_dirs'] = resource_dirs # There things become ugly. Resource targets may have resource dependencies # as well. Some of these dependencies are resources from other libraries # so we should not lint them here (they should be linted within their # libraries). But others are just generated resources that also contribute # to this library and we should check them. These generated resources has no # package_name so we skip all direct deps that has package names. for c in direct_resources_deps: if 'package_name' not in c: lint_info['resources_zips'].append(c['resources_zip']) if options.supports_android and options.type in ('android_apk', 'java_library'): # GN's project model doesn't exactly match traditional Android project # model: GN splits resources into separate targets, while in Android # resources are part of the library/APK. Android Lint expects an Android # project - with java sources and resources combined. So we assume that # direct resource dependencies of the library/APK are the resources of this # library in Android project sense. lint_info = config['lint'] = {} lint_info['resources_dirs'] = [] lint_info['resources_zips'] = [] for c in direct_resources_deps: lint_info['resources_dirs'] += c['lint'].get('resources_dirs', []) lint_info['resources_zips'] += c['lint'].get('resources_zips', []) if options.type in ('android_resources', 'android_apk', 'resource_rewriter'): config['resources'] = {} config['resources']['dependency_zips'] = [ c['resources_zip'] for c in all_resources_deps ] config['resources']['extra_package_names'] = [] config['resources']['extra_r_text_files'] = [] if options.type == 'android_apk' or options.type == 'resource_rewriter': config['resources']['extra_package_names'] = [ c['package_name'] for c in all_resources_deps if 'package_name' in c ] config['resources']['extra_r_text_files'] = [ c['r_text'] for c in all_resources_deps if 'r_text' in c ] if options.type in ['android_apk', 'deps_dex']: deps_dex_files = [c['dex_path'] for c in all_library_deps] if options.type in ('java_binary', 'java_library', 'android_apk'): javac_classpath = [c['jar_path'] for c in direct_library_deps] java_full_classpath = [c['jar_path'] for c in all_library_deps] # An instrumentation test apk should exclude the dex files that are in the apk # under test. if options.type == 'android_apk' and options.tested_apk_config: tested_apk_config = GetDepConfig(options.tested_apk_config) expected_tested_package = tested_apk_config['package_name'] AndroidManifest(options.android_manifest).CheckInstrumentation( expected_tested_package) if tested_apk_config['proguard_enabled']: assert options.proguard_enabled, ( 'proguard must be enabled for ' 'instrumentation apks if it\'s enabled for the tested apk.') # Include in the classpath classes that are added directly to the apk under # test (those that are not a part of a java_library). javac_classpath.append(tested_apk_config['jar_path']) java_full_classpath.append(tested_apk_config['jar_path']) # Exclude dex files from the test apk that exist within the apk under test. # TODO(agrieve): When proguard is enabled, this filtering logic happens # within proguard_util.py. Move the logic for the proguard case into # here as well. tested_apk_library_deps = tested_apk_deps.All('java_library') tested_apk_deps_dex_files = [ c['dex_path'] for c in tested_apk_library_deps ] deps_dex_files = [ p for p in deps_dex_files if not p in tested_apk_deps_dex_files ] if options.type == 'android_apk': deps_info['proguard_enabled'] = options.proguard_enabled deps_info['proguard_info'] = options.proguard_info config['proguard'] = {} proguard_config = config['proguard'] proguard_config['input_paths'] = [options.jar_path ] + java_full_classpath # Dependencies for the final dex file of an apk or a 'deps_dex'. if options.type in ['android_apk', 'deps_dex']: config['final_dex'] = {} dex_config = config['final_dex'] dex_config['dependency_dex_files'] = deps_dex_files if options.type in ('java_binary', 'java_library', 'android_apk'): config['javac']['classpath'] = javac_classpath config['javac']['interface_classpath'] = [ _AsInterfaceJar(p) for p in javac_classpath ] config['java'] = {'full_classpath': java_full_classpath} if options.type == 'android_apk': dependency_jars = [c['jar_path'] for c in all_library_deps] all_interface_jars = [ _AsInterfaceJar(p) for p in dependency_jars + [options.jar_path] ] config['dist_jar'] = { 'dependency_jars': dependency_jars, 'all_interface_jars': all_interface_jars, } manifest = AndroidManifest(options.android_manifest) deps_info['package_name'] = manifest.GetPackageName() if not options.tested_apk_config and manifest.GetInstrumentation(): # This must then have instrumentation only for itself. manifest.CheckInstrumentation(manifest.GetPackageName()) library_paths = [] java_libraries_list = None runtime_deps_files = build_utils.ParseGypList( options.shared_libraries_runtime_deps or '[]') if runtime_deps_files: library_paths = _ExtractSharedLibsFromRuntimeDeps( runtime_deps_files) # Create a java literal array with the "base" library names: # e.g. libfoo.so -> foo java_libraries_list = ( '{%s}' % ','.join(['"%s"' % s[3:-3] for s in library_paths])) all_inputs.extend(runtime_deps_files) config['native'] = { 'libraries': library_paths, 'java_libraries_list': java_libraries_list, } config['assets'], config['uncompressed_assets'] = (_MergeAssets( deps.All('android_assets'))) build_utils.WriteJson(config, options.build_config, only_if_changed=True) if options.depfile: build_utils.WriteDepfile(options.depfile, all_inputs)
def main(argv): parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option('--build-config', help='Path to build_config output.') parser.add_option('--type', help='Type of this target (e.g. android_library).') parser.add_option( '--possible-deps-configs', help='List of paths for dependency\'s build_config files. Some ' 'dependencies may not write build_config files. Missing build_config ' 'files are handled differently based on the type of this target.') # android_resources options parser.add_option('--srcjar', help='Path to target\'s resources srcjar.') parser.add_option('--resources-zip', help='Path to target\'s resources zip.') # android_library options parser.add_option('--jar-path', help='Path to target\'s jar output.') options, args = parser.parse_args(argv) if args: parser.error('No positional arguments should be given.') required_options = ('build_config', 'type') build_utils.CheckOptions(options, parser, required_options) if not options.type in ['android_library', 'android_resources']: raise Exception('Unknown type: <%s>' % options.type) if options.type == 'android_library': required_options = ('jar_path', ) build_utils.CheckOptions(options, parser, required_options) possible_deps_configs = build_utils.ParseGypList( options.possible_deps_configs) for c in possible_deps_configs: if not os.path.exists(c): # Currently we only allow deps to things that write build_config files. raise Exception('Unknown dep type: ' + c) direct_deps_config_paths = possible_deps_configs all_deps_config_paths = GetAllDepsConfigsInOrder(direct_deps_config_paths) direct_deps_configs = [GetDepConfig(p) for p in direct_deps_config_paths] all_deps_configs = [GetDepConfig(p) for p in all_deps_config_paths] direct_library_deps = DepsOfType('android_library', direct_deps_configs) all_resources_deps = DepsOfType('android_resources', all_deps_configs) # Initialize some common config. config = { 'deps_info': { 'path': options.build_config, 'type': options.type, 'deps_configs': direct_deps_config_paths, } } deps_info = config['deps_info'] if options.type == 'android_library': javac_classpath = [c['jar_path'] for c in direct_library_deps] deps_info['jar_path'] = options.jar_path config['javac'] = { 'classpath': javac_classpath, } # Only resources might have srcjars (normal srcjar targets are listed in # srcjar_deps). A resource's srcjar contains the R.java file for those # resources, and (like Android's default build system) we allow a library to # refer to the resources in any of its dependents. config['javac']['srcjars'] = [ c['srcjar'] for c in all_resources_deps if 'srcjar' in c ] if options.type == 'android_resources': deps_info['resources_zip'] = options.resources_zip if options.srcjar: deps_info['srcjar'] = options.srcjar config['resources'] = {} config['resources']['dependency_zips'] = [ c['resources_zip'] for c in all_resources_deps ] build_utils.WriteJson(config, options.build_config, only_if_changed=True) if options.depfile: build_utils.WriteDepfile( options.depfile, all_deps_config_paths + build_utils.GetPythonDependencies())
def main(argv): parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option('--build-config', help='Path to build_config output.') parser.add_option('--type', help='Type of this target (e.g. android_library).') parser.add_option( '--possible-deps-configs', help='List of paths for dependency\'s build_config files. Some ' 'dependencies may not write build_config files. Missing build_config ' 'files are handled differently based on the type of this target.') # android_resources/apk options parser.add_option('--srcjar', help='Path to target\'s resources srcjar.') parser.add_option('--resources-zip', help='Path to target\'s resources zip.') # android_library/apk options parser.add_option('--jar-path', help='Path to target\'s jar output.') parser.add_option('--dex-path', help='Path to target\'s dex output.') # apk native library options parser.add_option('--native-libs', help='List of top-level native libs.') parser.add_option('--readelf-path', help='Path to toolchain\'s readelf.') options, args = parser.parse_args(argv) if args: parser.error('No positional arguments should be given.') if not options.type in [ 'android_library', 'android_resources', 'android_apk' ]: raise Exception('Unknown type: <%s>' % options.type) required_options = ['build_config'] + { 'android_library': ['jar_path', 'dex_path'], 'android_resources': ['resources_zip'], 'android_apk': ['jar_path', 'dex_path', 'resources_zip'] }[options.type] if options.native_libs: required_options += ['readelf_path'] build_utils.CheckOptions(options, parser, required_options) possible_deps_config_paths = build_utils.ParseGypList( options.possible_deps_configs) allow_unknown_deps = options.type == 'android_apk' unknown_deps = [ c for c in possible_deps_config_paths if not os.path.exists(c) ] if unknown_deps and not allow_unknown_deps: raise Exception('Unknown deps: ' + unknown_deps) direct_deps_config_paths = [ c for c in possible_deps_config_paths if not c in unknown_deps ] all_deps_config_paths = GetAllDepsConfigsInOrder(direct_deps_config_paths) direct_deps_configs = [GetDepConfig(p) for p in direct_deps_config_paths] all_deps_configs = [GetDepConfig(p) for p in all_deps_config_paths] direct_library_deps = DepsOfType('android_library', direct_deps_configs) all_resources_deps = DepsOfType('android_resources', all_deps_configs) all_library_deps = DepsOfType('android_library', all_deps_configs) # Initialize some common config. config = { 'deps_info': { 'path': options.build_config, 'type': options.type, 'deps_configs': direct_deps_config_paths, } } deps_info = config['deps_info'] if options.type in ['android_library', 'android_apk']: javac_classpath = [c['jar_path'] for c in direct_library_deps] deps_info['resources_deps'] = [c['path'] for c in all_resources_deps] deps_info['jar_path'] = options.jar_path deps_info['dex_path'] = options.dex_path config['javac'] = { 'classpath': javac_classpath, } # Only resources might have srcjars (normal srcjar targets are listed in # srcjar_deps). A resource's srcjar contains the R.java file for those # resources, and (like Android's default build system) we allow a library to # refer to the resources in any of its dependents. config['javac']['srcjars'] = [ c['srcjar'] for c in all_resources_deps if 'srcjar' in c ] if options.type == 'android_resources' or options.type == 'android_apk': deps_info['resources_zip'] = options.resources_zip if options.srcjar: deps_info['srcjar'] = options.srcjar config['resources'] = {} config['resources']['dependency_zips'] = [ c['resources_zip'] for c in all_resources_deps ] if options.type == 'android_apk': config['apk_dex'] = {} dex_config = config['apk_dex'] # TODO(cjhopman): proguard version dex_deps_files = [c['dex_path'] for c in all_library_deps] dex_config['dependency_dex_files'] = dex_deps_files library_paths = [] java_libraries_list = [] if options.native_libs: libraries = build_utils.ParseGypList(options.native_libs) libraries_dir = os.path.dirname(libraries[0]) write_ordered_libraries.SetReadelfPath(options.readelf_path) write_ordered_libraries.SetLibraryDirs([libraries_dir]) all_native_library_deps = ( write_ordered_libraries. GetSortedTransitiveDependenciesForBinaries(libraries)) java_libraries_list = '{%s}' % ','.join( ['"%s"' % s for s in all_native_library_deps]) library_paths = map(write_ordered_libraries.FullLibraryPath, all_native_library_deps) config['native'] = { 'libraries': library_paths, 'java_libraries_list': java_libraries_list } build_utils.WriteJson(config, options.build_config, only_if_changed=True) if options.depfile: build_utils.WriteDepfile( options.depfile, all_deps_config_paths + build_utils.GetPythonDependencies())
def main(argv): options, _ = ParseArgs(argv) library_classpath = [options.android_sdk_jar] input_jars = build_utils.ParseGypList(options.input_jars_paths) dependency_class_filters = [ '*R.class', '*R$*.class', '*Manifest.class', '*BuildConfig.class' ] if options.testapp: build_utils.MergeZips(options.test_jar_path, input_jars, dependency_class_filters) if options.configuration_name == 'Release' and options.proguard_enabled: proguard_cmd = [ 'java', '-jar', options.proguard_jar_path, '-forceprocessing', '-libraryjars', ':'.join(library_classpath), '-dump', options.obfuscated_jar_path + '.dump', '-printseeds', options.obfuscated_jar_path + '.seeds', '-printusage', options.obfuscated_jar_path + '.usage', '-printmapping', options.obfuscated_jar_path + '.mapping', ] exclude_paths = [] configs = build_utils.ParseGypList(options.proguard_configs) if (options.tested_apk_obfuscated_jar_path and options.tested_apk_obfuscated_jar_path != '/'): # configs should only contain the process_resources.py generated config. assert len(configs) == 1, ( 'test apks should not have custom proguard configs: ' + str(configs)) tested_jar_info = build_utils.ReadJson( options.tested_apk_obfuscated_jar_path + '.info') exclude_paths = tested_jar_info['inputs'] configs = tested_jar_info['configs'] proguard_cmd += [ '-dontobfuscate', '-dontoptimize', '-dontshrink', '-dontskipnonpubliclibraryclassmembers', '-libraryjars', options.tested_apk_obfuscated_jar_path, '-applymapping', options.tested_apk_obfuscated_jar_path + '.mapping', ] proguard_injars = [p for p in input_jars if p not in exclude_paths] proguard_cmd += ['-injars', ':'.join(proguard_injars)] for config_file in configs: proguard_cmd += ['-include', config_file] # The output jar must be specified after inputs. proguard_cmd += ['-outjars', options.obfuscated_jar_path] build_utils.CheckOutput(proguard_cmd) this_info = {'inputs': proguard_injars, 'configs': configs} build_utils.WriteJson(this_info, options.obfuscated_jar_path + '.info') else: output_files = [ options.obfuscated_jar_path, options.obfuscated_jar_path + '.info', options.obfuscated_jar_path + '.dump', options.obfuscated_jar_path + '.seeds', options.obfuscated_jar_path + '.usage', options.obfuscated_jar_path + '.mapping' ] for f in output_files: if os.path.exists(f): os.remove(f) build_utils.Touch(f) if options.stamp: build_utils.Touch(options.stamp)
def WriteConfigurations(configurations, path): # Currently we only support installing to the first device. build_utils.WriteJson(configurations[:1], path, only_if_changed=True)
def main(args): args = build_utils.ExpandFileArgs(args) parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option( '--clear-dir', action='store_true', help='If set, the destination directory will be deleted ' 'before copying files to it. This is highly recommended to ' 'ensure that no stale files are left in the directory.') parser.add_option('--configuration-name', default='Release', help='Gyp configuration name (i.e. Debug, Release)') parser.add_option( '--enable-packing', choices=['0', '1'], help=('Pack relocations if 1 and configuration name is \'Release\',' ' otherwise plain file copy')) parser.add_option('--exclude-packing-list', default='', help='Names of any libraries explicitly not packed') parser.add_option('--android-pack-relocations', help='Path to the relocations packer binary') parser.add_option('--stripped-libraries-dir', help='Directory for stripped libraries') parser.add_option('--packed-libraries-dir', help='Directory for packed libraries') parser.add_option('--libraries', action='append', help='List of libraries') parser.add_option('--stamp', help='Path to touch on success') parser.add_option('--filelistjson', help='Output path of filelist.json to write') options, _ = parser.parse_args(args) enable_packing = (options.enable_packing == '1' and options.configuration_name == 'Release') exclude_packing_set = set( build_utils.ParseGypList(options.exclude_packing_list)) libraries = [] for libs_arg in options.libraries: libraries += build_utils.ParseGypList(libs_arg) if options.clear_dir: build_utils.DeleteDirectory(options.packed_libraries_dir) build_utils.MakeDirectory(options.packed_libraries_dir) output_paths = [] for library in libraries: library_path = os.path.join(options.stripped_libraries_dir, library) output_path = os.path.join(options.packed_libraries_dir, os.path.basename(library)) output_paths.append(output_path) if enable_packing and library not in exclude_packing_set: PackLibraryRelocations(options.android_pack_relocations, library_path, output_path) else: CopyLibraryUnchanged(library_path, output_path) if options.filelistjson: build_utils.WriteJson({'files': output_paths}, options.filelistjson) if options.depfile: build_utils.WriteDepfile( options.depfile, libraries + build_utils.GetPythonDependencies()) if options.stamp: build_utils.Touch(options.stamp) return 0
def main(argv): parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option('--build-config', help='Path to build_config output.') parser.add_option( '--type', help='Type of this target (e.g. android_library).') parser.add_option( '--possible-deps-configs', help='List of paths for dependency\'s build_config files. Some ' 'dependencies may not write build_config files. Missing build_config ' 'files are handled differently based on the type of this target.') # android_resources options parser.add_option('--srcjar', help='Path to target\'s resources srcjar.') parser.add_option('--resources-zip', help='Path to target\'s resources zip.') parser.add_option('--package-name', help='Java package name for these resources.') parser.add_option('--android-manifest', help='Path to android manifest.') # java library options parser.add_option('--jar-path', help='Path to target\'s jar output.') parser.add_option('--supports-android', action='store_true', help='Whether this library supports running on the Android platform.') parser.add_option('--requires-android', action='store_true', help='Whether this library requires running on the Android platform.') parser.add_option('--bypass-platform-checks', action='store_true', help='Bypass checks for support/require Android platform.') # android library options parser.add_option('--dex-path', help='Path to target\'s dex output.') # native library options parser.add_option('--native-libs', help='List of top-level native libs.') parser.add_option('--readelf-path', help='Path to toolchain\'s readelf.') options, args = parser.parse_args(argv) if args: parser.error('No positional arguments should be given.') if not options.type in [ 'java_library', 'android_resources', 'android_apk']: raise Exception('Unknown type: <%s>' % options.type) required_options = ['build_config'] + { 'java_library': ['jar_path'], 'android_resources': ['resources_zip'], 'android_apk': ['jar_path', 'dex_path', 'resources_zip'] }[options.type] if options.native_libs: required_options.append('readelf_path') build_utils.CheckOptions(options, parser, required_options) if options.type == 'java_library': if options.supports_android and not options.dex_path: raise Exception('java_library that supports Android requires a dex path.') if options.requires_android and not options.supports_android: raise Exception( '--supports-android is required when using --requires-android') possible_deps_config_paths = build_utils.ParseGypList( options.possible_deps_configs) allow_unknown_deps = options.type == 'android_apk' unknown_deps = [ c for c in possible_deps_config_paths if not os.path.exists(c)] if unknown_deps and not allow_unknown_deps: raise Exception('Unknown deps: ' + str(unknown_deps)) direct_deps_config_paths = [ c for c in possible_deps_config_paths if not c in unknown_deps] all_deps_config_paths = GetAllDepsConfigsInOrder(direct_deps_config_paths) direct_deps_configs = [GetDepConfig(p) for p in direct_deps_config_paths] all_deps_configs = [GetDepConfig(p) for p in all_deps_config_paths] direct_library_deps = DepsOfType('java_library', direct_deps_configs) all_library_deps = DepsOfType('java_library', all_deps_configs) direct_resources_deps = DepsOfType('android_resources', direct_deps_configs) all_resources_deps = DepsOfType('android_resources', all_deps_configs) # Initialize some common config. config = { 'deps_info': { 'name': os.path.basename(options.build_config), 'path': options.build_config, 'type': options.type, 'deps_configs': direct_deps_config_paths, } } deps_info = config['deps_info'] if options.type == 'java_library' and not options.bypass_platform_checks: deps_info['requires_android'] = options.requires_android deps_info['supports_android'] = options.supports_android deps_require_android = (all_resources_deps + [d['name'] for d in all_library_deps if d['requires_android']]) deps_not_support_android = ( [d['name'] for d in all_library_deps if not d['supports_android']]) if deps_require_android and not options.requires_android: raise Exception('Some deps require building for the Android platform: ' + str(deps_require_android)) if deps_not_support_android and options.supports_android: raise Exception('Not all deps support the Android platform: ' + str(deps_not_support_android)) if options.type in ['java_library', 'android_apk']: javac_classpath = [c['jar_path'] for c in direct_library_deps] java_full_classpath = [c['jar_path'] for c in all_library_deps] deps_info['resources_deps'] = [c['path'] for c in all_resources_deps] deps_info['jar_path'] = options.jar_path if options.type == 'android_apk' or options.supports_android: deps_info['dex_path'] = options.dex_path config['javac'] = { 'classpath': javac_classpath, } config['java'] = { 'full_classpath': java_full_classpath } if options.type == 'java_library': # Only resources might have srcjars (normal srcjar targets are listed in # srcjar_deps). A resource's srcjar contains the R.java file for those # resources, and (like Android's default build system) we allow a library to # refer to the resources in any of its dependents. config['javac']['srcjars'] = [ c['srcjar'] for c in direct_resources_deps if 'srcjar' in c] if options.type == 'android_apk': # Apks will get their resources srcjar explicitly passed to the java step. config['javac']['srcjars'] = [] if options.type == 'android_resources': deps_info['resources_zip'] = options.resources_zip if options.srcjar: deps_info['srcjar'] = options.srcjar if options.package_name: deps_info['package_name'] = options.package_name if options.type == 'android_resources' or options.type == 'android_apk': config['resources'] = {} config['resources']['dependency_zips'] = [ c['resources_zip'] for c in all_resources_deps] config['resources']['extra_package_names'] = [] if options.type == 'android_apk': config['resources']['extra_package_names'] = [ c['package_name'] for c in all_resources_deps if 'package_name' in c] # Dependencies for the final dex file of an apk or the standalone .dex.jar # output of a library. if options.type == 'android_apk' or (options.type == "java_library" and options.supports_android): config['final_dex'] = {} dex_config = config['final_dex'] # TODO(cjhopman): proguard version dex_deps_files = [c['dex_path'] for c in all_library_deps] dex_config['dependency_dex_files'] = dex_deps_files if options.type == 'android_apk': config['dist_jar'] = { 'dependency_jars': [ c['jar_path'] for c in all_library_deps ] } library_paths = [] java_libraries_list = [] if options.native_libs: libraries = build_utils.ParseGypList(options.native_libs) if libraries: libraries_dir = os.path.dirname(libraries[0]) write_ordered_libraries.SetReadelfPath(options.readelf_path) write_ordered_libraries.SetLibraryDirs([libraries_dir]) all_native_library_deps = ( write_ordered_libraries.GetSortedTransitiveDependenciesForBinaries( libraries)) # Create a java literal array with the "base" library names: # e.g. libfoo.so -> foo java_libraries_list = '{%s}' % ','.join( ['"%s"' % s[3:-3] for s in all_native_library_deps]) library_paths = map( write_ordered_libraries.FullLibraryPath, all_native_library_deps) config['native'] = { 'libraries': library_paths, 'java_libraries_list': java_libraries_list } build_utils.WriteJson(config, options.build_config, only_if_changed=True) if options.depfile: build_utils.WriteDepfile( options.depfile, all_deps_config_paths + build_utils.GetPythonDependencies())
def main(argv): parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option('--build-config', help='Path to build_config output.') parser.add_option( '--type', help='Type of this target (e.g. android_library).') parser.add_option( '--deps-configs', help='List of paths for dependency\'s build_config files. ') # android_resources options parser.add_option('--srcjar', help='Path to target\'s resources srcjar.') parser.add_option('--resources-zip', help='Path to target\'s resources zip.') parser.add_option('--r-text', help='Path to target\'s R.txt file.') parser.add_option('--package-name', help='Java package name for these resources.') parser.add_option('--android-manifest', help='Path to android manifest.') parser.add_option('--resource-dirs', action='append', default=[], help='GYP-list of resource dirs') # android_assets options parser.add_option('--asset-sources', help='List of asset sources.') parser.add_option('--asset-renaming-sources', help='List of asset sources with custom destinations.') parser.add_option('--asset-renaming-destinations', help='List of asset custom destinations.') parser.add_option('--disable-asset-compression', action='store_true', help='Whether to disable asset compression.') # java library options parser.add_option('--jar-path', help='Path to target\'s jar output.') parser.add_option('--java-sources-file', help='Path to .sources file') parser.add_option('--bundled-srcjars', help='GYP-list of .srcjars that have been included in this java_library.') parser.add_option('--supports-android', action='store_true', help='Whether this library supports running on the Android platform.') parser.add_option('--requires-android', action='store_true', help='Whether this library requires running on the Android platform.') parser.add_option('--bypass-platform-checks', action='store_true', help='Bypass checks for support/require Android platform.') parser.add_option('--extra-classpath-jars', help='GYP-list of .jar files to include on the classpath when compiling, ' 'but not to include in the final binary.') parser.add_option('--gradle-treat-as-prebuilt', action='store_true', help='Whether this library should be treated as a prebuilt library by ' 'generate_gradle.py.') parser.add_option('--main-class', help='Java class for java_binary targets.') parser.add_option('--java-resources-jar-path', help='Path to JAR that contains java resources. Everything ' 'from this JAR except meta-inf/ content and .class files ' 'will be added to the final APK.') parser.add_option('--bootclasspath', help='Path to custom android.jar/rt.jar') # android library options parser.add_option('--dex-path', help='Path to target\'s dex output.') # native library options parser.add_option('--shared-libraries-runtime-deps', help='Path to file containing runtime deps for shared ' 'libraries.') parser.add_option('--secondary-abi-shared-libraries-runtime-deps', help='Path to file containing runtime deps for secondary ' 'abi shared libraries.') parser.add_option('--enable-relocation-packing', help='Whether relocation packing is enabled.') # apk options parser.add_option('--apk-path', help='Path to the target\'s apk output.') parser.add_option('--incremental-apk-path', help="Path to the target's incremental apk output.") parser.add_option('--incremental-install-script-path', help="Path to the target's generated incremental install " "script.") parser.add_option('--tested-apk-config', help='Path to the build config of the tested apk (for an instrumentation ' 'test apk).') parser.add_option('--proguard-enabled', action='store_true', help='Whether proguard is enabled for this apk.') parser.add_option('--proguard-configs', help='GYP-list of proguard flag files to use in final apk.') parser.add_option('--proguard-info', help='Path to the proguard .info output for this apk.') parser.add_option('--fail', help='GYP-list of error message lines to fail with.') options, args = parser.parse_args(argv) if args: parser.error('No positional arguments should be given.') if options.fail: parser.error('\n'.join(build_utils.ParseGnList(options.fail))) required_options_map = { 'java_binary': ['build_config', 'jar_path'], 'java_library': ['build_config', 'jar_path'], 'java_prebuilt': ['build_config', 'jar_path'], 'android_assets': ['build_config'], 'android_resources': ['build_config', 'resources_zip'], 'android_apk': ['build_config', 'jar_path', 'dex_path', 'resources_zip'], 'deps_dex': ['build_config', 'dex_path'], 'dist_jar': ['build_config'], 'resource_rewriter': ['build_config'], 'group': ['build_config'], 'junit_binary': ['build_config'], } required_options = required_options_map.get(options.type) if not required_options: raise Exception('Unknown type: <%s>' % options.type) build_utils.CheckOptions(options, parser, required_options) # Java prebuilts are the same as libraries except for in gradle files. is_java_prebuilt = options.type == 'java_prebuilt' if is_java_prebuilt: options.type = 'java_library' if options.type == 'java_library': if options.supports_android and not options.dex_path: raise Exception('java_library that supports Android requires a dex path.') if options.requires_android and not options.supports_android: raise Exception( '--supports-android is required when using --requires-android') direct_deps_config_paths = build_utils.ParseGnList(options.deps_configs) direct_deps_config_paths = _FilterDepsPaths(direct_deps_config_paths, options.type) deps = Deps(direct_deps_config_paths) all_inputs = deps.AllConfigPaths() direct_library_deps = deps.Direct('java_library') all_library_deps = deps.All('java_library') direct_resources_deps = deps.Direct('android_resources') all_resources_deps = deps.All('android_resources') # Resources should be ordered with the highest-level dependency first so that # overrides are done correctly. all_resources_deps.reverse() # Initialize some common config. # Any value that needs to be queryable by dependents must go within deps_info. config = { 'deps_info': { 'name': os.path.basename(options.build_config), 'path': options.build_config, 'type': options.type, 'deps_configs': direct_deps_config_paths }, # Info needed only by generate_gradle.py. 'gradle': {} } deps_info = config['deps_info'] gradle = config['gradle'] if options.type == 'android_apk' and options.tested_apk_config: tested_apk_deps = Deps([options.tested_apk_config]) tested_apk_name = tested_apk_deps.Direct()[0]['name'] tested_apk_resources_deps = tested_apk_deps.All('android_resources') gradle['apk_under_test'] = tested_apk_name all_resources_deps = [ d for d in all_resources_deps if not d in tested_apk_resources_deps] # Required for generating gradle files. if options.type == 'java_library': deps_info['is_prebuilt'] = is_java_prebuilt deps_info['gradle_treat_as_prebuilt'] = options.gradle_treat_as_prebuilt if options.android_manifest: deps_info['android_manifest'] = options.android_manifest if options.type in ('java_binary', 'java_library', 'android_apk'): if options.java_sources_file: deps_info['java_sources_file'] = options.java_sources_file if options.bundled_srcjars: gradle['bundled_srcjars'] = ( build_utils.ParseGnList(options.bundled_srcjars)) else: gradle['bundled_srcjars'] = [] gradle['dependent_android_projects'] = [] gradle['dependent_java_projects'] = [] gradle['dependent_prebuilt_jars'] = deps.GradlePrebuiltJarPaths() if options.bootclasspath: gradle['bootclasspath'] = options.bootclasspath if options.main_class: gradle['main_class'] = options.main_class for c in deps.GradleLibraryProjectDeps(): if c['requires_android']: gradle['dependent_android_projects'].append(c['path']) else: gradle['dependent_java_projects'].append(c['path']) if options.type == 'android_apk': config['jni'] = {} all_java_sources = [c['java_sources_file'] for c in all_library_deps if 'java_sources_file' in c] if options.java_sources_file: all_java_sources.append(options.java_sources_file) config['jni']['all_source'] = all_java_sources if (options.type in ('java_binary', 'java_library')): deps_info['requires_android'] = options.requires_android deps_info['supports_android'] = options.supports_android if not options.bypass_platform_checks: deps_require_android = (all_resources_deps + [d['name'] for d in all_library_deps if d['requires_android']]) deps_not_support_android = ( [d['name'] for d in all_library_deps if not d['supports_android']]) if deps_require_android and not options.requires_android: raise Exception('Some deps require building for the Android platform: ' + str(deps_require_android)) if deps_not_support_android and options.supports_android: raise Exception('Not all deps support the Android platform: ' + str(deps_not_support_android)) if options.type in ('java_binary', 'java_library', 'android_apk'): deps_info['jar_path'] = options.jar_path if options.type == 'android_apk' or options.supports_android: deps_info['dex_path'] = options.dex_path if options.type == 'android_apk': deps_info['apk_path'] = options.apk_path deps_info['incremental_apk_path'] = options.incremental_apk_path deps_info['incremental_install_script_path'] = ( options.incremental_install_script_path) deps_info['enable_relocation_packing'] = options.enable_relocation_packing if options.type in ('java_binary', 'java_library', 'android_apk', 'dist_jar'): # Classpath values filled in below (after applying tested_apk_config). config['javac'] = {} if options.type in ('java_binary', 'java_library'): # Only resources might have srcjars (normal srcjar targets are listed in # srcjar_deps). A resource's srcjar contains the R.java file for those # resources, and (like Android's default build system) we allow a library to # refer to the resources in any of its dependents. config['javac']['srcjars'] = [ c['srcjar'] for c in all_resources_deps if 'srcjar' in c] # Used to strip out R.class for android_prebuilt()s. if options.type == 'java_library': config['javac']['resource_packages'] = [ c['package_name'] for c in all_resources_deps if 'package_name' in c] if options.type == 'android_apk': # Apks will get their resources srcjar explicitly passed to the java step config['javac']['srcjars'] = [] # Gradle may need to generate resources for some apks. gradle['srcjars'] = [ c['srcjar'] for c in direct_resources_deps if 'srcjar' in c] if options.type == 'android_assets': all_asset_sources = [] if options.asset_renaming_sources: all_asset_sources.extend( build_utils.ParseGnList(options.asset_renaming_sources)) if options.asset_sources: all_asset_sources.extend(build_utils.ParseGnList(options.asset_sources)) deps_info['assets'] = { 'sources': all_asset_sources } if options.asset_renaming_destinations: deps_info['assets']['outputs'] = ( build_utils.ParseGnList(options.asset_renaming_destinations)) if options.disable_asset_compression: deps_info['assets']['disable_compression'] = True if options.type == 'android_resources': deps_info['resources_zip'] = options.resources_zip if options.srcjar: deps_info['srcjar'] = options.srcjar if options.android_manifest: manifest = AndroidManifest(options.android_manifest) deps_info['package_name'] = manifest.GetPackageName() if options.package_name: deps_info['package_name'] = options.package_name if options.r_text: deps_info['r_text'] = options.r_text deps_info['resources_dirs'] = [] if options.resource_dirs: for gyp_list in options.resource_dirs: deps_info['resources_dirs'].extend(build_utils.ParseGnList(gyp_list)) if options.supports_android and options.type in ('android_apk', 'java_library'): # Lint all resources that are not already linted by a dependent library. owned_resource_dirs = set() owned_resource_zips = set() for c in all_resources_deps: # Always use resources_dirs in favour of resources_zips so that lint error # messages have paths that are closer to reality (and to avoid needing to # extract during lint). if c['resources_dirs']: owned_resource_dirs.update(c['resources_dirs']) else: owned_resource_zips.add(c['resources_zip']) for c in all_library_deps: if c['supports_android']: owned_resource_dirs.difference_update(c['owned_resources_dirs']) owned_resource_zips.difference_update(c['owned_resources_zips']) deps_info['owned_resources_dirs'] = list(owned_resource_dirs) deps_info['owned_resources_zips'] = list(owned_resource_zips) if options.type in ( 'android_resources', 'android_apk', 'junit_binary', 'resource_rewriter'): config['resources'] = {} config['resources']['dependency_zips'] = [ c['resources_zip'] for c in all_resources_deps] config['resources']['extra_package_names'] = [] config['resources']['extra_r_text_files'] = [] if options.type == 'android_apk' or options.type == 'resource_rewriter': config['resources']['extra_package_names'] = [ c['package_name'] for c in all_resources_deps if 'package_name' in c] config['resources']['extra_r_text_files'] = [ c['r_text'] for c in all_resources_deps if 'r_text' in c] if options.type in ['android_apk', 'deps_dex']: deps_dex_files = [c['dex_path'] for c in all_library_deps] if options.type in ('java_binary', 'java_library', 'android_apk', 'dist_jar'): javac_classpath = [c['jar_path'] for c in direct_library_deps] java_full_classpath = [c['jar_path'] for c in all_library_deps] if options.extra_classpath_jars: extra_jars = build_utils.ParseGnList(options.extra_classpath_jars) deps_info['extra_classpath_jars'] = extra_jars javac_classpath += extra_jars # The java code for an instrumentation test apk is assembled differently for # ProGuard vs. non-ProGuard. # # Without ProGuard: Each library's jar is dexed separately and then combined # into a single classes.dex. A test apk will include all dex files not already # present in the apk-under-test. At runtime all test code lives in the test # apk, and the program code lives in the apk-under-test. # # With ProGuard: Each library's .jar file is fed into ProGuard, which outputs # a single .jar, which is then dexed into a classes.dex. A test apk includes # all jar files from the program and the tests because having them separate # doesn't work with ProGuard's whole-program optimizations. Although the # apk-under-test still has all of its code in its classes.dex, none of it is # used at runtime because the copy of it within the test apk takes precidence. if options.type == 'android_apk' and options.tested_apk_config: tested_apk_config = GetDepConfig(options.tested_apk_config) expected_tested_package = tested_apk_config['package_name'] AndroidManifest(options.android_manifest).CheckInstrumentationElements( expected_tested_package) if options.proguard_enabled: # Add all tested classes to the test's classpath to ensure that the test's # java code is a superset of the tested apk's java code java_full_classpath += [ jar for jar in tested_apk_config['java']['full_classpath'] if jar not in java_full_classpath] if tested_apk_config['proguard_enabled']: assert options.proguard_enabled, ('proguard must be enabled for ' 'instrumentation apks if it\'s enabled for the tested apk.') # Include in the classpath classes that are added directly to the apk under # test (those that are not a part of a java_library). javac_classpath.append(tested_apk_config['jar_path']) java_full_classpath.append(tested_apk_config['jar_path']) # Exclude dex files from the test apk that exist within the apk under test. # TODO(agrieve): When proguard is enabled, this filtering logic happens # within proguard_util.py. Move the logic for the proguard case into # here as well. tested_apk_library_deps = tested_apk_deps.All('java_library') tested_apk_deps_dex_files = [c['dex_path'] for c in tested_apk_library_deps] deps_dex_files = [ p for p in deps_dex_files if not p in tested_apk_deps_dex_files] if options.proguard_configs: assert options.type == 'java_library' deps_info['proguard_configs'] = ( build_utils.ParseGnList(options.proguard_configs)) if options.type == 'android_apk': deps_info['proguard_enabled'] = options.proguard_enabled deps_info['proguard_info'] = options.proguard_info config['proguard'] = {} proguard_config = config['proguard'] proguard_config['input_paths'] = [options.jar_path] + java_full_classpath extra_jars = set() lib_configs = set() for c in all_library_deps: extra_jars.update(c.get('extra_classpath_jars', ())) lib_configs.update(c.get('proguard_configs', ())) proguard_config['lib_paths'] = list(extra_jars) proguard_config['lib_configs'] = list(lib_configs) # Dependencies for the final dex file of an apk or a 'deps_dex'. if options.type in ['android_apk', 'deps_dex']: config['final_dex'] = {} dex_config = config['final_dex'] dex_config['dependency_dex_files'] = deps_dex_files if options.type in ('java_binary', 'java_library', 'android_apk', 'dist_jar'): config['javac']['classpath'] = javac_classpath config['javac']['interface_classpath'] = [ _AsInterfaceJar(p) for p in javac_classpath] deps_info['java'] = { 'full_classpath': java_full_classpath } if options.type in ('android_apk', 'dist_jar'): dependency_jars = [c['jar_path'] for c in all_library_deps] all_interface_jars = [_AsInterfaceJar(p) for p in dependency_jars] if options.type == 'android_apk': all_interface_jars.append(_AsInterfaceJar(options.jar_path)) config['dist_jar'] = { 'dependency_jars': dependency_jars, 'all_interface_jars': all_interface_jars, } if options.type == 'android_apk': dependency_jars = [c['jar_path'] for c in all_library_deps] manifest = AndroidManifest(options.android_manifest) deps_info['package_name'] = manifest.GetPackageName() if not options.tested_apk_config and manifest.GetInstrumentationElements(): # This must then have instrumentation only for itself. manifest.CheckInstrumentationElements(manifest.GetPackageName()) library_paths = [] java_libraries_list = None runtime_deps_files = build_utils.ParseGnList( options.shared_libraries_runtime_deps or '[]') if runtime_deps_files: library_paths = _ExtractSharedLibsFromRuntimeDeps(runtime_deps_files) java_libraries_list = _CreateJavaLibrariesList(library_paths) secondary_abi_library_paths = [] secondary_abi_java_libraries_list = None secondary_abi_runtime_deps_files = build_utils.ParseGnList( options.secondary_abi_shared_libraries_runtime_deps or '[]') if secondary_abi_runtime_deps_files: secondary_abi_library_paths = _ExtractSharedLibsFromRuntimeDeps( secondary_abi_runtime_deps_files) secondary_abi_java_libraries_list = _CreateJavaLibrariesList( secondary_abi_library_paths) all_inputs.extend(runtime_deps_files) config['native'] = { 'libraries': library_paths, 'secondary_abi_libraries': secondary_abi_library_paths, 'java_libraries_list': java_libraries_list, 'secondary_abi_java_libraries_list': secondary_abi_java_libraries_list, } config['assets'], config['uncompressed_assets'] = ( _MergeAssets(deps.All('android_assets'))) config['compressed_locales_java_list'] = ( _CreateLocalePaksAssetJavaList(config['assets'])) config['uncompressed_locales_java_list'] = ( _CreateLocalePaksAssetJavaList(config['uncompressed_assets'])) config['extra_android_manifests'] = filter(None, ( d.get('android_manifest') for d in all_resources_deps)) # Collect java resources java_resources_jars = [d['java_resources_jar'] for d in all_library_deps if 'java_resources_jar' in d] if options.tested_apk_config: tested_apk_resource_jars = [d['java_resources_jar'] for d in tested_apk_library_deps if 'java_resources_jar' in d] java_resources_jars = [jar for jar in java_resources_jars if jar not in tested_apk_resource_jars] config['java_resources_jars'] = java_resources_jars if options.type == 'java_library' and options.java_resources_jar_path: deps_info['java_resources_jar'] = options.java_resources_jar_path build_utils.WriteJson(config, options.build_config, only_if_changed=True) if options.depfile: build_utils.WriteDepfile(options.depfile, options.build_config, all_inputs)
def _OnStaleMd5(changes, options, dex_cmd, paths): _RunDx(changes, options, dex_cmd, paths) build_utils.WriteJson( [os.path.relpath(p, options.output_directory) for p in paths], options.dex_path + '.inputs')