Skip to content

Commit

Permalink
Adding new ToolchainsFunction to report all available toolchains to B…
Browse files Browse the repository at this point in the history
…azel.

Part of bazelbuild#2219.

Change-Id: I76f3ebe88bd687c8b9ec47b91743a1cb724ec16f
  • Loading branch information
katre committed May 1, 2017
1 parent fe87e51 commit 7afafd3
Show file tree
Hide file tree
Showing 10 changed files with 392 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/main/java/com/google/devtools/build/lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,7 @@ java_library(
":util",
":vfs",
"//src/main/java/com/google/devtools/build/lib/actions",
"//src/main/java/com/google/devtools/build/lib/analysis/platform",
"//src/main/java/com/google/devtools/build/lib/buildeventstream/proto:build_event_stream_java_proto",
"//src/main/java/com/google/devtools/build/lib/causes",
"//src/main/java/com/google/devtools/build/lib/cmdline",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,15 @@ public DynamicConfigsConverter() {
)
public TriState buildPythonZip;

@Option(
name = "experimental_extra_toolchains",
converter = LabelListConverter.class,
defaultValue = "",
optionUsageRestrictions = OptionUsageRestrictions.UNDOCUMENTED,
help = "Extra targets to be considerd during toolchain resolution."
)
public List<Label> extraToolchains;

@Override
public FragmentOptions getHost(boolean fallback) {
Options host = (Options) getDefault();
Expand Down Expand Up @@ -1092,6 +1101,9 @@ public FragmentOptions getHost(boolean fallback) {
// === Pass on C++ compiler features.
host.defaultFeatures = ImmutableList.copyOf(defaultFeatures);

// Pass on extra toolchains.
host.extraToolchains = extraToolchains;

return host;
}

Expand All @@ -1102,7 +1114,9 @@ public void addAllLabels(Multimap<String, Label> labelMap) {
if ((runUnder != null) && (runUnder.getLabel() != null)) {
labelMap.put("RunUnder", runUnder.getLabel());
}
labelMap.putAll("extraToolchains", extraToolchains);
}

@Override
public Map<String, Set<Label>> getDefaultsLabels(BuildConfiguration.Options commonOptions) {
return ImmutableMap.<String, Set<Label>>of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.google.devtools.build.lib.analysis.WorkspaceStatusAction;
import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory;
import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory.BuildInfoKey;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.RuleVisibility;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
import com.google.devtools.build.lib.skyframe.SkyframeActionExecutor.ConflictException;
Expand Down Expand Up @@ -116,6 +117,8 @@ public static <T> Injected injected(Precomputed<T> precomputed, T value) {
public static final Precomputed<PathPackageLocator> PATH_PACKAGE_LOCATOR =
new Precomputed<>(SkyKey.create(SkyFunctions.PRECOMPUTED, "path_package_locator"));

public static final Precomputed<ImmutableList<Label>> EXTRA_TOOLCHAINS = new Precomputed<>(SkyKey.create(SkyFunctions.PRECOMPUTED, "extra_toolchains"));

private final Object value;

public PrecomputedValue(Object value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public final class SkyFunctions {
SkyFunctionName.create("ACTION_TEMPLATE_EXPANSION");
public static final SkyFunctionName LOCAL_REPOSITORY_LOOKUP =
SkyFunctionName.create("LOCAL_REPOSITORY_LOOKUP");
public static final SkyFunctionName TOOLCHAINS = SkyFunctionName.create("TOOLCHAINS");

public static Predicate<SkyKey> isSkyFunction(final SkyFunctionName functionName) {
return new Predicate<SkyKey>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ private ImmutableMap<SkyFunctionName, SkyFunction> skyFunctions(
SkyFunctions.ACTION_TEMPLATE_EXPANSION,
new ActionTemplateExpansionFunction(removeActionsAfterEvaluation));
map.put(SkyFunctions.LOCAL_REPOSITORY_LOOKUP, new LocalRepositoryLookupFunction());
map.put(SkyFunctions.TOOLCHAINS, new ToolchainsFunction());
map.putAll(extraSkyFunctions);
return map.build();
}
Expand Down Expand Up @@ -943,6 +944,10 @@ public final void setBlacklistedPackagePrefixesFile(PathFragment blacklistedPkgF
PrecomputedValue.BLACKLISTED_PACKAGE_PREFIXES_FILE.set(injectable(), blacklistedPkgFile);
}

private final void setExtraToolchains(List<Label> extraToolchains) {
PrecomputedValue.EXTRA_TOOLCHAINS.set(injectable(), ImmutableList.copyOf(extraToolchains));
}

/**
* Prepares the evaluator for loading.
*
Expand Down Expand Up @@ -1743,7 +1748,9 @@ public void sync(
for (Entry<String, String> v : opt.actionEnvironment) {
actionEnvironment.put(v.getKey(), v.getValue());
}
setExtraToolchains(opt.extraToolchains);
}

preparePackageLoading(
createPackageLocator(
eventHandler,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Copyright 2017 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.skyframe;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.platform.ToolchainInfo;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction.ConfiguredValueCreationException;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunctionException;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.ValueOrException;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;

/**
* {@link SkyFunction} that returns all {@link ToolchainInfo} providers available for toolchain
* resolution.
*/
public class ToolchainsFunction implements SkyFunction {

/** Ignores the key and returns all known instances of {@link ToolchainInfo}. */
@Nullable
@Override
public SkyValue compute(SkyKey skyKey, Environment env)
throws SkyFunctionException, InterruptedException {

BuildConfiguration configuration = (BuildConfiguration) skyKey.argument();

// Find toolchains passed in via command-line.
List<Label> extraToolchainLabels = PrecomputedValue.EXTRA_TOOLCHAINS.get(env);
ImmutableList<ToolchainInfo> extraToolchains =
resolveToolchainLabels(env, configuration, extraToolchainLabels);
if (extraToolchains == null) {
return null;
}

// TODO(katre): Add a way to register toolchains in WORKSPACE and resolve them here.

return ToolchainsValue.create(extraToolchains);
}

private ImmutableList<ToolchainInfo> resolveToolchainLabels(
Environment env, final BuildConfiguration configuration, List<Label> labels)
throws InterruptedException, ToolchainsFunctionException {
List<SkyKey> keys =
Lists.transform(
labels,
new Function<Label, SkyKey>() {
@Override
public SkyKey apply(Label label) {
return SkyKey.create(
SkyFunctions.CONFIGURED_TARGET, new ConfiguredTargetKey(label, configuration));
}
});

Map<SkyKey, ValueOrException<ConfiguredValueCreationException>> values =
env.getValuesOrThrow(keys, ConfiguredValueCreationException.class);
if (env.valuesMissing()) {
return null;
}
ImmutableList.Builder<ToolchainInfo> toolchains = new ImmutableList.Builder<>();
for (SkyKey key : keys) {
ConfiguredTargetKey configuredTargetKey = (ConfiguredTargetKey) key.argument();
Label toolchainLabel = configuredTargetKey.getLabel();
try {
ConfiguredTarget target =
((ConfiguredTargetValue) values.get(key).get()).getConfiguredTarget();
ToolchainInfo toolchainInfo = toolchain(target);
if (toolchainInfo == null) {
throw new ToolchainsFunctionException(new InvalidTargetException(toolchainLabel));
}
toolchains.add(toolchainInfo);
} catch (ConfiguredValueCreationException e) {
throw new ToolchainsFunctionException(e);
}
}
return toolchains.build();
}

/** Retrieves and casts the provider from the given target. */
public static ToolchainInfo toolchain(TransitiveInfoCollection target) {
Object provider = target.get(ToolchainInfo.SKYLARK_IDENTIFIER);
if (provider == null) {
return null;
}
Preconditions.checkState(provider instanceof ToolchainInfo);
return (ToolchainInfo) provider;
}

@Nullable
@Override
public String extractTag(SkyKey skyKey) {
return null;
}

/**
* Used to indicate that the given {@link Label} represents a {@link ConfiguredTarget} which is
* not a valid {@link ToolchainInfo} provider.
*/
public static final class InvalidTargetException extends Exception {
private final Label invalidLabel;

public InvalidTargetException(Label invalidLabel) {
super(String.format("target '%s' does not provide a toolchain", invalidLabel));
this.invalidLabel = invalidLabel;
}

public Label getInvalidLabel() {
return invalidLabel;
}
}

/** Used to indicate errors during the computation of an {@link ToolchainsValue}. */
private static final class ToolchainsFunctionException extends SkyFunctionException {
public ToolchainsFunctionException(ConfiguredValueCreationException e) {
super(e, Transience.PERSISTENT);
}

public ToolchainsFunctionException(InvalidTargetException e) {
super(e, Transience.PERSISTENT);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2017 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.skyframe;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.platform.ToolchainInfo;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;

/**
* A value which represents every toolchain known to Bazel and available for toolchain resolution.
*/
@AutoValue
public abstract class ToolchainsValue implements SkyValue {

/** Returns the {@link SkyKey} for {@link ToolchainsValue}s. */
public static SkyKey key(BuildConfiguration configuration) {
return SkyKey.create(SkyFunctions.TOOLCHAINS, configuration);
}

public static ToolchainsValue create(Iterable<ToolchainInfo> toolchains) {
return new AutoValue_ToolchainsValue(ImmutableList.copyOf(toolchains));
}

public abstract ImmutableList<ToolchainInfo> toolchains();
}
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,16 @@ protected ConfiguredTarget getConfiguredTarget(String label, BuildConfiguration
return getConfiguredTarget(Label.parseAbsolute(label), config);
}

/**
* Returns the ConfiguredTarget for the specified label, using the given build configuration. If
* the label corresponds to a target with a top-level configuration transition, that transition is
* applied to the given config in the returned ConfiguredTarget.
*/
protected ConfiguredTarget getConfiguredTarget(Label label)
throws LabelSyntaxException {
return getConfiguredTarget(label, targetConfig);
}

/**
* Returns the ConfiguredTarget for the specified label, using the
* given build configuration. If the label corresponds to a target with a top-level configuration
Expand Down
2 changes: 2 additions & 0 deletions src/test/java/com/google/devtools/build/lib/skyframe/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ java_test(
"//src/main/java/com/google/devtools/build/lib:util",
"//src/main/java/com/google/devtools/build/lib:vfs",
"//src/main/java/com/google/devtools/build/lib/actions",
"//src/main/java/com/google/devtools/build/lib/analysis/platform",
"//src/main/java/com/google/devtools/build/lib/cmdline",
"//src/main/java/com/google/devtools/build/lib/rules/cpp",
"//src/main/java/com/google/devtools/build/skyframe",
Expand All @@ -75,6 +76,7 @@ java_test(
"//src/test/java/com/google/devtools/build/lib:foundations_testutil",
"//src/test/java/com/google/devtools/build/lib:packages_testutil",
"//src/test/java/com/google/devtools/build/lib:testutil",
"//src/test/java/com/google/devtools/build/lib/skylark:testutil",
"//third_party:guava",
"//third_party:guava-testlib",
"//third_party:jsr305",
Expand Down
Loading

0 comments on commit 7afafd3

Please sign in to comment.