Skip to content

Commit

Permalink
[6.3.0] Add a new provider for passing dex related artifacts in andro…
Browse files Browse the repository at this point in the history
…id_binary (#18899)

* Creates an AndroidDexInfo provider to pass dex related artifacts from Starlark to Native Bazel.

PiperOrigin-RevId: 515061110
Change-Id: Ieefe430582c01264fb510de3ac1017d3332f51aa

* Enable android_binary to use AndroidDexInfo from its application_resources attribute.

android_binary will use the dexes, jar resources, and deploy jar from AndroidDexInfo if it is present.

RELNOTES: None.
PiperOrigin-RevId: 531000013
Change-Id: I67c3457d131041aa4bab5db0892cdc0f0584f2dc

---------

Co-authored-by: Zhaoqing Xu <zhaoqxu@google.com>
Co-authored-by: Googler <ahumesky@google.com>
Co-authored-by: Ian (Hee) Cha <heec@google.com>
  • Loading branch information
4 people committed Jul 11, 2023
1 parent 3c4b936 commit ab35c6f
Show file tree
Hide file tree
Showing 6 changed files with 242 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import com.google.devtools.build.lib.rules.android.AndroidDeviceBrokerInfo;
import com.google.devtools.build.lib.rules.android.AndroidDeviceRule;
import com.google.devtools.build.lib.rules.android.AndroidDeviceScriptFixtureRule;
import com.google.devtools.build.lib.rules.android.AndroidDexInfo;
import com.google.devtools.build.lib.rules.android.AndroidFeatureFlagSetProvider;
import com.google.devtools.build.lib.rules.android.AndroidHostServiceFixtureRule;
import com.google.devtools.build.lib.rules.android.AndroidIdeInfoProvider;
Expand Down Expand Up @@ -423,7 +424,8 @@ public void init(ConfiguredRuleClassProvider.Builder builder) {
ProguardMappingProvider.PROVIDER,
AndroidBinaryDataInfo.PROVIDER,
AndroidBinaryNativeLibsInfo.PROVIDER,
BaselineProfileProvider.PROVIDER);
BaselineProfileProvider.PROVIDER,
AndroidDexInfo.PROVIDER);
builder.addStarlarkBootstrap(bootstrap);

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.actions.SpawnActionTemplate;
import com.google.devtools.build.lib.analysis.actions.SpawnActionTemplate.OutputPathMapper;
import com.google.devtools.build.lib.analysis.actions.SymlinkAction;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
Expand Down Expand Up @@ -601,11 +602,16 @@ public static RuleConfiguredTargetBuilder createAndroidBinary(
proguardOutput,
postProcessingOutputMap);

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

// Compute the final DEX files by appending Java 8 legacy .dex if used.
Artifact finalClassesDex;
final Artifact finalClassesDex;
Java8LegacyDexOutput java8LegacyDexOutput;
ImmutableList<Artifact> finalShardDexZips = dexingOutput.shardDexZips;
if (AndroidCommon.getAndroidConfig(ruleContext).desugarJava8Libs()
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
Expand Down Expand Up @@ -690,7 +696,11 @@ public static RuleConfiguredTargetBuilder createAndroidBinary(
ApkActionsBuilder.create("apk")
.setClassesDex(finalClassesDex)
.addInputZip(resourceApk.getArtifact())
.setJavaResourceZip(dexingOutput.javaResourceJar, resourceExtractor)
.setJavaResourceZip(
androidDexInfo == null
? dexingOutput.javaResourceJar
: androidDexInfo.getJavaResourceJar(),
resourceExtractor)
.addInputZips(nativeLibsAar.toList())
.setNativeLibs(nativeLibs)
.setUnsignedApk(unsignedApk)
Expand Down Expand Up @@ -979,7 +989,10 @@ public static NestedSet<Artifact> getLibraryResourceJars(RuleContext ruleContext
return libraryResourceJarsBuilder.build();
}

/** Generates an uncompressed _deploy.jar of all the runtime jars. */
/**
* Generates an uncompressed _deploy.jar of all the runtime jars, or creates a link to the deploy
* jar created by this android_binary's android_binary_internal target if it is provided.
*/
public static Artifact createDeployJar(
RuleContext ruleContext,
JavaSemantics javaSemantics,
Expand All @@ -988,15 +1001,32 @@ public static Artifact createDeployJar(
boolean checkDesugarDeps,
Function<Artifact, Artifact> derivedJarFunction)
throws InterruptedException {

Artifact deployJar =
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_BINARY_DEPLOY_JAR);
new DeployArchiveBuilder(javaSemantics, ruleContext)
.setOutputJar(deployJar)
.setAttributes(attributes)
.addRuntimeJars(common.getRuntimeJars())
.setDerivedJarFunction(derivedJarFunction)
.setCheckDesugarDeps(checkDesugarDeps)
.build();

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

if (androidDexInfo != null && androidDexInfo.getDeployJar() != null) {
// Symlink to the deploy jar created by this android_binary's android_binary_internal target
// to satisfy the deploy jar implicit output of android_binary.
ruleContext.registerAction(
SymlinkAction.toArtifact(
ruleContext.getActionOwner(),
androidDexInfo.getDeployJar(), // target
deployJar, // symlink
"Symlinking Android deploy jar"));
} else {
new DeployArchiveBuilder(javaSemantics, ruleContext)
.setOutputJar(deployJar)
.setAttributes(attributes)
.addRuntimeJars(common.getRuntimeJars())
.setDerivedJarFunction(derivedJarFunction)
.setCheckDesugarDeps(checkDesugarDeps)
.build();
}

return deployJar;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2023 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.rules.android;

import static com.google.devtools.build.lib.rules.android.AndroidStarlarkData.fromNoneable;

import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.BuiltinProvider;
import com.google.devtools.build.lib.packages.NativeInfo;
import com.google.devtools.build.lib.starlarkbuildapi.android.AndroidDexInfoApi;
import javax.annotation.Nullable;
import net.starlark.java.eval.EvalException;

/** A provider for Android Dex artifacts */
@Immutable
public class AndroidDexInfo extends NativeInfo implements AndroidDexInfoApi<Artifact> {

public static final String PROVIDER_NAME = "AndroidDexInfo";
public static final Provider PROVIDER = new Provider();

private final Artifact deployJar;
private final Artifact finalClassesDexZip;
private final Artifact javaResourceJar;

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

@Override
public Provider getProvider() {
return PROVIDER;
}

@Override
public Artifact getDeployJar() {
return deployJar;
}

@Override
public Artifact getFinalClassesDexZip() {
return finalClassesDexZip;
}

@Override
@Nullable
public Artifact getJavaResourceJar() {
return javaResourceJar;
}

/** Provider for {@link AndroidDexInfo}. */
public static class Provider extends BuiltinProvider<AndroidDexInfo>
implements AndroidDexInfoApi.Provider<Artifact> {

private Provider() {
super(PROVIDER_NAME, AndroidDexInfo.class);
}

public String getName() {
return PROVIDER_NAME;
}

@Override
public AndroidDexInfo createInfo(
Artifact deployJar, Artifact finalClassesDexZip, Object javaResourceJar)
throws EvalException {

return new AndroidDexInfo(
deployJar, finalClassesDexZip, fromNoneable(javaResourceJar, Artifact.class));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ public AndroidBootstrap(
ProguardMappingProviderApi.Provider<?> proguardMappingProviderApiProvider,
AndroidBinaryDataInfoApi.Provider<?, ?, ?, ?> androidBinaryDataInfoProvider,
AndroidBinaryNativeLibsInfoApi.Provider<?> androidBinaryInternalNativeLibsInfoApiProvider,
BaselineProfileProviderApi.Provider<?> baselineProfileProvider) {
BaselineProfileProviderApi.Provider<?> baselineProfileProvider,
AndroidDexInfoApi.Provider<?> androidDexInfoApiProvider) {

this.androidCommon = androidCommon;
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
Expand Down Expand Up @@ -93,6 +94,7 @@ public AndroidBootstrap(
builder.put(ProguardMappingProviderApi.NAME, proguardMappingProviderApiProvider);
builder.put(AndroidBinaryDataInfoApi.NAME, androidBinaryDataInfoProvider);
builder.put(BaselineProfileProviderApi.NAME, baselineProfileProvider);
builder.put(AndroidDexInfoApi.NAME, androidDexInfoApiProvider);
providers = builder.build();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright 2023 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.starlarkbuildapi.android;

import com.google.devtools.build.docgen.annot.StarlarkConstructor;
import com.google.devtools.build.lib.starlarkbuildapi.FileApi;
import com.google.devtools.build.lib.starlarkbuildapi.core.ProviderApi;
import com.google.devtools.build.lib.starlarkbuildapi.core.StructApi;
import javax.annotation.Nullable;
import net.starlark.java.annot.Param;
import net.starlark.java.annot.ParamType;
import net.starlark.java.annot.StarlarkBuiltin;
import net.starlark.java.annot.StarlarkMethod;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.NoneType;

/** An Info that can provides dex artifacts. */
@StarlarkBuiltin(
name = "AndroidDexInfo",
doc =
"Do not use this module. It is intended for migration purposes only. If you depend on it, "
+ "you will be broken when it is removed.",
documented = false)
public interface AndroidDexInfoApi<FileT extends FileApi> extends StructApi {

/** Name of this info object. */
String NAME = "AndroidDexInfo";

@StarlarkMethod(
name = "deploy_jar",
doc = "The deploy jar.",
documented = false,
structField = true)
FileT getDeployJar();

@StarlarkMethod(
name = "final_classes_dex_zip",
doc = "The zip file containing the final dex classes.",
documented = false,
structField = true)
FileT getFinalClassesDexZip();

@Nullable
@StarlarkMethod(
name = "java_resource_jar",
doc = "The final Java resource jar.",
documented = false,
structField = true,
allowReturnNones = true)
FileT getJavaResourceJar();

/** Provider for {@link AndroidDexInfoApi}. */
@StarlarkBuiltin(
name = "Provider",
doc =
"Do not use this module. It is intended for migration purposes only. If you depend on "
+ "it, you will be broken when it is removed.",
documented = false)
interface Provider<FileT extends FileApi> extends ProviderApi {

@StarlarkMethod(
name = NAME,
doc = "The <code>AndroidDexInfo</code> constructor.",
documented = false,
parameters = {
@Param(
name = "deploy_jar",
allowedTypes = {
@ParamType(type = FileApi.class),
},
named = true,
doc = "The \"_deploy\" jar suitable for deployment."),
@Param(
name = "final_classes_dex_zip",
allowedTypes = {
@ParamType(type = FileApi.class),
},
named = true,
doc = "The zip file containing the final dex classes."),
@Param(
name = "java_resource_jar",
allowedTypes = {
@ParamType(type = FileApi.class),
@ParamType(type = NoneType.class),
},
named = true,
doc = "The final Java resource jar."),
},
selfCall = true)
@StarlarkConstructor
AndroidDexInfoApi<FileT> createInfo(
FileT deployJar, FileT finalClassesDexZip, Object javaResourceJar) throws EvalException;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ protected Artifact getFinalUnsignedApk(ConfiguredTarget target) {
target.getProvider(FileProvider.class).getFilesToBuild(), "_unsigned.apk");
}

protected Artifact getDeployJar(ConfiguredTarget target) {
return getFirstArtifactEndingWith(
target.getProvider(FileProvider.class).getFilesToBuild(), "_deploy.jar");
}

protected Artifact getResourceApk(ConfiguredTarget target) {
Artifact resourceApk =
getFirstArtifactEndingWith(
Expand Down

0 comments on commit ab35c6f

Please sign in to comment.