aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Florian Weikert <fwe@google.com>2015-07-30 13:28:26 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2015-07-30 15:43:12 +0000
commiteee8be6b88d5ce7bd34a3bca0643df34ae7caa4f (patch)
treea5f9ca3f9415adbb4a7dd4ba106e51698a0a7527
parent6798135c65b16a962b75e9ee1aea9de8ba694e8f (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
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java53
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/Jvm.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/DotExpression.java20
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()) {