diff options
author | Florian Weikert <fwe@google.com> | 2015-07-30 13:28:26 +0000 |
---|---|---|
committer | Damien Martin-Guillerez <dmarting@google.com> | 2015-07-30 15:43:12 +0000 |
commit | eee8be6b88d5ce7bd34a3bca0643df34ae7caa4f (patch) | |
tree | a5f9ca3f9415adbb4a7dd4ba106e51698a0a7527 | |
parent | 6798135c65b16a962b75e9ee1aea9de8ba694e8f (diff) |
Skylark: In addition to using ctx.configuration.fragment(CONF), the build configuration can now be accessed via ctx.configuration.CONF where CONF is in {cpp, jvm, java}.
--
MOS_MIGRATED_REVID=99470271
6 files changed, 99 insertions, 10 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java index 47d0eb3449..a4a830e7cd 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java @@ -396,7 +396,11 @@ public final class RuleConfiguredTargetBuilder { checkSkylarkObjectSafe(entry.getValue()); } return; - } else if (object instanceof ClassObject) { + } else if (object instanceof ClassObject && !(object instanceof BuildConfiguration)) { + // We had to make BuildConfiguration implement ClassObject in order to allow access to + // individual fragments as fields. + // However, we don't want to expose it to the outside world, thus forcing us to add this + // explicit check here. ClassObject struct = (ClassObject) object; for (String key : struct.getKeys()) { checkSkylarkObjectSafe(struct.getValue(key)); diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java index d613f1e37e..849b7785d2 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java @@ -19,6 +19,7 @@ import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -44,6 +45,7 @@ import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.rules.test.TestActionBuilder; +import com.google.devtools.build.lib.syntax.ClassObject; import com.google.devtools.build.lib.syntax.Label; import com.google.devtools.build.lib.syntax.Label.SyntaxException; import com.google.devtools.build.lib.syntax.SkylarkCallable; @@ -106,7 +108,7 @@ import javax.annotation.Nullable; @SkylarkModule(name = "configuration", doc = "Data required for the analysis of a target that comes from targets that " + "depend on it and not targets that it depends on.") -public final class BuildConfiguration { +public final class BuildConfiguration implements ClassObject { /** * An interface for language-specific configurations. @@ -194,6 +196,22 @@ public final class BuildConfiguration { } /** + * Determines whether this fragment can be accessed in Skylark as a field of + * ctx.configuration + */ + public boolean isSkylarkVisible() { + return false; + } + + /** + * If this fragment is skylarkVisible, it will be accessible in Skylark via + * ctx.configuration.NAME where NAME = getName() + */ + public String getName() { + return getClass().getName(); + } + + /** * Returns a fragment of the output directory name for this configuration. The output * directory for the whole configuration contains all the short names by all fragments. */ @@ -874,6 +892,7 @@ public final class BuildConfiguration { private Set<BuildConfiguration> allReachableConfigurations; private final ImmutableMap<Class<? extends Fragment>, Fragment> fragments; + private final ImmutableMap<String, Fragment> skylarkVisibleFragments; /** * Directories in the output tree. @@ -1033,6 +1052,8 @@ public final class BuildConfiguration { this.actionsEnabled = !actionsDisabled; this.fragments = ImmutableMap.copyOf(fragmentsMap); + this.skylarkVisibleFragments = buildIndexOfVisibleFragments(); + this.buildOptions = buildOptions; this.options = buildOptions.get(Options.class); @@ -1097,6 +1118,17 @@ public final class BuildConfiguration { checksum = Fingerprint.md5Digest(buildOptions.computeCacheKey()); } + private ImmutableMap<String, Fragment> buildIndexOfVisibleFragments() { + ImmutableMap.Builder<String, Fragment> builder = ImmutableMap.builder(); + + for (Fragment fragment : fragments.values()) { + if (fragment.isSkylarkVisible()) { + builder.put(fragment.getName(), fragment); + } + } + + return builder.build(); + } /** * Computes and returns the transitive optionName -> "option info" map for @@ -1610,7 +1642,7 @@ public final class BuildConfiguration { public String getMakeVariableDefault(String var) { return globalMakeEnv.get(var); } - + /** * Returns a configuration fragment instances of the given class. */ @@ -1890,4 +1922,21 @@ public final class BuildConfiguration { public List<Label> getTargetEnvironments() { return options.targetEnvironments; } + + @Override + @Nullable + public Object getValue(String name) { + return skylarkVisibleFragments.get(name); + } + + @Override + public ImmutableCollection<String> getKeys() { + return skylarkVisibleFragments.keySet(); + } + + @Override + @Nullable + public String errorMessage(String name) { + return String.format("There is no configuration fragment named '%s'", name); + } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java index a32c11697b..6401d4e3d9 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java @@ -662,6 +662,16 @@ public class CppConfiguration extends BuildConfiguration.Fragment { this.additionalMakeVariables = ImmutableMap.copyOf(makeVariablesBuilder); } + @Override + public boolean isSkylarkVisible() { + return true; + } + + @Override + public String getName() { + return "cpp"; + } + private List<OptionalFlag> convertOptionalOptions( List<CrosstoolConfig.CToolchain.OptionalFlag> optionalFlagList) throws IllegalArgumentException { diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java index 37137c9db1..71454c6ef5 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java @@ -104,6 +104,16 @@ public final class JavaConfiguration extends Fragment { } this.translationTargets = translationsBuilder.build(); } + + @Override + public boolean isSkylarkVisible() { + return true; + } + + @Override + public String getName() { + return "java"; + } @SkylarkCallable(name = "default_javac_flags", structField = true, doc = "The default flags for the Java compiler.") diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/Jvm.java b/src/main/java/com/google/devtools/build/lib/rules/java/Jvm.java index d822da836c..378dc60462 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/Jvm.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/Jvm.java @@ -46,6 +46,16 @@ public final class Jvm extends BuildConfiguration.Fragment { this.javaHome = javaHome; this.jvmLabel = jvmLabel; } + + @Override + public boolean isSkylarkVisible() { + return true; + } + + @Override + public String getName() { + return "jvm"; + } @Override public void addImplicitLabels(Multimap<String, Label> implicitLabels) { diff --git a/src/main/java/com/google/devtools/build/lib/syntax/DotExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/DotExpression.java index bb0e8ed54b..1b98a27aa5 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/DotExpression.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/DotExpression.java @@ -71,14 +71,20 @@ public final class DotExpression extends Expression { public static Object eval(Object objValue, String name, Location loc) throws EvalException { if (objValue instanceof ClassObject) { Object result = ((ClassObject) objValue).getValue(name); - result = SkylarkType.convertToSkylark(result, loc); - // If we access NestedSets using ClassObject.getValue() we won't know the generic type, - // so we have to disable it. This should not happen. - SkylarkType.checkTypeAllowedInSkylark(result, loc); - return result; + + // ClassObjects may have fields that are annotated with @SkylarkCallable. + // Since getValue() does not know about those, we cannot expect that result is a valid object. + if (result != null) { + result = SkylarkType.convertToSkylark(result, loc); + // If we access NestedSets using ClassObject.getValue() we won't know the generic type, + // so we have to disable it. This should not happen. + SkylarkType.checkTypeAllowedInSkylark(result, loc); + return result; + } } - List<MethodDescriptor> methods = FuncallExpression.getMethods(objValue.getClass(), - name, 0, loc); + + List<MethodDescriptor> methods = + FuncallExpression.getMethods(objValue.getClass(), name, 0, loc); if (methods != null && !methods.isEmpty()) { MethodDescriptor method = Iterables.getOnlyElement(methods); if (method.getAnnotation().structField()) { |