use of com.google.devtools.build.lib.syntax.SkylarkImport in project bazel by bazelbuild.
the class ASTFileLookupFunctionTest method testLoadFromBuildFileInRemoteRepo.
@Test
public void testLoadFromBuildFileInRemoteRepo() throws Exception {
scratch.deleteFile("tools/build_rules/prelude_blaze");
scratch.overwriteFile("WORKSPACE", "local_repository(", " name = 'a_remote_repo',", " path = '/a_remote_repo'", ")");
scratch.file("/a_remote_repo/remote_pkg/BUILD", "load(':ext.bzl', 'CONST')");
scratch.file("/a_remote_repo/remote_pkg/ext.bzl", "CONST = 17");
// Repository shuffling messes with toolchains.
invalidatePackages(/*alsoConfigs=*/
false);
SkyKey skyKey = ASTFileLookupValue.key(Label.parseAbsoluteUnchecked("@a_remote_repo//remote_pkg:BUILD"));
EvaluationResult<ASTFileLookupValue> result = SkyframeExecutorTestUtils.evaluate(getSkyframeExecutor(), skyKey, /*keepGoing=*/
false, reporter);
ImmutableList<SkylarkImport> imports = result.get(skyKey).getAST().getImports();
assertThat(imports).hasSize(1);
assertThat(imports.get(0).getImportString()).isEqualTo(":ext.bzl");
}
use of com.google.devtools.build.lib.syntax.SkylarkImport in project bazel by bazelbuild.
the class ToplevelSkylarkAspectFunction method compute.
@Nullable
@Override
public SkyValue compute(SkyKey skyKey, Environment env) throws LoadSkylarkAspectFunctionException, InterruptedException {
SkylarkAspectLoadingKey aspectLoadingKey = (SkylarkAspectLoadingKey) skyKey.argument();
String skylarkValueName = aspectLoadingKey.getSkylarkValueName();
SkylarkImport extensionFile = aspectLoadingKey.getSkylarkImport();
// Find label corresponding to skylark file, if one exists.
ImmutableMap<String, Label> labelLookupMap;
try {
labelLookupMap = SkylarkImportLookupFunction.findLabelsForLoadStatements(ImmutableList.of(extensionFile), Label.parseAbsoluteUnchecked("//:empty"), env);
} catch (SkylarkImportFailedException e) {
env.getListener().handle(Event.error(e.getMessage()));
throw new LoadSkylarkAspectFunctionException(new AspectCreationException(e.getMessage()));
}
if (labelLookupMap == null) {
return null;
}
SkylarkAspect skylarkAspect;
Label extensionFileLabel = Iterables.getOnlyElement(labelLookupMap.values());
try {
skylarkAspect = AspectFunction.loadSkylarkAspect(env, extensionFileLabel, skylarkValueName);
if (skylarkAspect == null) {
return null;
}
if (!skylarkAspect.getParamAttributes().isEmpty()) {
throw new AspectCreationException("Cannot instantiate parameterized aspect " + skylarkAspect.getName() + " at the top level.", extensionFileLabel);
}
} catch (AspectCreationException e) {
throw new LoadSkylarkAspectFunctionException(e);
}
SkyKey aspectKey = ActionLookupValue.key(AspectValue.createAspectKey(aspectLoadingKey.getTargetLabel(), aspectLoadingKey.getTargetConfiguration(), new AspectDescriptor(skylarkAspect.getAspectClass(), AspectParameters.EMPTY), aspectLoadingKey.getAspectConfiguration()));
return env.getValue(aspectKey);
}
use of com.google.devtools.build.lib.syntax.SkylarkImport in project bazel by bazelbuild.
the class SkylarkImportLookupFunction method findLabelsForLoadStatements.
/**
* Computes the set of {@link Label}s corresponding to a set of Skylark {@link LoadStatement}s.
*
* @param imports a collection of Skylark {@link LoadStatement}s
* @param containingFileLabel the {@link Label} of the file containing the load statements
* @return an {@link ImmutableMap} which maps a {@link String} used in the load statement to its
* corresponding {@Label}. Returns {@code null} if any Skyframe dependencies are unavailable.
* @throws SkylarkImportFailedException if no package can be found that contains the loaded file
*/
@Nullable
static ImmutableMap<String, Label> findLabelsForLoadStatements(ImmutableCollection<SkylarkImport> imports, Label containingFileLabel, Environment env) throws SkylarkImportFailedException, InterruptedException {
Preconditions.checkArgument(!containingFileLabel.getPackageIdentifier().getRepository().isDefault());
Map<String, Label> outputMap = Maps.newHashMapWithExpectedSize(imports.size());
// Filter relative vs. absolute paths.
ImmutableSet.Builder<PathFragment> absoluteImportsToLookup = new ImmutableSet.Builder<>();
// We maintain a multimap from path fragments to their correspond import strings, to cover the
// (unlikely) case where two distinct import strings generate the same path fragment.
ImmutableMultimap.Builder<PathFragment, String> pathToImports = new ImmutableMultimap.Builder<>();
for (SkylarkImport imp : imports) {
if (imp.hasAbsolutePath()) {
absoluteImportsToLookup.add(imp.getAbsolutePath());
pathToImports.put(imp.getAbsolutePath(), imp.getImportString());
} else {
outputMap.put(imp.getImportString(), imp.getLabel(containingFileLabel));
}
}
// Look up labels for absolute paths.
ImmutableMap<PathFragment, Label> absoluteLabels = labelsForAbsoluteImports(absoluteImportsToLookup.build(), env);
if (absoluteLabels == null) {
return null;
}
for (Entry<PathFragment, Label> entry : absoluteLabels.entrySet()) {
PathFragment currPath = entry.getKey();
Label currLabel = entry.getValue();
for (String importString : pathToImports.build().get(currPath)) {
outputMap.put(importString, currLabel);
}
}
ImmutableMap<String, Label> immutableOutputMap = ImmutableMap.copyOf(outputMap);
return immutableOutputMap;
}
use of com.google.devtools.build.lib.syntax.SkylarkImport in project bazel by bazelbuild.
the class SkylarkImportLookupFunction method computeInternal.
private SkyValue computeInternal(Label fileLabel, boolean inWorkspace, Environment env, @Nullable LinkedHashMap<Label, SkylarkImportLookupValue> alreadyVisited) throws InconsistentFilesystemException, SkylarkImportFailedException, InterruptedException {
PathFragment filePath = fileLabel.toPathFragment();
// Load the AST corresponding to this file.
ASTFileLookupValue astLookupValue;
try {
SkyKey astLookupKey = ASTFileLookupValue.key(fileLabel);
astLookupValue = (ASTFileLookupValue) env.getValueOrThrow(astLookupKey, ErrorReadingSkylarkExtensionException.class, InconsistentFilesystemException.class);
} catch (ErrorReadingSkylarkExtensionException e) {
throw SkylarkImportFailedException.errorReadingFile(filePath, e.getMessage());
}
if (astLookupValue == null) {
return null;
}
if (!astLookupValue.lookupSuccessful()) {
// Skylark import files have to exist.
throw SkylarkImportFailedException.noFile(astLookupValue.getErrorMsg());
}
BuildFileAST ast = astLookupValue.getAST();
if (ast.containsErrors()) {
throw SkylarkImportFailedException.skylarkErrors(filePath);
}
// Process the load statements in the file.
ImmutableList<SkylarkImport> imports = ast.getImports();
Map<String, Extension> extensionsForImports = Maps.newHashMapWithExpectedSize(imports.size());
ImmutableList.Builder<SkylarkFileDependency> fileDependencies = ImmutableList.builder();
ImmutableMap<String, Label> labelsForImports;
// Find the labels corresponding to the load statements.
labelsForImports = findLabelsForLoadStatements(imports, fileLabel, env);
if (labelsForImports == null) {
return null;
}
// Look up and load the imports.
ImmutableCollection<Label> importLabels = labelsForImports.values();
List<SkyKey> importLookupKeys = Lists.newArrayListWithExpectedSize(importLabels.size());
for (Label importLabel : importLabels) {
importLookupKeys.add(SkylarkImportLookupValue.key(importLabel, inWorkspace));
}
Map<SkyKey, SkyValue> skylarkImportMap;
boolean valuesMissing = false;
if (alreadyVisited == null) {
// Not inlining.
skylarkImportMap = env.getValues(importLookupKeys);
valuesMissing = env.valuesMissing();
} else {
// Inlining calls to SkylarkImportLookupFunction.
if (alreadyVisited.containsKey(fileLabel)) {
ImmutableList<Label> cycle = CycleUtils.splitIntoPathAndChain(Predicates.equalTo(fileLabel), alreadyVisited.keySet()).second;
throw new SkylarkImportFailedException("Skylark import cycle: " + cycle);
}
alreadyVisited.put(fileLabel, null);
skylarkImportMap = Maps.newHashMapWithExpectedSize(imports.size());
for (SkyKey importLookupKey : importLookupKeys) {
SkyValue skyValue = this.computeWithInlineCallsInternal(importLookupKey, env, alreadyVisited);
if (skyValue == null) {
Preconditions.checkState(env.valuesMissing(), "no skylark import value for %s", importLookupKey);
// We continue making inline calls even if some requested values are missing, to maximize
// the number of dependent (non-inlined) SkyFunctions that are requested, thus avoiding a
// quadratic number of restarts.
valuesMissing = true;
} else {
skylarkImportMap.put(importLookupKey, skyValue);
}
}
// All imports traversed, this key can no longer be part of a cycle.
Preconditions.checkState(alreadyVisited.remove(fileLabel) == null, fileLabel);
}
if (valuesMissing) {
// This means some imports are unavailable.
return null;
}
// Process the loaded imports.
for (Entry<String, Label> importEntry : labelsForImports.entrySet()) {
String importString = importEntry.getKey();
Label importLabel = importEntry.getValue();
SkyKey keyForLabel = SkylarkImportLookupValue.key(importLabel, inWorkspace);
SkylarkImportLookupValue importLookupValue = (SkylarkImportLookupValue) skylarkImportMap.get(keyForLabel);
extensionsForImports.put(importString, importLookupValue.getEnvironmentExtension());
fileDependencies.add(importLookupValue.getDependency());
}
// 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, extensionsForImports, env, inWorkspace);
SkylarkImportLookupValue result = new SkylarkImportLookupValue(extension, new SkylarkFileDependency(fileLabel, fileDependencies.build()));
if (alreadyVisited != null) {
alreadyVisited.put(fileLabel, result);
}
return result;
}
use of com.google.devtools.build.lib.syntax.SkylarkImport in project bazel by bazelbuild.
the class PackageFunction method fetchImportsFromBuildFile.
/**
* Fetch the skylark loads for this BUILD file. If any of them haven't been computed yet,
* returns null.
*/
@Nullable
static SkylarkImportResult fetchImportsFromBuildFile(Path buildFilePath, PackageIdentifier packageId, BuildFileAST buildFileAST, Environment env, SkylarkImportLookupFunction skylarkImportLookupFunctionForInlining) throws NoSuchPackageException, InterruptedException {
Preconditions.checkArgument(!packageId.getRepository().isDefault());
ImmutableList<SkylarkImport> imports = buildFileAST.getImports();
Map<String, Extension> importMap = Maps.newHashMapWithExpectedSize(imports.size());
ImmutableList.Builder<SkylarkFileDependency> fileDependencies = ImmutableList.builder();
ImmutableMap<String, Label> importPathMap;
// Find the labels corresponding to the load statements.
Label labelForCurrBuildFile;
try {
labelForCurrBuildFile = Label.create(packageId, "BUILD");
} catch (LabelSyntaxException e) {
// Shouldn't happen; the Label is well-formed by construction.
throw new IllegalStateException(e);
}
try {
importPathMap = SkylarkImportLookupFunction.findLabelsForLoadStatements(imports, labelForCurrBuildFile, env);
if (importPathMap == null) {
return null;
}
} catch (SkylarkImportFailedException e) {
throw new BuildFileContainsErrorsException(packageId, e.getMessage());
}
// 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, inWorkspace));
}
Map<SkyKey, SkyValue> skylarkImportMap = Maps.newHashMapWithExpectedSize(importPathMap.size());
boolean valuesMissing = false;
try {
if (skylarkImportLookupFunctionForInlining == null) {
// Not inlining
Map<SkyKey, ValueOrException2<SkylarkImportFailedException, InconsistentFilesystemException>> skylarkLookupResults = env.getValuesOrThrow(importLookupKeys, SkylarkImportFailedException.class, InconsistentFilesystemException.class);
valuesMissing = env.valuesMissing();
for (Map.Entry<SkyKey, ValueOrException2<SkylarkImportFailedException, InconsistentFilesystemException>> entry : skylarkLookupResults.entrySet()) {
// Fetching the value will raise any deferred exceptions
skylarkImportMap.put(entry.getKey(), entry.getValue().get());
}
} else {
// Inlining calls to SkylarkImportLookupFunction
LinkedHashMap<Label, SkylarkImportLookupValue> alreadyVisitedImports = Maps.newLinkedHashMapWithExpectedSize(importLookupKeys.size());
for (SkyKey importLookupKey : importLookupKeys) {
SkyValue skyValue = skylarkImportLookupFunctionForInlining.computeWithInlineCalls(importLookupKey, env, alreadyVisitedImports);
if (skyValue == null) {
Preconditions.checkState(env.valuesMissing(), "no skylark import value for %s", importLookupKey);
// We continue making inline calls even if some requested values are missing, to
// maximize the number of dependent (non-inlined) SkyFunctions that are requested, thus
// avoiding a quadratic number of restarts.
valuesMissing = true;
} else {
skylarkImportMap.put(importLookupKey, skyValue);
}
}
}
} catch (SkylarkImportFailedException e) {
throw new BuildFileContainsErrorsException(packageId, e.getMessage());
} catch (InconsistentFilesystemException e) {
throw new NoSuchPackageException(packageId, e.getMessage(), e);
}
if (valuesMissing) {
// Some imports are unavailable.
return null;
}
// Process the loaded imports.
for (Entry<String, Label> importEntry : importPathMap.entrySet()) {
String importString = importEntry.getKey();
Label importLabel = importEntry.getValue();
SkyKey keyForLabel = SkylarkImportLookupValue.key(importLabel, inWorkspace);
SkylarkImportLookupValue importLookupValue = (SkylarkImportLookupValue) skylarkImportMap.get(keyForLabel);
importMap.put(importString, importLookupValue.getEnvironmentExtension());
fileDependencies.add(importLookupValue.getDependency());
}
return new SkylarkImportResult(importMap, transitiveClosureOfLabels(fileDependencies.build()));
}
Aggregations