/** * The only dep for this rule should be {@link #javaLibrary}. Therefore, the ABI key for the deps * of this buildable is the hash of the {@code .class} files for {@link #javaLibrary}. */ @Override public Sha1HashCode getAbiKeyForDeps(DefaultRuleKeyBuilderFactory defaultRuleKeyBuilderFactory) { return computeAbiKey(javaLibrary.getClassNamesToHashes()); }
@Override public ImmutableList<Step> getBuildSteps( BuildContext context, final BuildableContext buildableContext) { ImmutableList.Builder<Step> steps = ImmutableList.builder(); steps.add(new RmStep(getProjectFilesystem(), getPathToDex(), /* shouldForceDeletion */ true)); // Make sure that the buck-out/gen/ directory exists for this.buildTarget. steps.add(new MkdirStep(getProjectFilesystem(), getPathToDex().getParent())); // If there are classes, run dx. final ImmutableSortedMap<String, HashCode> classNamesToHashes = javaLibrary.getClassNamesToHashes(); final boolean hasClassesToDx = !classNamesToHashes.isEmpty(); final Supplier<Integer> linearAllocEstimate; if (hasClassesToDx) { Path pathToOutputFile = javaLibrary.getPathToOutput(); EstimateLinearAllocStep estimate = new EstimateLinearAllocStep(getProjectFilesystem(), pathToOutputFile); steps.add(estimate); linearAllocEstimate = estimate; // To be conservative, use --force-jumbo for these intermediate .dex files so that they can be // merged into a final classes.dex that uses jumbo instructions. DxStep dx = new DxStep( getProjectFilesystem(), getPathToDex(), Collections.singleton(pathToOutputFile), EnumSet.of( DxStep.Option.USE_CUSTOM_DX_IF_AVAILABLE, DxStep.Option.RUN_IN_PROCESS, DxStep.Option.NO_OPTIMIZE, DxStep.Option.FORCE_JUMBO)); steps.add(dx); // The `DxStep` delegates to android tools to build a ZIP with timestamps in it, making // the output non-deterministic. So use an additional scrubbing step to zero these out. steps.add(new ZipScrubberStep(getProjectFilesystem(), getPathToDex())); } else { linearAllocEstimate = Suppliers.ofInstance(0); } // Run a step to record artifacts and metadata. The values recorded depend upon whether dx was // run. String stepName = hasClassesToDx ? "record_dx_success" : "record_empty_dx"; AbstractExecutionStep recordArtifactAndMetadataStep = new AbstractExecutionStep(stepName) { @Override public StepExecutionResult execute(ExecutionContext context) throws IOException { if (hasClassesToDx) { buildableContext.recordArtifact(getPathToDex()); } buildableContext.addMetadata( LINEAR_ALLOC_KEY_ON_DISK_METADATA, String.valueOf(linearAllocEstimate.get())); // Record the classnames to hashes map. buildableContext.addMetadata( CLASSNAMES_TO_HASHES, context .getObjectMapper() .writeValueAsString( Maps.transformValues(classNamesToHashes, Functions.toStringFunction()))); return StepExecutionResult.SUCCESS; } }; steps.add(recordArtifactAndMetadataStep); return steps.build(); }