def _ParseOptions(): args = build_utils.ExpandFileArgs(sys.argv[1:]) parser = argparse.ArgumentParser() build_utils.AddDepfileOption(parser) group = parser.add_mutually_exclusive_group(required=True) group.add_argument('--proguard-path', help='Path to the proguard.jar to use.') group.add_argument('--r8-path', help='Path to the R8.jar to use.') parser.add_argument( '--input-paths', required=True, help='GN-list of .jar files to optimize.') parser.add_argument( '--output-path', required=True, help='Path to the generated .jar file.') parser.add_argument( '--proguard-configs', action='append', required=True, help='GN-list of configuration files.') parser.add_argument( '--proguard-config-exclusions', help='GN-list of paths to filter out of --proguard-configs') parser.add_argument( '--apply-mapping', help='Path to ProGuard mapping to apply.') parser.add_argument( '--mapping-output', required=True, help='Path for ProGuard to output mapping file to.') parser.add_argument( '--extra-mapping-output-paths', help='GN-list of additional paths to copy output mapping file to.') parser.add_argument( '--output-config', help='Path to write the merged ProGuard config file to.') parser.add_argument( '--expected-configs-file', help='Path to a file containing the expected merged ProGuard configs') parser.add_argument( '--verify-expected-configs', action='store_true', help='Fail if the expected merged ProGuard configs differ from the ' 'generated merged ProGuard configs.') parser.add_argument( '--classpath', action='append', help='GN-list of .jar files to include as libraries.') parser.add_argument( '--main-dex-rules-path', action='append', help='Path to main dex rules for multidex' '- only works with R8.') parser.add_argument( '--min-api', help='Minimum Android API level compatibility.') parser.add_argument( '--verbose', '-v', action='store_true', help='Print all ProGuard output') parser.add_argument( '--repackage-classes', help='Unique package name given to an asynchronously proguarded module') parser.add_argument( '--disable-outlining', action='store_true', help='Disable the outlining optimization provided by R8.') options = parser.parse_args(args) if options.main_dex_rules_path and not options.r8_path: parser.error('R8 must be enabled to pass main dex rules.') if options.expected_configs_file and not options.output_config: parser.error('--expected-configs-file requires --output-config') if options.proguard_path and options.disable_outlining: parser.error('--disable-outlining requires --r8-path') options.classpath = build_utils.ParseGnList(options.classpath) options.proguard_configs = build_utils.ParseGnList(options.proguard_configs) options.proguard_config_exclusions = (build_utils.ParseGnList( options.proguard_config_exclusions)) options.input_paths = build_utils.ParseGnList(options.input_paths) options.extra_mapping_output_paths = build_utils.ParseGnList( options.extra_mapping_output_paths) if options.apply_mapping: options.apply_mapping = os.path.abspath(options.apply_mapping) return options
def main(argv): argv = build_utils.ExpandFileArgs(argv) parser = argparse.ArgumentParser(description=__doc__) build_utils.AddDepfileOption(parser) parser.add_argument('--build-vars', help='Path to GN build vars file', required=True) parser.add_argument('--root-manifest', help='Root manifest which to merge into', required=True) parser.add_argument('--expected-manifest', help='Expected contents for the merged manifest.') parser.add_argument('--normalized-output', help='Normalized merged manifest.') parser.add_argument( '--verify-expected-manifest', action='store_true', help='Fail if expected contents do not match merged manifest contents.' ) parser.add_argument('--output', help='Output manifest path', required=True) parser.add_argument('--extras', help='GN list of additional manifest to merge') args = parser.parse_args(argv) classpath = _BuildManifestMergerClasspath( build_utils.ReadBuildVars(args.build_vars)) with build_utils.AtomicOutput(args.output) as output: cmd = [ 'java', '-cp', classpath, _MANIFEST_MERGER_MAIN_CLASS, '--out', output.name, ] extras = build_utils.ParseGnList(args.extras) if extras: cmd += ['--libs', ':'.join(extras)] with _ProcessManifest(args.root_manifest) as tup: root_manifest, package = tup cmd += [ '--main', root_manifest, '--property', 'PACKAGE=' + package ] build_utils.CheckOutput( cmd, # https://issuetracker.google.com/issues/63514300: # The merger doesn't set a nonzero exit code for failures. fail_func=lambda returncode, stderr: returncode != 0 or build_utils.IsTimeStale(output.name, [root_manifest] + extras)) if args.expected_manifest: with build_utils.AtomicOutput( args.normalized_output) as normalized_output: normalized_output.write(_NormalizeManifest(args.output)) diff = diff_utils.DiffFileContents(args.expected_manifest, args.normalized_output) if diff: print """ {} Detected AndroidManifest change. Please update by running: cp {} {} See https://chromium.googlesource.com/chromium/src/+/HEAD/chrome/android/java/README.md for more info. """.format(diff, os.path.abspath(args.normalized_output), os.path.abspath(args.expected_manifest)) if args.verify_expected_manifest: sys.exit(1) if args.depfile: inputs = extras + classpath.split(':') build_utils.WriteDepfile(args.depfile, args.output, inputs=inputs, add_pydeps=False)
def main(args): args = build_utils.ExpandFileArgs(args) options = _ParseArgs(args) native_libs = sorted(options.native_libs) input_paths = [options.resource_apk, __file__] # Include native libs in the depfile_deps since GN doesn't know about the # dependencies when is_component_build=true. depfile_deps = list(native_libs) secondary_native_libs = [] if options.secondary_native_libs: secondary_native_libs = sorted(options.secondary_native_libs) depfile_deps += secondary_native_libs if options.dex_file: input_paths.append(options.dex_file) input_strings = [options.android_abi, options.native_lib_placeholders, options.secondary_native_lib_placeholders, str(options.uncompress_shared_libraries)] if options.secondary_android_abi: input_strings.append(options.secondary_android_abi) if options.java_resources: # Included via .build_config, so need to write it to depfile. depfile_deps.extend(options.java_resources) assets = _ExpandPaths(options.assets) uncompressed_assets = _ExpandPaths(options.uncompressed_assets) if options.apk_pak_info_path: pak_infos = _FilterPakInfoPaths( options.assets + options.uncompressed_assets) depfile_deps.extend(pak_infos) for src_path, dest_path in itertools.chain(assets, uncompressed_assets): # Included via .build_config, so need to write it to depfile. depfile_deps.append(src_path) input_strings.append(dest_path) output_paths = [options.output_apk] if options.apk_pak_info_path: output_paths.append(options.apk_pak_info_path) if options.apk_res_info_path: output_paths.append(options.apk_res_info_path) # Bundle modules have a structure similar to APKs, except that resources # are compiled in protobuf format (instead of binary xml), and that some # files are located into different top-level directories, e.g.: # AndroidManifest.xml -> manifest/AndroidManifest.xml # classes.dex -> dex/classes.dex # res/ -> res/ (unchanged) # assets/ -> assets/ (unchanged) # <other-file> -> root/<other-file> # # Hence, the following variables are used to control the location of files in # the final archive. if options.format == 'bundle-module': apk_manifest_dir = 'manifest/' apk_root_dir = 'root/' apk_dex_dir = 'dex/' else: apk_manifest_dir = '' apk_root_dir = '' apk_dex_dir = '' def on_stale_md5(): with tempfile.NamedTemporaryFile() as tmp_apk: tmp_file = tmp_apk.name with zipfile.ZipFile(options.resource_apk) as resource_apk, \ zipfile.ZipFile(tmp_file, 'w', zipfile.ZIP_DEFLATED) as out_apk: def copy_resource(zipinfo, out_dir=''): compress = zipinfo.compress_type != zipfile.ZIP_STORED build_utils.AddToZipHermetic(out_apk, out_dir + zipinfo.filename, data=resource_apk.read(zipinfo.filename), compress=compress) # Make assets come before resources in order to maintain the same file # ordering as GYP / aapt. http://crbug.com/561862 resource_infos = resource_apk.infolist() # 1. AndroidManifest.xml assert resource_infos[0].filename == 'AndroidManifest.xml' copy_resource(resource_infos[0], out_dir=apk_manifest_dir) # 2. Assets if options.write_asset_list: data = _CreateAssetsList( itertools.chain(assets, uncompressed_assets)) build_utils.AddToZipHermetic(out_apk, 'assets/assets_list', data=data) _AddAssets(out_apk, assets, disable_compression=False) _AddAssets(out_apk, uncompressed_assets, disable_compression=True) # 3. Dex files if options.dex_file and options.dex_file.endswith('.zip'): with zipfile.ZipFile(options.dex_file, 'r') as dex_zip: for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')): build_utils.AddToZipHermetic(out_apk, apk_dex_dir + dex, data=dex_zip.read(dex), compress=not options.uncompress_dex) elif options.dex_file: build_utils.AddToZipHermetic(out_apk, apk_dex_dir + 'classes.dex', src_path=options.dex_file, compress=not options.uncompress_dex) # 4. Native libraries. _AddNativeLibraries(out_apk, native_libs, options.android_abi, options.uncompress_shared_libraries) if options.secondary_android_abi: _AddNativeLibraries(out_apk, secondary_native_libs, options.secondary_android_abi, options.uncompress_shared_libraries) for name in sorted(options.native_lib_placeholders): # Note: Empty libs files are ignored by md5check (can cause issues # with stale builds when the only change is adding/removing # placeholders). apk_path = 'lib/%s/%s' % (options.android_abi, name) build_utils.AddToZipHermetic(out_apk, apk_path, data='') for name in sorted(options.secondary_native_lib_placeholders): # Note: Empty libs files are ignored by md5check (can cause issues # with stale builds when the only change is adding/removing # placeholders). apk_path = 'lib/%s/%s' % (options.secondary_android_abi, name) build_utils.AddToZipHermetic(out_apk, apk_path, data='') # 5. Resources for info in resource_infos[1:]: copy_resource(info) # 6. Java resources that should be accessible via # Class.getResourceAsStream(), in particular parts of Emma jar. # Prebuilt jars may contain class files which we shouldn't include. for java_resource in options.java_resources: with zipfile.ZipFile(java_resource, 'r') as java_resource_jar: for apk_path in java_resource_jar.namelist(): apk_path_lower = apk_path.lower() if apk_path_lower.startswith('meta-inf/'): continue if apk_path_lower.endswith('/'): continue if apk_path_lower.endswith('.class'): continue build_utils.AddToZipHermetic( out_apk, apk_root_dir + apk_path, data=java_resource_jar.read(apk_path)) if options.apk_pak_info_path: _MergePakInfoFiles(options.apk_pak_info_path, pak_infos) if options.apk_res_info_path: _MergeResInfoFiles(options.apk_res_info_path, options.resource_apk) if options.format == 'apk': finalize_apk.FinalizeApk(options.apksigner_path, options.zipalign_path, tmp_file, options.output_apk, options.key_path, options.key_passwd, options.key_name) else: shutil.move(tmp_file, options.output_apk) tmp_apk.delete = False build_utils.CallAndWriteDepfileIfStale( on_stale_md5, options, input_paths=input_paths + depfile_deps, input_strings=input_strings, output_paths=output_paths, depfile_deps=depfile_deps, add_pydeps=False)
def main(args): build_utils.InitLogging('APKBUILDER_DEBUG') args = build_utils.ExpandFileArgs(args) options = _ParseArgs(args) # Until Python 3.7, there's no better way to set compression level. # The default is 6. if options.best_compression: # Compresses about twice as slow as the default. zlib.Z_DEFAULT_COMPRESSION = 9 else: # Compresses about twice as fast as the default. zlib.Z_DEFAULT_COMPRESSION = 1 # Manually align only when alignment is necessary. # Python's zip implementation duplicates file comments in the central # directory, whereas zipalign does not, so use zipalign for official builds. fast_align = options.format == 'apk' and not options.best_compression native_libs = sorted(options.native_libs) # Include native libs in the depfile_deps since GN doesn't know about the # dependencies when is_component_build=true. depfile_deps = list(native_libs) # For targets that depend on static library APKs, dex paths are created by # the static library's dexsplitter target and GN doesn't know about these # paths. if options.dex_file: depfile_deps.append(options.dex_file) secondary_native_libs = [] if options.secondary_native_libs: secondary_native_libs = sorted(options.secondary_native_libs) depfile_deps += secondary_native_libs if options.java_resources: # Included via .build_config, so need to write it to depfile. depfile_deps.extend(options.java_resources) assets = _ExpandPaths(options.assets) uncompressed_assets = _ExpandPaths(options.uncompressed_assets) # Included via .build_config, so need to write it to depfile. depfile_deps.extend(x[0] for x in assets) depfile_deps.extend(x[0] for x in uncompressed_assets) # Bundle modules have a structure similar to APKs, except that resources # are compiled in protobuf format (instead of binary xml), and that some # files are located into different top-level directories, e.g.: # AndroidManifest.xml -> manifest/AndroidManifest.xml # classes.dex -> dex/classes.dex # res/ -> res/ (unchanged) # assets/ -> assets/ (unchanged) # <other-file> -> root/<other-file> # # Hence, the following variables are used to control the location of files in # the final archive. if options.format == 'bundle-module': apk_manifest_dir = 'manifest/' apk_root_dir = 'root/' apk_dex_dir = 'dex/' else: apk_manifest_dir = '' apk_root_dir = '' apk_dex_dir = '' def _GetAssetDetails(assets, uncompressed_assets, fast_align, allow_reads): asset_details = _GetAssetsToAdd(assets, fast_align, disable_compression=False, allow_reads=allow_reads) asset_details.extend( _GetAssetsToAdd(uncompressed_assets, fast_align, disable_compression=True, allow_reads=allow_reads)) return asset_details # We compute expectations without reading the files. This allows us to check # expectations for different targets by just generating their build_configs # and not have to first generate all the actual files and all their # dependencies (for example by just passing --only-verify-expectations). expectation_asset_details = _GetAssetDetails(assets, uncompressed_assets, fast_align, allow_reads=False) libs_to_add = _GetNativeLibrariesToAdd(native_libs, options.android_abi, options.uncompress_shared_libraries, fast_align) if options.secondary_android_abi: libs_to_add.extend( _GetNativeLibrariesToAdd(secondary_native_libs, options.secondary_android_abi, options.uncompress_shared_libraries, fast_align)) if options.expected_native_libs_and_assets: _VerifyNativeLibsAndAssets( libs_to_add, expectation_asset_details, options.expected_native_libs_and_assets, options.native_libs_and_assets_expectation_failure_file, options.fail_on_expectations) if options.only_verify_expectations: _MaybeWriteDepAndStampFiles(options, depfile_deps) return # If we are past this point, we are going to actually create the final apk so # we should recompute asset details again but maybe perform some optimizations # based on the size of the files on disk. assets_to_add = _GetAssetDetails(assets, uncompressed_assets, fast_align, allow_reads=True) # Targets generally do not depend on apks, so no need for only_if_changed. with build_utils.AtomicOutput(options.output_apk, only_if_changed=False) as f: with zipfile.ZipFile(options.resource_apk) as resource_apk, \ zipfile.ZipFile(f, 'w') as out_apk: def add_to_zip(zip_path, data, compress=True, alignment=4): zipalign.AddToZipHermetic( out_apk, zip_path, data=data, compress=compress, alignment=0 if compress and not fast_align else alignment) def copy_resource(zipinfo, out_dir=''): add_to_zip( out_dir + zipinfo.filename, resource_apk.read(zipinfo.filename), compress=zipinfo.compress_type != zipfile.ZIP_STORED) # Make assets come before resources in order to maintain the same file # ordering as GYP / aapt. http://crbug.com/561862 resource_infos = resource_apk.infolist() # 1. AndroidManifest.xml logging.debug('Adding AndroidManifest.xml') copy_resource(resource_apk.getinfo('AndroidManifest.xml'), out_dir=apk_manifest_dir) # 2. Assets logging.debug('Adding assets/') _AddFiles(out_apk, assets_to_add) # 3. Dex files logging.debug('Adding classes.dex') if options.dex_file: with open(options.dex_file) as dex_file_obj: if options.dex_file.endswith('.dex'): max_dex_number = 1 # This is the case for incremental_install=true. add_to_zip(apk_dex_dir + 'classes.dex', dex_file_obj.read(), compress=not options.uncompress_dex) else: max_dex_number = 0 with zipfile.ZipFile(dex_file_obj) as dex_zip: for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')): max_dex_number += 1 add_to_zip(apk_dex_dir + dex, dex_zip.read(dex), compress=not options.uncompress_dex) if options.jdk_libs_dex_file: with open(options.jdk_libs_dex_file) as dex_file_obj: add_to_zip(apk_dex_dir + 'classes{}.dex'.format(max_dex_number + 1), dex_file_obj.read(), compress=not options.uncompress_dex) # 4. Native libraries. logging.debug('Adding lib/') _AddFiles(out_apk, libs_to_add) # Add a placeholder lib if the APK should be multi ABI but is missing libs # for one of the ABIs. native_lib_placeholders = options.native_lib_placeholders secondary_native_lib_placeholders = ( options.secondary_native_lib_placeholders) if options.is_multi_abi: if ((secondary_native_libs or secondary_native_lib_placeholders) and not native_libs and not native_lib_placeholders): native_lib_placeholders += ['libplaceholder.so'] if ((native_libs or native_lib_placeholders) and not secondary_native_libs and not secondary_native_lib_placeholders): secondary_native_lib_placeholders += ['libplaceholder.so'] # Add placeholder libs. for name in sorted(native_lib_placeholders): # Note: Empty libs files are ignored by md5check (can cause issues # with stale builds when the only change is adding/removing # placeholders). apk_path = 'lib/%s/%s' % (options.android_abi, name) add_to_zip(apk_path, '', alignment=0x1000) for name in sorted(secondary_native_lib_placeholders): # Note: Empty libs files are ignored by md5check (can cause issues # with stale builds when the only change is adding/removing # placeholders). apk_path = 'lib/%s/%s' % (options.secondary_android_abi, name) add_to_zip(apk_path, '', alignment=0x1000) # 5. Resources logging.debug('Adding res/') for info in sorted(resource_infos, key=lambda i: i.filename): if info.filename != 'AndroidManifest.xml': copy_resource(info) # 6. Java resources that should be accessible via # Class.getResourceAsStream(), in particular parts of Emma jar. # Prebuilt jars may contain class files which we shouldn't include. logging.debug('Adding Java resources') for java_resource in options.java_resources: with zipfile.ZipFile(java_resource, 'r') as java_resource_jar: for apk_path in sorted(java_resource_jar.namelist()): apk_path_lower = apk_path.lower() if apk_path_lower.startswith('meta-inf/'): continue if apk_path_lower.endswith('/'): continue if apk_path_lower.endswith('.class'): continue add_to_zip(apk_root_dir + apk_path, java_resource_jar.read(apk_path)) if options.format == 'apk': zipalign_path = None if fast_align else options.zipalign_path finalize_apk.FinalizeApk(options.apksigner_jar, zipalign_path, f.name, f.name, options.key_path, options.key_passwd, options.key_name, int(options.min_sdk_version)) logging.debug('Moving file into place') _MaybeWriteDepAndStampFiles(options, depfile_deps)
def main(argv): logging.basicConfig( level=logging.INFO if os.environ.get('_JAVAC_DEBUG') else logging.WARNING, format='%(levelname).1s %(relativeCreated)6d %(message)s') colorama.init() argv = build_utils.ExpandFileArgs(argv) options, java_files = _ParseOptions(argv) # Until we add a version of javac via DEPS, use errorprone with all checks # disabled rather than javac. This ensures builds are reproducible. # https://crbug.com/693079 # As of Jan 2019, on a z920, compiling chrome_java times: # * With javac: 17 seconds # * With errorprone (checks disabled): 20 seconds # * With errorprone (checks enabled): 30 seconds if options.errorprone_path: javac_path = options.errorprone_path else: javac_path = distutils.spawn.find_executable('javac') javac_cmd = [ javac_path, '-g', # Chromium only allows UTF8 source files. Being explicit avoids # javac pulling a default encoding from the user's environment. '-encoding', 'UTF-8', # Prevent compiler from compiling .java files not listed as inputs. # See: http://blog.ltgt.net/most-build-tools-misuse-javac/ '-sourcepath', ':', ] if options.enable_errorprone: for warning in ERRORPRONE_WARNINGS_TO_TURN_OFF: javac_cmd.append('-Xep:{}:OFF'.format(warning)) for warning in ERRORPRONE_WARNINGS_TO_ERROR: javac_cmd.append('-Xep:{}:ERROR'.format(warning)) elif options.errorprone_path: javac_cmd.append('-XepDisableAllChecks') if options.java_version: javac_cmd.extend([ '-source', options.java_version, '-target', options.java_version, ]) if options.chromium_code: javac_cmd.extend(['-Xlint:unchecked', '-Werror']) else: # XDignore.symbol.file makes javac compile against rt.jar instead of # ct.sym. This means that using a java internal package/class will not # trigger a compile warning or error. javac_cmd.extend(['-XDignore.symbol.file']) if options.processors: javac_cmd.extend(['-processor', ','.join(options.processors)]) if options.bootclasspath: javac_cmd.extend(['-bootclasspath', ':'.join(options.bootclasspath)]) # Annotation processors crash when given interface jars. active_classpath = ( options.full_classpath if options.processors else options.interface_classpath) classpath = [] if active_classpath: classpath.extend(active_classpath) if options.processorpath: javac_cmd.extend(['-processorpath', ':'.join(options.processorpath)]) if options.processor_args: for arg in options.processor_args: javac_cmd.extend(['-A%s' % arg]) javac_cmd.extend(options.javac_arg) classpath_inputs = (options.bootclasspath + options.interface_classpath + options.processorpath) # GN already knows of java_files, so listing them just make things worse when # they change. depfile_deps = [javac_path] + classpath_inputs + options.java_srcjars input_paths = depfile_deps + java_files output_paths = [ options.jar_path, options.jar_path + '.info', ] if options.incremental: output_paths.append(options.jar_path + '.pdb') # An escape hatch to be able to check if incremental compiles are causing # problems. force = int(os.environ.get('DISABLE_INCREMENTAL_JAVAC', 0)) # List python deps in input_strings rather than input_paths since the contents # of them does not change what gets written to the depsfile. build_utils.CallAndWriteDepfileIfStale( lambda changes: _OnStaleMd5(changes, options, javac_cmd, java_files, classpath_inputs, classpath), options, depfile_deps=depfile_deps, input_paths=input_paths, input_strings=javac_cmd + classpath, output_paths=output_paths, force=force, pass_changes=True, add_pydeps=False) logging.info('Script complete: %s', __file__)
def _ParseArgs(argv): parser = argparse.ArgumentParser() build_utils.AddDepfileOption(parser) parser.add_argument('--target-name', help='Fully qualified GN target name.') parser.add_argument('--skip-build-server', action='store_true', help='Avoid using the build server.') parser.add_argument('--lint-binary-path', required=True, help='Path to lint executable.') parser.add_argument('--backported-methods', help='Path to backported methods file created by R8.') parser.add_argument( '--cache-dir', required=True, help='Path to the directory in which the android cache ' 'directory tree should be stored.') parser.add_argument('--config-path', help='Path to lint suppressions file.') parser.add_argument('--lint-gen-dir', required=True, help='Path to store generated xml files.') parser.add_argument('--stamp', help='Path to stamp upon success.') parser.add_argument('--android-sdk-version', help='Version (API level) of the Android SDK used for ' 'building.') parser.add_argument('--min-sdk-version', required=True, help='Minimal SDK version to lint against.') parser.add_argument('--android-sdk-root', required=True, help='Lint needs an explicit path to the android sdk.') parser.add_argument( '--testonly', action='store_true', help='If set, some checks like UnusedResources will be ' 'disabled since they are not helpful for test ' 'targets.') parser.add_argument( '--create-cache', action='store_true', help='Whether this invocation is just warming the cache.') parser.add_argument('--warnings-as-errors', action='store_true', help='Treat all warnings as errors.') parser.add_argument('--java-sources', help='File containing a list of java sources files.') parser.add_argument('--aars', help='GN list of included aars.') parser.add_argument('--srcjars', help='GN list of included srcjars.') parser.add_argument('--manifest-path', help='Path to original AndroidManifest.xml') parser.add_argument('--extra-manifest-paths', action='append', help='GYP-list of manifest paths to merge into the ' 'original AndroidManifest.xml') parser.add_argument('--resource-sources', default=[], action='append', help='GYP-list of resource sources files, similar to ' 'java sources files, but for resource files.') parser.add_argument( '--resource-zips', default=[], action='append', help='GYP-list of resource zips, zip files of generated ' 'resource files.') parser.add_argument('--classpath', help='List of jars to add to the classpath.') parser.add_argument( '--baseline', help='Baseline file to ignore existing errors and fail ' 'on new errors.') args = parser.parse_args(build_utils.ExpandFileArgs(argv)) args.java_sources = build_utils.ParseGnList(args.java_sources) args.aars = build_utils.ParseGnList(args.aars) args.srcjars = build_utils.ParseGnList(args.srcjars) args.resource_sources = build_utils.ParseGnList(args.resource_sources) args.extra_manifest_paths = build_utils.ParseGnList( args.extra_manifest_paths) args.resource_zips = build_utils.ParseGnList(args.resource_zips) args.classpath = build_utils.ParseGnList(args.classpath) return args
def main(argv): build_utils.InitLogging('JAVAC_DEBUG') argv = build_utils.ExpandFileArgs(argv) options, java_files = _ParseOptions(argv) # Only use the build server for errorprone runs. if (options.enable_errorprone and not options.skip_build_server and server_utils.MaybeRunCommand(name=options.target_name, argv=sys.argv, stamp_file=options.jar_path)): return javac_cmd = [] if options.gomacc_path: javac_cmd.append(options.gomacc_path) javac_cmd.append(build_utils.JAVAC_PATH) javac_args = [ '-g', # Chromium only allows UTF8 source files. Being explicit avoids # javac pulling a default encoding from the user's environment. '-encoding', 'UTF-8', # Prevent compiler from compiling .java files not listed as inputs. # See: http://blog.ltgt.net/most-build-tools-misuse-javac/ '-sourcepath', ':', ] if options.enable_errorprone: # All errorprone args are passed space-separated in a single arg. errorprone_flags = ['-Xplugin:ErrorProne'] # Make everything a warning so that when treat_warnings_as_errors is false, # they do not fail the build. errorprone_flags += ['-XepAllErrorsAsWarnings'] # Don't check generated files. errorprone_flags += ['-XepDisableWarningsInGeneratedCode'] errorprone_flags.extend('-Xep:{}:OFF'.format(x) for x in ERRORPRONE_WARNINGS_TO_DISABLE) errorprone_flags.extend('-Xep:{}:WARN'.format(x) for x in ERRORPRONE_WARNINGS_TO_ENABLE) if ERRORPRONE_CHECKS_TO_APPLY: errorprone_flags += [ '-XepPatchLocation:IN_PLACE', '-XepPatchChecks:,' + ','.join(ERRORPRONE_CHECKS_TO_APPLY) ] javac_args += ['-XDcompilePolicy=simple', ' '.join(errorprone_flags)] # This flag quits errorprone after checks and before code generation, since # we do not need errorprone outputs, this speeds up errorprone by 4 seconds # for chrome_java. if not ERRORPRONE_CHECKS_TO_APPLY: javac_args += ['-XDshould-stop.ifNoError=FLOW'] if options.java_version: javac_args.extend([ '-source', options.java_version, '-target', options.java_version, ]) if options.java_version == '1.8': # Android's boot jar doesn't contain all java 8 classes. options.bootclasspath.append(build_utils.RT_JAR_PATH) # This effectively disables all annotation processors, even including # annotation processors in service provider configuration files named # META-INF/. See the following link for reference: # https://docs.oracle.com/en/java/javase/11/tools/javac.html javac_args.extend(['-proc:none']) if options.bootclasspath: javac_args.extend(['-bootclasspath', ':'.join(options.bootclasspath)]) if options.processorpath: javac_args.extend(['-processorpath', ':'.join(options.processorpath)]) if options.processor_args: for arg in options.processor_args: javac_args.extend(['-A%s' % arg]) javac_args.extend(options.javac_arg) classpath_inputs = (options.bootclasspath + options.classpath + options.processorpath) depfile_deps = classpath_inputs # Files that are already inputs in GN should go in input_paths. input_paths = depfile_deps + options.java_srcjars + java_files if options.header_jar: input_paths.append(options.header_jar) input_paths += [x[0] for x in options.additional_jar_files] output_paths = [options.jar_path] if not options.enable_errorprone: output_paths += [options.jar_path + '.info'] input_strings = javac_cmd + javac_args + options.classpath + java_files + [ options.warnings_as_errors, options.jar_info_exclude_globs ] # Use md5_check for |pass_changes| feature. md5_check.CallAndWriteDepfileIfStale(lambda changes: _OnStaleMd5( changes, options, javac_cmd, javac_args, java_files), options, depfile_deps=depfile_deps, input_paths=input_paths, input_strings=input_strings, output_paths=output_paths, pass_changes=True)
def _ParseOptions(): args = build_utils.ExpandFileArgs(sys.argv[1:]) parser = argparse.ArgumentParser() build_utils.AddDepfileOption(parser) parser.add_argument('--r8-path', required=True, help='Path to the R8.jar to use.') parser.add_argument('--desugar-jdk-libs-json', help='Path to desugar_jdk_libs.json.') parser.add_argument('--input-paths', action='append', required=True, help='GN-list of .jar files to optimize.') parser.add_argument('--desugar-jdk-libs-jar', help='Path to desugar_jdk_libs.jar.') parser.add_argument('--desugar-jdk-libs-configuration-jar', help='Path to desugar_jdk_libs_configuration.jar.') parser.add_argument('--output-path', help='Path to the generated .jar file.') parser.add_argument('--proguard-configs', action='append', required=True, help='GN-list of configuration files.') parser.add_argument('--apply-mapping', help='Path to ProGuard mapping to apply.') parser.add_argument('--mapping-output', required=True, help='Path for ProGuard to output mapping file to.') parser.add_argument( '--extra-mapping-output-paths', help='GN-list of additional paths to copy output mapping file to.') parser.add_argument('--classpath', action='append', help='GN-list of .jar files to include as libraries.') parser.add_argument('--main-dex-rules-path', action='append', help='Path to main dex rules for multidex' '- only works with R8.') parser.add_argument('--min-api', help='Minimum Android API level compatibility.') parser.add_argument('--verbose', '-v', action='store_true', help='Print all ProGuard output') parser.add_argument('--repackage-classes', help='Package all optimized classes are put in.') parser.add_argument( '--disable-outlining', action='store_true', help='Disable the outlining optimization provided by R8.') parser.add_argument( '--disable-checks', action='store_true', help='Disable -checkdiscard directives and missing symbols check') parser.add_argument('--sourcefile', help='Value for source file attribute') parser.add_argument( '--force-enable-assertions', action='store_true', help='Forcefully enable javac generated assertion code.') parser.add_argument( '--feature-jars', action='append', help='GN list of path to jars which comprise the corresponding feature.' ) parser.add_argument( '--dex-dest', action='append', dest='dex_dests', help='Destination for dex file of the corresponding feature.') parser.add_argument('--feature-name', action='append', dest='feature_names', help='The name of the feature module.') parser.add_argument( '--uses-split', action='append', help='List of name pairs separated by : mapping a feature module to a ' 'dependent feature module.') parser.add_argument('--warnings-as-errors', action='store_true', help='Treat all warnings as errors.') parser.add_argument('--show-desugar-default-interface-warnings', action='store_true', help='Enable desugaring warnings.') parser.add_argument('--dump-inputs', action='store_true', help='Use when filing R8 bugs to capture inputs.' ' Stores inputs to r8inputs.zip') parser.add_argument( '--stamp', help='File to touch upon success. Mutually exclusive with --output-path' ) parser.add_argument( '--desugared-library-keep-rule-output', help='Path to desugared library keep rule output file.') diff_utils.AddCommandLineFlags(parser) options = parser.parse_args(args) if options.feature_names: if options.output_path: parser.error('Feature splits cannot specify an output in GN.') if not options.actual_file and not options.stamp: parser.error('Feature splits require a stamp file as output.') elif not options.output_path: parser.error('Output path required when feature splits aren\'t used') options.classpath = build_utils.ParseGnList(options.classpath) options.proguard_configs = build_utils.ParseGnList( options.proguard_configs) options.input_paths = build_utils.ParseGnList(options.input_paths) options.extra_mapping_output_paths = build_utils.ParseGnList( options.extra_mapping_output_paths) if options.feature_names: if 'base' not in options.feature_names: parser.error( '"base" feature required when feature arguments are used.') if len(options.feature_names) != len(options.feature_jars) or len( options.feature_names) != len(options.dex_dests): parser.error('Invalid feature argument lengths.') options.feature_jars = [ build_utils.ParseGnList(x) for x in options.feature_jars ] split_map = {} if options.uses_split: for split_pair in options.uses_split: child, parent = split_pair.split(':') for name in (child, parent): if name not in options.feature_names: parser.error( '"%s" referenced in --uses-split not present.' % name) split_map[child] = parent options.uses_split = split_map return options
def main(argv): colorama.init() argv = build_utils.ExpandFileArgs(argv) options, java_files = _ParseOptions(argv) if options.use_errorprone_path: javac_path = options.use_errorprone_path else: javac_path = distutils.spawn.find_executable('javac') javac_cmd = [javac_path] javac_cmd.extend(( '-g', # Chromium only allows UTF8 source files. Being explicit avoids # javac pulling a default encoding from the user's environment. '-encoding', 'UTF-8', # Prevent compiler from compiling .java files not listed as inputs. # See: http://blog.ltgt.net/most-build-tools-misuse-javac/ '-sourcepath', ':', )) if options.use_errorprone_path: for warning in ERRORPRONE_WARNINGS_TO_TURN_OFF: javac_cmd.append('-Xep:{}:OFF'.format(warning)) for warning in ERRORPRONE_WARNINGS_TO_ERROR: javac_cmd.append('-Xep:{}:ERROR'.format(warning)) if options.java_version: javac_cmd.extend([ '-source', options.java_version, '-target', options.java_version, ]) if options.chromium_code: javac_cmd.extend(['-Xlint:unchecked', '-Werror']) else: # XDignore.symbol.file makes javac compile against rt.jar instead of # ct.sym. This means that using a java internal package/class will not # trigger a compile warning or error. javac_cmd.extend(['-XDignore.symbol.file']) if options.processors: javac_cmd.extend(['-processor', ','.join(options.processors)]) if options.bootclasspath: javac_cmd.extend(['-bootclasspath', ':'.join(options.bootclasspath)]) # Annotation processors crash when given interface jars. active_classpath = (options.full_classpath if options.processors else options.interface_classpath) classpath = [] if active_classpath: classpath.extend(active_classpath) if options.processorpath: javac_cmd.extend(['-processorpath', ':'.join(options.processorpath)]) if options.processor_args: for arg in options.processor_args: javac_cmd.extend(['-A%s' % arg]) javac_cmd.extend(options.javac_arg) classpath_inputs = (options.bootclasspath + options.interface_classpath + options.processorpath) # GN already knows of java_files, so listing them just make things worse when # they change. depfile_deps = [javac_path] + classpath_inputs + options.java_srcjars input_paths = depfile_deps + java_files output_paths = [ options.jar_path, options.jar_path + '.info', ] if options.incremental: output_paths.append(options.jar_path + '.pdb') # An escape hatch to be able to check if incremental compiles are causing # problems. force = int(os.environ.get('DISABLE_INCREMENTAL_JAVAC', 0)) # List python deps in input_strings rather than input_paths since the contents # of them does not change what gets written to the depsfile. build_utils.CallAndWriteDepfileIfStale(lambda changes: _OnStaleMd5( changes, options, javac_cmd, java_files, classpath_inputs, classpath), options, depfile_deps=depfile_deps, input_paths=input_paths, input_strings=javac_cmd + classpath, output_paths=output_paths, force=force, pass_changes=True)
def main(argv): arg_parser = argparse.ArgumentParser() build_utils.AddDepfileOption(arg_parser) arg_parser.add_argument( '--sources-files', required=True, action='append', help='A list of .sources files which contain Java ' 'file paths.') arg_parser.add_argument( '--header-path', help='Path to output header file (optional).') arg_parser.add_argument( '--srcjar-path', required=True, help='Path to output srcjar for GEN_JNI.java (and J/N.java if proxy' ' hash is enabled).') arg_parser.add_argument( '--sources-exclusions', default=[], help='A list of Java files which should be ignored ' 'by the parser.') arg_parser.add_argument( '--namespace', default='', help='Namespace to wrap the registration functions ' 'into.') # TODO(crbug.com/898261) hook these flags up to the build config to enable # mocking in instrumentation tests arg_parser.add_argument( '--enable_proxy_mocks', default=False, action='store_true', help='Allows proxy native impls to be mocked through Java.') arg_parser.add_argument( '--require_mocks', default=False, action='store_true', help='Requires all used native implementations to have a mock set when ' 'called. Otherwise an exception will be thrown.') arg_parser.add_argument( '--use_proxy_hash', action='store_true', help='Enables hashing of the native declaration for methods in ' 'an @JniNatives interface') args = arg_parser.parse_args(build_utils.ExpandFileArgs(argv[1:])) if not args.enable_proxy_mocks and args.require_mocks: arg_parser.error( 'Invalid arguments: --require_mocks without --enable_proxy_mocks. ' 'Cannot require mocks if they are not enabled.') sources_files = sorted(set(build_utils.ParseGnList(args.sources_files))) proxy_opts = ProxyOptions( use_hash=args.use_proxy_hash, require_mocks=args.require_mocks, enable_mocks=args.enable_proxy_mocks) java_file_paths = [] for f in sources_files: # Skip generated files, since the GN targets do not declare any deps. java_file_paths.extend( p for p in build_utils.ReadSourcesList(f) if p.startswith('..') and p not in args.sources_exclusions) _Generate( java_file_paths, args.srcjar_path, proxy_opts=proxy_opts, header_path=args.header_path, namespace=args.namespace) if args.depfile: build_utils.WriteDepfile(args.depfile, args.srcjar_path, sources_files + java_file_paths)
def main(argv): build_utils.InitLogging('JAVAC_DEBUG') colorama.init() argv = build_utils.ExpandFileArgs(argv) options, java_files = _ParseOptions(argv) javac_path = build_utils.JAVAC_PATH javac_cmd = [ javac_path, '-g', # Chromium only allows UTF8 source files. Being explicit avoids # javac pulling a default encoding from the user's environment. '-encoding', 'UTF-8', # Prevent compiler from compiling .java files not listed as inputs. # See: http://blog.ltgt.net/most-build-tools-misuse-javac/ '-sourcepath', ':', ] if options.enable_errorprone: # All errorprone args are passed space-separated in a single arg. errorprone_flags = ['-Xplugin:ErrorProne'] for warning in ERRORPRONE_WARNINGS_TO_TURN_OFF: errorprone_flags.append('-Xep:{}:OFF'.format(warning)) for warning in ERRORPRONE_WARNINGS_TO_ERROR: errorprone_flags.append('-Xep:{}:ERROR'.format(warning)) if not options.warnings_as_errors: errorprone_flags.append('-XepAllErrorsAsWarnings') javac_cmd += ['-XDcompilePolicy=simple', ' '.join(errorprone_flags)] if options.java_version: javac_cmd.extend([ '-source', options.java_version, '-target', options.java_version, ]) if options.java_version == '1.8': # Android's boot jar doesn't contain all java 8 classes. options.bootclasspath.append(build_utils.RT_JAR_PATH) if options.warnings_as_errors: javac_cmd.extend(['-Werror']) else: # XDignore.symbol.file makes javac compile against rt.jar instead of # ct.sym. This means that using a java internal package/class will not # trigger a compile warning or error. javac_cmd.extend(['-XDignore.symbol.file']) if options.processors: javac_cmd.extend(['-processor', ','.join(options.processors)]) if options.bootclasspath: javac_cmd.extend(['-bootclasspath', ':'.join(options.bootclasspath)]) if options.processorpath: javac_cmd.extend(['-processorpath', ':'.join(options.processorpath)]) if options.processor_args: for arg in options.processor_args: javac_cmd.extend(['-A%s' % arg]) javac_cmd.extend(options.javac_arg) classpath_inputs = (options.bootclasspath + options.classpath + options.processorpath) # GN already knows of java_files, so listing them just make things worse when # they change. depfile_deps = classpath_inputs + options.java_srcjars input_paths = depfile_deps + java_files input_paths += [x[0] for x in options.additional_jar_files] output_paths = [ options.jar_path, options.jar_path + '.info', ] input_strings = javac_cmd + options.classpath + java_files if options.jar_info_exclude_globs: input_strings.append(options.jar_info_exclude_globs) md5_check.CallAndWriteDepfileIfStale( lambda: _OnStaleMd5(options, javac_cmd, java_files, options.classpath), options, depfile_deps=depfile_deps, input_paths=input_paths, input_strings=input_strings, output_paths=output_paths)
def main(args): args = build_utils.ExpandFileArgs(args) options = _ParseArgs(args) path = options.arsc_path or options.proto_path debug_temp_resources_dir = os.environ.get(_ENV_DEBUG_VARIABLE) if debug_temp_resources_dir: path = os.path.join(debug_temp_resources_dir, os.path.basename(path)) else: # Use a deterministic temp directory since .pb files embed the absolute # path of resources: crbug.com/939984 path = path + '.tmpdir' build_utils.DeleteDirectory(path) build_utils.MakeDirectory(path) with resource_utils.BuildContext( temp_dir=path, keep_files=bool(debug_temp_resources_dir)) as build: manifest_package_name = _PackageApk(options, build) # If --shared-resources-whitelist is used, the all resources listed in # the corresponding R.txt file will be non-final, and an onResourcesLoaded() # will be generated to adjust them at runtime. # # Otherwise, if --shared-resources is used, the all resources will be # non-final, and an onResourcesLoaded() method will be generated too. # # Otherwise, all resources will be final, and no method will be generated. # rjava_build_options = resource_utils.RJavaBuildOptions() if options.shared_resources_whitelist: rjava_build_options.ExportSomeResources( options.shared_resources_whitelist) rjava_build_options.GenerateOnResourcesLoaded() elif options.shared_resources or options.app_as_shared_lib: rjava_build_options.ExportAllResources() rjava_build_options.GenerateOnResourcesLoaded() custom_root_package_name = options.r_java_root_package_name grandparent_custom_package_name = None if options.package_name and not options.arsc_package_name: # Feature modules have their own custom root package name and should # inherit from the appropriate base module package. This behaviour should # not be present for test apks with an apk under test. Thus, # arsc_package_name is used as it is only defined for test apks with an # apk under test. custom_root_package_name = options.package_name grandparent_custom_package_name = options.r_java_root_package_name if options.shared_resources or options.app_as_shared_lib: package_for_library = manifest_package_name else: package_for_library = None resource_utils.CreateRJavaFiles( build.srcjar_dir, package_for_library, build.r_txt_path, options.extra_res_packages, options.extra_r_text_files, rjava_build_options, options.srcjar_out, custom_root_package_name, grandparent_custom_package_name, options.extra_main_r_text_files) build_utils.ZipDir(build.srcjar_path, build.srcjar_dir) # Sanity check that the created resources have the expected package ID. if options.package_id: expected_id = options.package_id elif options.shared_resources: expected_id = 0 else: expected_id = 127 # == '0x7f'. _, package_id = resource_utils.ExtractArscPackage( options.aapt2_path, build.arsc_path if options.arsc_path else build.proto_path) if package_id != expected_id: raise Exception( 'Invalid package ID 0x%x (expected 0x%x)' % (package_id, expected_id)) _WriteOutputs(options, build) if options.depfile: build_utils.WriteDepfile( options.depfile, options.srcjar_out, inputs=options.dependencies_res_zips + options.extra_r_text_files, add_pydeps=False)
def main(argv): colorama.init() argv = build_utils.ExpandFileArgs(argv) options, java_files = _ParseOptions(argv) if options.src_gendirs: java_files += build_utils.FindInDirectories(options.src_gendirs, '*.java') java_files = _FilterJavaFiles(java_files, options.javac_includes) javac_cmd = ['javac'] if options.use_errorprone_path: javac_cmd = [options.use_errorprone_path] + ERRORPRONE_OPTIONS javac_cmd.extend(( '-g', # Chromium only allows UTF8 source files. Being explicit avoids # javac pulling a default encoding from the user's environment. '-encoding', 'UTF-8', # Make sure we do not pass an empty string to -classpath and -sourcepath. '-classpath', ':'.join(options.classpath) or ':', # Prevent compiler from compiling .java files not listed as inputs. # See: http://blog.ltgt.net/most-build-tools-misuse-javac/ '-sourcepath', ':', )) if options.bootclasspath: javac_cmd.extend(['-bootclasspath', ':'.join(options.bootclasspath)]) if options.java_version: javac_cmd.extend([ '-source', options.java_version, '-target', options.java_version, ]) if options.chromium_code: javac_cmd.extend(['-Xlint:unchecked', '-Xlint:deprecation']) else: # XDignore.symbol.file makes javac compile against rt.jar instead of # ct.sym. This means that using a java internal package/class will not # trigger a compile warning or error. javac_cmd.extend(['-XDignore.symbol.file']) if options.processors: javac_cmd.extend(['-processor', ','.join(options.processors)]) if options.processor_args: for arg in options.processor_args: javac_cmd.extend(['-A%s' % arg]) classpath_inputs = options.bootclasspath if options.classpath: if options.classpath[0].endswith('.interface.jar'): classpath_inputs.extend(options.classpath) else: # TODO(agrieve): Remove this .TOC heuristic once GYP is no more. for path in options.classpath: if os.path.exists(path + '.TOC'): classpath_inputs.append(path + '.TOC') else: classpath_inputs.append(path) # Compute the list of paths that when changed, we need to rebuild. input_paths = classpath_inputs + options.java_srcjars + java_files output_paths = [ options.jar_path, options.jar_path.replace('.jar', '.excluded.jar'), ] if options.incremental: output_paths.append(options.jar_path + '.pdb') # An escape hatch to be able to check if incremental compiles are causing # problems. force = int(os.environ.get('DISABLE_INCREMENTAL_JAVAC', 0)) # List python deps in input_strings rather than input_paths since the contents # of them does not change what gets written to the depsfile. build_utils.CallAndWriteDepfileIfStale(lambda changes: _OnStaleMd5( changes, options, javac_cmd, java_files, classpath_inputs), options, input_paths=input_paths, input_strings=javac_cmd, output_paths=output_paths, force=force, pass_changes=True)
def main(args): args = build_utils.ExpandFileArgs(args) options = _ParseArgs(args) debug_temp_resources_dir = os.environ.get(_ENV_DEBUG_VARIABLE) if debug_temp_resources_dir: debug_temp_resources_dir = os.path.join( debug_temp_resources_dir, os.path.basename(options.arsc_path)) build_utils.DeleteDirectory(debug_temp_resources_dir) build_utils.MakeDirectory(debug_temp_resources_dir) with resource_utils.BuildContext(debug_temp_resources_dir) as build: _PackageApk(options, build) # If --shared-resources-whitelist is used, the all resources listed in # the corresponding R.txt file will be non-final, and an onResourcesLoaded() # will be generated to adjust them at runtime. # # Otherwise, if --shared-resources is used, the all resources will be # non-final, and an onResourcesLoaded() method will be generated too. # # Otherwise, all resources will be final, and no method will be generated. # rjava_build_options = resource_utils.RJavaBuildOptions() if options.shared_resources_whitelist: rjava_build_options.ExportSomeResources( options.shared_resources_whitelist) rjava_build_options.GenerateOnResourcesLoaded() elif options.shared_resources or options.app_as_shared_lib: rjava_build_options.ExportAllResources() rjava_build_options.GenerateOnResourcesLoaded() resource_utils.CreateRJavaFiles(build.srcjar_dir, None, build.r_txt_path, options.extra_res_packages, options.extra_r_text_files, rjava_build_options) if options.srcjar_out: build_utils.ZipDir(build.srcjar_path, build.srcjar_dir) # Sanity check that the created resources have the expected package ID. expected_id = _PackageIdFromOptions(options) if expected_id is None: expected_id = '0x00' if options.shared_resources else '0x7f' expected_id = int(expected_id, 16) _, package_id = resource_utils.ExtractArscPackage( options.aapt2_path, build.arsc_path if options.arsc_path else build.proto_path) if package_id != expected_id: raise Exception('Invalid package ID 0x%x (expected 0x%x)' % (package_id, expected_id)) _WriteOutputs(options, build) if options.depfile: build_utils.WriteDepfile(options.depfile, options.arsc_path or options.proto_path, inputs=options.dependencies_res_zips + options.extra_r_text_files, add_pydeps=False)