aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java4
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/apple/XcodeConfigTest.java91
2 files changed, 92 insertions, 3 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
index 32a78c9ad2..5b2b6e30ec 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
@@ -754,7 +754,7 @@ public class SkylarkRuleClassFunctions {
&& ((String) attribute.getDefaultValue(null)).isEmpty()) {
hasDefault = false; // isValueSet() is always true for attr.string.
}
- if (!Attribute.isImplicit(nativeName)) {
+ if (!Attribute.isImplicit(nativeName) && !Attribute.isLateBound(nativeName)) {
if (!attribute.checkAllowedValues() || attribute.getType() != Type.STRING) {
throw new EvalException(
ast.getLocation(),
@@ -776,7 +776,7 @@ public class SkylarkRuleClassFunctions {
nativeName, allowed.getErrorReason(defaultVal)));
}
}
- } else if (!hasDefault) { // Implicit attribute
+ } else if (!hasDefault) { // Implicit or late bound attribute
String skylarkName = "_" + nativeName.substring(1);
throw new EvalException(
ast.getLocation(),
diff --git a/src/test/java/com/google/devtools/build/lib/rules/apple/XcodeConfigTest.java b/src/test/java/com/google/devtools/build/lib/rules/apple/XcodeConfigTest.java
index e2c21f7658..e0c8266daa 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/apple/XcodeConfigTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/apple/XcodeConfigTest.java
@@ -689,6 +689,91 @@ public class XcodeConfigTest extends BuildViewTestCase {
assertContainsEvent("apple_bitcode mode 'embedded' is unsupported");
}
+ // Verifies that the --xcode_config configuration value can be accessed via the
+ // configuration_field() skylark method and used in a skylark rule.
+ @Test
+ public void testConfigurationFieldForRule() throws Exception {
+ scratch.file("x/provider_grabber.bzl",
+ "def _impl(ctx):",
+ " conf = ctx.attr._xcode_dep[apple_common.XcodeVersionConfig]",
+ " return struct(",
+ " providers = [conf],",
+ " )",
+
+ "provider_grabber = rule(implementation = _impl,",
+ " attrs = { '_xcode_dep': attr.label(",
+ " default = configuration_field(",
+ " fragment = 'apple', name = 'xcode_config_label')),",
+ " },",
+ " fragments = ['apple'],",
+ ")");
+
+ scratch.file("x/BUILD",
+ "load('//x:provider_grabber.bzl', 'provider_grabber')",
+ "xcode_config(name='config1', default=':version1', versions=[':version1'])",
+ "xcode_config(name='config2', default=':version2', versions=[':version2'])",
+ "xcode_version(name = 'version1', version = '1.0')",
+ "xcode_version(name = 'version2', version = '2.0')",
+ "provider_grabber(name='provider_grabber')");
+
+ useConfiguration("--xcode_version_config=//x:config1");
+ assertXcodeVersion("1.0", "//x:provider_grabber");
+
+ useConfiguration("--xcode_version_config=//x:config2");
+ assertXcodeVersion("2.0", "//x:provider_grabber");
+ }
+
+ // Verifies that the --xcode_config configuration value can be accessed via the
+ // configuration_field() skylark method and used in a skylark aspect.
+ @Test
+ public void testConfigurationFieldForAspect() throws Exception {
+ scratch.file("x/provider_grabber.bzl",
+ "def _aspect_impl(target, ctx):",
+ " conf = ctx.attr._xcode_dep[apple_common.XcodeVersionConfig]",
+ " return struct(",
+ " providers = [conf],",
+ " )",
+ "",
+ "MyAspect = aspect(implementation = _aspect_impl,",
+ " attrs = { '_xcode_dep': attr.label(",
+ " default = configuration_field(",
+ " fragment = 'apple', name = 'xcode_config_label')),",
+ " },",
+ " fragments = ['apple'],",
+ ")",
+ "",
+ "def _rule_impl(ctx):",
+ " conf = ctx.attr.dep[0][apple_common.XcodeVersionConfig]",
+ " return struct(",
+ " providers = [conf],",
+ " )",
+ "",
+ "provider_grabber = rule(implementation = _rule_impl,",
+ " attrs = { 'dep' : ",
+ " attr.label_list(mandatory=True, allow_files=True, aspects = [MyAspect]) },",
+ ")");
+
+ scratch.file("x/BUILD",
+ "load('//x:provider_grabber.bzl', 'provider_grabber')",
+ "xcode_config(name='config1', default=':version1', versions=[':version1'])",
+ "xcode_config(name='config2', default=':version2', versions=[':version2'])",
+ "xcode_version(name = 'version1', version = '1.0')",
+ "xcode_version(name = 'version2', version = '2.0')",
+ "java_library(",
+ " name = 'fake_lib',",
+ ")",
+ "provider_grabber(",
+ " name = 'provider_grabber',",
+ " dep = [':fake_lib'],",
+ ")");
+
+ useConfiguration("--xcode_version_config=//x:config1");
+ assertXcodeVersion("1.0", "//x:provider_grabber");
+
+ useConfiguration("--xcode_version_config=//x:config2");
+ assertXcodeVersion("2.0", "//x:provider_grabber");
+ }
+
private DottedVersion getSdkVersionForPlatform(ApplePlatform platform) throws Exception {
ConfiguredTarget xcodeConfig = getConfiguredTarget("//xcode:foo");
XcodeConfigProvider provider = xcodeConfig.get(XcodeConfigProvider.PROVIDER);
@@ -702,7 +787,11 @@ public class XcodeConfigTest extends BuildViewTestCase {
}
private void assertXcodeVersion(String version) throws Exception {
- ConfiguredTarget xcodeConfig = getConfiguredTarget("//xcode:foo");
+ assertXcodeVersion(version, "//xcode:foo");
+ }
+
+ private void assertXcodeVersion(String version, String providerTargetLabel) throws Exception {
+ ConfiguredTarget xcodeConfig = getConfiguredTarget(providerTargetLabel);
XcodeConfigProvider provider = xcodeConfig.get(XcodeConfigProvider.PROVIDER);
assertThat(provider.getXcodeVersion()).isEqualTo(DottedVersion.fromString(version));
}