-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds aar_import rule to Bazel along with tools needed to implement it…
…. Currently only uses AndroidManifest.xml, classes.jar and res/ from AARs. This is sufficient for many of the AARs of Google Play Services and Android Support Repository. The next step will be for AndroidSdkRepositoryRule to scan the SDK and generate aar_import rules for the AARs within. The rule is not yet documented because it is not intended for end users to use it yet. We should probably support more of the features of AARs before that time. See http://tools.android.com/tech-docs/new-build-system/aar-format for all of the files that can be included in AARs. Also note that R.txt from the AAR is intentionally ignored and regenerated based on the contents of res/. This is more correct, because the R.txt inside of an AAR can contain ids for dependencies of the AAR that are not included in res/. See #564 for discussion of supporting AARs and #1745 for motivation to get it done soon. -- MOS_MIGRATED_REVID=133127933
- Loading branch information
1 parent
03b9cfd
commit f8a6752
Showing
9 changed files
with
312 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
150 changes: 150 additions & 0 deletions
150
src/main/java/com/google/devtools/build/lib/bazel/rules/android/AarImport.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
// Copyright 2016 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.bazel.rules.android; | ||
|
||
import com.google.common.collect.ImmutableList; | ||
import com.google.devtools.build.lib.actions.Action; | ||
import com.google.devtools.build.lib.actions.Artifact; | ||
import com.google.devtools.build.lib.analysis.ConfiguredTarget; | ||
import com.google.devtools.build.lib.analysis.FileProvider; | ||
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; | ||
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; | ||
import com.google.devtools.build.lib.analysis.RuleContext; | ||
import com.google.devtools.build.lib.analysis.RunfilesProvider; | ||
import com.google.devtools.build.lib.analysis.actions.PopulateTreeArtifactAction; | ||
import com.google.devtools.build.lib.analysis.actions.SpawnAction; | ||
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; | ||
import com.google.devtools.build.lib.collect.nestedset.Order; | ||
import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; | ||
import com.google.devtools.build.lib.rules.android.AndroidCommon; | ||
import com.google.devtools.build.lib.rules.android.AndroidResourcesProvider; | ||
import com.google.devtools.build.lib.rules.android.ApplicationManifest; | ||
import com.google.devtools.build.lib.rules.android.LocalResourceContainer; | ||
import com.google.devtools.build.lib.rules.android.ResourceApk; | ||
import com.google.devtools.build.lib.rules.android.ResourceDependencies; | ||
import com.google.devtools.build.lib.rules.java.JavaCommon; | ||
import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider; | ||
import com.google.devtools.build.lib.vfs.PathFragment; | ||
|
||
/** | ||
* An implementation for the aar_import rule. | ||
* | ||
* AAR files are zip archives that contain an Android Manifest, JARs, resources, assets, native | ||
* libraries, Proguard configuration and lint jars. Currently the aar_import rule supports AARs with | ||
* an AndroidManifest.xml, classes.jar and res/. Assets, native libraries and additional embedded | ||
* jars are not yet supported. | ||
* | ||
* @see <a href="http://tools.android.com/tech-docs/new-build-system/aar-format">AAR Format</a> | ||
*/ | ||
public class AarImport implements RuleConfiguredTargetFactory { | ||
private static final String ANDROID_MANIFEST = "AndroidManifest.xml"; | ||
private static final String CLASSES_JAR = "classes.jar"; | ||
|
||
@Override | ||
public ConfiguredTarget create(RuleContext ruleContext) | ||
throws InterruptedException, RuleErrorException { | ||
RuleConfiguredTargetBuilder ruleBuilder = new RuleConfiguredTargetBuilder(ruleContext); | ||
Artifact aar = ruleContext.getPrerequisiteArtifact("aar", Mode.TARGET); | ||
|
||
// classes.jar is required in every AAR. | ||
Artifact classesJar = createAarArtifact(ruleContext, CLASSES_JAR); | ||
ruleContext.registerAction( | ||
createSingleFileExtractor(ruleContext, aar, CLASSES_JAR, classesJar)); | ||
|
||
// AndroidManifest.xml is required in every AAR. | ||
Artifact androidManifestArtifact = createAarArtifact(ruleContext, ANDROID_MANIFEST); | ||
ruleContext.registerAction( | ||
createSingleFileExtractor(ruleContext, aar, ANDROID_MANIFEST, androidManifestArtifact)); | ||
|
||
Artifact resourcesManifest = createAarArtifact(ruleContext, "resource_manifest"); | ||
ruleContext.registerAction( | ||
createManifestExtractor(ruleContext, aar, "res/.*", resourcesManifest)); | ||
|
||
Artifact resources = createResourcesTreeArtifact(ruleContext); | ||
ruleContext.registerAction(createTreePopulater(ruleContext, aar, resourcesManifest, resources)); | ||
|
||
ApplicationManifest androidManifest = | ||
ApplicationManifest.fromExplicitManifest(ruleContext, androidManifestArtifact) | ||
.renamePackage(ruleContext, AndroidCommon.getJavaPackage(ruleContext)); | ||
|
||
FileProvider resourcesProvider = new FileProvider( | ||
new NestedSetBuilder<Artifact>(Order.NAIVE_LINK_ORDER).add(resources).build()); | ||
|
||
ResourceApk resourceApk = androidManifest.packWithDataAndResources( | ||
ruleContext, | ||
new LocalResourceContainer.Builder(ruleContext) | ||
.withResources(ImmutableList.of(resourcesProvider)) | ||
.build(), | ||
ResourceDependencies.fromRuleDeps(ruleContext, JavaCommon.isNeverLink(ruleContext))); | ||
|
||
return ruleBuilder | ||
.setFilesToBuild( | ||
NestedSetBuilder | ||
.<Artifact>stableOrder() | ||
.add(resources) | ||
.add(classesJar) | ||
.build()) | ||
.add(RunfilesProvider.class, RunfilesProvider.EMPTY) | ||
.add(AndroidResourcesProvider.class, resourceApk.toResourceProvider(ruleContext.getLabel())) | ||
.add( | ||
JavaRuleOutputJarsProvider.class, | ||
new JavaRuleOutputJarsProvider.Builder() | ||
.addOutputJar(classesJar, null, null) | ||
.build()) | ||
.build(); | ||
} | ||
|
||
private static Action[] createSingleFileExtractor(RuleContext ruleContext, Artifact aar, | ||
String filename, Artifact outputArtifact) { | ||
return new SpawnAction.Builder() | ||
.setExecutable(ruleContext.getExecutablePrerequisite("$unzip", Mode.HOST)) | ||
.addArgument("-j") | ||
.addInputArgument(aar) | ||
.addArgument(filename) | ||
.addArgument("-d") | ||
.addOutput(outputArtifact) | ||
.addArgument(outputArtifact.getExecPath().getParentDirectory().getPathString()) | ||
.build(ruleContext); | ||
} | ||
|
||
private static Action createTreePopulater(RuleContext ruleContext, Artifact aar, | ||
Artifact manifest, Artifact outputTree) { | ||
return new PopulateTreeArtifactAction( | ||
ruleContext.getActionOwner(), | ||
aar, | ||
manifest, | ||
outputTree, | ||
ruleContext.getExecutablePrerequisite("$zipper", Mode.HOST)); | ||
} | ||
|
||
private static Action[] createManifestExtractor(RuleContext ruleContext, Artifact aar, | ||
String filenameRegexp, Artifact manifest) { | ||
return new SpawnAction.Builder() | ||
.setExecutable(ruleContext.getExecutablePrerequisite("$zip_manifest_creator", Mode.HOST)) | ||
.addArgument(filenameRegexp) | ||
.addInputArgument(aar) | ||
.addOutputArgument(manifest) | ||
.build(ruleContext); | ||
} | ||
|
||
private static Artifact createAarArtifact(RuleContext ruleContext, String name) { | ||
return ruleContext.getUniqueDirectoryArtifact( | ||
"_aar", name, ruleContext.getBinOrGenfilesDirectory()); | ||
} | ||
|
||
private static Artifact createResourcesTreeArtifact(RuleContext ruleContext) { | ||
PathFragment rootRelativePath = ruleContext.getUniqueDirectory("_aar/unzipped"); | ||
return ruleContext.getTreeArtifact(rootRelativePath, ruleContext.getBinOrGenfilesDirectory()); | ||
} | ||
} |
71 changes: 71 additions & 0 deletions
71
src/main/java/com/google/devtools/build/lib/bazel/rules/android/AarImportRule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// Copyright 2016 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.bazel.rules.android; | ||
|
||
import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST; | ||
import static com.google.devtools.build.lib.packages.Attribute.attr; | ||
import static com.google.devtools.build.lib.packages.BuildType.LABEL; | ||
|
||
import com.google.devtools.build.lib.analysis.BaseRuleClasses; | ||
import com.google.devtools.build.lib.analysis.RuleDefinition; | ||
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; | ||
import com.google.devtools.build.lib.cmdline.Label; | ||
import com.google.devtools.build.lib.packages.RuleClass; | ||
import com.google.devtools.build.lib.packages.RuleClass.Builder; | ||
import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.AndroidAaptBaseRule; | ||
import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider; | ||
import com.google.devtools.build.lib.util.FileType; | ||
import com.google.devtools.build.lib.util.FileTypeSet; | ||
|
||
/** Rule definition for the aar_import rule. */ | ||
public class AarImportRule implements RuleDefinition { | ||
|
||
@Override | ||
public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) { | ||
return builder | ||
.setUndocumented() | ||
.add(attr("aar", LABEL) | ||
.mandatory() | ||
.allowedFileTypes(FileType.of(".aar"))) | ||
.add(attr("$zip_manifest_creator", LABEL) | ||
.cfg(HOST) | ||
.exec() | ||
.value(Label.parseAbsoluteUnchecked( | ||
environment.getToolsRepository() + "//tools/zip:zip_manifest_creator"))) | ||
.add(attr("$unzip", LABEL) | ||
.cfg(HOST) | ||
.exec() | ||
.value(Label.parseAbsoluteUnchecked( | ||
environment.getToolsRepository() + "//tools/zip:unzip")) | ||
.allowedFileTypes(FileTypeSet.ANY_FILE)) | ||
.add(attr("$zipper", LABEL) | ||
.cfg(HOST) | ||
.exec() | ||
.value(Label.parseAbsoluteUnchecked( | ||
environment.getToolsRepository() + "//tools/zip:zipper"))) | ||
.advertiseProvider(JavaCompilationArgsProvider.class) | ||
.build(); | ||
} | ||
|
||
@Override | ||
public Metadata getMetadata() { | ||
return RuleDefinition.Metadata.builder() | ||
.name("aar_import") | ||
// AndroidAaptBaseRule is needed for $android_manifest_merger which is used by the | ||
// ApplicationManifest class. | ||
.ancestors(BaseRuleClasses.RuleBase.class, AndroidAaptBaseRule.class) | ||
.factoryClass(AarImport.class) | ||
.build(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#!/bin/bash | ||
# | ||
# Copyright 2016 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. | ||
|
||
# This exists so that unzip can be invoked by a SpawnAction. It relies on unzip | ||
# existing in the user's path. | ||
|
||
unzip "$@" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#!/bin/bash | ||
# | ||
# Copyright 2016 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. | ||
|
||
# This script takes in a regular expression and a zip file and writes a file | ||
# containing the names of all files in the zip file that match the regular | ||
# expression with one per line. Names of directories are not included. | ||
|
||
if [ "$#" -ne 3 ]; then | ||
echo "Usage: zip_manifest_creator.sh <regexp> <input zip> <output manifest>" | ||
exit 1 | ||
fi | ||
|
||
REGEX="$1" | ||
INPUT_ZIP="$2" | ||
OUTPUT_MANIFEST="$3" | ||
|
||
zipinfo -1 "$INPUT_ZIP" -x "*/" | grep -x "$REGEX" > "$OUTPUT_MANIFEST" |