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
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 21fbab7..aa795bb 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 @@
  */
 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 @@
 
   @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 9b684e9..ef69aef 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.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 @@
     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 0000000..c45cc22
--- /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 7dab291..f0f6025 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.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 @@
         </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 8954aa0..3368c9c 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.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 @@
         "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 0000000..a536fdc
--- /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 0000000..e25ee2b
--- /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);
+  }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/BazelMockCcSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/BazelMockCcSupport.java
index 521d56a..47708aa 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/util/BazelMockCcSupport.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/BazelMockCcSupport.java
@@ -77,6 +77,7 @@
     config.create(
         "/bazel_tools_workspace/tools/cpp/BUILD",
         "package(default_visibility=['//visibility:public'])",
+        "toolchain_lookup(name = 'lookup')",
         "cc_library(name = 'stl')",
         "cc_library(name = 'malloc')",
         "cc_toolchain_suite(",
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java
index 5901ace..b24bd9f 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java
@@ -498,6 +498,7 @@
     config.create(
         "tools/cpp/BUILD",
         "package(default_visibility = ['//visibility:public'])",
+        "toolchain_lookup(name = 'lookup')",
         "cc_library(name = 'stl')",
         "alias(name='toolchain', actual='//third_party/crosstool')",
         "cc_library(name = 'malloc')",
diff --git a/src/test/java/com/google/devtools/build/lib/rules/ToolchainLookupTest.java b/src/test/java/com/google/devtools/build/lib/rules/ToolchainLookupTest.java
new file mode 100644
index 0000000..54a8d58
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/ToolchainLookupTest.java
@@ -0,0 +1,33 @@
+// 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 static com.google.common.truth.Truth.assertThat;
+
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import org.junit.Test;
+
+/**
+ * Unit tests for the {@code toolchain_lookup} rule.
+ */
+public class ToolchainLookupTest extends BuildViewTestCase {
+  @Test
+  public void testSmoke() throws Exception {
+    ConfiguredTarget cc = getConfiguredTarget(getRuleClassProvider().getToolsRepository()
+        + "//tools/cpp:lookup");
+    assertThat(cc.getProvider(ToolchainProvider.class).getMakeVariables())
+        .containsKey("TARGET_CPU");
+  }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java
index cf29915..7900089 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java
@@ -21,23 +21,32 @@
 import static org.junit.Assert.assertTrue;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.devtools.build.lib.actions.Action;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
 import com.google.devtools.build.lib.analysis.AnalysisUtils;
+import com.google.devtools.build.lib.analysis.BaseRuleClasses;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.OutputGroupProvider;
+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.analysis.config.ConfigurationFactory;
 import com.google.devtools.build.lib.analysis.mock.BazelAnalysisMock;
 import com.google.devtools.build.lib.analysis.util.AnalysisMock;
 import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
 import com.google.devtools.build.lib.bazel.rules.BazelRuleClassProvider;
+import com.google.devtools.build.lib.bazel.rules.BazelToolchainLookup;
+import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.flags.InvocationPolicyEnforcer;
+import com.google.devtools.build.lib.packages.RuleClass;
 import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.rules.ToolchainLookup;
 import com.google.devtools.build.lib.testutil.MoreAsserts;
 import com.google.devtools.build.lib.util.FileType;
 import com.google.devtools.build.lib.util.OsUtils;
@@ -813,6 +822,45 @@
             RepositoryName.MAIN).getExecPath().getPathString()));
   }
 
+  /**
+   * A {@code toolchain_lookup} rule for testing that only supports C++.
+   */
+  public static class OnlyCppToolchainLookup extends ToolchainLookup {
+    public OnlyCppToolchainLookup() {
+      super(
+          ImmutableMap.<Label, Class<? extends BuildConfiguration.Fragment>>of(),
+          ImmutableMap.<Label, ImmutableMap<String, String>>of());
+    }
+  }
+
+  /**
+   * A {@code toolchain_lookup} rule for testing that only supports C++.
+   */
+  public static class OnlyCppToolchainLookupRule 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)
+          .removeAttribute("licenses")
+          .removeAttribute("distribs")
+          .build();
+    }
+
+    @Override
+    public Metadata getMetadata() {
+      return Metadata.builder()
+          .name("toolchain_lookup")
+          .factoryClass(BazelToolchainLookup.class)
+          .ancestors(BaseRuleClasses.BaseRule.class)
+          .build();
+    }
+  }
+
+  /**
+   * Tests for the case where there are only C++ rules defined.
+   */
   @RunWith(JUnit4.class)
   public static class OnlyCppRules extends CcCommonTest {
     @Override
@@ -835,6 +883,7 @@
           BazelRuleClassProvider.CORE_WORKSPACE_RULES.init(builder);
           BazelRuleClassProvider.BASIC_RULES.init(builder);
           BazelRuleClassProvider.CPP_RULES.init(builder);
+          builder.addRuleDefinition(new OnlyCppToolchainLookupRule());
           return builder.build();
         }
 
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleContextTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleContextTest.java
index 15277ff..b60dace 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleContextTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleContextTest.java
@@ -565,6 +565,7 @@
                 "srcs",
                 "stamp",
                 "tags",
+                "toolchains",
                 "tools",
                 "visibility")),
         result);