aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar asteinb <asteinb@google.com>2018-03-29 08:57:14 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-03-29 08:58:22 -0700
commit6db5972b93ac1178a2ddee88c56342fc4dcd2c0a (patch)
treed25f622d2b87e4c8426b825da5d2401f236d8750
parent6fc594815dae501077e3b038b256c1f9249b58df (diff)
Split AndroidAssets class out of LocalResourceContainer
AndroidAssets will be the new home for asset-related code (including, in the future, from ResourceContainer). This is the first step towards decoupling Android asset and resource processing. LocalResourceContainer will be replaced with resource-specific code in the next change. RELNOTES: none PiperOrigin-RevId: 190936954
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java117
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java9
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/LocalResourceContainer.java42
4 files changed, 125 insertions, 51 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java
new file mode 100644
index 0000000000..10c82988a6
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java
@@ -0,0 +1,117 @@
+// Copyright 2018 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 com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
+import com.google.devtools.build.lib.analysis.FileProvider;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
+import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
+import com.google.devtools.build.lib.syntax.Type;
+import com.google.devtools.build.lib.vfs.PathFragment;
+
+/** Wraps this target's Android assets */
+public final class AndroidAssets {
+ private static final String ASSETS_ATTR = "assets";
+ private static final String ASSETS_DIR_ATTR = "assets_dir";
+
+ static void validateAssetsAndAssetsDir(RuleContext ruleContext) throws RuleErrorException {
+ if (ruleContext.attributes().isAttributeValueExplicitlySpecified(ASSETS_ATTR)
+ ^ ruleContext.attributes().isAttributeValueExplicitlySpecified(ASSETS_DIR_ATTR)) {
+ ruleContext.throwWithRuleError(
+ String.format(
+ "'%s' and '%s' should be either both empty or both non-empty",
+ ASSETS_ATTR, ASSETS_DIR_ATTR));
+ }
+ }
+
+ /** Collects this rule's android assets. */
+ public static AndroidAssets from(RuleContext ruleContext) throws RuleErrorException {
+ validateAssetsAndAssetsDir(ruleContext);
+
+ if (!ruleContext.attributes().has(ASSETS_ATTR)) {
+ return new AndroidAssets(ImmutableList.of(), ImmutableList.of());
+ }
+
+ PathFragment assetsDir = getAssetDir(ruleContext);
+
+ ImmutableList.Builder<Artifact> assets = ImmutableList.builder();
+ ImmutableList.Builder<PathFragment> assetRoots = ImmutableList.builder();
+
+ for (TransitiveInfoCollection target :
+ ruleContext.getPrerequisitesIf(ASSETS_ATTR, Mode.TARGET, FileProvider.class)) {
+ for (Artifact file : target.getProvider(FileProvider.class).getFilesToBuild()) {
+ PathFragment packageFragment =
+ file.getArtifactOwner().getLabel().getPackageIdentifier().getSourceRoot();
+ PathFragment packageRelativePath = file.getRootRelativePath().relativeTo(packageFragment);
+ if (packageRelativePath.startsWith(assetsDir)) {
+ PathFragment relativePath = packageRelativePath.relativeTo(assetsDir);
+ PathFragment path = file.getExecPath();
+ assetRoots.add(path.subFragment(0, path.segmentCount() - relativePath.segmentCount()));
+ } else {
+ ruleContext.attributeError(ASSETS_ATTR,
+ String.format(
+ "'%s' (generated by '%s') is not beneath '%s'",
+ file.getRootRelativePath(), target.getLabel(), assetsDir));
+ throw new RuleErrorException();
+ }
+ assets.add(file);
+ }
+ }
+
+ return new AndroidAssets(assets.build(), assetRoots.build());
+ }
+
+ static PathFragment getAssetDir(RuleContext ruleContext) {
+ if (!ruleContext.attributes().has(ASSETS_DIR_ATTR)) {
+ return PathFragment.EMPTY_FRAGMENT;
+ }
+ return PathFragment.create(ruleContext.attributes().get(ASSETS_DIR_ATTR, Type.STRING));
+ }
+
+ /**
+ * Creates a {@link AndroidAssets} containing all the assets in a directory artifact, for use with
+ * AarImport rules.
+ *
+ * <p>In general, {@link #from(RuleContext)} should be used instead, but it can't be for AarImport
+ * since we don't know about its individual assets at analysis time.
+ *
+ * @param assetsDir the tree artifact containing a {@code assets/} directory
+ */
+ static AndroidAssets forAarImport(SpecialArtifact assetsDir) {
+ Preconditions.checkArgument(assetsDir.isTreeArtifact());
+ return new AndroidAssets(
+ ImmutableList.of(assetsDir), ImmutableList.of(assetsDir.getExecPath().getChild("assets")));
+ }
+
+ private final ImmutableList<Artifact> assets;
+ private final ImmutableList<PathFragment> assetRoots;
+
+ private AndroidAssets(ImmutableList<Artifact> assets, ImmutableList<PathFragment> assetRoots) {
+ this.assets = assets;
+ this.assetRoots = assetRoots;
+ }
+
+ public ImmutableList<Artifact> getAssets() {
+ return assets;
+ }
+
+ public ImmutableList<PathFragment> getAssetRoots() {
+ return assetRoots;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
index 871e36263c..5834c50b0f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
@@ -45,7 +45,6 @@ import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.packages.TriState;
import com.google.devtools.build.lib.rules.android.AndroidConfiguration.AndroidAaptVersion;
-import com.google.devtools.build.lib.rules.android.ResourceContainer.ResourceType;
import com.google.devtools.build.lib.rules.cpp.CcLinkParams;
import com.google.devtools.build.lib.rules.cpp.CcLinkParamsInfo;
import com.google.devtools.build.lib.rules.cpp.CcLinkParamsStore;
@@ -791,14 +790,6 @@ public class AndroidCommon {
asNeverLink);
}
- public static PathFragment getAssetDir(RuleContext ruleContext) {
- if (ruleContext.attributes().has(ResourceType.ASSETS.getAttribute() + "_dir")) {
- return PathFragment.create(
- ruleContext.attributes().get(ResourceType.ASSETS.getAttribute() + "_dir", Type.STRING));
- }
- return PathFragment.EMPTY_FRAGMENT;
- }
-
/**
* Collects Java compilation arguments for this target.
*
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java b/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
index f3ecd81b13..ac2a51d376 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
@@ -296,7 +296,7 @@ public final class ApplicationManifest {
throws InterruptedException, RuleErrorException {
LocalResourceContainer data =
LocalResourceContainer.forAssetsAndResources(
- ruleContext, "assets", AndroidCommon.getAssetDir(ruleContext), "local_resource_files");
+ ruleContext, "assets", AndroidAssets.getAssetDir(ruleContext), "local_resource_files");
ResourceContainer resourceContainer =
ResourceContainer.builderFromRule(ruleContext)
@@ -447,7 +447,7 @@ public final class ApplicationManifest {
throws InterruptedException, RuleErrorException {
LocalResourceContainer data =
LocalResourceContainer.forAssetsAndResources(
- ruleContext, "assets", AndroidCommon.getAssetDir(ruleContext), "resource_files");
+ ruleContext, "assets", AndroidAssets.getAssetDir(ruleContext), "resource_files");
// Filter the resources during analysis to prevent processing of dependencies on unwanted
// resources during execution.
@@ -522,7 +522,7 @@ public final class ApplicationManifest {
throws InterruptedException, RuleErrorException {
LocalResourceContainer data =
LocalResourceContainer.forAssetsAndResources(
- ruleContext, "assets", AndroidCommon.getAssetDir(ruleContext), "resource_files");
+ ruleContext, "assets", AndroidAssets.getAssetDir(ruleContext), "resource_files");
ResourceFilter resourceFilter =
resourceFilterFactory.getResourceFilter(ruleContext, resourceDeps, data);
@@ -604,7 +604,7 @@ public final class ApplicationManifest {
// resources during execution.
LocalResourceContainer data =
LocalResourceContainer.forAssetsAndResources(
- ruleContext, "assets", AndroidCommon.getAssetDir(ruleContext), "resource_files");
+ ruleContext, "assets", AndroidAssets.getAssetDir(ruleContext), "resource_files");
ResourceFilter resourceFilter =
ResourceFilterFactory.fromRuleContext(ruleContext)
.getResourceFilter(ruleContext, resourceDeps, data);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/LocalResourceContainer.java b/src/main/java/com/google/devtools/build/lib/rules/android/LocalResourceContainer.java
index 68806fcf93..d849166e7a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/LocalResourceContainer.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/LocalResourceContainer.java
@@ -22,13 +22,11 @@ import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.RuleContext;
-import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.packages.RuleErrorConsumer;
-import com.google.devtools.build.lib.rules.android.ResourceContainer.ResourceType;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.Arrays;
import java.util.LinkedHashSet;
@@ -85,20 +83,11 @@ public final class LocalResourceContainer {
* via {@code ruleContext}
*/
public static void validateRuleContext(RuleContext ruleContext) throws RuleErrorException {
- validateAssetsAndAssetsDir(ruleContext);
+ AndroidAssets.validateAssetsAndAssetsDir(ruleContext);
validateNoAndroidResourcesInSources(ruleContext);
validateManifest(ruleContext);
}
- private static void validateAssetsAndAssetsDir(RuleContext ruleContext)
- throws RuleErrorException {
- if (ruleContext.attributes().isAttributeValueExplicitlySpecified("assets")
- ^ ruleContext.attributes().isAttributeValueExplicitlySpecified("assets_dir")) {
- ruleContext.throwWithRuleError(
- "'assets' and 'assets_dir' should be either both empty or both non-empty");
- }
- }
-
/**
* Validates that there are no targets with resources in the srcs, as they
* should not be used with the Android data logic.
@@ -138,30 +127,7 @@ public final class LocalResourceContainer {
ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), ImmutableList.of());
}
- ImmutableList.Builder<Artifact> assets = ImmutableList.builder();
- ImmutableList.Builder<PathFragment> assetRoots = ImmutableList.builder();
-
- for (TransitiveInfoCollection target :
- ruleContext.getPrerequisitesIf(assetsAttr, Mode.TARGET, FileProvider.class)) {
- for (Artifact file : target.getProvider(FileProvider.class).getFilesToBuild()) {
- PathFragment packageFragment =
- file.getArtifactOwner().getLabel().getPackageIdentifier().getSourceRoot();
- PathFragment packageRelativePath = file.getRootRelativePath().relativeTo(packageFragment);
- if (packageRelativePath.startsWith(assetsDir)) {
- PathFragment relativePath = packageRelativePath.relativeTo(assetsDir);
- PathFragment path = file.getExecPath();
- assetRoots.add(path.subFragment(0, path.segmentCount() - relativePath.segmentCount()));
- } else {
- ruleContext.attributeError(
- ResourceType.ASSETS.getAttribute(),
- String.format(
- "'%s' (generated by '%s') is not beneath '%s'",
- file.getRootRelativePath(), target.getLabel(), assetsDir));
- throw new RuleErrorException();
- }
- assets.add(file);
- }
- }
+ AndroidAssets assets = AndroidAssets.from(ruleContext);
ImmutableList<Artifact> resources =
getResources(
@@ -170,8 +136,8 @@ public final class LocalResourceContainer {
return new LocalResourceContainer(
resources,
getResourceRoots(ruleContext, resources, resourcesAttr),
- assets.build(),
- assetRoots.build());
+ assets.getAssets(),
+ assets.getAssetRoots());
}