Skip to content

Commit

Permalink
Add fields "filtered_deploy_jar" and "shuffled_java_resource_jar" to …
Browse files Browse the repository at this point in the history
…AndroidDexInfo and wire them up in rule android_binary.

PiperOrigin-RevId: 563858224
Change-Id: I1c77631b83530ef0295cba82e2586c16c1c7450b
  • Loading branch information
Zhaoqing Xu authored and copybara-github committed Sep 8, 2023
1 parent 5be6e55 commit fcfcb92
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -657,97 +657,115 @@ public static RuleConfiguredTargetBuilder createAndroidBinary(
}

Artifact jarToDex = proguardOutput.getOutputJar();
DexingOutput dexingOutput =
dex(
ruleContext,
androidSemantics,
binaryJar,
jarToDex,
isBinaryJarFiltered,
androidCommon,
resourceApk.getMainDexProguardConfig(),
resourceClasses,
derivedJarFunction,
proguardOutputMap,
postProcessingOutputMap,
proguardOutput.getLibraryJar(),
proguardOutput.getStartupProfileRewritten(),
!proguardSpecs.isEmpty());

DexPostprocessingOutput dexPostprocessingOutput =
androidSemantics.postprocessClassesDexZip(
ruleContext,
filesBuilder,
dexingOutput.classesDexZip,
proguardOutput,
postProcessingOutputMap,
dexingOutput.mainDexList);


DexingOutput dexingOutput = null;
DexPostprocessingOutput dexPostprocessingOutput = null;
ImmutableList<Artifact> finalShardDexZips = null;
Java8LegacyDexOutput java8LegacyDexOutput = null;
// Compute the final DEX files by appending Java 8 legacy .dex if used.
final Artifact finalClassesDex;
Java8LegacyDexOutput java8LegacyDexOutput = null;
ImmutableList<Artifact> finalShardDexZips = dexingOutput.shardDexZips;

if (androidDexInfo != null) {
finalClassesDex = androidDexInfo.getFinalClassesDexZip();
} else if (AndroidCommon.getAndroidConfig(ruleContext).desugarJava8Libs()
&& dexPostprocessingOutput.classesDexZip().getFilename().endsWith(".zip")) {
if (binaryJar.equals(jarToDex)) {
// No shrinking: use canned Java 8 legacy .dex file
java8LegacyDexOutput = Java8LegacyDexOutput.getCanned(ruleContext);
} else {
// Shrinking is used: build custom Java 8 legacy .dex file
java8LegacyDexOutput = buildJava8LegacyDex(ruleContext, jarToDex);

// Merge the mapping files from shrinking the program and Java 8 legacy .dex file.
if (finalProguardOutputMap != null) {
ruleContext.registerAction(
createSpawnActionBuilder(ruleContext)
.useDefaultShellEnvironment()
.setExecutable(ruleContext.getExecutablePrerequisite("$merge_proguard_maps"))
.addInput(dexPostprocessingOutput.proguardMap())
.addInput(java8LegacyDexOutput.getMap())
.addOutput(finalProguardOutputMap)
.addCommandLine(
CustomCommandLine.builder()
.addExecPath("--pg-map", dexPostprocessingOutput.proguardMap())
.addExecPath("--pg-map", java8LegacyDexOutput.getMap())
.addExecPath("--pg-map-output", finalProguardOutputMap)
.build())
.setMnemonic("MergeProguardMaps")
.setProgressMessage(
"Merging app and desugared library Proguard maps for %{label}")
.build(ruleContext));
}
finalShardDexZips = ImmutableList.of();
if (androidDexInfo.getShuffledJavaResourceJar() != null) {
// Symlink to the java resource jar created by this android_binary's android_binary_internal
// target to satisfy its implicit output of android_binary.
ruleContext.registerAction(
SymlinkAction.toArtifact(
ruleContext.getActionOwner(),
androidDexInfo.getShuffledJavaResourceJar(), // target
ruleContext.getImplicitOutputArtifact(
AndroidRuleClasses.JAVA_RESOURCES_JAR), // symlink
"Symlinking Android shuffled java resources jar"));
}
} else {
dexingOutput =
dex(
ruleContext,
androidSemantics,
binaryJar,
jarToDex,
isBinaryJarFiltered,
androidCommon,
resourceApk.getMainDexProguardConfig(),
resourceClasses,
derivedJarFunction,
proguardOutputMap,
postProcessingOutputMap,
proguardOutput.getLibraryJar(),
proguardOutput.getStartupProfileRewritten(),
!proguardSpecs.isEmpty());

// Append legacy .dex library to app's .dex files
finalClassesDex = getDxArtifact(ruleContext, "_final_classes.dex.zip");
ruleContext.registerAction(
createSpawnActionBuilder(ruleContext)
.useDefaultShellEnvironment()
.setMnemonic("AppendJava8LegacyDex")
.setProgressMessage("Adding Java 8 legacy library for %s", ruleContext.getLabel())
.setExecutable(ruleContext.getExecutablePrerequisite("$merge_dexzips"))
.addInput(dexPostprocessingOutput.classesDexZip())
.addInput(java8LegacyDexOutput.getDex())
.addOutput(finalClassesDex)
// Order matters here: we want java8LegacyDex to be the highest-numbered classesN.dex
.addCommandLine(
CustomCommandLine.builder()
.addExecPath("--input_zip", dexPostprocessingOutput.classesDexZip())
.addExecPath("--input_zip", java8LegacyDexOutput.getDex())
.addExecPath("--output_zip", finalClassesDex)
.build())
.build(ruleContext));
finalShardDexZips =
ImmutableList.<Artifact>builder()
.addAll(finalShardDexZips)
.add(java8LegacyDexOutput.getDex())
.build();
dexPostprocessingOutput =
androidSemantics.postprocessClassesDexZip(
ruleContext,
filesBuilder,
dexingOutput.classesDexZip,
proguardOutput,
postProcessingOutputMap,
dexingOutput.mainDexList);

finalShardDexZips = dexingOutput.shardDexZips;
if (AndroidCommon.getAndroidConfig(ruleContext).desugarJava8Libs()
&& dexPostprocessingOutput.classesDexZip().getFilename().endsWith(".zip")) {
if (binaryJar.equals(jarToDex)) {
// No shrinking: use canned Java 8 legacy .dex file
java8LegacyDexOutput = Java8LegacyDexOutput.getCanned(ruleContext);
} else {
// Shrinking is used: build custom Java 8 legacy .dex file
java8LegacyDexOutput = buildJava8LegacyDex(ruleContext, jarToDex);

// Merge the mapping files from shrinking the program and Java 8 legacy .dex file.
if (finalProguardOutputMap != null) {
ruleContext.registerAction(
createSpawnActionBuilder(ruleContext)
.useDefaultShellEnvironment()
.setExecutable(ruleContext.getExecutablePrerequisite("$merge_proguard_maps"))
.addInput(dexPostprocessingOutput.proguardMap())
.addInput(java8LegacyDexOutput.getMap())
.addOutput(finalProguardOutputMap)
.addCommandLine(
CustomCommandLine.builder()
.addExecPath("--pg-map", dexPostprocessingOutput.proguardMap())
.addExecPath("--pg-map", java8LegacyDexOutput.getMap())
.addExecPath("--pg-map-output", finalProguardOutputMap)
.build())
.setMnemonic("MergeProguardMaps")
.setProgressMessage(
"Merging app and desugared library Proguard maps for %{label}")
.build(ruleContext));
}
}

} else {
finalClassesDex = dexPostprocessingOutput.classesDexZip();
// Append legacy .dex library to app's .dex files
finalClassesDex = getDxArtifact(ruleContext, "_final_classes.dex.zip");
ruleContext.registerAction(
createSpawnActionBuilder(ruleContext)
.useDefaultShellEnvironment()
.setMnemonic("AppendJava8LegacyDex")
.setProgressMessage("Adding Java 8 legacy library for %{label}")
.setExecutable(ruleContext.getExecutablePrerequisite("$merge_dexzips"))
.addInput(dexPostprocessingOutput.classesDexZip())
.addInput(java8LegacyDexOutput.getDex())
.addOutput(finalClassesDex)
// Order matters here: we want java8LegacyDex to be the highest-numbered
// classesN.dex
.addCommandLine(
CustomCommandLine.builder()
.addExecPath("--input_zip", dexPostprocessingOutput.classesDexZip())
.addExecPath("--input_zip", java8LegacyDexOutput.getDex())
.addExecPath("--output_zip", finalClassesDex)
.build())
.build(ruleContext));
finalShardDexZips =
ImmutableList.<Artifact>builder()
.addAll(finalShardDexZips)
.add(java8LegacyDexOutput.getDex())
.build();

} else {
finalClassesDex = dexPostprocessingOutput.classesDexZip();
}
}

if (hasProguardSpecs) {
Expand Down Expand Up @@ -900,7 +918,12 @@ public static RuleConfiguredTargetBuilder createAndroidBinary(
androidCommon.isNeverLink(),
/* isLibrary = */ false);

if (dexPostprocessingOutput.proguardMap() != null) {
ProguardMappingProvider proguardMappingProvider =
ruleContext.getPrerequisite("application_resources", ProguardMappingProvider.PROVIDER);

if (proguardMappingProvider != null) {
builder.addNativeDeclaredProvider(proguardMappingProvider);
} else if (dexPostprocessingOutput != null && dexPostprocessingOutput.proguardMap() != null) {
builder.addNativeDeclaredProvider(
new ProguardMappingProvider(dexPostprocessingOutput.proguardMap()));
}
Expand All @@ -913,7 +936,9 @@ public static RuleConfiguredTargetBuilder createAndroidBinary(
AndroidBinaryMobileInstall.addMobileInstall(
ruleContext,
builder,
dexingOutput.javaResourceJar,
androidDexInfo == null
? dexingOutput.javaResourceJar
: androidDexInfo.getJavaResourceJar(),
finalShardDexZips,
javaSemantics,
nativeLibs,
Expand Down Expand Up @@ -2551,15 +2576,30 @@ private static Artifact getFilteredDeployJar(RuleContext ruleContext, Artifact d
.getPreDexJar();
Artifact filteredDeployJar =
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_TEST_FILTERED_JAR);
AndroidCommon.createZipFilterAction(
ruleContext,
deployJar,
filterJar,
filteredDeployJar,
CheckHashMismatchMode.NONE,
ruleContext
.getFragment(AndroidConfiguration.class)
.removeRClassesFromInstrumentationTestJar());

AndroidDexInfo androidDexInfo =
ruleContext.getPrerequisite("application_resources", AndroidDexInfo.PROVIDER);

if (androidDexInfo != null && androidDexInfo.getFilteredDeployJar() != null) {
// Symlink to the filtered deploy jar created by this android_binary's android_binary_internal
// target to satisfy the filtered deploy jar implicit output of android_binary.
ruleContext.registerAction(
SymlinkAction.toArtifact(
ruleContext.getActionOwner(),
androidDexInfo.getFilteredDeployJar(), // target
filteredDeployJar, // symlink
"Symlinking Android filtered deploy jar"));
} else {
AndroidCommon.createZipFilterAction(
ruleContext,
deployJar,
filterJar,
filteredDeployJar,
CheckHashMismatchMode.NONE,
ruleContext
.getFragment(AndroidConfiguration.class)
.removeRClassesFromInstrumentationTestJar());
}
return filteredDeployJar;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,24 @@ public class AndroidDexInfo extends NativeInfo implements AndroidDexInfoApi<Arti

private final Artifact deployJar;
private final Artifact finalClassesDexZip;
private final Artifact filteredDeployJar;
private final Artifact finalProguardOutputMap;
private final Artifact javaResourceJar;
private final Artifact shuffledJavaResourceJar;

public AndroidDexInfo(
Artifact deployJar,
Artifact finalClassesDexZip,
Artifact filteredDeployJar,
Artifact finalProguardOutputMap,
Artifact javaResourceJar) {
Artifact javaResourceJar,
Artifact shuffledJavaResourceJar) {
this.deployJar = deployJar;
this.finalClassesDexZip = finalClassesDexZip;
this.filteredDeployJar = filteredDeployJar;
this.finalProguardOutputMap = finalProguardOutputMap;
this.javaResourceJar = javaResourceJar;
this.shuffledJavaResourceJar = shuffledJavaResourceJar;
}

@Override
Expand Down Expand Up @@ -74,6 +80,18 @@ public Artifact getFinalProguardOutputMap() {
return finalProguardOutputMap;
}

@Override
@Nullable
public Artifact getFilteredDeployJar() {
return filteredDeployJar;
}

@Override
@Nullable
public Artifact getShuffledJavaResourceJar() {
return shuffledJavaResourceJar;
}

/** Provider for {@link AndroidDexInfo}. */
public static class Provider extends BuiltinProvider<AndroidDexInfo>
implements AndroidDexInfoApi.Provider<Artifact> {
Expand All @@ -90,15 +108,19 @@ public String getName() {
public AndroidDexInfo createInfo(
Artifact deployJar,
Object finalClassesDexZip,
Object filteredDeployJar,
Object finalProguardOutputMap,
Object javaResourceJar)
Object javaResourceJar,
Object shuffledJavaResourceJar)
throws EvalException {

return new AndroidDexInfo(
deployJar,
fromNoneable(finalClassesDexZip, Artifact.class),
fromNoneable(filteredDeployJar, Artifact.class),
fromNoneable(finalProguardOutputMap, Artifact.class),
fromNoneable(javaResourceJar, Artifact.class));
fromNoneable(javaResourceJar, Artifact.class),
fromNoneable(shuffledJavaResourceJar, Artifact.class));
}
}
}
Loading

0 comments on commit fcfcb92

Please sign in to comment.