Search in sources :

Example 1 with SkylarkImport

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");
}
Also used : SkyKey(com.google.devtools.build.skyframe.SkyKey) SkylarkImport(com.google.devtools.build.lib.syntax.SkylarkImport) Test(org.junit.Test)

Example 2 with SkylarkImport

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);
}
Also used : SkylarkImport(com.google.devtools.build.lib.syntax.SkylarkImport) AspectCreationException(com.google.devtools.build.lib.skyframe.AspectFunction.AspectCreationException) SkyKey(com.google.devtools.build.skyframe.SkyKey) SkylarkAspectLoadingKey(com.google.devtools.build.lib.skyframe.AspectValue.SkylarkAspectLoadingKey) SkylarkAspect(com.google.devtools.build.lib.packages.SkylarkAspect) Label(com.google.devtools.build.lib.cmdline.Label) SkylarkImportFailedException(com.google.devtools.build.lib.skyframe.SkylarkImportLookupFunction.SkylarkImportFailedException) AspectDescriptor(com.google.devtools.build.lib.packages.AspectDescriptor) Nullable(javax.annotation.Nullable)

Example 3 with SkylarkImport

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;
}
Also used : Label(com.google.devtools.build.lib.cmdline.Label) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) SkylarkImport(com.google.devtools.build.lib.syntax.SkylarkImport) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMultimap(com.google.common.collect.ImmutableMultimap) Nullable(javax.annotation.Nullable)

Example 4 with SkylarkImport

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;
}
Also used : SkyKey(com.google.devtools.build.skyframe.SkyKey) ImmutableList(com.google.common.collect.ImmutableList) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) Label(com.google.devtools.build.lib.cmdline.Label) SkylarkImport(com.google.devtools.build.lib.syntax.SkylarkImport) Extension(com.google.devtools.build.lib.syntax.Environment.Extension) SkyValue(com.google.devtools.build.skyframe.SkyValue) BuildFileAST(com.google.devtools.build.lib.syntax.BuildFileAST)

Example 5 with SkylarkImport

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()));
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) Label(com.google.devtools.build.lib.cmdline.Label) SkyValue(com.google.devtools.build.skyframe.SkyValue) SkyKey(com.google.devtools.build.skyframe.SkyKey) BuildFileContainsErrorsException(com.google.devtools.build.lib.packages.BuildFileContainsErrorsException) LabelSyntaxException(com.google.devtools.build.lib.cmdline.LabelSyntaxException) ValueOrException2(com.google.devtools.build.skyframe.ValueOrException2) SkylarkImport(com.google.devtools.build.lib.syntax.SkylarkImport) Extension(com.google.devtools.build.lib.syntax.Environment.Extension) NoSuchPackageException(com.google.devtools.build.lib.packages.NoSuchPackageException) SkylarkImportFailedException(com.google.devtools.build.lib.skyframe.SkylarkImportLookupFunction.SkylarkImportFailedException) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Nullable(javax.annotation.Nullable)

Aggregations

SkylarkImport (com.google.devtools.build.lib.syntax.SkylarkImport)7 SkyKey (com.google.devtools.build.skyframe.SkyKey)5 Label (com.google.devtools.build.lib.cmdline.Label)4 PathFragment (com.google.devtools.build.lib.vfs.PathFragment)3 Nullable (javax.annotation.Nullable)3 ImmutableList (com.google.common.collect.ImmutableList)2 AspectDescriptor (com.google.devtools.build.lib.packages.AspectDescriptor)2 SkylarkImportFailedException (com.google.devtools.build.lib.skyframe.SkylarkImportLookupFunction.SkylarkImportFailedException)2 Extension (com.google.devtools.build.lib.syntax.Environment.Extension)2 SkyValue (com.google.devtools.build.skyframe.SkyValue)2 Test (org.junit.Test)2 ImmutableMap (com.google.common.collect.ImmutableMap)1 ImmutableMultimap (com.google.common.collect.ImmutableMultimap)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 BuildConfiguration (com.google.devtools.build.lib.analysis.config.BuildConfiguration)1 LabelSyntaxException (com.google.devtools.build.lib.cmdline.LabelSyntaxException)1 ThreadCompatible (com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible)1 BuildFileContainsErrorsException (com.google.devtools.build.lib.packages.BuildFileContainsErrorsException)1 NativeAspectClass (com.google.devtools.build.lib.packages.NativeAspectClass)1 NoSuchPackageException (com.google.devtools.build.lib.packages.NoSuchPackageException)1