use of com.google.devtools.build.lib.rules.java.ProguardHelper.ProguardOutput in project bazel by bazelbuild.
the class JavaBinary method applyProguardIfRequested.
/**
* This method uses {@link ProguardHelper#applyProguardIfRequested} to create a proguard action
* if necessary and adds any artifacts created by proguard to the given {@code filesBuilder}.
* This is convenience to make sure the proguarded Jar is included in the files to build, which is
* necessary because the Jar written by proguard is used at runtime.
* If this method returns {@code true} the Proguard is being used and we need to use a
* {@link DeployArchiveBuilder} to write the input artifact assumed by
* {@link ProguardHelper#applyProguardIfRequested}.
*/
private static boolean applyProguardIfRequested(RuleContext ruleContext, Artifact deployJar, ImmutableList<Artifact> bootclasspath, String mainClassName, JavaSemantics semantics, NestedSetBuilder<Artifact> filesBuilder) throws InterruptedException {
// We only support proguarding tests so Proguard doesn't try to proguard itself.
if (!ruleContext.getRule().getRuleClass().endsWith("_test")) {
return false;
}
ProguardOutput output = JavaBinaryProguardHelper.INSTANCE.applyProguardIfRequested(ruleContext, deployJar, bootclasspath, mainClassName, semantics);
if (output == null) {
return false;
}
output.addAllToSet(filesBuilder);
return true;
}
use of com.google.devtools.build.lib.rules.java.ProguardHelper.ProguardOutput in project bazel by bazelbuild.
the class AndroidBinary method createAndroidBinary.
public static RuleConfiguredTargetBuilder createAndroidBinary(RuleContext ruleContext, NestedSetBuilder<Artifact> filesBuilder, Artifact binaryJar, Function<Artifact, Artifact> derivedJarFunction, boolean isBinaryJarFiltered, JavaCommon javaCommon, AndroidCommon androidCommon, JavaSemantics javaSemantics, AndroidSemantics androidSemantics, NativeLibs nativeLibs, ApplicationManifest applicationManifest, ResourceApk resourceApk, ResourceApk incrementalResourceApk, ResourceApk instantRunResourceApk, ResourceApk splitResourceApk, boolean shrinkResources, JavaTargetAttributes resourceClasses, ImmutableList<Artifact> apksUnderTest, ImmutableList<Artifact> additionalMergedManifests, Artifact proguardMapping) throws InterruptedException, RuleErrorException {
ImmutableList<Artifact> proguardSpecs = ProguardHelper.collectTransitiveProguardSpecs(ruleContext, ImmutableList.of(resourceApk.getResourceProguardConfig()));
boolean rexEnabled = ruleContext.getFragment(AndroidConfiguration.class).useRexToCompressDexFiles() || (ruleContext.attributes().get("rewrite_dexes_with_rex", Type.BOOLEAN));
// TODO(bazel-team): Verify that proguard spec files don't contain -printmapping directions
// which this -printmapping command line flag will override.
Artifact proguardOutputMap = null;
if (ProguardHelper.genProguardMapping(ruleContext.attributes()) || ProguardHelper.getJavaOptimizationMode(ruleContext).alwaysGenerateOutputMapping() || shrinkResources) {
if (rexEnabled) {
proguardOutputMap = ProguardHelper.getProguardTempArtifact(ruleContext, ProguardHelper.getJavaOptimizationMode(ruleContext).name().toLowerCase(), "proguard_output_for_rex.map");
} else {
proguardOutputMap = ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_PROGUARD_MAP);
}
}
ProguardOutput proguardOutput = applyProguard(ruleContext, androidCommon, javaSemantics, binaryJar, proguardSpecs, proguardMapping, proguardOutputMap);
if (shrinkResources) {
resourceApk = shrinkResources(ruleContext, resourceApk, proguardSpecs, proguardOutput, filesBuilder);
}
Artifact jarToDex = proguardOutput.getOutputJar();
DexingOutput dexingOutput = shouldDexWithJack(ruleContext) ? dexWithJack(ruleContext, androidCommon, proguardSpecs) : dex(ruleContext, androidSemantics, binaryJar, jarToDex, isBinaryJarFiltered, androidCommon, resourceApk.getMainDexProguardConfig(), resourceClasses, derivedJarFunction);
NestedSet<Artifact> nativeLibsZips = AndroidCommon.collectTransitiveNativeLibsZips(ruleContext).build();
Artifact finalDexes;
Artifact finalProguardMap;
if (rexEnabled) {
finalDexes = getDxArtifact(ruleContext, "rexed_dexes.zip");
Builder rexActionBuilder = new SpawnAction.Builder();
rexActionBuilder.setExecutable(ruleContext.getExecutablePrerequisite("$rex_wrapper", Mode.HOST)).setMnemonic("Rex").setProgressMessage("Rexing dex files").addArgument("--dex_input").addInputArgument(dexingOutput.classesDexZip).addArgument("--dex_output").addOutputArgument(finalDexes);
if (proguardOutput.getMapping() != null) {
finalProguardMap = ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_PROGUARD_MAP);
Artifact finalRexPackageMap = getDxArtifact(ruleContext, "rex_output_package.map");
rexActionBuilder.addArgument("--proguard_input_map").addInputArgument(proguardOutput.getMapping()).addArgument("--proguard_output_map").addOutputArgument(finalProguardMap).addArgument("--rex_output_package_map").addOutputArgument(finalRexPackageMap);
if (ruleContext.attributes().isAttributeValueExplicitlySpecified("rex_package_map")) {
Artifact rexPackageMap = ruleContext.getPrerequisiteArtifact("rex_package_map", Mode.TARGET);
rexActionBuilder.addArgument("--rex_input_package_map").addInputArgument(rexPackageMap);
}
} else {
finalProguardMap = proguardOutput.getMapping();
}
// determine whether or not to pass the flag to Rex
if (ruleContext.attributes().isAttributeValueExplicitlySpecified("main_dex_list")) {
rexActionBuilder.addArgument("--keep-main-dex");
}
ruleContext.registerAction(rexActionBuilder.build(ruleContext));
} else {
finalDexes = dexingOutput.classesDexZip;
finalProguardMap = proguardOutput.getMapping();
}
if (!proguardSpecs.isEmpty()) {
proguardOutput.addAllToSet(filesBuilder, finalProguardMap);
}
ApkSigningMethod signingMethod = ruleContext.getFragment(AndroidConfiguration.class).getApkSigningMethod();
Artifact unsignedApk = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_BINARY_UNSIGNED_APK);
Artifact zipAlignedApk = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_BINARY_APK);
ApkActionsBuilder.create("apk", signingMethod).setClassesDex(finalDexes).setResourceApk(resourceApk.getArtifact()).setJavaResourceZip(dexingOutput.javaResourceJar).setNativeLibsZips(nativeLibsZips).setNativeLibs(nativeLibs).setUnsignedApk(unsignedApk).setSignedApk(zipAlignedApk).setZipalignApk(true).registerActions(ruleContext, androidSemantics);
// Don't add blacklistedApk, so it's only built if explicitly requested.
filesBuilder.add(binaryJar);
filesBuilder.add(unsignedApk);
filesBuilder.add(zipAlignedApk);
NestedSet<Artifact> filesToBuild = filesBuilder.build();
Iterable<Artifact> dataDeps = ImmutableList.of();
if (ruleContext.attributes().has("data", BuildType.LABEL_LIST) && ruleContext.getAttributeMode("data") == Mode.DATA) {
dataDeps = ruleContext.getPrerequisiteArtifacts("data", Mode.DATA).list();
}
Artifact deployInfo = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.DEPLOY_INFO);
AndroidDeployInfoAction.createDeployInfoAction(ruleContext, deployInfo, resourceApk.getManifest(), additionalMergedManifests, Iterables.concat(ImmutableList.of(zipAlignedApk), apksUnderTest), dataDeps);
NestedSet<Artifact> coverageMetadata = (androidCommon.getInstrumentedJar() != null) ? NestedSetBuilder.create(Order.STABLE_ORDER, androidCommon.getInstrumentedJar()) : NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER);
RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext);
Artifact incrementalApk = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_BINARY_INCREMENTAL_APK);
Artifact fullDeployMarker = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.FULL_DEPLOY_MARKER);
Artifact incrementalDeployMarker = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.INCREMENTAL_DEPLOY_MARKER);
Artifact splitDeployMarker = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.SPLIT_DEPLOY_MARKER);
Artifact incrementalDexManifest = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.DEX_MANIFEST);
ruleContext.registerAction(new SpawnAction.Builder().setMnemonic("AndroidDexManifest").setProgressMessage("Generating incremental installation manifest for " + ruleContext.getLabel()).setExecutable(ruleContext.getExecutablePrerequisite("$build_incremental_dexmanifest", Mode.HOST)).addOutputArgument(incrementalDexManifest).addInputArguments(dexingOutput.shardDexZips).useParameterFile(ParameterFileType.UNQUOTED).build(ruleContext));
Artifact stubData = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.MOBILE_INSTALL_STUB_APPLICATION_DATA);
Artifact stubDex = getStubDex(ruleContext, javaSemantics, false);
ruleContext.assertNoErrors();
ApkActionsBuilder incrementalActionsBuilder = ApkActionsBuilder.create("incremental apk", signingMethod).setClassesDex(stubDex).setResourceApk(incrementalResourceApk.getArtifact()).setJavaResourceZip(dexingOutput.javaResourceJar).setNativeLibsZips(nativeLibsZips).setJavaResourceFile(stubData).setSignedApk(incrementalApk);
if (!ruleContext.getFragment(AndroidConfiguration.class).useIncrementalNativeLibs()) {
incrementalActionsBuilder.setNativeLibs(nativeLibs);
}
incrementalActionsBuilder.registerActions(ruleContext, androidSemantics);
Artifact argsArtifact = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.MOBILE_INSTALL_ARGS);
ruleContext.registerAction(new WriteAdbArgsAction(ruleContext.getActionOwner(), argsArtifact));
createInstallAction(ruleContext, false, fullDeployMarker, argsArtifact, incrementalDexManifest, incrementalResourceApk.getArtifact(), incrementalApk, nativeLibs, stubData);
createInstallAction(ruleContext, true, incrementalDeployMarker, argsArtifact, incrementalDexManifest, incrementalResourceApk.getArtifact(), incrementalApk, nativeLibs, stubData);
Artifact incrementalDeployInfo = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.DEPLOY_INFO_INCREMENTAL);
AndroidDeployInfoAction.createDeployInfoAction(ruleContext, incrementalDeployInfo, resourceApk.getManifest(), additionalMergedManifests, ImmutableList.<Artifact>of(), dataDeps);
NestedSet<Artifact> fullInstallOutputGroup = NestedSetBuilder.<Artifact>stableOrder().add(fullDeployMarker).add(incrementalDeployInfo).build();
NestedSet<Artifact> incrementalInstallOutputGroup = NestedSetBuilder.<Artifact>stableOrder().add(incrementalDeployMarker).add(incrementalDeployInfo).build();
NestedSetBuilder<Artifact> splitApkSetBuilder = NestedSetBuilder.compileOrder();
// Put the Android resource APK first so that this split gets installed first.
//
// This avoids some logcat spam during installation, because otherwise the Android package
// manager would complain about references to missing resources in the manifest during the
// installation of each split (said references would eventually get installed, but it cannot
// know that in advance)
Artifact resourceSplitApk = getDxArtifact(ruleContext, "android_resources.apk");
ApkActionsBuilder.create("split Android resource apk", signingMethod).setResourceApk(splitResourceApk.getArtifact()).setSignedApk(resourceSplitApk).registerActions(ruleContext, androidSemantics);
splitApkSetBuilder.add(resourceSplitApk);
for (int i = 0; i < dexingOutput.shardDexZips.size(); i++) {
String splitName = "dex" + (i + 1);
Artifact splitApkResources = createSplitApkResources(ruleContext, applicationManifest, splitName, true);
Artifact splitApk = getDxArtifact(ruleContext, splitName + ".apk");
ApkActionsBuilder.create("split dex apk " + (i + 1), signingMethod).setClassesDex(dexingOutput.shardDexZips.get(i)).setResourceApk(splitApkResources).setSignedApk(splitApk).registerActions(ruleContext, androidSemantics);
splitApkSetBuilder.add(splitApk);
}
Artifact nativeSplitApkResources = createSplitApkResources(ruleContext, applicationManifest, "native", false);
Artifact nativeSplitApk = getDxArtifact(ruleContext, "native.apk");
ApkActionsBuilder.create("split native apk", signingMethod).setResourceApk(nativeSplitApkResources).setNativeLibs(nativeLibs).setSignedApk(nativeSplitApk).registerActions(ruleContext, androidSemantics);
splitApkSetBuilder.add(nativeSplitApk);
Artifact javaSplitApkResources = createSplitApkResources(ruleContext, applicationManifest, "java_resources", false);
Artifact javaSplitApk = getDxArtifact(ruleContext, "java_resources.apk");
ApkActionsBuilder.create("split Java resource apk", signingMethod).setResourceApk(javaSplitApkResources).setJavaResourceZip(dexingOutput.javaResourceJar).setSignedApk(javaSplitApk).registerActions(ruleContext, androidSemantics);
splitApkSetBuilder.add(javaSplitApk);
Artifact splitMainApkResources = getDxArtifact(ruleContext, "split_main.ap_");
ruleContext.registerAction(new SpawnAction.Builder().setMnemonic("AndroidStripResources").setProgressMessage("Stripping resources from split main apk").setExecutable(ruleContext.getExecutablePrerequisite("$strip_resources", Mode.HOST)).addArgument("--input_resource_apk").addInputArgument(resourceApk.getArtifact()).addArgument("--output_resource_apk").addOutputArgument(splitMainApkResources).build(ruleContext));
NestedSet<Artifact> splitApks = splitApkSetBuilder.build();
Artifact splitMainApk = getDxArtifact(ruleContext, "split_main.apk");
Artifact splitStubDex = getStubDex(ruleContext, javaSemantics, true);
ruleContext.assertNoErrors();
ApkActionsBuilder.create("split main apk", signingMethod).setClassesDex(splitStubDex).setResourceApk(splitMainApkResources).setNativeLibsZips(nativeLibsZips).setSignedApk(splitMainApk).registerActions(ruleContext, androidSemantics);
splitApkSetBuilder.add(splitMainApk);
NestedSet<Artifact> allSplitApks = splitApkSetBuilder.build();
createSplitInstallAction(ruleContext, splitDeployMarker, argsArtifact, splitMainApk, splitApks, stubData);
Artifact splitDeployInfo = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.DEPLOY_INFO_SPLIT);
AndroidDeployInfoAction.createDeployInfoAction(ruleContext, splitDeployInfo, resourceApk.getManifest(), additionalMergedManifests, ImmutableList.<Artifact>of(), dataDeps);
NestedSet<Artifact> splitInstallOutputGroup = NestedSetBuilder.<Artifact>stableOrder().addTransitive(allSplitApks).add(splitDeployMarker).add(splitDeployInfo).build();
Artifact debugKeystore = androidSemantics.getApkDebugSigningKey(ruleContext);
Artifact apkManifest = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.APK_MANIFEST);
createApkManifestAction(ruleContext, apkManifest, // text proto
false, androidCommon, resourceClasses, instantRunResourceApk, nativeLibs, debugKeystore);
Artifact apkManifestText = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.APK_MANIFEST_TEXT);
createApkManifestAction(ruleContext, apkManifestText, // text proto
true, androidCommon, resourceClasses, instantRunResourceApk, nativeLibs, debugKeystore);
androidCommon.addTransitiveInfoProviders(builder, androidSemantics, null, /* aar */
resourceApk, zipAlignedApk, apksUnderTest);
androidSemantics.addTransitiveInfoProviders(builder, ruleContext, javaCommon, androidCommon, jarToDex);
if (proguardOutput.getMapping() != null) {
builder.add(ProguardMappingProvider.class, ProguardMappingProvider.create(finalProguardMap));
}
return builder.setFilesToBuild(filesToBuild).add(RunfilesProvider.class, RunfilesProvider.simple(new Runfiles.Builder(ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles()).addRunfiles(ruleContext, RunfilesProvider.DEFAULT_RUNFILES).addTransitiveArtifacts(filesToBuild).build())).add(JavaSourceInfoProvider.class, JavaSourceInfoProvider.fromJavaTargetAttributes(resourceClasses, javaSemantics)).add(ApkProvider.class, ApkProvider.create(NestedSetBuilder.create(Order.STABLE_ORDER, zipAlignedApk), coverageMetadata, NestedSetBuilder.create(Order.STABLE_ORDER, applicationManifest.getManifest()))).add(AndroidPreDexJarProvider.class, AndroidPreDexJarProvider.create(jarToDex)).addOutputGroup("mobile_install_full" + INTERNAL_SUFFIX, fullInstallOutputGroup).addOutputGroup("mobile_install_incremental" + INTERNAL_SUFFIX, incrementalInstallOutputGroup).addOutputGroup("mobile_install_split" + INTERNAL_SUFFIX, splitInstallOutputGroup).addOutputGroup("apk_manifest", apkManifest).addOutputGroup("apk_manifest_text", apkManifestText).addOutputGroup("android_deploy_info", deployInfo);
}
use of com.google.devtools.build.lib.rules.java.ProguardHelper.ProguardOutput in project bazel by bazelbuild.
the class AndroidBinary method createEmptyProguardAction.
private static ProguardOutput createEmptyProguardAction(RuleContext ruleContext, JavaSemantics semantics, Artifact proguardOutputJar, Artifact deployJarArtifact, Artifact proguardOutputMap) throws InterruptedException {
NestedSetBuilder<Artifact> failures = NestedSetBuilder.<Artifact>stableOrder();
ProguardOutput outputs = ProguardHelper.getProguardOutputs(proguardOutputJar, /* proguardSeeds */
(Artifact) null, /* proguardUsage */
(Artifact) null, ruleContext, semantics, proguardOutputMap);
outputs.addAllToSet(failures);
JavaOptimizationMode optMode = getJavaOptimizationMode(ruleContext);
ruleContext.registerAction(new FailAction(ruleContext.getActionOwner(), failures.build(), String.format("Can't run Proguard %s", optMode == JavaOptimizationMode.LEGACY ? "without proguard_specs" : "in optimization mode " + optMode)));
return new ProguardOutput(deployJarArtifact, null, null, null, null, null, null);
}
use of com.google.devtools.build.lib.rules.java.ProguardHelper.ProguardOutput in project bazel by bazelbuild.
the class AndroidBinary method applyProguard.
/**
* Applies the proguard specifications, and creates a ProguardedJar. Proguard's output artifacts
* are added to the given {@code filesBuilder}.
*/
private static ProguardOutput applyProguard(RuleContext ruleContext, AndroidCommon common, JavaSemantics javaSemantics, Artifact deployJarArtifact, ImmutableList<Artifact> proguardSpecs, Artifact proguardMapping, @Nullable Artifact proguardOutputMap) throws InterruptedException {
Artifact proguardOutputJar = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_BINARY_PROGUARD_JAR);
// Proguard will be only used for binaries which specify a proguard_spec
if (proguardSpecs.isEmpty()) {
// always be created.
return createEmptyProguardAction(ruleContext, javaSemantics, proguardOutputJar, deployJarArtifact, proguardOutputMap);
}
AndroidSdkProvider sdk = AndroidSdkProvider.fromRuleContext(ruleContext);
NestedSet<Artifact> libraryJars = NestedSetBuilder.<Artifact>naiveLinkOrder().add(sdk.getAndroidJar()).addTransitive(common.getTransitiveNeverLinkLibraries()).build();
Artifact proguardSeeds = ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_PROGUARD_SEEDS);
Artifact proguardUsage = ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_PROGUARD_USAGE);
ProguardOutput result = ProguardHelper.createProguardAction(ruleContext, sdk.getProguard(), deployJarArtifact, proguardSpecs, proguardSeeds, proguardUsage, proguardMapping, libraryJars, proguardOutputJar, javaSemantics, getProguardOptimizationPasses(ruleContext), proguardOutputMap, ruleContext.getFragment(AndroidConfiguration.class).useSingleJarForProguardLibraryJars());
return result;
}
Aggregations