Skip to content

Commit

Permalink
Add register_toolchains function to the WORKSPACE for registering too…
Browse files Browse the repository at this point in the history
…lchains to use.

Part of bazelbuild#2219.

Change-Id: Id6dfe6ec102f609bb19461242a098bf977be29ae
  • Loading branch information
katre committed Jul 10, 2017
1 parent d579b6e commit 661187b
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 11 deletions.
14 changes: 14 additions & 0 deletions src/main/java/com/google/devtools/build/lib/packages/Package.java
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ protected NameConflictException(String message) {
private ImmutableList<Event> events;
private ImmutableList<Postable> posts;

private ImmutableList<Label> registeredToolchainLabels;

/**
* Package initialization, part 1 of 3: instantiates a new package with the
* given name.
Expand Down Expand Up @@ -317,6 +319,7 @@ protected void finishInit(Builder builder) {
this.features = ImmutableSortedSet.copyOf(builder.features);
this.events = ImmutableList.copyOf(builder.events);
this.posts = ImmutableList.copyOf(builder.posts);
this.registeredToolchainLabels = ImmutableList.copyOf(builder.registeredToolchainLabels);
}

/**
Expand Down Expand Up @@ -643,6 +646,10 @@ public Set<Label> getDefaultRestrictedTo() {
return defaultRestrictedTo;
}

public ImmutableList<Label> getRegisteredToolchainLabels() {
return registeredToolchainLabels;
}

@Override
public String toString() {
return "Package(" + name + ")="
Expand Down Expand Up @@ -694,6 +701,7 @@ public static Builder newExternalPackageBuilder(Builder.Helper helper, Path work
* {@link com.google.devtools.build.lib.skyframe.PackageFunction}.
*/
public static class Builder {

public static interface Helper {
/**
* Returns a fresh {@link Package} instance that a {@link Builder} will internally mutate
Expand Down Expand Up @@ -756,6 +764,8 @@ public void onLoadingComplete(Package pkg) {

protected ExternalPackageBuilder externalPackageData = new ExternalPackageBuilder();

protected List<Label> registeredToolchainLabels = new ArrayList<>();

/**
* True iff the "package" function has already been called in this package.
*/
Expand Down Expand Up @@ -1270,6 +1280,10 @@ void addRule(Rule rule) throws NameConflictException, InterruptedException {
addRuleUnchecked(rule);
}

void addRegisteredToolchainLabels(List<Label> toolchains) {
this.registeredToolchainLabels.addAll(toolchains);
}

private Builder beforeBuild(boolean discoverAssumedInputFiles) throws InterruptedException {
Preconditions.checkNotNull(pkg);
Preconditions.checkNotNull(filename);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,14 @@
import com.google.devtools.build.lib.syntax.Mutability;
import com.google.devtools.build.lib.syntax.ParserInputSource;
import com.google.devtools.build.lib.syntax.Runtime;
import com.google.devtools.build.lib.syntax.Runtime.NoneType;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkSignatureProcessor;
import com.google.devtools.build.lib.vfs.Path;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand All @@ -60,7 +63,6 @@
* Parser for WORKSPACE files. Fills in an ExternalPackage.Builder
*/
public class WorkspaceFactory {
public static final String BIND = "bind";
private static final Pattern LEGAL_WORKSPACE_NAME = Pattern.compile("^\\p{Alpha}\\w*$");

// List of static function added by #addWorkspaceFunctions. Used to trim them out from the
Expand Down Expand Up @@ -260,6 +262,7 @@ public void setParent(
if (aPackage.containsErrors()) {
builder.setContainsErrors();
}
builder.addRegisteredToolchainLabels(aPackage.getRegisteredToolchainLabels());
for (Rule rule : aPackage.getTargets(Rule.class)) {
try {
// The old rule references another Package instance and we wan't to keep the invariant that
Expand Down Expand Up @@ -382,6 +385,56 @@ public Object invoke(String name, String actual, FuncallExpression ast, Environm
};
}

@SkylarkSignature(
name = "register_toolchains",
objectType = Object.class,
returnType = NoneType.class,
doc =
"Registers a toolchain created with the toolchain() rule so that it is available for "
+ "toolchain resolution.",
extraPositionals =
@Param(
name = "toolchain_labels",
type = SkylarkList.class,
generic1 = String.class,
doc = "The labels of the toolchains to register."
),
useAst = true,
useEnvironment = true
)
private static final BuiltinFunction.Factory newRegisterToolchainsFunction =
new BuiltinFunction.Factory("register_toolchains") {
public BuiltinFunction create(final RuleFactory ruleFactory) {
return new BuiltinFunction(
"register_toolchains", FunctionSignature.POSITIONALS, BuiltinFunction.USE_AST_ENV) {
public Object invoke(
SkylarkList<String> toolchainLabels, FuncallExpression ast, Environment env)
throws EvalException, InterruptedException {

// Collect the toolchain labels.
List<Label> toolchains = new ArrayList<>();
for (String rawLabel :
toolchainLabels.getContents(String.class, "toolchain_labels")) {
try {
toolchains.add(Label.parseAbsolute(rawLabel));
} catch (LabelSyntaxException e) {
throw new EvalException(
ast.getLocation(),
String.format("Unable to parse toolchain %s: %s", rawLabel, e.getMessage()),
e);
}
}

// Add to the package definition for later.
Package.Builder builder = PackageFactory.getContext(env, ast).pkgBuilder;
builder.addRegisteredToolchainLabels(toolchains);

return NONE;
}
};
}
};

/**
* Returns a function-value implementing the build rule "ruleClass" (e.g. cc_library) in the
* specified package context.
Expand Down Expand Up @@ -426,15 +479,16 @@ public Object invoke(Map<String, Object> kwargs, FuncallExpression ast, Environm

private static ImmutableMap<String, BaseFunction> createWorkspaceFunctions(
boolean allowOverride, RuleFactory ruleFactory) {
ImmutableMap.Builder<String, BaseFunction> mapBuilder = ImmutableMap.builder();
mapBuilder.put(BIND, newBindFunction(ruleFactory));
Map<String, BaseFunction> map = new HashMap<>();
map.put("bind", newBindFunction(ruleFactory));
map.put("register_toolchains", newRegisterToolchainsFunction.apply(ruleFactory));
for (String ruleClass : ruleFactory.getRuleClassNames()) {
if (!ruleClass.equals(BIND)) {
if (!map.containsKey(ruleClass)) {
BaseFunction ruleFunction = newRuleFunction(ruleFactory, ruleClass, allowOverride);
mapBuilder.put(ruleClass, ruleFunction);
map.put(ruleClass, ruleFunction);
}
}
return mapBuilder.build();
return ImmutableMap.copyOf(map);
}

private void addWorkspaceFunctions(Environment workspaceEnv, StoredEventHandler localReporter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.skyframe.PackageLookupValue;
import com.google.devtools.build.lib.skyframe.PackageValue;
import com.google.devtools.build.lib.skyframe.WorkspaceFileValue;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.util.Preconditions;
Expand Down Expand Up @@ -171,6 +172,24 @@ public static Rule getRepository(
return rule;
}

/**
* Loads the external package and then returns the registered toolchain labels.
*
* @param env the environment to use for lookups
*/
@Nullable
public static List<Label> getRegisteredToolchainLabels(Environment env)
throws ExternalPackageException, InterruptedException {
PackageValue externalPackageValue =
(PackageValue) env.getValue(PackageValue.key(Label.EXTERNAL_PACKAGE_IDENTIFIER));
if (externalPackageValue == null) {
return null;
}

Package externalPackage = externalPackageValue.getPackage();
return externalPackage.getRegisteredToolchainLabels();
}

/** Exception thrown when something goes wrong accessing a rule. */
public static class ExternalPackageException extends SkyFunctionException {
public ExternalPackageException(NoSuchPackageException cause, Transience transience) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,9 @@ private SkyValue getExternalPackage(Environment env, Path packageLookupPath)
env.getListener().post(post);
}

packageFactory.afterDoneLoadingPackage(pkg);
if (packageFactory != null) {
packageFactory.afterDoneLoadingPackage(pkg);
}
return new PackageValue(pkg);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,10 @@ public SignatureException(String message, @Nullable Parameter<?, ?> parameter) {
}
}

/** A ready-made signature to allow only positional arguments and put them in a star parameter */
public static final FunctionSignature POSITIONALS =
FunctionSignature.of(0, 0, 0, true, false, "star");

/** A ready-made signature to allow only keyword arguments and put them in a kwarg parameter */
public static final FunctionSignature KWARGS =
FunctionSignature.of(0, 0, 0, false, true, "kwargs");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import static org.junit.Assert.fail;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.StoredEventHandler;
import com.google.devtools.build.lib.packages.Package.Builder;
Expand Down Expand Up @@ -83,6 +84,31 @@ public void testIllegalWorkspaceFunctionPosition() throws Exception {
"workspace() function should be used only at the top of the WORKSPACE file");
}

@Test
public void testRegisterToolchains() throws Exception {
WorkspaceFactoryHelper helper = parse("register_toolchains('//toolchain:tc1')");
assertThat(helper.getPackage().getRegisteredToolchainLabels())
.containsExactly(Label.parseAbsolute("//toolchain:tc1"));
}

@Test
public void testRegisterToolchains_multipleLabels() throws Exception {
WorkspaceFactoryHelper helper =
parse("register_toolchains(", " '//toolchain:tc1',", " '//toolchain:tc2')");
assertThat(helper.getPackage().getRegisteredToolchainLabels())
.containsExactly(
Label.parseAbsolute("//toolchain:tc1"), Label.parseAbsolute("//toolchain:tc2"));
}

@Test
public void testRegisterToolchains_multipleCalls() throws Exception {
WorkspaceFactoryHelper helper =
parse("register_toolchains('//toolchain:tc1')", "register_toolchains('//toolchain:tc2')");
assertThat(helper.getPackage().getRegisteredToolchainLabels())
.containsExactly(
Label.parseAbsolute("//toolchain:tc1"), Label.parseAbsolute("//toolchain:tc2"));
}

private WorkspaceFactoryHelper parse(String... args) {
return new WorkspaceFactoryHelper(args);
}
Expand Down
Loading

0 comments on commit 661187b

Please sign in to comment.