aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/docgen/RuleDocumentationAttribute.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/PackageSerializer.java12
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/ProtoUtils.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/Type.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuite.java39
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuiteRule.java50
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java42
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java186
-rw-r--r--src/main/protobuf/build.proto9
9 files changed, 283 insertions, 66 deletions
diff --git a/src/main/java/com/google/devtools/build/docgen/RuleDocumentationAttribute.java b/src/main/java/com/google/devtools/build/docgen/RuleDocumentationAttribute.java
index 0d6f5d691a..c68dae2dbc 100644
--- a/src/main/java/com/google/devtools/build/docgen/RuleDocumentationAttribute.java
+++ b/src/main/java/com/google/devtools/build/docgen/RuleDocumentationAttribute.java
@@ -45,6 +45,8 @@ class RuleDocumentationAttribute implements Comparable<RuleDocumentationAttribut
.put(Type.TRISTATE, "Integer")
.put(Type.LABEL, "<a href=\"build-ref.html#labels\">Label</a>")
.put(Type.LABEL_LIST, "List of <a href=\"build-ref.html#labels\">labels</a>")
+ .put(Type.LABEL_DICT_UNARY,
+ "Dictionary mapping strings to <a href=\"build-ref.html#labels\">labels</a>")
.put(Type.LABEL_LIST_DICT,
"Dictionary mapping strings to lists of <a href=\"build-ref.html#labels\">labels</a>")
.put(Type.NODEP_LABEL, "<a href=\"build-ref.html#name\">Name</a>")
diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageSerializer.java b/src/main/java/com/google/devtools/build/lib/packages/PackageSerializer.java
index 75067b726d..16b318cb62 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/PackageSerializer.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/PackageSerializer.java
@@ -19,6 +19,7 @@ import static com.google.devtools.build.lib.packages.Type.FILESET_ENTRY_LIST;
import static com.google.devtools.build.lib.packages.Type.INTEGER;
import static com.google.devtools.build.lib.packages.Type.INTEGER_LIST;
import static com.google.devtools.build.lib.packages.Type.LABEL;
+import static com.google.devtools.build.lib.packages.Type.LABEL_DICT_UNARY;
import static com.google.devtools.build.lib.packages.Type.LABEL_LIST;
import static com.google.devtools.build.lib.packages.Type.LABEL_LIST_DICT;
import static com.google.devtools.build.lib.packages.Type.LICENSE;
@@ -252,6 +253,17 @@ public class PackageSerializer {
attrPb.addStringListDictValue(entry);
}
}
+ } else if (type == LABEL_DICT_UNARY) {
+ for (Object value : values) {
+ Map<String, Label> dict = (Map<String, Label>) value;
+ for (Map.Entry<String, Label> dictEntry : dict.entrySet()) {
+ Build.LabelDictUnaryEntry entry = Build.LabelDictUnaryEntry.newBuilder()
+ .setKey(dictEntry.getKey())
+ .setValue(dictEntry.getValue().toString())
+ .build();
+ attrPb.addLabelDictUnaryValue(entry);
+ }
+ }
} else if (type == LABEL_LIST_DICT) {
for (Object value : values) {
Map<String, List<Label>> dict = (Map<String, List<Label>>) value;
diff --git a/src/main/java/com/google/devtools/build/lib/packages/ProtoUtils.java b/src/main/java/com/google/devtools/build/lib/packages/ProtoUtils.java
index 7b6eaf1efa..653e283e84 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/ProtoUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/ProtoUtils.java
@@ -20,6 +20,7 @@ import static com.google.devtools.build.lib.packages.Type.FILESET_ENTRY_LIST;
import static com.google.devtools.build.lib.packages.Type.INTEGER;
import static com.google.devtools.build.lib.packages.Type.INTEGER_LIST;
import static com.google.devtools.build.lib.packages.Type.LABEL;
+import static com.google.devtools.build.lib.packages.Type.LABEL_DICT_UNARY;
import static com.google.devtools.build.lib.packages.Type.LABEL_LIST;
import static com.google.devtools.build.lib.packages.Type.LABEL_LIST_DICT;
import static com.google.devtools.build.lib.packages.Type.LICENSE;
@@ -65,6 +66,7 @@ public class ProtoUtils {
.put(LICENSE, Discriminator.LICENSE)
.put(STRING_DICT, Discriminator.STRING_DICT)
.put(FILESET_ENTRY_LIST, Discriminator.FILESET_ENTRY_LIST)
+ .put(LABEL_DICT_UNARY, Discriminator.LABEL_DICT_UNARY)
.put(LABEL_LIST_DICT, Discriminator.LABEL_LIST_DICT)
.put(STRING_LIST_DICT, Discriminator.STRING_LIST_DICT)
.put(BOOLEAN, Discriminator.BOOLEAN)
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Type.java b/src/main/java/com/google/devtools/build/lib/packages/Type.java
index b1ca03e8a0..96191626dc 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Type.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Type.java
@@ -336,6 +336,11 @@ public abstract class Type<T> {
DictType.create(STRING, LABEL_LIST);
/**
+ * The type of a dictionary of {@linkplain #LABEL labels}.
+ */
+ public static final DictType<String, Label> LABEL_DICT_UNARY = DictType.create(STRING, LABEL);
+
+ /**
* The type of a list of {@linkplain #FILESET_ENTRY FilesetEntries}.
*/
public static final ListType<FilesetEntry> FILESET_ENTRY_LIST = ListType.create(FILESET_ENTRY);
@@ -1003,7 +1008,7 @@ public abstract class Type<T> {
* Returns whether the specified type is a label type or not.
*/
public static boolean isLabelType(Type<?> type) {
- return type == LABEL || type == LABEL_LIST
+ return type == LABEL || type == LABEL_LIST || type == LABEL_DICT_UNARY
|| type == NODEP_LABEL || type == NODEP_LABEL_LIST
|| type == LABEL_LIST_DICT || type == FILESET_ENTRY_LIST;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuite.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuite.java
new file mode 100644
index 0000000000..17d14feb37
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuite.java
@@ -0,0 +1,39 @@
+// Copyright 2015 Google Inc. 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.cpp;
+
+import com.google.devtools.build.lib.actions.Artifact;
+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.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
+import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
+
+/**
+ * Implementation of the {@code cc_toolchain_suite} rule.
+ *
+ * <p>This is currently a no-op because the logic that transforms this rule into something that can
+ * be understood by the {@code cc_*} rules is in
+ * {@link com.google.devtools.build.lib.rules.cpp.CppConfigurationLoader}.
+ */
+public class CcToolchainSuite implements RuleConfiguredTargetFactory {
+
+ @Override
+ public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException {
+ return new RuleConfiguredTargetBuilder(ruleContext)
+ .setFilesToBuild(NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER))
+ .build();
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuiteRule.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuiteRule.java
new file mode 100644
index 0000000000..9bc59c9d24
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuiteRule.java
@@ -0,0 +1,50 @@
+// Copyright 2015 Google Inc. 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.cpp;
+
+import static com.google.devtools.build.lib.packages.Attribute.attr;
+
+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.packages.RuleClass;
+import com.google.devtools.build.lib.packages.RuleClass.Builder;
+import com.google.devtools.build.lib.packages.Type;
+
+/**
+ * Definition of the {@code cc_toolchain_sute} rule.
+ */
+public final class CcToolchainSuiteRule implements RuleDefinition {
+
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
+ return builder
+ .setUndocumented()
+ .add(attr("toolchains", Type.LABEL_DICT_UNARY)
+ .mandatory()
+ .nonconfigurable("Used during configuration creation"))
+ .add(attr("proto", Type.STRING)
+ .nonconfigurable("Used during configuration creation"))
+ .build();
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("cc_toolchain_suite")
+ .ancestors(BaseRuleClasses.BaseRule.class)
+ .factoryClass(CcToolchainSuite.class)
+ .build();
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java
index bf26f630f8..9d4818ef24 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java
@@ -28,8 +28,10 @@ import com.google.devtools.build.lib.packages.InputFile;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.NoSuchThingException;
+import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.syntax.Label;
import com.google.devtools.build.lib.syntax.Label.SyntaxException;
import com.google.devtools.build.lib.vfs.Path;
@@ -108,13 +110,14 @@ public class CppConfigurationLoader implements ConfigurationFragmentFactory {
if (directories == null) {
return null;
}
- Label crosstoolTop = RedirectChaser.followRedirects(env,
+ Label crosstoolTopLabel = RedirectChaser.followRedirects(env,
options.get(CppOptions.class).crosstoolTop, "crosstool_top");
- if (crosstoolTop == null) {
+ if (crosstoolTopLabel == null) {
return null;
}
+
CrosstoolConfigurationLoader.CrosstoolFile file =
- CrosstoolConfigurationLoader.readCrosstool(env, crosstoolTop);
+ CrosstoolConfigurationLoader.readCrosstool(env, crosstoolTopLabel);
if (file == null) {
return null;
}
@@ -150,12 +153,33 @@ public class CppConfigurationLoader implements ConfigurationFragmentFactory {
}
Label ccToolchainLabel;
+ Target crosstoolTop;
+
try {
- ccToolchainLabel = crosstoolTop.getRelative("cc-compiler-" + toolchain.getTargetCpu());
- } catch (Label.SyntaxException e) {
- throw new InvalidConfigurationException(String.format(
- "'%s' is not a valid CPU. It should only consist of characters valid in labels",
- toolchain.getTargetCpu()));
+ crosstoolTop = env.getTarget(crosstoolTopLabel);
+ } catch (NoSuchThingException e) {
+ throw new IllegalStateException(e); // Should have been found out during redirect chasing
+ }
+
+ if (crosstoolTop instanceof Rule
+ && ((Rule) crosstoolTop).getRuleClass().equals("cc_toolchain_suite")) {
+ Rule ccToolchainSuite = (Rule) crosstoolTop;
+ ccToolchainLabel = NonconfigurableAttributeMapper.of(ccToolchainSuite)
+ .get("toolchains", Type.LABEL_DICT_UNARY)
+ .get(toolchain.getTargetCpu());
+ if (ccToolchainLabel == null) {
+ throw new InvalidConfigurationException(String.format(
+ "cc_toolchain_suite '%s' does not contain a toolchain for CPU '%s'",
+ crosstoolTopLabel, toolchain.getTargetCpu()));
+ }
+ } else {
+ try {
+ ccToolchainLabel = crosstoolTopLabel.getRelative("cc-compiler-" + toolchain.getTargetCpu());
+ } catch (Label.SyntaxException e) {
+ throw new InvalidConfigurationException(String.format(
+ "'%s' is not a valid CPU. It should only consist of characters valid in labels",
+ toolchain.getTargetCpu()));
+ }
}
Target ccToolchain;
@@ -176,6 +200,6 @@ public class CppConfigurationLoader implements ConfigurationFragmentFactory {
}
return new CppConfigurationParameters(toolchain, file.getMd5(), options,
- fdoZip, directories.getExecRoot(), crosstoolTop, ccToolchainLabel);
+ fdoZip, directories.getExecRoot(), crosstoolTopLabel, ccToolchainLabel);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java
index a113f5f126..e5957581ae 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java
@@ -14,24 +14,30 @@
package com.google.devtools.build.lib.rules.cpp;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
+import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
import com.google.common.io.BaseEncoding;
import com.google.devtools.build.lib.analysis.RedirectChaser;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.ConfigurationEnvironment;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.packages.NoSuchThingException;
+import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
import com.google.devtools.build.lib.packages.Package;
+import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.syntax.Label;
import com.google.devtools.build.lib.syntax.Label.SyntaxException;
-import com.google.devtools.build.lib.util.Pair;
+import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CrosstoolRelease;
import com.google.protobuf.TextFormat;
import com.google.protobuf.TextFormat.ParseException;
import com.google.protobuf.UninitializedMessageException;
@@ -39,6 +45,7 @@ import com.google.protobuf.UninitializedMessageException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;
@@ -46,6 +53,10 @@ import javax.annotation.Nullable;
/**
* A loader that reads Crosstool configuration files and creates CToolchain
* instances from them.
+ *
+ * <p>Note that this class contains a cache for the text format -> proto objects mapping of
+ * Crosstool protos that is completely independent from Skyframe or anything else. This should be
+ * done in a saner way.
*/
public class CrosstoolConfigurationLoader {
private static final String CROSSTOOL_CONFIGURATION_FILENAME = "CROSSTOOL";
@@ -54,53 +65,27 @@ public class CrosstoolConfigurationLoader {
* Cache for storing result of toReleaseConfiguration function based on path and md5 sum of
* input file. We can use md5 because result of this function depends only on the file content.
*/
- private static final LoadingCache<Pair<Path, String>, CrosstoolConfig.CrosstoolRelease>
- crosstoolReleaseCache = CacheBuilder.newBuilder().concurrencyLevel(4).maximumSize(100).build(
- new CacheLoader<Pair<Path, String>, CrosstoolConfig.CrosstoolRelease>() {
- @Override
- public CrosstoolConfig.CrosstoolRelease load(Pair<Path, String> key) throws IOException {
- char[] data = FileSystemUtils.readContentAsLatin1(key.first);
- return toReleaseConfiguration(key.first.getPathString(), new String(data));
- }
- });
-
+ private static final Cache<String, CrosstoolRelease> crosstoolReleaseCache =
+ CacheBuilder.newBuilder().concurrencyLevel(4).maximumSize(100).build();
/**
* A class that holds the results of reading a CROSSTOOL file.
*/
public static class CrosstoolFile {
- private final Label crosstoolTop;
- private Path crosstoolPath;
- private CrosstoolConfig.CrosstoolRelease crosstool;
- private String md5;
-
- CrosstoolFile(Label crosstoolTop) {
- this.crosstoolTop = crosstoolTop;
- }
-
- void setCrosstoolPath(Path crosstoolPath) {
- this.crosstoolPath = crosstoolPath;
- }
+ private final String location;
+ private final CrosstoolConfig.CrosstoolRelease crosstool;
+ private final String md5;
- void setCrosstool(CrosstoolConfig.CrosstoolRelease crosstool) {
+ CrosstoolFile(String location, CrosstoolConfig.CrosstoolRelease crosstool, String md5) {
+ this.location = location;
this.crosstool = crosstool;
- }
-
- void setMd5(String md5) {
this.md5 = md5;
}
/**
- * Returns the crosstool top as resolved.
- */
- public Label getCrosstoolTop() {
- return crosstoolTop;
- }
-
- /**
- * Returns the absolute path from which the CROSSTOOL file was read.
+ * Returns a user-friendly location of the CROSSTOOL proto for error messages.
*/
- public Path getCrosstoolPath() {
- return crosstoolPath;
+ public String getLocation() {
+ return location;
}
/**
@@ -145,27 +130,115 @@ public class CrosstoolConfigurationLoader {
}
}
- private static boolean findCrosstoolConfiguration(
- ConfigurationEnvironment env,
- CrosstoolConfigurationLoader.CrosstoolFile file)
+ /**
+ * This class is the in-memory representation of a text-formatted Crosstool proto file.
+ *
+ * <p>This layer of abstraction is here so that we can load these protos either from BUILD files
+ * or from CROSSTOOL files.
+ *
+ * <p>An implementation of this class should override {@link #getContents()} and call
+ * the constructor with the MD5 checksum of what that method will return and a human-readable name
+ * used in error messages.
+ */
+ private abstract static class CrosstoolProto {
+ private final byte[] md5;
+ private final String name;
+
+ private CrosstoolProto(byte[] md5, String name) {
+ this.md5 = md5;
+ this.name = name;
+ }
+
+ /**
+ * The binary MD5 checksum of the proto.
+ */
+ public byte[] getMd5() {
+ return md5;
+ }
+
+ /**
+ * A user-friendly string describing the location of the proto.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * The proto itself.
+ */
+ public abstract String getContents() throws IOException;
+ }
+
+ private static CrosstoolProto getCrosstoolProtofromBuildFile(
+ ConfigurationEnvironment env, Label crosstoolTop) {
+ Target target;
+ try {
+ target = env.getTarget(crosstoolTop);
+ } catch (NoSuchThingException e) {
+ throw new IllegalStateException(e); // Should have beeen evaluated by RedirectChaser
+ }
+
+ if (!(target instanceof Rule)) {
+ return null;
+ }
+
+ Rule rule = (Rule) target;
+ if (!(rule.getRuleClass().equals("cc_toolchain_suite"))
+ || !rule.isAttributeValueExplicitlySpecified("proto")) {
+ return null;
+ }
+
+ final String contents = NonconfigurableAttributeMapper.of(rule).get("proto", Type.STRING);
+ byte[] md5 = new Fingerprint().addBytes(contents.getBytes(UTF_8)).digestAndReset();
+ return new CrosstoolProto(md5, "cc_toolchain_suite rule " + crosstoolTop.toString()) {
+
+ @Override
+ public String getContents() throws IOException {
+ return contents;
+ }
+ };
+ }
+
+ private static CrosstoolProto getCrosstoolProtoFromCrosstoolFile(
+ ConfigurationEnvironment env, Label crosstoolTop)
throws IOException, InvalidConfigurationException {
- Label crosstoolTop = file.getCrosstoolTop();
- Path path = null;
+ final Path path;
try {
Package containingPackage = env.getTarget(crosstoolTop.getLocalTargetLabel("BUILD"))
.getPackage();
if (containingPackage == null) {
- return false;
+ return null;
}
path = env.getPath(containingPackage, CROSSTOOL_CONFIGURATION_FILENAME);
} catch (SyntaxException e) {
throw new InvalidConfigurationException(e);
} catch (NoSuchThingException e) {
// Handled later
+ return null;
}
- // If we can't find a file, fall back to the provided alternative.
if (path == null || !path.exists()) {
+ return null;
+ }
+
+ return new CrosstoolProto(path.getMD5Digest(), "CROSSTOOL file " + path.getPathString()) {
+ @Override
+ public String getContents() throws IOException {
+ return new String(FileSystemUtils.readContentAsLatin1(path.getInputStream()));
+ }
+ };
+ }
+
+ private static CrosstoolFile findCrosstoolConfiguration(
+ ConfigurationEnvironment env, Label crosstoolTop)
+ throws IOException, InvalidConfigurationException {
+
+ CrosstoolProto crosstoolProto = getCrosstoolProtofromBuildFile(env, crosstoolTop);
+ if (crosstoolProto == null) {
+ crosstoolProto = getCrosstoolProtoFromCrosstoolFile(env, crosstoolTop);
+ }
+
+ if (crosstoolProto == null) {
throw new InvalidConfigurationException("The crosstool_top you specified was resolved to '" +
crosstoolTop + "', which does not contain a CROSSTOOL file. " +
"You can use a crosstool from the depot by specifying its label.");
@@ -173,18 +246,22 @@ public class CrosstoolConfigurationLoader {
// Do this before we read the data, so if it changes, we get a different MD5 the next time.
// Alternatively, we could calculate the MD5 of the contents, which we also read, but this
// is faster if the file comes from a file system with md5 support.
- file.setCrosstoolPath(path);
- String md5 = BaseEncoding.base16().lowerCase().encode(path.getMD5Digest());
+ final CrosstoolProto finalProto = crosstoolProto;
+ String md5 = BaseEncoding.base16().lowerCase().encode(finalProto.getMd5());
CrosstoolConfig.CrosstoolRelease release;
try {
- release = crosstoolReleaseCache.get(new Pair<Path, String>(path, md5));
- file.setCrosstool(release);
- file.setMd5(md5);
+ release = crosstoolReleaseCache.get(md5, new Callable<CrosstoolRelease>() {
+ @Override
+ public CrosstoolRelease call() throws Exception {
+ return toReleaseConfiguration(finalProto.getName(), finalProto.getContents());
+ }
+ });
} catch (ExecutionException e) {
throw new InvalidConfigurationException(e);
}
+
+ return new CrosstoolFile(finalProto.getName(), release, md5);
}
- return true;
}
/**
@@ -197,11 +274,8 @@ public class CrosstoolConfigurationLoader {
if (crosstoolTop == null) {
return null;
}
- CrosstoolConfigurationLoader.CrosstoolFile file =
- new CrosstoolConfigurationLoader.CrosstoolFile(crosstoolTop);
try {
- boolean allDependenciesPresent = findCrosstoolConfiguration(env, file);
- return allDependenciesPresent ? file : null;
+ return findCrosstoolConfiguration(env, crosstoolTop);
} catch (IOException e) {
throw new InvalidConfigurationException(e);
}
diff --git a/src/main/protobuf/build.proto b/src/main/protobuf/build.proto
index a84df42b43..6780d4d844 100644
--- a/src/main/protobuf/build.proto
+++ b/src/main/protobuf/build.proto
@@ -38,6 +38,11 @@ message StringDictUnaryEntry {
required string value = 2;
}
+message LabelDictUnaryEntry {
+ required string key = 1;
+ required string value = 2;
+}
+
message LabelListDictEntry {
required string key = 1;
repeated string value = 2;
@@ -112,6 +117,7 @@ message Attribute {
INTEGER_LIST = 16; // int_list_value
STRING_DICT_UNARY = 17; // string_dict_unary_value
UNKNOWN = 18; // unknown type, use only for build extensions
+ LABEL_DICT_UNARY = 19; // label_dict_unary_value
}
// Values for the TriState field type.
@@ -186,6 +192,9 @@ message Attribute {
// If this is a string dict unary, each entry will be stored here.
repeated StringDictUnaryEntry string_dict_unary_value = 18;
+
+ // If this is a label dict unary, each entry will be stored here.
+ repeated LabelDictUnaryEntry label_dict_unary_value = 19;
}
// A rule from a BUILD file (e.g., cc_library, java_binary). The rule class