aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google
diff options
context:
space:
mode:
authorGravatar Lukacs Berki <lberki@google.com>2016-11-22 16:18:48 +0000
committerGravatar Dmitry Lomov <dslomov@google.com>2016-11-22 18:15:08 +0000
commit8bb7b8fa364639c09dc4a50b5c960e1867b8e283 (patch)
tree9b1bb1f83f3a7cf4612195554e4dd449247ef8cd /src/main/java/com/google
parent0edd35414dbe916457c5e98d7c08e1b4cfcf8d57 (diff)
Initial checkin of the toolchain_lookup() rule for expressing explicit dependencies on Make variables and toolchains.
I'm not particularly happy with the fact that it needs to depend on every configuration fragment that defines Make variables, but this seemed more reasonable than having a rule class for every fragment, just to have a lonely single rule of that class. -- MOS_MIGRATED_REVID=139910229
Diffstat (limited to 'src/main/java/com/google')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/ConfigurationMakeVariableContext.java13
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/BazelToolchainLookup.java73
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/BazelGenRuleRule.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRule.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/ToolchainLookup.java68
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/ToolchainProvider.java50
7 files changed, 219 insertions, 2 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationMakeVariableContext.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationMakeVariableContext.java
index 21fbab7537..aa795bbea2 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationMakeVariableContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationMakeVariableContext.java
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.analysis;
+import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.MakeVariableExpander.ExpansionException;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.packages.Package;
@@ -28,12 +29,19 @@ import java.util.Map;
*/
public class ConfigurationMakeVariableContext implements MakeVariableExpander.Context {
private final Package pkg;
+ private final Map<String, String> toolchainEnv;
private final Map<String, String> commandLineEnv;
private final Map<String, String> globalEnv;
private final String platform;
public ConfigurationMakeVariableContext(Package pkg, BuildConfiguration configuration) {
+ this(pkg, configuration, ImmutableMap.<String, String>of());
+ }
+
+ public ConfigurationMakeVariableContext(Package pkg, BuildConfiguration configuration,
+ ImmutableMap<String, String> toolchainEnv) {
this.pkg = pkg;
+ this.toolchainEnv = toolchainEnv;
commandLineEnv = configuration.getCommandLineBuildVariables();
globalEnv = configuration.getGlobalMakeEnvironment();
platform = configuration.getPlatformName();
@@ -41,7 +49,10 @@ public class ConfigurationMakeVariableContext implements MakeVariableExpander.Co
@Override
public String lookupMakeVariable(String var) throws ExpansionException {
- String value = commandLineEnv.get(var);
+ String value = toolchainEnv.get(var);
+ if (value == null) {
+ value = commandLineEnv.get(var);
+ }
if (value == null) {
value = pkg.lookupMakeVariable(var, platform);
}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
index 9b684e9561..ef69aefd5a 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
@@ -29,6 +29,7 @@ import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.ConfigRuleClasses;
import com.google.devtools.build.lib.analysis.constraints.EnvironmentRule;
+import com.google.devtools.build.lib.bazel.rules.BazelToolchainLookup.BazelToolchainLookupRule;
import com.google.devtools.build.lib.bazel.rules.android.AndroidNdkRepositoryRule;
import com.google.devtools.build.lib.bazel.rules.android.AndroidSdkRepositoryRule;
import com.google.devtools.build.lib.bazel.rules.android.BazelAarImportRule;
@@ -280,6 +281,10 @@ public class BazelRuleClassProvider {
J2OBJC_RULES.init(builder);
ANDROID_STUDIO_ASPECT.init(builder);
VARIOUS_WORKSPACE_RULES.init(builder);
+
+ // This rule is a little special: it needs to depend on every configuration fragment that has
+ // Make variables, so we can't put it in any of the above buckets.
+ builder.addRuleDefinition(new BazelToolchainLookupRule());
}
public static final RuleSet BAZEL_SETUP =
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelToolchainLookup.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelToolchainLookup.java
new file mode 100644
index 0000000000..c45cc22a61
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelToolchainLookup.java
@@ -0,0 +1,73 @@
+// Copyright 2016 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.bazel.rules;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.analysis.BaseRuleClasses;
+import com.google.devtools.build.lib.analysis.RuleDefinition;
+import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.packages.RuleClass;
+import com.google.devtools.build.lib.rules.ToolchainLookup;
+import com.google.devtools.build.lib.rules.android.AndroidConfiguration;
+import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
+import com.google.devtools.build.lib.rules.java.Jvm;
+
+/**
+ * Implementation of {@code toolchain_lookup}.
+ */
+public class BazelToolchainLookup extends ToolchainLookup {
+
+ /**
+ * Definition for {@code toolchain_lookup}.
+ */
+ public static class BazelToolchainLookupRule implements RuleDefinition {
+
+ @Override
+ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment environment) {
+ return builder
+ // This means that *every* toolchain_lookup rule depends on every configuration fragment
+ // that contributes Make variables, regardless of which one it is.
+ .requiresConfigurationFragments(
+ CppConfiguration.class, Jvm.class, AndroidConfiguration.class)
+ .removeAttribute("licenses")
+ .removeAttribute("distribs")
+ .build();
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return Metadata.builder()
+ .name("toolchain_lookup")
+ .factoryClass(BazelToolchainLookup.class)
+ .ancestors(BaseRuleClasses.BaseRule.class)
+ .build();
+ }
+ }
+
+ public BazelToolchainLookup() {
+ super(
+ ImmutableMap.<Label, Class<? extends BuildConfiguration.Fragment>>builder()
+ .put(Label.parseAbsoluteUnchecked("@bazel_tools//tools/cpp:lookup"),
+ CppConfiguration.class)
+ .put(Label.parseAbsoluteUnchecked("@bazel_tools//tools/jdk:lookup"),
+ Jvm.class)
+ .put(Label.parseAbsoluteUnchecked("@bazel_tools//tools/android:lookup"),
+ AndroidConfiguration.class)
+ .build(),
+ ImmutableMap.<Label, ImmutableMap<String, String>>of());
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/BazelGenRuleRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/BazelGenRuleRule.java
index 7dab291608..f0f6025b73 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/BazelGenRuleRule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/BazelGenRuleRule.java
@@ -22,14 +22,18 @@ import static com.google.devtools.build.lib.packages.BuildType.OUTPUT_LIST;
import static com.google.devtools.build.lib.syntax.Type.BOOLEAN;
import static com.google.devtools.build.lib.syntax.Type.STRING;
+import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
+import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder;
+import com.google.devtools.build.lib.rules.ToolchainProvider;
+import com.google.devtools.build.lib.util.FileTypeSet;
/**
* Rule definition for the genrule rule.
@@ -82,6 +86,10 @@ public final class BazelGenRuleRule implements RuleDefinition {
</p>
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(attr("tools", LABEL_LIST).cfg(HOST).legacyAllowAnyFileType())
+ .add(attr("toolchains", LABEL_LIST)
+ .allowedFileTypes(FileTypeSet.NO_FILE)
+ .mandatoryNativeProviders(ImmutableList.<Class<? extends TransitiveInfoProvider>>of(
+ ToolchainProvider.class)))
.add(attr("$genrule_setup", LABEL).cfg(HOST).value(env.getToolsLabel(GENRULE_SETUP_LABEL)))
/* <!-- #BLAZE_RULE(genrule).ATTRIBUTE(outs) -->
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRule.java
index 8954aa01ed..3368c9ce97 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRule.java
@@ -41,6 +41,7 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
+import com.google.devtools.build.lib.rules.ToolchainProvider;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.List;
@@ -172,7 +173,8 @@ public class GenRule implements RuleConfiguredTargetFactory {
"cmd",
command,
new ConfigurationMakeVariableContext(
- ruleContext.getRule().getPackage(), ruleContext.getConfiguration()) {
+ ruleContext.getRule().getPackage(), ruleContext.getConfiguration(),
+ ToolchainProvider.getToolchainMakeVariables(ruleContext, "toolchains")) {
@Override
public String lookupMakeVariable(String name) throws ExpansionException {
if (name.equals("SRCS")) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/ToolchainLookup.java b/src/main/java/com/google/devtools/build/lib/rules/ToolchainLookup.java
new file mode 100644
index 0000000000..a536fdc679
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/ToolchainLookup.java
@@ -0,0 +1,68 @@
+// Copyright 2016 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;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.Runfiles;
+import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.cmdline.Label;
+import java.util.TreeMap;
+
+/**
+ * Abstract base class for {@code toolchain_lookup}.
+ */
+public class ToolchainLookup implements RuleConfiguredTargetFactory {
+ private final ImmutableMap<Label, Class<? extends BuildConfiguration.Fragment>> fragmentMap;
+ private final ImmutableMap<Label, ImmutableMap<String, String>> hardcodedVariableMap;
+
+ protected ToolchainLookup(
+ ImmutableMap<Label, Class<? extends BuildConfiguration.Fragment>> fragmentMap,
+ ImmutableMap<Label, ImmutableMap<String, String>> hardcodedVariableMap) {
+ this.fragmentMap = fragmentMap;
+ this.hardcodedVariableMap = hardcodedVariableMap;
+ }
+
+ @Override
+ public ConfiguredTarget create(RuleContext ruleContext)
+ throws InterruptedException, RuleErrorException {
+ // This cannot be an ImmutableMap.Builder because that asserts when a key is duplicated
+ TreeMap<String, String> makeVariables = new TreeMap<>();
+ Class<? extends BuildConfiguration.Fragment> fragmentClass =
+ fragmentMap.get(ruleContext.getLabel());
+ if (fragmentClass != null) {
+ BuildConfiguration.Fragment fragment = ruleContext.getFragment(fragmentClass);
+ ImmutableMap.Builder<String, String> fragmentBuilder = ImmutableMap.builder();
+ fragment.addGlobalMakeVariables(fragmentBuilder);
+ makeVariables.putAll(fragmentBuilder.build());
+ }
+
+ ImmutableMap<String, String> hardcodedVariables =
+ hardcodedVariableMap.get(ruleContext.getLabel());
+ if (hardcodedVariables != null) {
+ makeVariables.putAll(hardcodedVariables);
+ }
+ // This will eventually go to Skyframe using getAnalysisEnvironment.getSkyframeEnv() to figure
+ // out the lookup rule -> toolchain rule mapping. For now, it only provides Make variables that
+ // come from BuildConfiguration so no need to ask Skyframe.
+ return new RuleConfiguredTargetBuilder(ruleContext)
+ .addProvider(new ToolchainProvider(ImmutableMap.copyOf(makeVariables)))
+ .addProvider(RunfilesProvider.simple(Runfiles.EMPTY))
+ .build();
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/ToolchainProvider.java b/src/main/java/com/google/devtools/build/lib/rules/ToolchainProvider.java
new file mode 100644
index 0000000000..e25ee2b229
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/ToolchainProvider.java
@@ -0,0 +1,50 @@
+// Copyright 2016 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;
+
+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.TransitiveInfoProvider;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+import java.util.TreeMap;
+
+/**
+ * A toolchain, determined from the current platform.
+ */
+@Immutable
+public final class ToolchainProvider implements TransitiveInfoProvider {
+ private final ImmutableMap<String, String> makeVariables;
+
+ public ToolchainProvider(ImmutableMap<String, String> makeVariables) {
+ this.makeVariables = makeVariables;
+ }
+
+ public ImmutableMap<String, String> getMakeVariables() {
+ return makeVariables;
+ }
+
+ public static ImmutableMap<String, String> getToolchainMakeVariables(
+ RuleContext ruleContext, String attributeName) {
+ // Cannot be an ImmutableMap.Builder because we want to support duplicate keys
+ TreeMap<String, String> result = new TreeMap<>();
+ for (ToolchainProvider provider :
+ ruleContext.getPrerequisites(attributeName, Mode.TARGET, ToolchainProvider.class)) {
+ result.putAll(provider.getMakeVariables());
+ }
+
+ return ImmutableMap.copyOf(result);
+ }
+}