Search in sources :

Example 1 with Extension

use of com.google.devtools.build.lib.syntax.Environment.Extension in project bazel by bazelbuild.

the class WorkspaceFactory method execute.

private void execute(BuildFileAST ast, @Nullable Map<String, Extension> importedExtensions, StoredEventHandler localReporter) throws InterruptedException {
    Environment.Builder environmentBuilder = Environment.builder(mutability).setGlobals(BazelLibrary.GLOBALS).setEventHandler(localReporter);
    if (importedExtensions != null) {
        Map<String, Extension> map = new HashMap<String, Extension>(parentImportMap);
        map.putAll(importedExtensions);
        importMap = ImmutableMap.<String, Extension>copyOf(importedExtensions);
    } else {
        importMap = parentImportMap;
    }
    environmentBuilder.setImportedExtensions(importMap);
    Environment workspaceEnv = environmentBuilder.setPhase(Phase.WORKSPACE).build();
    addWorkspaceFunctions(workspaceEnv, localReporter);
    for (Map.Entry<String, Object> binding : parentVariableBindings.entrySet()) {
        try {
            workspaceEnv.update(binding.getKey(), binding.getValue());
        } catch (EvalException e) {
            // This should never happen because everything was already evaluated.
            throw new IllegalStateException(e);
        }
    }
    if (!ast.exec(workspaceEnv, localReporter)) {
        localReporter.handle(Event.error("Error evaluating WORKSPACE file"));
    }
    // Save the list of variable bindings for the next part of the workspace file. The list of
    // variable bindings of interest are the global variable bindings that are defined by the user,
    // so not the workspace functions.
    // Workspace functions are not serializable and should not be passed over sky values. They
    // also have a package builder specific to the current part and should be reinitialized for
    // each workspace file.
    ImmutableMap.Builder<String, Object> bindingsBuilder = ImmutableMap.builder();
    Frame globals = workspaceEnv.getGlobals();
    for (String s : globals.getDirectVariableNames()) {
        Object o = globals.get(s);
        if (!isAWorkspaceFunction(s, o)) {
            bindingsBuilder.put(s, o);
        }
    }
    variableBindings = bindingsBuilder.build();
    builder.addEvents(localReporter.getEvents());
    if (localReporter.hasErrors()) {
        builder.setContainsErrors();
    }
    localReporter.clear();
}
Also used : Frame(com.google.devtools.build.lib.syntax.Environment.Frame) HashMap(java.util.HashMap) EvalException(com.google.devtools.build.lib.syntax.EvalException) ImmutableMap(com.google.common.collect.ImmutableMap) EnvironmentExtension(com.google.devtools.build.lib.packages.PackageFactory.EnvironmentExtension) Extension(com.google.devtools.build.lib.syntax.Environment.Extension) Environment(com.google.devtools.build.lib.syntax.Environment) ClassObject(com.google.devtools.build.lib.syntax.ClassObject) HashMap(java.util.HashMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap)

Example 2 with Extension

use of com.google.devtools.build.lib.syntax.Environment.Extension 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 3 with Extension

use of com.google.devtools.build.lib.syntax.Environment.Extension in project bazel by bazelbuild.

the class SkylarkImportLookupFunction method createExtension.

/**
   * Creates the Extension to be imported.
   */
private Extension createExtension(BuildFileAST ast, Label extensionLabel, Map<String, Extension> importMap, 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.
    // A more accurate - however much more complicated - way would be to calculate a hash based on
    // the transitive closure of the accessible AST nodes.
    PathFragment extensionFile = extensionLabel.toPathFragment();
    try (Mutability mutability = Mutability.create("importing %s", extensionFile)) {
        com.google.devtools.build.lib.syntax.Environment extensionEnv = ruleClassProvider.createSkylarkRuleClassEnvironment(extensionLabel, mutability, eventHandler, ast.getContentHashCode(), importMap).setupOverride("native", packageFactory.getNativeModule(inWorkspace));
        execAndExport(ast, extensionLabel, eventHandler, extensionEnv);
        Event.replayEventsOn(env.getListener(), eventHandler.getEvents());
        if (eventHandler.hasErrors()) {
            throw SkylarkImportFailedException.errors(extensionFile);
        }
        return new Extension(extensionEnv);
    }
}
Also used : Extension(com.google.devtools.build.lib.syntax.Environment.Extension) StoredEventHandler(com.google.devtools.build.lib.events.StoredEventHandler) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) Mutability(com.google.devtools.build.lib.syntax.Mutability)

Example 4 with Extension

use of com.google.devtools.build.lib.syntax.Environment.Extension 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

Extension (com.google.devtools.build.lib.syntax.Environment.Extension)4 ImmutableList (com.google.common.collect.ImmutableList)2 ImmutableMap (com.google.common.collect.ImmutableMap)2 Label (com.google.devtools.build.lib.cmdline.Label)2 SkylarkImport (com.google.devtools.build.lib.syntax.SkylarkImport)2 PathFragment (com.google.devtools.build.lib.vfs.PathFragment)2 SkyKey (com.google.devtools.build.skyframe.SkyKey)2 SkyValue (com.google.devtools.build.skyframe.SkyValue)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 LabelSyntaxException (com.google.devtools.build.lib.cmdline.LabelSyntaxException)1 StoredEventHandler (com.google.devtools.build.lib.events.StoredEventHandler)1 BuildFileContainsErrorsException (com.google.devtools.build.lib.packages.BuildFileContainsErrorsException)1 NoSuchPackageException (com.google.devtools.build.lib.packages.NoSuchPackageException)1 EnvironmentExtension (com.google.devtools.build.lib.packages.PackageFactory.EnvironmentExtension)1 SkylarkImportFailedException (com.google.devtools.build.lib.skyframe.SkylarkImportLookupFunction.SkylarkImportFailedException)1 BuildFileAST (com.google.devtools.build.lib.syntax.BuildFileAST)1 ClassObject (com.google.devtools.build.lib.syntax.ClassObject)1 Environment (com.google.devtools.build.lib.syntax.Environment)1 Frame (com.google.devtools.build.lib.syntax.Environment.Frame)1