diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-05-17 17:24:03 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-06-22 07:51:41 +0000 |
commit | 774f54339e5db91f785733232d3950366db65d07 (patch) | |
tree | 068e1b47bd1af94d77094ed12b604a6b83d9c22a /chromium/build/android/gyp/dex.py | |
parent | f7eaed5286974984ba5f9e3189d8f49d03e99f81 (diff) |
BASELINE: Update Chromium to 102.0.5005.57
Change-Id: I885f714bb40ee724c28f94ca6bd8dbdb39915158
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/build/android/gyp/dex.py')
-rwxr-xr-x | chromium/build/android/gyp/dex.py | 246 |
1 files changed, 53 insertions, 193 deletions
diff --git a/chromium/build/android/gyp/dex.py b/chromium/build/android/gyp/dex.py index 49deee4a8ca..883e0faac64 100755 --- a/chromium/build/android/gyp/dex.py +++ b/chromium/build/android/gyp/dex.py @@ -18,10 +18,6 @@ from util import build_utils from util import md5_check from util import zipalign -sys.path.insert(1, os.path.join(os.path.dirname(__file__), os.path.pardir)) - -import convert_dex_profile - _DEX_XMX = '2G' # Increase this when __final_dex OOMs. @@ -46,6 +42,11 @@ _IGNORE_WARNINGS = ( # desugar doesn't preserve interfaces in the same way. This should be # removed when D8 is used for desugaring. r'Warning: Cannot emulate interface ', + # Desugaring configs may occasionally not match types in our program. This + # may happen temporarily until we move over to the new desugared library + # json flags. See crbug.com/1302088 - this should be removed when this bug + # is fixed. + r'Warning: Specification conversion: The following prefixes do not match any type:', # pylint: disable=line-too-long # Only relevant for R8 when optimizing an app that doesn't use proto. r'Ignoring -shrinkunusedprotofields since the protobuf-lite runtime is', ) @@ -131,37 +132,8 @@ def _ParseArgs(args): action='store_true', help='Use when filing D8 bugs to capture inputs.' ' Stores inputs to d8inputs.zip') - - group = parser.add_argument_group('Dexlayout') - group.add_argument( - '--dexlayout-profile', - help=('Text profile for dexlayout. If present, a dexlayout ' - 'pass will happen')) - group.add_argument( - '--profman-path', - help=('Path to ART profman binary. There should be a lib/ directory at ' - 'the same path with shared libraries (shared with dexlayout).')) - group.add_argument( - '--dexlayout-path', - help=('Path to ART dexlayout binary. There should be a lib/ directory at ' - 'the same path with shared libraries (shared with dexlayout).')) - group.add_argument('--dexdump-path', help='Path to dexdump binary.') - group.add_argument( - '--proguard-mapping-path', - help=('Path to proguard map from obfuscated symbols in the jar to ' - 'unobfuscated symbols present in the code. If not present, the jar ' - 'is assumed not to be obfuscated.')) - options = parser.parse_args(args) - if options.dexlayout_profile: - build_utils.CheckOptions( - options, - parser, - required=('profman_path', 'dexlayout_path', 'dexdump_path')) - elif options.proguard_mapping_path is not None: - parser.error('Unexpected proguard mapping without dexlayout') - if options.main_dex_rules_path and not options.multi_dex: parser.error('--main-dex-rules-path is unused if multidex is not enabled') @@ -223,14 +195,23 @@ def _RunD8(dex_cmd, input_paths, output_path, warnings_as_errors, stderr_filter = CreateStderrFilter(show_desugar_default_interface_warnings) - with tempfile.NamedTemporaryFile(mode='w') as flag_file: + is_debug = logging.getLogger().isEnabledFor(logging.DEBUG) + + # Avoid deleting the flag file when DEX_DEBUG is set in case the flag file + # needs to be examined after the build. + with tempfile.NamedTemporaryFile(mode='w', delete=not is_debug) as flag_file: # Chosen arbitrarily. Needed to avoid command-line length limits. MAX_ARGS = 50 if len(dex_cmd) > MAX_ARGS: - flag_file.write('\n'.join(dex_cmd[MAX_ARGS:])) - flag_file.flush() - dex_cmd = dex_cmd[:MAX_ARGS] - dex_cmd.append('@' + flag_file.name) + # Add all flags to D8 (anything after the first --) as well as all + # positional args at the end to the flag file. + for idx, cmd in enumerate(dex_cmd): + if cmd.startswith('--'): + flag_file.write('\n'.join(dex_cmd[idx:])) + flag_file.flush() + dex_cmd = dex_cmd[:idx] + dex_cmd.append('@' + flag_file.name) + break # stdout sometimes spams with things like: # Stripped invalid locals information from 1 method. @@ -239,128 +220,6 @@ def _RunD8(dex_cmd, input_paths, output_path, warnings_as_errors, fail_on_output=warnings_as_errors) -def _EnvWithArtLibPath(binary_path): - """Return an environment dictionary for ART host shared libraries. - - Args: - binary_path: the path to an ART host binary. - - Returns: - An environment dictionary where LD_LIBRARY_PATH has been augmented with the - shared library path for the binary. This assumes that there is a lib/ - directory in the same location as the binary. - """ - lib_path = os.path.join(os.path.dirname(binary_path), 'lib') - env = os.environ.copy() - libraries = [l for l in env.get('LD_LIBRARY_PATH', '').split(':') if l] - libraries.append(lib_path) - env['LD_LIBRARY_PATH'] = ':'.join(libraries) - return env - - -def _CreateBinaryProfile(text_profile, input_dex, profman_path, temp_dir): - """Create a binary profile for dexlayout. - - Args: - text_profile: The ART text profile that will be converted to a binary - profile. - input_dex: The input dex file to layout. - profman_path: Path to the profman binary. - temp_dir: Directory to work in. - - Returns: - The name of the binary profile, which will live in temp_dir. - """ - binary_profile = os.path.join( - temp_dir, 'binary_profile-for-' + os.path.basename(text_profile)) - open(binary_profile, 'w').close() # Touch binary_profile. - profman_cmd = [profman_path, - '--apk=' + input_dex, - '--dex-location=' + input_dex, - '--create-profile-from=' + text_profile, - '--reference-profile-file=' + binary_profile] - build_utils.CheckOutput( - profman_cmd, - env=_EnvWithArtLibPath(profman_path), - stderr_filter=lambda output: - build_utils.FilterLines(output, '|'.join( - [r'Could not find (method_id|proto_id|name):', - r'Could not create type list']))) - return binary_profile - - -def _LayoutDex(binary_profile, input_dex, dexlayout_path, temp_dir): - """Layout a dexfile using a profile. - - Args: - binary_profile: An ART binary profile, eg output from _CreateBinaryProfile. - input_dex: The dex file used to create the binary profile. - dexlayout_path: Path to the dexlayout binary. - temp_dir: Directory to work in. - - Returns: - List of output files produced by dexlayout. This will be one if the input - was a single dexfile, or multiple files if the input was a multidex - zip. These output files are located in temp_dir. - """ - dexlayout_output_dir = os.path.join(temp_dir, 'dexlayout_output') - os.mkdir(dexlayout_output_dir) - dexlayout_cmd = [ dexlayout_path, - '-u', # Update checksum - '-p', binary_profile, - '-w', dexlayout_output_dir, - input_dex ] - build_utils.CheckOutput( - dexlayout_cmd, - env=_EnvWithArtLibPath(dexlayout_path), - stderr_filter=lambda output: - build_utils.FilterLines(output, - r'Can.t mmap dex file.*please zipalign')) - output_files = os.listdir(dexlayout_output_dir) - if not output_files: - raise Exception('dexlayout unexpectedly produced no output') - return sorted([os.path.join(dexlayout_output_dir, f) for f in output_files]) - - -def _ZipMultidex(file_dir, dex_files): - """Zip dex files into a multidex. - - Args: - file_dir: The directory into which to write the output. - dex_files: The dexfiles forming the multizip. Their names must end with - classes.dex, classes2.dex, ... - - Returns: - The name of the multidex file, which will live in file_dir. - """ - ordered_files = [] # List of (archive name, file name) - for f in dex_files: - if f.endswith('dex.jar'): - ordered_files.append(('classes.dex', f)) - break - if not ordered_files: - raise Exception('Could not find classes.dex multidex file in %s' % - dex_files) - for dex_idx in range(2, len(dex_files) + 1): - archive_name = 'classes%d.dex' % dex_idx - for f in dex_files: - if f.endswith(archive_name): - ordered_files.append((archive_name, f)) - break - else: - raise Exception('Could not find classes%d.dex multidex file in %s' % - dex_files) - if len(set(f[1] for f in ordered_files)) != len(ordered_files): - raise Exception('Unexpected clashing filenames for multidex in %s' % - dex_files) - - zip_name = os.path.join(file_dir, 'multidex_classes.zip') - build_utils.DoZip(((archive_name, os.path.join(file_dir, file_name)) - for archive_name, file_name in ordered_files), - zip_name) - return zip_name - - def _ZipAligned(dex_files, output_path): """Creates a .dex.jar with 4-byte aligned files. @@ -374,30 +233,6 @@ def _ZipAligned(dex_files, output_path): zipalign.AddToZipHermetic(z, name, src_path=dex_file, alignment=4) -def _PerformDexlayout(tmp_dir, tmp_dex_output, options): - if options.proguard_mapping_path is not None: - matching_profile = os.path.join(tmp_dir, 'obfuscated_profile') - convert_dex_profile.ObfuscateProfile( - options.dexlayout_profile, tmp_dex_output, - options.proguard_mapping_path, options.dexdump_path, matching_profile) - else: - logging.warning('No obfuscation for %s', options.dexlayout_profile) - matching_profile = options.dexlayout_profile - binary_profile = _CreateBinaryProfile(matching_profile, tmp_dex_output, - options.profman_path, tmp_dir) - output_files = _LayoutDex(binary_profile, tmp_dex_output, - options.dexlayout_path, tmp_dir) - if len(output_files) > 1: - return _ZipMultidex(tmp_dir, output_files) - - if zipfile.is_zipfile(output_files[0]): - return output_files[0] - - final_output = os.path.join(tmp_dir, 'dex_classes.zip') - _ZipAligned(output_files, final_output) - return final_output - - def _CreateFinalDex(d8_inputs, output, tmp_dir, dex_cmd, options=None): tmp_dex_output = os.path.join(tmp_dir, 'tmp_dex_output.zip') needs_dexing = not all(f.endswith('.dex') for f in d8_inputs) @@ -428,9 +263,6 @@ def _CreateFinalDex(d8_inputs, output, tmp_dir, dex_cmd, options=None): _ZipAligned(sorted(d8_inputs), tmp_dex_output) logging.debug('Quick-zipped %d files', len(d8_inputs)) - if options and options.dexlayout_profile: - tmp_dex_output = _PerformDexlayout(tmp_dir, tmp_dex_output, options) - # The dex file is complete and can be moved out of tmp_dir. shutil.move(tmp_dex_output, output) @@ -457,12 +289,34 @@ def _DeleteStaleIncrementalDexFiles(dex_dir, dex_files): def _ParseDesugarDeps(desugar_dependencies_file): + # pylint: disable=line-too-long + """Returns a dict of dependent/dependency mapping parsed from the file. + + Example file format: + $ tail out/Debug/gen/base/base_java__dex.desugardeps + org/chromium/base/task/SingleThreadTaskRunnerImpl.class + <- org/chromium/base/task/SingleThreadTaskRunner.class + <- org/chromium/base/task/TaskRunnerImpl.class + org/chromium/base/task/TaskRunnerImpl.class + <- org/chromium/base/task/TaskRunner.class + org/chromium/base/task/TaskRunnerImplJni$1.class + <- obj/base/jni_java.turbine.jar:org/chromium/base/JniStaticTestMocker.class + org/chromium/base/task/TaskRunnerImplJni.class + <- org/chromium/base/task/TaskRunnerImpl$Natives.class + """ + # pylint: enable=line-too-long dependents_from_dependency = collections.defaultdict(set) if desugar_dependencies_file and os.path.exists(desugar_dependencies_file): with open(desugar_dependencies_file, 'r') as f: + dependent = None for line in f: - dependent, dependency = line.rstrip().split(' -> ') - dependents_from_dependency[dependency].add(dependent) + line = line.rstrip() + if line.startswith(' <- '): + dependency = line[len(' <- '):] + # Note that this is a reversed mapping from the one in CustomD8.java. + dependents_from_dependency[dependency].add(dependent) + else: + dependent = line return dependents_from_dependency @@ -522,14 +376,14 @@ def _CreateIntermediateDexFiles(changes, options, tmp_dir, dex_cmd): strings_changed, non_direct_input_changed) changes = None - if changes: + if changes is None: + required_desugar_classes_set = set() + else: required_desugar_classes_set = _ComputeRequiredDesugarClasses( changes, options.desugar_dependencies, options.class_inputs, options.classpath) logging.debug('Class files needing re-desugar: %d', len(required_desugar_classes_set)) - else: - required_desugar_classes_set = set() class_files = _ExtractClassFiles(changes, tmp_extract_dir, options.class_inputs, required_desugar_classes_set) @@ -540,7 +394,13 @@ def _CreateIntermediateDexFiles(changes, options, tmp_dir, dex_cmd): # Dex necessary classes into intermediate dex files. dex_cmd = dex_cmd + ['--intermediate', '--file-per-class-file'] if options.desugar_dependencies and not options.skip_custom_d8: - dex_cmd += ['--file-tmp-prefix', tmp_extract_dir] + # Adding os.sep to remove the entire prefix. + dex_cmd += ['--file-tmp-prefix', tmp_extract_dir + os.sep] + if changes is None and os.path.exists(options.desugar_dependencies): + # Since incremental dexing only ever adds to the desugar_dependencies + # file, whenever full dexes are required the .desugardeps files need to + # be manually removed. + os.unlink(options.desugar_dependencies) _RunD8(dex_cmd, class_files, options.incremental_dir, options.warnings_as_errors, options.show_desugar_default_interface_warnings) |