Enable load() statement in the WORKSPACE file.
RELNOTES[NEW]: Skylark macros are now enabled in WORKSPACE file.
Design document at https://docs.google.com/document/d/1jKbNXOVp2T1zJD_iRnVr8k5D0xZKgO8blMVDlXOksJg/preview
Fixes #337
--
MOS_MIGRATED_REVID=108860301
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Package.java b/src/main/java/com/google/devtools/build/lib/packages/Package.java
index 579e060..a9ad155 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Package.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Package.java
@@ -688,6 +688,16 @@
}
/**
+ * Derive a LegacyBuilder from a normal Builder.
+ */
+ LegacyBuilder(Builder builder) {
+ super(builder.pkg);
+ if (builder.getFilename() != null) {
+ setFilename(builder.getFilename());
+ }
+ }
+
+ /**
* Sets the globber used for this package's glob expansions.
*/
LegacyBuilder setGlobber(Globber globber) {
@@ -717,8 +727,8 @@
}
}
- public static Builder newExternalPackageBuilder(Path workspacePath, String runfilesPrefix) {
- Builder b = new Builder(new Package(EXTERNAL_PACKAGE_IDENTIFIER, runfilesPrefix));
+ public static LegacyBuilder newExternalPackageBuilder(Path workspacePath, String runfilesPrefix) {
+ LegacyBuilder b = new LegacyBuilder(EXTERNAL_PACKAGE_IDENTIFIER, runfilesPrefix);
b.setFilename(workspacePath);
b.setMakeEnv(new MakeEnvironment.Builder());
return b;
@@ -799,6 +809,11 @@
return pkg.getPackageIdentifier();
}
+ /** Determine if we are in the WORKSPACE file or not */
+ public boolean isWorkspace() {
+ return pkg.getPackageIdentifier().equals(EXTERNAL_PACKAGE_IDENTIFIER);
+ }
+
/**
* Sets the name of this package's BUILD file.
*/
diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
index 987b572..6093a40 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
@@ -390,6 +390,7 @@
this.environmentExtensions = ImmutableList.copyOf(environmentExtensions);
this.packageArguments = createPackageArguments();
this.nativeModule = newNativeModule();
+ this.workspaceNativeModule = WorkspaceFactory.newNativeModule(ruleClassProvider);
}
/**
@@ -1223,10 +1224,11 @@
}
private final ClassObject nativeModule;
+ private final ClassObject workspaceNativeModule;
/** @return the Skylark struct to bind to "native" */
- public ClassObject getNativeModule() {
- return nativeModule;
+ public ClassObject getNativeModule(boolean workspace) {
+ return workspace ? workspaceNativeModule : nativeModule;
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java b/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java
index d15994a..684289f 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java
@@ -101,8 +101,7 @@
} catch (LabelSyntaxException e) {
throw new InvalidRuleException("illegal rule name: " + name + ": " + e.getMessage());
}
- boolean inWorkspaceFile =
- location.getPath() != null && location.getPath().getBaseName().contains("WORKSPACE");
+ boolean inWorkspaceFile = pkgBuilder.isWorkspace();
if (ruleClass.getWorkspaceOnly() && !inWorkspaceFile) {
throw new RuleFactory.InvalidRuleException(
ruleClass + " must be in the WORKSPACE file " + "(used by " + label + ")");
diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
index 4527f5e..4a089c3 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
@@ -17,24 +17,29 @@
import static com.google.devtools.build.lib.syntax.Runtime.NONE;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.LabelValidator;
import com.google.devtools.build.lib.events.Event;
-import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.events.StoredEventHandler;
import com.google.devtools.build.lib.packages.Package.Builder;
+import com.google.devtools.build.lib.packages.Package.LegacyBuilder;
import com.google.devtools.build.lib.packages.PackageFactory.EnvironmentExtension;
import com.google.devtools.build.lib.syntax.BaseFunction;
import com.google.devtools.build.lib.syntax.BuildFileAST;
import com.google.devtools.build.lib.syntax.BuiltinFunction;
+import com.google.devtools.build.lib.syntax.ClassObject;
import com.google.devtools.build.lib.syntax.Environment;
+import com.google.devtools.build.lib.syntax.Environment.Extension;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.FunctionSignature;
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.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.File;
import java.util.Map;
@@ -45,8 +50,17 @@
* Parser for WORKSPACE files. Fills in an ExternalPackage.Builder
*/
public class WorkspaceFactory {
- private final Builder builder;
- private final Environment environment;
+ public static final String BIND = "bind";
+
+ private final LegacyBuilder builder;
+ private final StoredEventHandler localReporter;
+
+ private final Path installDir;
+ private final Path workspaceDir;
+ private final Mutability mutability;
+
+ private final ImmutableMap<String, BaseFunction> workspaceFunctions;
+ private final ImmutableList<EnvironmentExtension> environmentExtensions;
/**
* @param builder a builder for the Workspace
@@ -54,8 +68,10 @@
* @param mutability the Mutability for the current evaluation context
*/
public WorkspaceFactory(
- Builder builder, RuleClassProvider ruleClassProvider,
- ImmutableList<EnvironmentExtension> environmentExtensions, Mutability mutability) {
+ LegacyBuilder builder,
+ RuleClassProvider ruleClassProvider,
+ ImmutableList<EnvironmentExtension> environmentExtensions,
+ Mutability mutability) {
this(builder, ruleClassProvider, environmentExtensions, mutability, null, null);
}
@@ -69,62 +85,106 @@
* @param workspaceDir the workspace directory
*/
public WorkspaceFactory(
- Builder builder,
+ LegacyBuilder builder,
RuleClassProvider ruleClassProvider,
ImmutableList<EnvironmentExtension> environmentExtensions,
Mutability mutability,
@Nullable Path installDir,
@Nullable Path workspaceDir) {
this.builder = builder;
- this.environment = createWorkspaceEnv(builder, ruleClassProvider, environmentExtensions,
- mutability, installDir, workspaceDir);
+ this.localReporter = new StoredEventHandler();
+ this.mutability = mutability;
+ this.installDir = installDir;
+ this.workspaceDir = workspaceDir;
+ this.environmentExtensions = environmentExtensions;
+ this.workspaceFunctions = createWorkspaceFunctions(ruleClassProvider);
}
- public void parse(ParserInputSource source)
- throws InterruptedException {
- StoredEventHandler localReporter = new StoredEventHandler();
- BuildFileAST buildFileAST;
+ // State while parsing the WORKSPACE file.
+ // We store them so we can pause the parsing and load skylark imports from the
+ // WorkspaceFileFunction. Loading skylark imports require access to the .skyframe package
+ // which this package cannot depends on.
+ private BuildFileAST buildFileAST = null;
+ private Environment.Builder environmentBuilder = null;
+ private ParserInputSource source = null;
+
+ // Called by com.google.devtools.build.workspace.Resolver from //src/tools/generate_workspace.
+ public void parse(ParserInputSource source) throws InterruptedException {
+ // This method is split in 2 so WorkspaceFileFunction can call the two parts separately and
+ // do the Skylark load imports in between.
+ parseBuildFile(source);
+ execute();
+ }
+
+ public void parseBuildFile(ParserInputSource source) {
+ this.source = source;
buildFileAST = BuildFileAST.parseBuildFile(source, localReporter, false);
if (buildFileAST.containsErrors()) {
+ environmentBuilder = null;
localReporter.handle(Event.error("WORKSPACE file could not be parsed"));
} else {
- if (!buildFileAST.exec(environment, localReporter)) {
+ environmentBuilder =
+ Environment.builder(mutability)
+ .setGlobals(Environment.BUILD)
+ .setEventHandler(localReporter);
+ }
+ }
+
+ public void execute() throws InterruptedException {
+ if (environmentBuilder != null) {
+ Environment workspaceEnv = environmentBuilder.setLoadingPhase().build();
+ addWorkspaceFunctions(workspaceEnv);
+ if (!buildFileAST.exec(workspaceEnv, localReporter)) {
localReporter.handle(Event.error("Error evaluating WORKSPACE file " + source.getPath()));
}
}
+ environmentBuilder = null;
+ buildFileAST = null;
+ source = null;
builder.addEvents(localReporter.getEvents());
if (localReporter.hasErrors()) {
builder.setContainsErrors();
}
+ localReporter.clear();
+ }
+
+ public BuildFileAST getBuildFileAST() {
+ return buildFileAST;
+ }
+
+ public void setImportedExtensions(Map<PathFragment, Extension> importedExtensions) {
+ environmentBuilder.setImportedExtensions(importedExtensions);
}
// TODO(bazel-team): use @SkylarkSignature annotations on a BuiltinFunction.Factory
// for signature + documentation of this and other functions in this file.
- private static BuiltinFunction newWorkspaceNameFunction(final Builder builder) {
- return new BuiltinFunction("workspace",
- FunctionSignature.namedOnly("name"), BuiltinFunction.USE_LOC) {
- public Object invoke(String name, Location loc) throws EvalException {
+ private static BuiltinFunction newWorkspaceNameFunction() {
+ return new BuiltinFunction(
+ "workspace", FunctionSignature.namedOnly("name"), BuiltinFunction.USE_AST_ENV) {
+ public Object invoke(String name, FuncallExpression ast, Environment env)
+ throws EvalException {
String errorMessage = LabelValidator.validateTargetName(name);
if (errorMessage != null) {
- throw new EvalException(loc, errorMessage);
+ throw new EvalException(ast.getLocation(), errorMessage);
}
- builder.setWorkspaceName(name);
+
+ PackageFactory.getContext(env, ast).pkgBuilder.setWorkspaceName(name);
return NONE;
}
};
}
- private static BuiltinFunction newBindFunction(
- final RuleFactory ruleFactory, final Builder builder) {
+ private static BuiltinFunction newBindFunction(final RuleFactory ruleFactory) {
return new BuiltinFunction(
- "bind", FunctionSignature.namedOnly(1, "name", "actual"), BuiltinFunction.USE_LOC) {
- public Object invoke(String name, String actual, Location loc)
+ "bind", FunctionSignature.namedOnly(1, "name", "actual"), BuiltinFunction.USE_AST_ENV) {
+ public Object invoke(String name, String actual, FuncallExpression ast, Environment env)
throws EvalException, InterruptedException {
Label nameLabel = null;
try {
nameLabel = Label.parseAbsolute("//external:" + name);
try {
+ LegacyBuilder builder = PackageFactory.getContext(env, ast).pkgBuilder;
RuleClass ruleClass = ruleFactory.getRuleClass("bind");
builder
.externalPackageData()
@@ -133,16 +193,16 @@
ruleClass,
nameLabel,
actual == null ? null : Label.parseAbsolute(actual),
- loc);
+ ast.getLocation());
} catch (
RuleFactory.InvalidRuleException | Package.NameConflictException
| LabelSyntaxException
e) {
- throw new EvalException(loc, e.getMessage());
+ throw new EvalException(ast.getLocation(), e.getMessage());
}
} catch (LabelSyntaxException e) {
- throw new EvalException(loc, e.getMessage());
+ throw new EvalException(ast.getLocation(), e.getMessage());
}
return NONE;
}
@@ -154,12 +214,13 @@
* specified package context.
*/
private static BuiltinFunction newRuleFunction(
- final RuleFactory ruleFactory, final Builder builder, final String ruleClassName) {
+ final RuleFactory ruleFactory, final String ruleClassName) {
return new BuiltinFunction(
ruleClassName, FunctionSignature.KWARGS, BuiltinFunction.USE_AST_ENV) {
public Object invoke(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
throws EvalException, InterruptedException {
try {
+ Builder builder = PackageFactory.getContext(env, ast).pkgBuilder;
RuleClass ruleClass = ruleFactory.getRuleClass(ruleClassName);
RuleClass bindRuleClass = ruleFactory.getRuleClass("bind");
builder
@@ -175,22 +236,25 @@
};
}
- private Environment createWorkspaceEnv(
- Builder builder,
- RuleClassProvider ruleClassProvider,
- ImmutableList<EnvironmentExtension> environmentExtensions,
- Mutability mutability,
- Path installDir,
- Path workspaceDir) {
- Environment workspaceEnv = Environment.builder(mutability)
- .setGlobals(Environment.BUILD)
- .setLoadingPhase()
- .build();
+ private static ImmutableMap<String, BaseFunction> createWorkspaceFunctions(
+ RuleClassProvider ruleClassProvider) {
+ ImmutableMap.Builder<String, BaseFunction> mapBuilder = ImmutableMap.builder();
RuleFactory ruleFactory = new RuleFactory(ruleClassProvider);
+ mapBuilder.put(BIND, newBindFunction(ruleFactory));
+ for (String ruleClass : ruleFactory.getRuleClassNames()) {
+ if (!ruleClass.equals(BIND)) {
+ BaseFunction ruleFunction = newRuleFunction(ruleFactory, ruleClass);
+ mapBuilder.put(ruleClass, ruleFunction);
+ }
+ }
+ return mapBuilder.build();
+ }
+
+ private void addWorkspaceFunctions(Environment workspaceEnv) {
try {
- for (String ruleClass : ruleFactory.getRuleClassNames()) {
- BaseFunction ruleFunction = newRuleFunction(ruleFactory, builder, ruleClass);
- workspaceEnv.update(ruleClass, ruleFunction);
+ workspaceEnv.update("workspace", newWorkspaceNameFunction());
+ for (Map.Entry<String, BaseFunction> function : workspaceFunctions.entrySet()) {
+ workspaceEnv.update(function.getKey(), function.getValue());
}
if (installDir != null) {
workspaceEnv.update("__embedded_dir__", installDir.getPathString());
@@ -200,16 +264,32 @@
}
File jreDirectory = new File(System.getProperty("java.home"));
workspaceEnv.update("DEFAULT_SERVER_JAVABASE", jreDirectory.getParentFile().toString());
- workspaceEnv.update("bind", newBindFunction(ruleFactory, builder));
- workspaceEnv.update("workspace", newWorkspaceNameFunction(builder));
for (EnvironmentExtension extension : environmentExtensions) {
extension.updateWorkspace(workspaceEnv);
}
-
- return workspaceEnv;
+ workspaceEnv.setupDynamic(
+ PackageFactory.PKG_CONTEXT,
+ new PackageFactory.PackageContext(builder, null, localReporter));
} catch (EvalException e) {
throw new AssertionError(e);
}
}
+
+ private static ClassObject newNativeModule(
+ ImmutableMap<String, BaseFunction> workspaceFunctions) {
+ ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
+ for (String nativeFunction : Runtime.getFunctionNames(SkylarkNativeModule.class)) {
+ builder.put(nativeFunction, Runtime.getFunction(SkylarkNativeModule.class, nativeFunction));
+ }
+ for (Map.Entry<String, BaseFunction> function : workspaceFunctions.entrySet()) {
+ builder.put(function.getKey(), function.getValue());
+ }
+
+ return new ClassObject.SkylarkClassObject(builder.build(), "no native function or rule '%s'");
+ }
+
+ public static ClassObject newNativeModule(RuleClassProvider ruleClassProvider) {
+ return newNativeModule(createWorkspaceFunctions(ruleClassProvider));
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/WorkspaceBaseRule.java b/src/main/java/com/google/devtools/build/lib/rules/repository/WorkspaceBaseRule.java
index 64bb1d5..581559c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/WorkspaceBaseRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/WorkspaceBaseRule.java
@@ -14,6 +14,9 @@
package com.google.devtools.build.lib.rules.repository;
+import static com.google.devtools.build.lib.packages.Attribute.attr;
+import static com.google.devtools.build.lib.syntax.Type.STRING;
+
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.packages.RuleClass;
@@ -28,6 +31,9 @@
public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
return builder
.exemptFromConstraintChecking("workspace rules aren't built for target environments")
+ .add(attr("generator_name", STRING).undocumented("internal"))
+ .add(attr("generator_function", STRING).undocumented("internal"))
+ .add(attr("generator_location", STRING).undocumented("internal"))
.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
index d365738..97f6fdd 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
@@ -73,7 +73,7 @@
Environment env, Label extensionLabel, String skylarkValueName)
throws ConversionException {
- SkyKey importFileKey = SkylarkImportLookupValue.key(extensionLabel);
+ SkyKey importFileKey = SkylarkImportLookupValue.key(extensionLabel, false);
SkylarkImportLookupValue skylarkImportLookupValue =
(SkylarkImportLookupValue) env.getValue(importFileKey);
if (skylarkImportLookupValue == null) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
index 197d929..ce1b4c3 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
@@ -539,7 +539,12 @@
ImmutableList.<Label>of());
} else {
importResult =
- fetchImportsFromBuildFile(buildFilePath, packageId, astAfterPreprocessing.ast, env);
+ fetchImportsFromBuildFile(
+ buildFilePath,
+ packageId,
+ astAfterPreprocessing.ast,
+ env,
+ skylarkImportLookupFunctionForInlining);
}
return importResult;
@@ -550,11 +555,12 @@
* returns null.
*/
@Nullable
- private SkylarkImportResult fetchImportsFromBuildFile(
+ static SkylarkImportResult fetchImportsFromBuildFile(
Path buildFilePath,
PackageIdentifier packageId,
BuildFileAST buildFileAST,
- Environment env)
+ Environment env,
+ SkylarkImportLookupFunction skylarkImportLookupFunctionForInlining)
throws PackageFunctionException, InterruptedException {
ImmutableList<LoadStatement> loadStmts = buildFileAST.getImports();
Map<PathFragment, Extension> importMap = Maps.newHashMapWithExpectedSize(loadStmts.size());
@@ -584,8 +590,9 @@
// Look up and load the imports.
ImmutableCollection<Label> importLabels = importPathMap.values();
List<SkyKey> importLookupKeys = Lists.newArrayListWithExpectedSize(importLabels.size());
+ boolean inWorkspace = buildFilePath.getBaseName().endsWith("WORKSPACE");
for (Label importLabel : importLabels) {
- importLookupKeys.add(SkylarkImportLookupValue.key(importLabel));
+ importLookupKeys.add(SkylarkImportLookupValue.key(importLabel, inWorkspace));
}
Map<SkyKey, SkyValue> skylarkImportMap = Maps.newHashMapWithExpectedSize(importPathMap.size());
boolean valuesMissing = false;
@@ -625,6 +632,7 @@
skylarkImportMap.put(importLookupKey, skyValue);
}
}
+
}
} catch (SkylarkImportFailedException e) {
env.getListener().handle(Event.error(Location.fromFile(buildFilePath), e.getMessage()));
@@ -644,7 +652,7 @@
for (Entry<PathFragment, Label> importEntry : importPathMap.entrySet()) {
PathFragment importPath = importEntry.getKey();
Label importLabel = importEntry.getValue();
- SkyKey keyForLabel = SkylarkImportLookupValue.key(importLabel);
+ SkyKey keyForLabel = SkylarkImportLookupValue.key(importLabel, inWorkspace);
SkylarkImportLookupValue importLookupValue =
(SkylarkImportLookupValue) skylarkImportMap.get(keyForLabel);
importMap.put(importPath, importLookupValue.getEnvironmentExtension());
@@ -654,14 +662,14 @@
return new SkylarkImportResult(importMap, transitiveClosureOfLabels(fileDependencies.build()));
}
- private ImmutableList<Label> transitiveClosureOfLabels(
+ private static ImmutableList<Label> transitiveClosureOfLabels(
ImmutableList<SkylarkFileDependency> immediateDeps) {
Set<Label> transitiveClosure = Sets.newHashSet();
transitiveClosureOfLabels(immediateDeps, transitiveClosure);
return ImmutableList.copyOf(transitiveClosure);
}
- private void transitiveClosureOfLabels(
+ private static void transitiveClosureOfLabels(
ImmutableList<SkylarkFileDependency> immediateDeps, Set<Label> transitiveClosure) {
for (SkylarkFileDependency dep : immediateDeps) {
if (transitiveClosure.add(dep.getLabel())) {
@@ -954,16 +962,16 @@
* Used to declare all the exception types that can be wrapped in the exception thrown by
* {@link PackageFunction#compute}.
*/
- private static class PackageFunctionException extends SkyFunctionException {
+ static class PackageFunctionException extends SkyFunctionException {
public PackageFunctionException(NoSuchPackageException e, Transience transience) {
super(e, transience);
}
}
/** A simple value class to store the result of the Skylark imports.*/
- private static final class SkylarkImportResult {
- private final Map<PathFragment, Extension> importMap;
- private final ImmutableList<Label> fileDependencies;
+ static final class SkylarkImportResult {
+ final Map<PathFragment, Extension> importMap;
+ final ImmutableList<Label> fileDependencies;
private SkylarkImportResult(
Map<PathFragment, Extension> importMap,
ImmutableList<Label> fileDependencies) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java
index 5eed6a6..3262e3d 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java
@@ -32,6 +32,7 @@
import com.google.devtools.build.lib.packages.PackageFactory;
import com.google.devtools.build.lib.packages.RuleClassProvider;
import com.google.devtools.build.lib.rules.SkylarkRuleClassFunctions;
+import com.google.devtools.build.lib.skyframe.SkylarkImportLookupValue.SkylarkImportLookupKey;
import com.google.devtools.build.lib.syntax.BuildFileAST;
import com.google.devtools.build.lib.syntax.Environment.Extension;
import com.google.devtools.build.lib.syntax.EvalException;
@@ -77,9 +78,9 @@
@Override
public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException,
InterruptedException {
- Label fileLabel = (Label) skyKey.argument();
+ SkylarkImportLookupKey key = (SkylarkImportLookupKey) skyKey.argument();
try {
- return computeInternal(fileLabel, env, null);
+ return computeInternal(key.importLabel, key.inWorkspace, env, null);
} catch (InconsistentFilesystemException e) {
throw new SkylarkImportLookupFunctionException(e, Transience.PERSISTENT);
} catch (SkylarkImportFailedException e) {
@@ -91,22 +92,23 @@
throws InconsistentFilesystemException,
SkylarkImportFailedException,
InterruptedException {
- return computeWithInlineCallsInternal(
- (Label) skyKey.argument(), env, new LinkedHashSet<Label>());
+ return computeWithInlineCallsInternal(skyKey, env, new LinkedHashSet<Label>());
}
private SkyValue computeWithInlineCallsInternal(
- Label fileLabel, Environment env, Set<Label> visited)
- throws InconsistentFilesystemException,
- SkylarkImportFailedException,
- InterruptedException {
- return computeInternal(fileLabel, env, Preconditions.checkNotNull(visited, fileLabel));
+ SkyKey skyKey, Environment env, Set<Label> visited)
+ throws InconsistentFilesystemException, SkylarkImportFailedException, InterruptedException {
+ SkylarkImportLookupKey key = (SkylarkImportLookupKey) skyKey.argument();
+ return computeInternal(
+ key.importLabel,
+ key.inWorkspace,
+ env,
+ Preconditions.checkNotNull(visited, key.importLabel));
}
- SkyValue computeInternal(Label fileLabel, Environment env, @Nullable Set<Label> visited)
- throws InconsistentFilesystemException,
- SkylarkImportFailedException,
- InterruptedException {
+ SkyValue computeInternal(
+ Label fileLabel, boolean inWorkspace, Environment env, @Nullable Set<Label> visited)
+ throws InconsistentFilesystemException, SkylarkImportFailedException, InterruptedException {
PathFragment filePath = fileLabel.toPathFragment();
// Load the AST corresponding to this file.
@@ -147,7 +149,7 @@
List<SkyKey> importLookupKeys =
Lists.newArrayListWithExpectedSize(importLabels.size());
for (Label importLabel : importLabels) {
- importLookupKeys.add(SkylarkImportLookupValue.key(importLabel));
+ importLookupKeys.add(SkylarkImportLookupValue.key(importLabel, inWorkspace));
}
Map<SkyKey, SkyValue> skylarkImportMap;
boolean valuesMissing = false;
@@ -168,9 +170,7 @@
}
skylarkImportMap = Maps.newHashMapWithExpectedSize(loadStmts.size());
for (SkyKey importLookupKey : importLookupKeys) {
- SkyValue skyValue =
- this.computeWithInlineCallsInternal(
- (Label) importLookupKey.argument(), env, visited);
+ SkyValue skyValue = this.computeWithInlineCallsInternal(importLookupKey, env, visited);
if (skyValue == null) {
Preconditions.checkState(
env.valuesMissing(), "no skylark import value for %s", importLookupKey);
@@ -194,7 +194,7 @@
for (Entry<PathFragment, Label> importEntry : importPathMap.entrySet()) {
PathFragment importPath = importEntry.getKey();
Label importLabel = importEntry.getValue();
- SkyKey keyForLabel = SkylarkImportLookupValue.key(importLabel);
+ SkyKey keyForLabel = SkylarkImportLookupValue.key(importLabel, inWorkspace);
SkylarkImportLookupValue importLookupValue =
(SkylarkImportLookupValue) skylarkImportMap.get(keyForLabel);
importMap.put(importPath, importLookupValue.getEnvironmentExtension());
@@ -202,7 +202,8 @@
}
// Skylark UserDefinedFunction-s in that file will share this function definition Environment,
// which will be frozen by the time it is returned by createExtension.
- Extension extension = createExtension(ast, fileLabel, importMap, env);
+
+ Extension extension = createExtension(ast, fileLabel, importMap, env, inWorkspace);
return new SkylarkImportLookupValue(
extension, new SkylarkFileDependency(fileLabel, fileDependencies.build()));
@@ -363,8 +364,9 @@
BuildFileAST ast,
Label extensionLabel,
Map<PathFragment, Extension> importMap,
- Environment env)
- throws SkylarkImportFailedException, InterruptedException {
+ Environment env,
+ boolean inWorkspace)
+ throws SkylarkImportFailedException, InterruptedException {
StoredEventHandler eventHandler = new StoredEventHandler();
// TODO(bazel-team): this method overestimates the changes which can affect the
// Skylark RuleClass. For example changes to comments or unused functions can modify the hash.
@@ -373,9 +375,10 @@
PathFragment extensionFile = extensionLabel.toPathFragment();
try (Mutability mutability = Mutability.create("importing %s", extensionFile)) {
com.google.devtools.build.lib.syntax.Environment extensionEnv =
- ruleClassProvider.createSkylarkRuleClassEnvironment(
- mutability, eventHandler, ast.getContentHashCode(), importMap)
- .setupOverride("native", packageFactory.getNativeModule());
+ ruleClassProvider
+ .createSkylarkRuleClassEnvironment(
+ mutability, eventHandler, ast.getContentHashCode(), importMap)
+ .setupOverride("native", packageFactory.getNativeModule(inWorkspace));
ast.exec(extensionEnv, eventHandler);
try {
SkylarkRuleClassFunctions.exportRuleFunctionsAndAspects(extensionEnv, extensionLabel);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupValue.java
index c298977..3574e2b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupValue.java
@@ -15,10 +15,14 @@
import com.google.common.base.Preconditions;
import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.syntax.Environment.Extension;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
+import java.io.Serializable;
+import java.util.Objects;
+
/**
* A value that represents a Skylark import lookup result. The lookup value corresponds to
* exactly one Skylark file, identified by an absolute {@link Label} {@link SkyKey} argument. The
@@ -55,10 +59,41 @@
}
/**
- * Returns a SkyKey to look up {@link Label} {@code importLabel}, which must be an absolute
- * label.
+ * SkyKey for a Skylark import composed of the label of the Skylark extension and wether it is
+ * loaded from the WORKSPACE file or from a BUILD file.
*/
- static SkyKey key(Label importLabel) {
- return new SkyKey(SkyFunctions.SKYLARK_IMPORTS_LOOKUP, importLabel);
+ @Immutable
+ public static final class SkylarkImportLookupKey implements Serializable {
+ public final Label importLabel;
+ public final boolean inWorkspace;
+
+ public SkylarkImportLookupKey(Label importLabel, boolean inWorkspace) {
+ Preconditions.checkNotNull(importLabel);
+ this.importLabel = importLabel;
+ this.inWorkspace = inWorkspace;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof SkylarkImportLookupKey)) {
+ return false;
+ }
+ SkylarkImportLookupKey other = (SkylarkImportLookupKey) obj;
+ return importLabel.equals(other.importLabel)
+ && inWorkspace == other.inWorkspace;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(importLabel, inWorkspace);
+ }
+ }
+
+ static SkyKey key(Label importLabel, boolean inWorkspace) {
+ return new SkyKey(
+ SkyFunctions.SKYLARK_IMPORTS_LOOKUP, new SkylarkImportLookupKey(importLabel, inWorkspace));
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkModuleCycleReporter.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkModuleCycleReporter.java
index 4da76f0..41f71d3 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkModuleCycleReporter.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkModuleCycleReporter.java
@@ -18,7 +18,6 @@
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
-import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.skyframe.CycleInfo;
@@ -54,13 +53,16 @@
.append(lastPathElement.argument()).append("/BUILD: ")
.append("cycle in referenced extension files: ");
- AbstractLabelCycleReporter.printCycle(cycleInfo.getCycle(), cycleMessage,
+ AbstractLabelCycleReporter.printCycle(
+ cycleInfo.getCycle(),
+ cycleMessage,
new Function<SkyKey, String>() {
- @Override
- public String apply(SkyKey input) {
- return ((Label) input.argument()).toString();
- }
- });
+ @Override
+ public String apply(SkyKey input) {
+ return ((SkylarkImportLookupValue.SkylarkImportLookupKey) input.argument())
+ .importLabel.toString();
+ }
+ });
// TODO(bazel-team): it would be nice to pass the Location of the load Statement in the
// BUILD file.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java
index 0f73697..345800d 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java
@@ -15,11 +15,12 @@
package com.google.devtools.build.lib.skyframe;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
-import com.google.devtools.build.lib.packages.Package.Builder;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.packages.Package.LegacyBuilder;
import com.google.devtools.build.lib.packages.PackageFactory;
import com.google.devtools.build.lib.packages.RuleClassProvider;
import com.google.devtools.build.lib.packages.WorkspaceFactory;
-import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.skyframe.PackageFunction.PackageFunctionException;
import com.google.devtools.build.lib.syntax.Mutability;
import com.google.devtools.build.lib.syntax.ParserInputSource;
import com.google.devtools.build.lib.vfs.Path;
@@ -54,6 +55,8 @@
@Override
public SkyValue compute(SkyKey skyKey, Environment env) throws WorkspaceFileFunctionException,
InterruptedException {
+ final Environment skyEnvironment = env;
+
RootedPath workspaceRoot = (RootedPath) skyKey.argument();
FileValue workspaceFileValue = (FileValue) env.getValue(FileValue.key(workspaceRoot));
if (workspaceFileValue == null) {
@@ -61,7 +64,7 @@
}
Path repoWorkspace = workspaceRoot.getRoot().getRelative(workspaceRoot.getRelativePath());
- Builder builder =
+ LegacyBuilder builder =
com.google.devtools.build.lib.packages.Package.newExternalPackageBuilder(
repoWorkspace, packageFactory.getRuleClassProvider().getRunfilesPrefix());
try (Mutability mutability = Mutability.create("workspace %s", repoWorkspace)) {
@@ -73,15 +76,23 @@
mutability,
directories.getEmbeddedBinariesRoot(),
directories.getWorkspace());
- parser.parse(
- ParserInputSource.create(
- ruleClassProvider.getDefaultWorkspaceFile(), new PathFragment("DEFAULT.WORKSPACE")));
- if (!workspaceFileValue.exists()) {
- return new PackageValue(builder.build());
- }
-
try {
- parser.parse(ParserInputSource.create(repoWorkspace, workspaceFileValue.getSize()));
+ PathFragment pathFragment = new PathFragment("/DEFAULT.WORKSPACE");
+ if (!parse(
+ ParserInputSource.create(ruleClassProvider.getDefaultWorkspaceFile(), pathFragment),
+ repoWorkspace, parser, skyEnvironment)) {
+ return null;
+ }
+ if (!workspaceFileValue.exists()) {
+ return new PackageValue(builder.build());
+ }
+
+ if (!parse(
+ ParserInputSource.create(repoWorkspace), repoWorkspace, parser, skyEnvironment)) {
+ return null;
+ }
+ } catch (PackageFunctionException e) {
+ throw new WorkspaceFileFunctionException(e, Transience.PERSISTENT);
} catch (IOException e) {
throw new WorkspaceFileFunctionException(e, Transience.TRANSIENT);
}
@@ -90,17 +101,43 @@
return new PackageValue(builder.build());
}
+ private boolean loadSkylarkImports(Path repoWorkspace, WorkspaceFactory parser,
+ Environment skyEnvironment) throws PackageFunctionException, InterruptedException {
+ // Load skylark imports
+ PackageFunction.SkylarkImportResult importResult;
+ importResult = PackageFunction.fetchImportsFromBuildFile(repoWorkspace,
+ PackageIdentifier.createInDefaultRepo("external"),
+ parser.getBuildFileAST(),
+ skyEnvironment,
+ null);
+ if (importResult == null) {
+ return false;
+ }
+ parser.setImportedExtensions(importResult.importMap);
+ return true;
+ }
+
+ private boolean parse(ParserInputSource source, Path repoWorkspace, WorkspaceFactory parser,
+ Environment skyEnvironment) throws PackageFunctionException, InterruptedException {
+ parser.parseBuildFile(source);
+ if (!loadSkylarkImports(repoWorkspace, parser, skyEnvironment)) {
+ return false;
+ }
+ parser.execute();
+ return true;
+ }
+
@Override
public String extractTag(SkyKey skyKey) {
return null;
}
private static final class WorkspaceFileFunctionException extends SkyFunctionException {
- public WorkspaceFileFunctionException(IOException e, Transience transience) {
+ public WorkspaceFileFunctionException(Exception e, Transience transience) {
super(e, transience);
}
- public WorkspaceFileFunctionException(EvalException e) {
+ public WorkspaceFileFunctionException(Exception e) {
super(e, Transience.PERSISTENT);
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/packages/ExternalPackageTest.java b/src/test/java/com/google/devtools/build/lib/packages/ExternalPackageTest.java
index 3d83246..5af665a 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/ExternalPackageTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/ExternalPackageTest.java
@@ -48,15 +48,12 @@
public void testMultipleRulesWithSameName() throws Exception {
Builder builder = Package.newExternalPackageBuilder(workspacePath, "TESTING");
- // The WORKSPACE file allows rules to be overridden, but the TestRuleClassProvider doesn't
- // provide WORKSPACE rules (new_local_repo et al). So for the test, we create an
- // ExternalPackage with BUILD rules, even though these rules wouldn't ordinarily be added to
- // ExternalPackage.
- Location buildFile = Location.fromFile(getOutputPath().getRelative("BUILD"));
+ // The WORKSPACE file allows rules to be overridden.
+ Location buildFile = Location.fromFile(getOutputPath().getRelative("WORKSPACE"));
// Add first rule.
RuleClass ruleClass =
- TestRuleClassProvider.getRuleClassProvider().getRuleClassMap().get("cc_library");
+ TestRuleClassProvider.getRuleClassProvider().getRuleClassMap().get("local_repository");
RuleClass bindRuleClass =
TestRuleClassProvider.getRuleClassProvider().getRuleClassMap().get("bind");
@@ -70,7 +67,8 @@
.createAndAddRepositoryRule(builder, ruleClass, bindRuleClass, kwargs, ast);
// Add another rule with the same name.
- ruleClass = TestRuleClassProvider.getRuleClassProvider().getRuleClassMap().get("sh_test");
+ ruleClass =
+ TestRuleClassProvider.getRuleClassProvider().getRuleClassMap().get("new_local_repository");
ast =
new FuncallExpression(
new Identifier(ruleClass.getName()), Lists.<Argument.Passed>newArrayList());
@@ -81,6 +79,6 @@
Package pkg = builder.build();
// Make sure the second rule "wins."
- assertEquals("sh_test rule", pkg.getTarget("my-rule").getTargetKind());
+ assertEquals("new_local_repository rule", pkg.getTarget("my-rule").getTargetKind());
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/packages/RuleFactoryTest.java b/src/test/java/com/google/devtools/build/lib/packages/RuleFactoryTest.java
index 9634a02..c09de9f 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/RuleFactoryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/RuleFactoryTest.java
@@ -147,7 +147,7 @@
public void testBuildRuleFailsInWorkspaceFile() throws Exception {
Path myPkgPath = scratch.resolve("/foo/workspace/WORKSPACE");
Package.Builder pkgBuilder =
- new Package.Builder(PackageIdentifier.createInDefaultRepo("mypkg"), "TESTING")
+ new Package.Builder(Package.EXTERNAL_PACKAGE_IDENTIFIER, "TESTING")
.setFilename(myPkgPath)
.setMakeEnv(new MakeEnvironment.Builder());
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunctionTest.java
index 6304b9c..99999be 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunctionTest.java
@@ -121,7 +121,7 @@
}
private SkyKey key(String label) throws Exception {
- return SkylarkImportLookupValue.key(Label.parseAbsoluteUnchecked(label));
+ return SkylarkImportLookupValue.key(Label.parseAbsoluteUnchecked(label), false);
}
private void checkLabel(String labelRequested, String labelFound) throws Exception {
@@ -134,7 +134,7 @@
public void testSkylarkImportLookupNoBuildFile() throws Exception {
scratch.file("pkg/ext.bzl", "");
SkyKey skylarkImportLookupKey =
- SkylarkImportLookupValue.key(Label.parseAbsoluteUnchecked("//pkg:ext.bzl"));
+ SkylarkImportLookupValue.key(Label.parseAbsoluteUnchecked("//pkg:ext.bzl"), false);
EvaluationResult<SkylarkImportLookupValue> result =
SkyframeExecutorTestUtils.evaluate(
getSkyframeExecutor(), skylarkImportLookupKey, /*keepGoing=*/ false, reporter);
@@ -150,7 +150,7 @@
scratch.file("pkg1/ext.bzl", "a = 1");
scratch.file("pkg2/ext.bzl", "load('/pkg1/ext', 'a')");
SkyKey skylarkImportLookupKey =
- SkylarkImportLookupValue.key(Label.parseAbsoluteUnchecked("//pkg:ext.bzl"));
+ SkylarkImportLookupValue.key(Label.parseAbsoluteUnchecked("//pkg:ext.bzl"), false);
EvaluationResult<SkylarkImportLookupValue> result =
SkyframeExecutorTestUtils.evaluate(
getSkyframeExecutor(), skylarkImportLookupKey, /*keepGoing=*/ false, reporter);
@@ -165,7 +165,7 @@
scratch.file("pkg/BUILD", "");
scratch.file("pkg/ext.bzl", "load('/pkg/oops\u0000', 'a')");
SkyKey skylarkImportLookupKey =
- SkylarkImportLookupValue.key(Label.parseAbsoluteUnchecked("//pkg:ext.bzl"));
+ SkylarkImportLookupValue.key(Label.parseAbsoluteUnchecked("//pkg:ext.bzl"), false);
EvaluationResult<SkylarkImportLookupValue> result =
SkyframeExecutorTestUtils.evaluate(
getSkyframeExecutor(), skylarkImportLookupKey, /*keepGoing=*/ false, reporter);
@@ -180,7 +180,7 @@
scratch.file("pkg/BUILD", "");
scratch.file("pkg/ext.bzl", "load('oops\u0000', 'a')");
SkyKey skylarkImportLookupKey =
- SkylarkImportLookupValue.key(Label.parseAbsoluteUnchecked("//pkg:ext.bzl"));
+ SkylarkImportLookupValue.key(Label.parseAbsoluteUnchecked("//pkg:ext.bzl"), false);
EvaluationResult<SkylarkImportLookupValue> result =
SkyframeExecutorTestUtils.evaluate(
getSkyframeExecutor(), skylarkImportLookupKey, /*keepGoing=*/ false, reporter);
diff --git a/src/test/shell/bazel/BUILD b/src/test/shell/bazel/BUILD
index a041d34..d882efe 100644
--- a/src/test/shell/bazel/BUILD
+++ b/src/test/shell/bazel/BUILD
@@ -172,6 +172,13 @@
)
sh_test(
+ name = "skylark_repository_test",
+ size = "large",
+ srcs = ["skylark_repository_test.sh"],
+ data = [":test-deps"],
+)
+
+sh_test(
name = "runfiles_test",
size = "medium",
srcs = ["runfiles_test.sh"],
diff --git a/src/test/shell/bazel/skylark_repository_test.sh b/src/test/shell/bazel/skylark_repository_test.sh
new file mode 100755
index 0000000..bc1cd6e
--- /dev/null
+++ b/src/test/shell/bazel/skylark_repository_test.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+#
+# Copyright 2015 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.
+#
+# Test the local_repository binding
+#
+
+# Load test environment
+source $(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/test-setup.sh \
+ || { echo "test-setup.sh not found!" >&2; exit 1; }
+
+# Basic test.
+function test_macro_local_repository() {
+ create_new_workspace
+ repo2=$new_workspace_dir
+
+ mkdir -p carnivore
+ cat > carnivore/BUILD <<'EOF'
+genrule(
+ name = "mongoose",
+ cmd = "echo 'Tra-la!' > $@",
+ outs = ["moogoose.txt"],
+ visibility = ["//visibility:public"],
+)
+EOF
+ cd ${WORKSPACE_DIR}
+ pwd
+ cat > WORKSPACE <<EOF
+load('/test', 'macro')
+
+macro('$repo2')
+EOF
+
+ # Empty package for the .bzl file
+ echo -n >BUILD
+
+ # Our macro
+ cat >test.bzl <<EOF
+def macro(path):
+ print('bleh')
+ native.local_repository(name='endangered', path=path)
+ native.bind(name='mongoose', actual='@endangered//carnivore:mongoose')
+EOF
+ mkdir -p zoo
+ cat > zoo/BUILD <<'EOF'
+genrule(
+ name = "ball-pit1",
+ srcs = ["@endangered//carnivore:mongoose"],
+ outs = ["ball-pit1.txt"],
+ cmd = "cat $< >$@",
+)
+
+genrule(
+ name = "ball-pit2",
+ srcs = ["//external:mongoose"],
+ outs = ["ball-pit2.txt"],
+ cmd = "cat $< >$@",
+)
+EOF
+
+ bazel build //zoo:ball-pit1 >& $TEST_log || fail "Failed to build"
+ expect_log "bleh."
+ cat bazel-genfiles/zoo/ball-pit1.txt >$TEST_log
+ expect_log "Tra-la!"
+
+ bazel build //zoo:ball-pit2 >& $TEST_log || fail "Failed to build"
+ cat bazel-genfiles/zoo/ball-pit2.txt >$TEST_log
+ expect_log "Tra-la!"
+}
+
+function tear_down() {
+ true
+}
+
+run_suite "local repository tests"
diff --git a/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/Resolver.java b/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/Resolver.java
index 5c4fc8e..ecc5659 100644
--- a/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/Resolver.java
+++ b/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/Resolver.java
@@ -74,7 +74,7 @@
*/
public Package parse(Path workspacePath) {
resolver.addHeader(workspacePath.getPathString());
- Package.Builder builder =
+ Package.LegacyBuilder builder =
Package.newExternalPackageBuilder(workspacePath, ruleClassProvider.getRunfilesPrefix());
try (Mutability mutability = Mutability.create("External Package %s", workspacePath)) {
new WorkspaceFactory(builder, ruleClassProvider, environmentExtensions, mutability)