aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/packages
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/packages')
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/ExternalPackage.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java222
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/Preprocessor.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/RuleClass.java14
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java28
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java96
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java73
7 files changed, 211 insertions, 236 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/packages/ExternalPackage.java b/src/main/java/com/google/devtools/build/lib/packages/ExternalPackage.java
index 49852ee747..fda1a8321c 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/ExternalPackage.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/ExternalPackage.java
@@ -24,7 +24,6 @@ import com.google.devtools.build.lib.cmdline.TargetParsingException;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.events.StoredEventHandler;
import com.google.devtools.build.lib.packages.RuleFactory.InvalidRuleException;
-import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.Label;
import com.google.devtools.build.lib.syntax.Label.SyntaxException;
@@ -121,8 +120,7 @@ public class ExternalPackage extends Package {
attributes.put("actual", actual);
}
StoredEventHandler handler = new StoredEventHandler();
- Rule rule = RuleFactory.createRule(
- this, bindRuleClass, attributes, handler, null, location, null);
+ Rule rule = RuleFactory.createRule(this, bindRuleClass, attributes, handler, null, location);
overwriteRule(rule);
rule.setVisibility(ConstantRuleVisibility.PUBLIC);
}
@@ -132,11 +130,11 @@ public class ExternalPackage extends Package {
* WORKSPACE files to overwrite "earlier" ones.
*/
public Builder createAndAddRepositoryRule(RuleClass ruleClass, RuleClass bindRuleClass,
- Map<String, Object> kwargs, FuncallExpression ast, Environment env)
+ Map<String, Object> kwargs, FuncallExpression ast)
throws InvalidRuleException, NameConflictException, SyntaxException {
StoredEventHandler eventHandler = new StoredEventHandler();
- Rule tempRule = RuleFactory.createRule(
- this, ruleClass, kwargs, eventHandler, ast, ast.getLocation(), env);
+ Rule tempRule = RuleFactory.createRule(this, ruleClass, kwargs, eventHandler, ast,
+ ast.getLocation());
addEvents(eventHandler.getEvents());
try {
repositoryMap.put(RepositoryName.create("@" + tempRule.getName()), tempRule);
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 cde726bffb..ffea0bddad 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
@@ -46,9 +46,10 @@ import com.google.devtools.build.lib.syntax.FunctionSignature;
import com.google.devtools.build.lib.syntax.GlobList;
import com.google.devtools.build.lib.syntax.Identifier;
import com.google.devtools.build.lib.syntax.Label;
-import com.google.devtools.build.lib.syntax.Mutability;
+import com.google.devtools.build.lib.syntax.MethodLibrary;
import com.google.devtools.build.lib.syntax.ParserInputSource;
import com.google.devtools.build.lib.syntax.Runtime;
+import com.google.devtools.build.lib.syntax.SkylarkEnvironment;
import com.google.devtools.build.lib.syntax.SkylarkSignature;
import com.google.devtools.build.lib.syntax.SkylarkSignature.Param;
import com.google.devtools.build.lib.syntax.SkylarkSignatureProcessor;
@@ -325,6 +326,7 @@ public final class PackageFactory {
private final RuleFactory ruleFactory;
private final RuleClassProvider ruleClassProvider;
+ private final Environment globalEnv;
private AtomicReference<? extends UnixGlob.FilesystemCalls> syscalls;
private Preprocessor.Factory preprocessorFactory = Preprocessor.Factory.NullFactory.INSTANCE;
@@ -365,6 +367,7 @@ public final class PackageFactory {
this.platformSetRegexps = platformSetRegexps;
this.ruleFactory = new RuleFactory(ruleClassProvider);
this.ruleClassProvider = ruleClassProvider;
+ globalEnv = newGlobalEnvironment();
threadPool = new ThreadPoolExecutor(100, 100, 15L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
new ThreadFactoryBuilder().setNameFormat("Legacy globber %d").build());
@@ -399,6 +402,15 @@ public final class PackageFactory {
/**
+ * Returns the static environment initialized once and shared by all packages
+ * created by this factory. No updates occur to this environment once created.
+ */
+ @VisibleForTesting
+ public Environment getEnvironment() {
+ return globalEnv;
+ }
+
+ /**
* Returns the immutable, unordered set of names of all the known rule
* classes.
*/
@@ -619,8 +631,8 @@ public final class PackageFactory {
"'environment_group argument'", context.pkgBuilder.getBuildFileLabel());
try {
- context.pkgBuilder.addEnvironmentGroup(
- name, environments, defaults, context.eventHandler, loc);
+ context.pkgBuilder.addEnvironmentGroup(name, environments, defaults,
+ context.eventHandler, loc);
return Runtime.NONE;
} catch (Label.SyntaxException e) {
throw new EvalException(loc,
@@ -898,7 +910,7 @@ public final class PackageFactory {
Environment env)
throws RuleFactory.InvalidRuleException, Package.NameConflictException {
RuleClass ruleClass = getBuiltInRuleClass(ruleClassName, ruleFactory);
- RuleFactory.createAndAddRule(context, ruleClass, kwargs, ast, env);
+ RuleFactory.createAndAddRule(context, ruleClass, kwargs, ast, env.getStackTrace());
}
private static RuleClass getBuiltInRuleClass(String ruleClassName, RuleFactory ruleFactory) {
@@ -946,6 +958,16 @@ public final class PackageFactory {
};
}
+ /**
+ * Returns a new environment populated with common entries that can be shared
+ * across packages and that don't require the context.
+ */
+ private static Environment newGlobalEnvironment() {
+ Environment env = new Environment();
+ MethodLibrary.setupMethodEnvironment(env);
+ return env;
+ }
+
/****************************************************************************
* Package creation.
*/
@@ -973,7 +995,7 @@ public final class PackageFactory {
Preprocessor.Result preprocessingResult,
Iterable<Event> preprocessingEvents,
List<Statement> preludeStatements,
- Map<PathFragment, Environment> imports,
+ Map<PathFragment, SkylarkEnvironment> imports,
ImmutableList<Label> skylarkFileDependencies,
CachingPackageLocator locator,
RuleVisibility defaultVisibility,
@@ -1042,12 +1064,12 @@ public final class PackageFactory {
packageId,
buildFile,
preprocessingResult,
- /*preprocessingEvents=*/localReporter.getEvents(),
- /*preludeStatements=*/ImmutableList.<Statement>of(),
- /*imports=*/ImmutableMap.<PathFragment, Environment>of(),
- /*skylarkFileDependencies=*/ImmutableList.<Label>of(),
+ localReporter.getEvents(), /* preprocessingEvents */
+ ImmutableList.<Statement>of(), /* preludeStatements */
+ ImmutableMap.<PathFragment, SkylarkEnvironment>of(), /* imports */
+ ImmutableList.<Label>of(), /* skylarkFileDependencies */
locator,
- /*defaultVisibility=*/ConstantRuleVisibility.PUBLIC,
+ ConstantRuleVisibility.PUBLIC, /* defaultVisibility */
globber)
.build();
Event.replayEventsOn(eventHandler, result.getEvents());
@@ -1088,13 +1110,8 @@ public final class PackageFactory {
return Preprocessor.Result.noPreprocessing(inputSource);
}
try {
- return preprocessor.preprocess(
- inputSource,
- packageId.toString(),
- globber,
- eventHandler,
- Environment.BUILD,
- ruleFactory.getRuleClassNames());
+ return preprocessor.preprocess(inputSource, packageId.toString(), globber, eventHandler,
+ globalEnv, ruleFactory.getRuleClassNames());
} catch (IOException e) {
eventHandler.handle(Event.error(Location.fromFile(buildFile),
"preprocessing failed: " + e.getMessage()));
@@ -1195,20 +1212,19 @@ public final class PackageFactory {
// or if not possible, at least make them straight copies from the native module variant.
// or better, use a common Environment.Frame for these common bindings
// (that shares a backing ImmutableMap for the bindings?)
- pkgEnv
- .setup("native", nativeModule)
- .setup("distribs", newDistribsFunction.apply(context))
- .setup("glob", newGlobFunction.apply(context, /*async=*/false))
- .setup("mocksubinclude", newMockSubincludeFunction.apply(context))
- .setup("licenses", newLicensesFunction.apply(context))
- .setup("exports_files", newExportsFilesFunction.apply())
- .setup("package_group", newPackageGroupFunction.apply())
- .setup("package", newPackageFunction(packageArguments))
- .setup("environment_group", newEnvironmentGroupFunction.apply(context));
+ pkgEnv.update("native", nativeModule);
+ pkgEnv.update("distribs", newDistribsFunction.apply(context));
+ pkgEnv.update("glob", newGlobFunction.apply(context, /*async=*/false));
+ pkgEnv.update("mocksubinclude", newMockSubincludeFunction.apply(context));
+ pkgEnv.update("licenses", newLicensesFunction.apply(context));
+ pkgEnv.update("exports_files", newExportsFilesFunction.apply());
+ pkgEnv.update("package_group", newPackageGroupFunction.apply());
+ pkgEnv.update("package", newPackageFunction(packageArguments));
+ pkgEnv.update("environment_group", newEnvironmentGroupFunction.apply(context));
for (String ruleClass : ruleFactory.getRuleClassNames()) {
BaseFunction ruleFunction = newRuleFunction(ruleFactory, ruleClass);
- pkgEnv.setup(ruleClass, ruleFunction);
+ pkgEnv.update(ruleClass, ruleFunction);
}
for (EnvironmentExtension extension : environmentExtensions) {
@@ -1239,65 +1255,62 @@ public final class PackageFactory {
PackageIdentifier packageId, BuildFileAST buildFileAST, Path buildFilePath, Globber globber,
Iterable<Event> pastEvents, RuleVisibility defaultVisibility, boolean containsError,
boolean containsTransientError, MakeEnvironment.Builder pkgMakeEnv,
- Map<PathFragment, Environment> imports,
+ Map<PathFragment, SkylarkEnvironment> imports,
ImmutableList<Label> skylarkFileDependencies) throws InterruptedException {
+ // Important: Environment should be unreachable by the end of this method!
+ StoredEventHandler eventHandler = new StoredEventHandler();
+ Environment pkgEnv = new Environment(globalEnv, eventHandler);
+ pkgEnv.setLoadingPhase();
+
Package.LegacyBuilder pkgBuilder = new Package.LegacyBuilder(
packageId, ruleClassProvider.getRunfilesPrefix());
- StoredEventHandler eventHandler = new StoredEventHandler();
- try (Mutability mutability = Mutability.create("package %s", packageId)) {
- Environment pkgEnv = Environment.builder(mutability)
- .setGlobals(Environment.BUILD)
- .setEventHandler(eventHandler)
- .setImportedExtensions(imports)
- .setLoadingPhase()
- .build();
-
- pkgBuilder.setGlobber(globber)
- .setFilename(buildFilePath)
- .setMakeEnv(pkgMakeEnv)
- .setDefaultVisibility(defaultVisibility)
- // "defaultVisibility" comes from the command line. Let's give the BUILD file a chance to
- // set default_visibility once, be reseting the PackageBuilder.defaultVisibilitySet flag.
- .setDefaultVisibilitySet(false)
- .setSkylarkFileDependencies(skylarkFileDependencies)
- .setWorkspaceName(externalPkg.getWorkspaceName());
-
- Event.replayEventsOn(eventHandler, pastEvents);
-
- // Stuff that closes over the package context:
- PackageContext context = new PackageContext(pkgBuilder, globber, eventHandler);
- buildPkgEnv(pkgEnv, context, ruleFactory);
- pkgEnv.setupDynamic(PKG_CONTEXT, context);
- pkgEnv.setupDynamic(Runtime.PKG_NAME, packageId.toString());
-
- if (containsError) {
- pkgBuilder.setContainsErrors();
- }
+ pkgBuilder.setGlobber(globber)
+ .setFilename(buildFilePath)
+ .setMakeEnv(pkgMakeEnv)
+ .setDefaultVisibility(defaultVisibility)
+ // "defaultVisibility" comes from the command line. Let's give the BUILD file a chance to
+ // set default_visibility once, be reseting the PackageBuilder.defaultVisibilitySet flag.
+ .setDefaultVisibilitySet(false)
+ .setSkylarkFileDependencies(skylarkFileDependencies)
+ .setWorkspaceName(externalPkg.getWorkspaceName());
- if (containsTransientError) {
- pkgBuilder.setContainsTemporaryErrors();
- }
+ Event.replayEventsOn(eventHandler, pastEvents);
- if (!validatePackageIdentifier(packageId, buildFileAST.getLocation(), eventHandler)) {
- pkgBuilder.setContainsErrors();
- }
+ // Stuff that closes over the package context:`
+ PackageContext context = new PackageContext(pkgBuilder, globber, eventHandler);
+ buildPkgEnv(pkgEnv, context, ruleFactory);
- if (!validateAssignmentStatements(pkgEnv, buildFileAST, eventHandler)) {
- pkgBuilder.setContainsErrors();
- }
+ if (containsError) {
+ pkgBuilder.setContainsErrors();
+ }
- if (buildFileAST.containsErrors()) {
- pkgBuilder.setContainsErrors();
- }
+ if (containsTransientError) {
+ pkgBuilder.setContainsTemporaryErrors();
+ }
- // TODO(bazel-team): (2009) the invariant "if errors are reported, mark the package
- // as containing errors" is strewn all over this class. Refactor to use an
- // event sensor--and see if we can simplify the calling code in
- // createPackage().
- if (!buildFileAST.exec(pkgEnv, eventHandler)) {
- pkgBuilder.setContainsErrors();
- }
+ if (!validatePackageIdentifier(packageId, buildFileAST.getLocation(), eventHandler)) {
+ pkgBuilder.setContainsErrors();
+ }
+
+ pkgEnv.setImportedExtensions(imports);
+ pkgEnv.updateAndPropagate(PKG_CONTEXT, context);
+ pkgEnv.updateAndPropagate(Runtime.PKG_NAME, packageId.toString());
+
+ if (!validateAssignmentStatements(pkgEnv, buildFileAST, eventHandler)) {
+ pkgBuilder.setContainsErrors();
+ }
+
+ if (buildFileAST.containsErrors()) {
+ pkgBuilder.setContainsErrors();
+ }
+
+ // TODO(bazel-team): (2009) the invariant "if errors are reported, mark the package
+ // as containing errors" is strewn all over this class. Refactor to use an
+ // event sensor--and see if we can simplify the calling code in
+ // createPackage().
+ if (!buildFileAST.exec(pkgEnv, eventHandler)) {
+ pkgBuilder.setContainsErrors();
}
pkgBuilder.addEvents(eventHandler.getEvents());
@@ -1316,36 +1329,29 @@ public final class PackageFactory {
// of all globs.
return;
}
- try (Mutability mutability = Mutability.create("prefetchGlobs for %s", packageId)) {
- Environment pkgEnv = Environment.builder(mutability)
- .setGlobals(Environment.BUILD)
- .setEventHandler(NullEventHandler.INSTANCE)
- .setLoadingPhase()
- .build();
-
- Package.LegacyBuilder pkgBuilder = new Package.LegacyBuilder(packageId,
- ruleClassProvider.getRunfilesPrefix());
-
- pkgBuilder.setFilename(buildFilePath)
- .setMakeEnv(pkgMakeEnv)
- .setDefaultVisibility(defaultVisibility)
- // "defaultVisibility" comes from the command line. Let's give the BUILD file a chance to
- // set default_visibility once, be reseting the PackageBuilder.defaultVisibilitySet flag.
- .setDefaultVisibilitySet(false);
-
- // Stuff that closes over the package context:
- PackageContext context = new PackageContext(pkgBuilder, globber, NullEventHandler.INSTANCE);
- buildPkgEnv(pkgEnv, context, ruleFactory);
- try {
- pkgEnv.update("glob", newGlobFunction.apply(context, /*async=*/true));
- // The Fileset function is heavyweight in that it can run glob(). Avoid this during the
- // preloading phase.
- pkgEnv.update("FilesetEntry", Runtime.NONE);
- } catch (EvalException e) {
- throw new AssertionError(e);
- }
- buildFileAST.exec(pkgEnv, NullEventHandler.INSTANCE);
- }
+ // Important: Environment should be unreachable by the end of this method!
+ Environment pkgEnv = new Environment();
+ pkgEnv.setLoadingPhase();
+
+ Package.LegacyBuilder pkgBuilder = new Package.LegacyBuilder(packageId,
+ ruleClassProvider.getRunfilesPrefix());
+
+ pkgBuilder.setFilename(buildFilePath)
+ .setMakeEnv(pkgMakeEnv)
+ .setDefaultVisibility(defaultVisibility)
+ // "defaultVisibility" comes from the command line. Let's give the BUILD file a chance to
+ // set default_visibility once, be reseting the PackageBuilder.defaultVisibilitySet flag.
+ .setDefaultVisibilitySet(false);
+
+ // Stuff that closes over the package context:
+ PackageContext context = new PackageContext(pkgBuilder, globber, NullEventHandler.INSTANCE);
+ buildPkgEnv(pkgEnv, context, ruleFactory);
+ pkgEnv.update("glob", newGlobFunction.apply(context, /*async=*/true));
+ // The Fileset function is heavyweight in that it can run glob(). Avoid this during the
+ // preloading phase.
+ pkgEnv.remove("FilesetEntry");
+
+ buildFileAST.exec(pkgEnv, NullEventHandler.INSTANCE);
}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Preprocessor.java b/src/main/java/com/google/devtools/build/lib/packages/Preprocessor.java
index c44776ad8b..a479ca9f55 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Preprocessor.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Preprocessor.java
@@ -141,7 +141,7 @@ public interface Preprocessor {
* @param packageName the BUILD file's package.
* @param globber a globber for evaluating globs.
* @param eventHandler a eventHandler on which to report warnings/errors.
- * @param globals the global bindings for the Python environment.
+ * @param globalEnv the GLOBALS Python environment.
* @param ruleNames the set of names of all rules in the build language.
* @throws IOException if there was an I/O problem during preprocessing.
* @return a pair of the ParserInputSource and a map of subincludes seen during the evaluation
@@ -151,7 +151,7 @@ public interface Preprocessor {
String packageName,
Globber globber,
EventHandler eventHandler,
- Environment.Frame globals,
+ Environment globalEnv,
Set<String> ruleNames)
throws IOException, InterruptedException;
}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
index 7906a2bcda..59fcbb595b 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -34,13 +34,13 @@ import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
import com.google.devtools.build.lib.syntax.Argument;
import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.FragmentClassNameResolver;
import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.GlobList;
import com.google.devtools.build.lib.syntax.Label;
import com.google.devtools.build.lib.syntax.Label.SyntaxException;
import com.google.devtools.build.lib.syntax.Runtime;
+import com.google.devtools.build.lib.syntax.SkylarkEnvironment;
import com.google.devtools.build.lib.util.StringUtil;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -498,7 +498,7 @@ public final class RuleClass {
private BaseFunction configuredTargetFunction = null;
private Function<? super Rule, Map<String, Label>> externalBindingsFunction =
NO_EXTERNAL_BINDINGS;
- private Environment ruleDefinitionEnvironment = null;
+ private SkylarkEnvironment ruleDefinitionEnvironment = null;
private Set<Class<?>> configurationFragments = new LinkedHashSet<>();
private MissingFragmentPolicy missingFragmentPolicy = MissingFragmentPolicy.FAIL_ANALYSIS;
private Set<String> requiredFragmentNames = new LinkedHashSet<>();
@@ -792,7 +792,7 @@ public final class RuleClass {
/**
* Sets the rule definition environment. Meant for Skylark usage.
*/
- public Builder setRuleDefinitionEnvironment(Environment env) {
+ public Builder setRuleDefinitionEnvironment(SkylarkEnvironment env) {
this.ruleDefinitionEnvironment = env;
return this;
}
@@ -964,7 +964,7 @@ public final class RuleClass {
* The Skylark rule definition environment of this RuleClass.
* Null for non Skylark executable RuleClasses.
*/
- @Nullable private final Environment ruleDefinitionEnvironment;
+ @Nullable private final SkylarkEnvironment ruleDefinitionEnvironment;
/**
* The set of required configuration fragments; this should list all fragments that can be
@@ -1015,7 +1015,7 @@ public final class RuleClass {
ImmutableSet<Class<?>> advertisedProviders,
@Nullable BaseFunction configuredTargetFunction,
Function<? super Rule, Map<String, Label>> externalBindingsFunction,
- @Nullable Environment ruleDefinitionEnvironment,
+ @Nullable SkylarkEnvironment ruleDefinitionEnvironment,
Set<Class<?>> allowedConfigurationFragments,
MissingFragmentPolicy missingFragmentPolicy,
boolean supportsConstraintChecking,
@@ -1076,7 +1076,7 @@ public final class RuleClass {
ImmutableSet<Class<?>> advertisedProviders,
@Nullable BaseFunction configuredTargetFunction,
Function<? super Rule, Map<String, Label>> externalBindingsFunction,
- @Nullable Environment ruleDefinitionEnvironment,
+ @Nullable SkylarkEnvironment ruleDefinitionEnvironment,
Set<Class<?>> allowedConfigurationFragments,
Set<String> allowedConfigurationFragmentNames,
@Nullable FragmentClassNameResolver fragmentNameResolver,
@@ -1725,7 +1725,7 @@ public final class RuleClass {
/**
* Returns this RuleClass's rule definition environment.
*/
- @Nullable public Environment getRuleDefinitionEnvironment() {
+ @Nullable public SkylarkEnvironment getRuleDefinitionEnvironment() {
return ruleDefinitionEnvironment;
}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java
index b3ca83fe36..958d88ac7c 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java
@@ -15,14 +15,12 @@
package com.google.devtools.build.lib.packages;
import com.google.devtools.build.lib.events.EventHandler;
-import com.google.devtools.build.lib.syntax.Environment;
-import com.google.devtools.build.lib.syntax.Mutability;
+import com.google.devtools.build.lib.syntax.SkylarkEnvironment;
+import com.google.devtools.build.lib.syntax.ValidationEnvironment;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.Map;
-import javax.annotation.Nullable;
-
/**
* The collection of the supported build rules. Provides an Environment for Skylark rule creation.
*/
@@ -49,19 +47,17 @@ public interface RuleClassProvider {
Map<String, Class<? extends AspectFactory<?, ?, ?>>> getAspectFactoryMap();
/**
- * Returns a new Skylark Environment instance for rule creation.
- * Implementations need to be thread safe.
- * Be sure to close() the mutability before you return the results of said evaluation.
- * @param mutability the Mutability for the current evaluation context
- * @param eventHandler the EventHandler for warnings, errors, etc.
- * @param astFileContentHashCode the hash code identifying this environment.
- * @return an Environment, in which to evaluate load time skylark forms.
+ * Returns a new Skylark Environment instance for rule creation. Implementations need to be
+ * thread safe.
+ */
+ SkylarkEnvironment createSkylarkRuleClassEnvironment(
+ EventHandler eventHandler, String astFileContentHashCode);
+
+ /**
+ * Returns a validation environment for static analysis of skylark files.
+ * The environment has to contain all built-in functions and objects.
*/
- Environment createSkylarkRuleClassEnvironment(
- Mutability mutability,
- EventHandler eventHandler,
- @Nullable String astFileContentHashCode,
- @Nullable Map<PathFragment, Environment> importMap);
+ ValidationEnvironment getSkylarkValidationEnvironment();
/**
* Returns the default content of the WORKSPACE file.
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 2eb94b19d9..33f9d49793 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
@@ -15,24 +15,20 @@
package com.google.devtools.build.lib.packages;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.packages.Package.NameConflictException;
import com.google.devtools.build.lib.packages.PackageFactory.PackageContext;
-import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.Label;
import com.google.devtools.build.lib.syntax.Label.SyntaxException;
-import com.google.devtools.build.lib.syntax.UserDefinedFunction;
-import com.google.devtools.build.lib.util.Pair;
+import com.google.devtools.build.lib.syntax.StackTraceElement;
import java.util.Map;
import java.util.Set;
-import javax.annotation.Nullable;
-
/**
* Given a rule class and a set of attributes, returns a Rule instance. Also
* performs a number of checks and associates the rule and the owning package
@@ -82,7 +78,7 @@ public class RuleFactory {
EventHandler eventHandler,
FuncallExpression ast,
Location location,
- @Nullable Environment env)
+ ImmutableList<StackTraceElement> stackTrace)
throws InvalidRuleException {
Preconditions.checkNotNull(ruleClass);
String ruleClassName = ruleClass.getName();
@@ -112,19 +108,31 @@ public class RuleFactory {
}
try {
- return ruleClass.createRuleWithLabel(
- pkgBuilder,
- label,
- addGeneratorAttributesForMacros(attributeValues, env),
- eventHandler,
- ast,
+ Rule rule = ruleClass.createRuleWithLabel(pkgBuilder, label,
+ addGeneratorAttributesForMacros(attributeValues, stackTrace), eventHandler, ast,
location);
+ return rule;
} catch (SyntaxException e) {
throw new RuleFactory.InvalidRuleException(ruleClass + " " + e.getMessage());
}
}
/**
+ * Creates and returns a rule instance (without a stack trace).
+ */
+ static Rule createRule(
+ Package.Builder pkgBuilder,
+ RuleClass ruleClass,
+ Map<String, Object> attributeValues,
+ EventHandler eventHandler,
+ FuncallExpression ast,
+ Location location)
+ throws InvalidRuleException {
+ return createRule(pkgBuilder, ruleClass, attributeValues, eventHandler, ast, location,
+ ImmutableList.<StackTraceElement>of());
+ }
+
+ /**
* Creates a rule instance, adds it to the package and returns it.
*
* @param pkgBuilder the under-construction package to which the rule belongs
@@ -137,40 +145,34 @@ public class RuleFactory {
* rule creation
* @param ast the abstract syntax tree of the rule expression (optional)
* @param location the location at which this rule was declared
+ * @param stackTrace the stack trace containing all functions that led to the creation of
+ * this rule (optional)
* @throws InvalidRuleException if the rule could not be constructed for any
* reason (e.g. no <code>name</code> attribute is defined)
- * @throws InvalidRuleException, NameConflictException
+ * @throws NameConflictException
*/
- static Rule createAndAddRule(
- Package.Builder pkgBuilder,
- RuleClass ruleClass,
- Map<String, Object> attributeValues,
- EventHandler eventHandler,
- FuncallExpression ast,
- Location location,
- Environment env)
+ static Rule createAndAddRule(Package.Builder pkgBuilder,
+ RuleClass ruleClass,
+ Map<String, Object> attributeValues,
+ EventHandler eventHandler,
+ FuncallExpression ast,
+ Location location,
+ ImmutableList<StackTraceElement> stackTrace)
throws InvalidRuleException, NameConflictException {
Rule rule = createRule(
- pkgBuilder, ruleClass, attributeValues, eventHandler, ast, location, env);
+ pkgBuilder, ruleClass, attributeValues, eventHandler, ast, location, stackTrace);
pkgBuilder.addRule(rule);
return rule;
}
- public static Rule createAndAddRule(
- PackageContext context,
+ public static Rule createAndAddRule(PackageContext context,
RuleClass ruleClass,
Map<String, Object> attributeValues,
FuncallExpression ast,
- Environment env)
+ ImmutableList<StackTraceElement> stackTrace)
throws InvalidRuleException, NameConflictException {
- return createAndAddRule(
- context.pkgBuilder,
- ruleClass,
- attributeValues,
- context.eventHandler,
- ast,
- ast.getLocation(),
- env);
+ return createAndAddRule(context.pkgBuilder, ruleClass, attributeValues, context.eventHandler,
+ ast, ast.getLocation(), stackTrace);
}
/**
@@ -190,28 +192,22 @@ public class RuleFactory {
* <p>Otherwise, it returns the given attributes without any changes.
*/
private static Map<String, Object> addGeneratorAttributesForMacros(
- Map<String, Object> args, @Nullable Environment env) {
- // Returns the original arguments if a) there is only the rule itself on the stack
- // trace (=> no macro) or b) the attributes have already been set by Python pre-processing.
- if (env == null) {
- return args;
- }
- boolean hasName = args.containsKey("generator_name");
- boolean hasFunc = args.containsKey("generator_function");
- // TODO(bazel-team): resolve cases in our code where hasName && !hasFunc, or hasFunc && !hasName
- if (hasName || hasFunc) {
- return args;
- }
- Pair<BaseFunction, Location> topCall = env.getTopCall();
- if (topCall == null || !(topCall.first instanceof UserDefinedFunction)) {
+ Map<String, Object> args, ImmutableList<StackTraceElement> stackTrace) {
+ if (stackTrace.size() <= 2 || args.containsKey("generator_name")
+ || args.containsKey("generator_function")) {
+ // Returns the original arguments if a) there is only the rule itself on the stack
+ // trace (=> no macro) or b) the attributes have already been set by Python pre-processing.
+ // The stack trace will always have at least two entries: one for the call to the rule and one
+ // for its implementation. Consequently, we check for size <= 2.
return args;
}
+ StackTraceElement generator = stackTrace.get(0);
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
builder.putAll(args);
builder.put("generator_name", args.get("name"));
- builder.put("generator_function", topCall.first.getName());
- builder.put("generator_location", topCall.second.toString());
+ builder.put("generator_function", generator.getName());
+ builder.put("generator_location", Location.printPathAndLine(generator.getLocation()));
try {
return builder.build();
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 abbbdf88d3..054865fafd 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
@@ -29,7 +29,7 @@ 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.Label;
-import com.google.devtools.build.lib.syntax.Mutability;
+import com.google.devtools.build.lib.syntax.MethodLibrary;
import com.google.devtools.build.lib.syntax.ParserInputSource;
import java.io.File;
@@ -44,30 +44,14 @@ public class WorkspaceFactory {
private final Builder builder;
private final Environment environment;
- /**
- * @param builder a builder for the Workspace
- * @param ruleClassProvider a provider for known rule classes
- * @param mutability the Mutability for the current evaluation context
- */
- public WorkspaceFactory(
- Builder builder, RuleClassProvider ruleClassProvider, Mutability mutability) {
- this(builder, ruleClassProvider, mutability, null);
+ public WorkspaceFactory(Builder builder, RuleClassProvider ruleClassProvider) {
+ this(builder, ruleClassProvider, null);
}
- // TODO(bazel-team): document installDir
- /**
- * @param builder a builder for the Workspace
- * @param ruleClassProvider a provider for known rule classes
- * @param mutability the Mutability for the current evaluation context
- * @param installDir an optional directory into which to install software
- */
public WorkspaceFactory(
- Builder builder,
- RuleClassProvider ruleClassProvider,
- Mutability mutability,
- @Nullable String installDir) {
+ Builder builder, RuleClassProvider ruleClassProvider, @Nullable String installDir) {
this.builder = builder;
- this.environment = createWorkspaceEnv(builder, ruleClassProvider, mutability, installDir);
+ this.environment = createWorkspaceEnv(builder, ruleClassProvider, installDir);
}
public void parse(ParserInputSource source)
@@ -138,13 +122,13 @@ public class WorkspaceFactory {
private static BuiltinFunction newRuleFunction(
final RuleFactory ruleFactory, final Builder builder, final String ruleClassName) {
return new BuiltinFunction(ruleClassName,
- FunctionSignature.KWARGS, BuiltinFunction.USE_AST_ENV) {
- public Object invoke(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
+ FunctionSignature.KWARGS, BuiltinFunction.USE_AST) {
+ public Object invoke(Map<String, Object> kwargs, FuncallExpression ast)
throws EvalException {
try {
RuleClass ruleClass = ruleFactory.getRuleClass(ruleClassName);
RuleClass bindRuleClass = ruleFactory.getRuleClass("bind");
- builder.createAndAddRepositoryRule(ruleClass, bindRuleClass, kwargs, ast, env);
+ builder.createAndAddRepositoryRule(ruleClass, bindRuleClass, kwargs, ast);
} catch (RuleFactory.InvalidRuleException | Package.NameConflictException |
Label.SyntaxException e) {
throw new EvalException(ast.getLocation(), e.getMessage());
@@ -155,30 +139,25 @@ public class WorkspaceFactory {
}
private Environment createWorkspaceEnv(
- Builder builder,
- RuleClassProvider ruleClassProvider,
- Mutability mutability,
- String installDir) {
- Environment workspaceEnv = Environment.builder(mutability)
- .setGlobals(Environment.BUILD)
- .setLoadingPhase()
- .build();
+ Builder builder, RuleClassProvider ruleClassProvider, String installDir) {
+ Environment workspaceEnv = new Environment();
+ MethodLibrary.setupMethodEnvironment(workspaceEnv);
+ workspaceEnv.setLoadingPhase();
+
RuleFactory ruleFactory = new RuleFactory(ruleClassProvider);
- try {
- for (String ruleClass : ruleFactory.getRuleClassNames()) {
- BaseFunction ruleFunction = newRuleFunction(ruleFactory, builder, ruleClass);
- workspaceEnv.update(ruleClass, ruleFunction);
- }
- if (installDir != null) {
- workspaceEnv.update("__embedded_dir__", installDir);
- }
- 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));
- return workspaceEnv;
- } catch (EvalException e) {
- throw new AssertionError(e);
+ for (String ruleClass : ruleFactory.getRuleClassNames()) {
+ BaseFunction ruleFunction = newRuleFunction(ruleFactory, builder, ruleClass);
+ workspaceEnv.update(ruleClass, ruleFunction);
}
+
+ if (installDir != null) {
+ workspaceEnv.update("__embedded_dir__", installDir);
+ }
+ 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));
+ return workspaceEnv;
}
}