diff options
author | mstaib <mstaib@google.com> | 2017-04-12 16:37:48 +0000 |
---|---|---|
committer | Jakob Buchgraber <buchgr@google.com> | 2017-04-13 09:36:45 +0200 |
commit | b127fbbb9cec67407d6d19d3664d57700c085158 (patch) | |
tree | 5e99542e2eb3d983e8c1f9a6f341e2e5d84a5c9f /src/main/java/com/google/devtools/build | |
parent | f76ad07c5ab4984ce6836d8ac15e7265742f30c7 (diff) |
Add feature_flags attribute to Android binary rules.
This is the first actual user of the config_feature_flag rule, able to actually
set its value (and thus give a point to using it!)
This feature is not fully launched yet, but it is usable in any build
containing this change.
RELNOTES: None.
PiperOrigin-RevId: 152948153
Diffstat (limited to 'src/main/java/com/google/devtools/build')
6 files changed, 110 insertions, 6 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD index afbafdf117..cd90d661d8 100644 --- a/src/main/java/com/google/devtools/build/lib/BUILD +++ b/src/main/java/com/google/devtools/build/lib/BUILD @@ -984,6 +984,7 @@ java_library( ":vfs", "//src/main/java/com/google/devtools/build/lib:skylarkinterface", "//src/main/java/com/google/devtools/build/lib/actions", + "//src/main/java/com/google/devtools/build/lib/rules/config", "//src/main/java/com/google/devtools/build/lib/rules/cpp", "//src/main/java/com/google/devtools/common/options", "//src/main/protobuf:android_deploy_info_java_proto", diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/BazelAndroidBinaryRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/BazelAndroidBinaryRule.java index 8fedd68833..a5a4fe57d3 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/BazelAndroidBinaryRule.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/BazelAndroidBinaryRule.java @@ -25,7 +25,9 @@ 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.AndroidBinaryOnlyRule; import com.google.devtools.build.lib.rules.android.AndroidConfiguration; +import com.google.devtools.build.lib.rules.android.AndroidFeatureFlagSetProvider; import com.google.devtools.build.lib.rules.android.AndroidRuleClasses; +import com.google.devtools.build.lib.rules.config.ConfigFeatureFlagTransitionFactory; import com.google.devtools.build.lib.rules.cpp.CppConfiguration; import com.google.devtools.build.lib.rules.cpp.CppRuleClasses; import com.google.devtools.build.lib.rules.java.JavaConfiguration; @@ -82,6 +84,8 @@ public class BazelAndroidBinaryRule implements RuleDefinition { </ul> <!-- #END_BLAZE_RULE.IMPLICIT_OUTPUTS --> */ .setImplicitOutputsFunction(AndroidRuleClasses.ANDROID_BINARY_IMPLICIT_OUTPUTS) + .cfg( + new ConfigFeatureFlagTransitionFactory(AndroidFeatureFlagSetProvider.FEATURE_FLAG_ATTR)) .build(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java index 655d546568..29dad5109b 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java @@ -809,7 +809,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { return builder .setFilesToBuild(filesToBuild) - .add( + .addProvider( RunfilesProvider.class, RunfilesProvider.simple( new Runfiles.Builder( @@ -818,16 +818,20 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { .addRunfiles(ruleContext, RunfilesProvider.DEFAULT_RUNFILES) .addTransitiveArtifacts(filesToBuild) .build())) - .add( + .addProvider( JavaSourceInfoProvider.class, JavaSourceInfoProvider.fromJavaTargetAttributes(resourceClasses, javaSemantics)) - .add( + .addProvider( ApkProvider.class, ApkProvider.create( NestedSetBuilder.create(Order.STABLE_ORDER, zipAlignedApk), coverageMetadata, NestedSetBuilder.create(Order.STABLE_ORDER, applicationManifest.getManifest()))) - .add(AndroidPreDexJarProvider.class, AndroidPreDexJarProvider.create(jarToDex)) + .addProvider(AndroidPreDexJarProvider.class, AndroidPreDexJarProvider.create(jarToDex)) + .addProvider( + AndroidFeatureFlagSetProvider.class, + AndroidFeatureFlagSetProvider.create( + AndroidFeatureFlagSetProvider.getAndValidateFlagMapFromRuleContext(ruleContext))) .addOutputGroup("mobile_install_full" + INTERNAL_SUFFIX, fullInstallOutputGroup) .addOutputGroup( "mobile_install_incremental" + INTERNAL_SUFFIX, incrementalInstallOutputGroup) diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidFeatureFlagSetProvider.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidFeatureFlagSetProvider.java new file mode 100644 index 0000000000..315aea19c6 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidFeatureFlagSetProvider.java @@ -0,0 +1,82 @@ +// Copyright 2017 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.auto.value.AutoValue; +import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; +import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; +import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; +import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.packages.BuildType; +import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper; +import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; +import com.google.devtools.build.lib.rules.config.ConfigFeatureFlagProvider; +import java.util.Map; + +/** + * Provider for checking the set of feature flags used by an android_binary. + * + * <p>Because the feature flags are completely replaced by android_binary, android_test uses this + * provider to ensure that the test sets the same flags as the binary. Otherwise, the dependencies + * of the android_test will be compiled with different flags from the android_binary code which runs + * in the same Android virtual machine, which may cause compatibility issues at runtime. + */ +@AutoValue +@Immutable +public abstract class AndroidFeatureFlagSetProvider implements TransitiveInfoProvider { + + /** The name of the attribute used by Android rules to set config_feature_flags. */ + public static final String FEATURE_FLAG_ATTR = "feature_flags"; + + AndroidFeatureFlagSetProvider() {} + + /** Creates a new AndroidFeatureFlagSetProvider with the given flags. */ + public static AndroidFeatureFlagSetProvider create(Map<Label, String> flags) { + return new AutoValue_AndroidFeatureFlagSetProvider(ImmutableMap.copyOf(flags)); + } + + /** + * Builds a map which can be used with create, confirming that the desired flag values were + * actually received, and producing an error if they were not (because dynamic configurations are + * not enabled). + */ + public static ImmutableMap<Label, String> getAndValidateFlagMapFromRuleContext( + RuleContext ruleContext) throws RuleErrorException { + Map<Label, String> expectedValues = + NonconfigurableAttributeMapper.of(ruleContext.getRule()) + .get(FEATURE_FLAG_ATTR, BuildType.LABEL_KEYED_STRING_DICT); + Iterable<? extends TransitiveInfoCollection> actualTargets = + ruleContext.getPrerequisites(FEATURE_FLAG_ATTR, Mode.TARGET); + for (TransitiveInfoCollection target : actualTargets) { + Label label = target.getLabel(); + String expectedValue = expectedValues.get(label); + String actualValue = ConfigFeatureFlagProvider.fromTarget(target).getValue(); + + if (!expectedValue.equals(actualValue)) { + // TODO(mstaib): when static configurations are removed, remove this error case + ruleContext.attributeError( + FEATURE_FLAG_ATTR, + "Setting " + FEATURE_FLAG_ATTR + " requires dynamic configurations to be enabled"); + throw new RuleErrorException(); + } + } + return ImmutableMap.copyOf(expectedValues); + } + + public abstract ImmutableMap<Label, String> getFlags(); +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java index 7a05c36d0c..7c289e3ccb 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java @@ -16,6 +16,7 @@ package com.google.devtools.build.lib.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 static com.google.devtools.build.lib.packages.BuildType.LABEL_KEYED_STRING_DICT; import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST; import static com.google.devtools.build.lib.packages.BuildType.TRISTATE; import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.fromTemplates; @@ -46,6 +47,7 @@ import com.google.devtools.build.lib.packages.RuleClass.Builder; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; import com.google.devtools.build.lib.packages.TriState; import com.google.devtools.build.lib.rules.android.AndroidConfiguration.ConfigurationDistinguisher; +import com.google.devtools.build.lib.rules.config.ConfigFeatureFlagProvider; import com.google.devtools.build.lib.rules.cpp.CppOptions; import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider; import com.google.devtools.build.lib.rules.java.JavaConfiguration; @@ -795,6 +797,12 @@ public final class AndroidRuleClasses { Rex suggests an updated package map that can be saved and reused for subsequent builds. */ .add(attr("rex_package_map", LABEL).legacyAllowAnyFileType().undocumented("experimental")) + .add(attr(AndroidFeatureFlagSetProvider.FEATURE_FLAG_ATTR, LABEL_KEYED_STRING_DICT) + .undocumented("the feature flag feature has not yet been launched") + .allowedRuleClasses("config_feature_flag") + .allowedFileTypes() + .nonconfigurable("defines an aspect of configuration") + .mandatoryProviders(ImmutableList.of(ConfigFeatureFlagProvider.SKYLARK_IDENTIFIER))) .advertiseProvider(JavaCompilationArgsProvider.class) .build(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagProvider.java b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagProvider.java index 1bc6481234..265388eb1f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagProvider.java @@ -46,8 +46,13 @@ public abstract class ConfigFeatureFlagProvider extends SkylarkClassObject static final ClassObjectConstructor SKYLARK_CONSTRUCTOR = new NativeClassObjectConstructor(SKYLARK_NAME) {}; - /** Identifier used to retrieve this provider from rules which export it. */ - static final SkylarkProviderIdentifier SKYLARK_IDENTIFIER = + /** + * Identifier used to retrieve this provider from rules which export it. + * + * <p>Prefer to use {@link #fromTarget(TransitiveInfoCollection)} for the purposes of getting this + * provider from a TransitiveInfoCollection; this should be used for mandatoryProviders only. + */ + public static final SkylarkProviderIdentifier SKYLARK_IDENTIFIER = SkylarkProviderIdentifier.forKey(SKYLARK_CONSTRUCTOR.getKey()); ConfigFeatureFlagProvider() { |