Search in sources :

Example 11 with EvalException

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

the class ConfiguredAttributeMapper method resolveSelector.

private <T> ConfigKeyAndValue<T> resolveSelector(String attributeName, Selector<T> selector) throws EvalException {
    ConfigMatchingProvider matchingCondition = null;
    Set<Label> conditionLabels = new LinkedHashSet<>();
    ConfigKeyAndValue<T> matchingResult = null;
    // Find the matching condition and record its value (checking for duplicates).
    for (Map.Entry<Label, T> entry : selector.getEntries().entrySet()) {
        Label selectorKey = entry.getKey();
        if (BuildType.Selector.isReservedLabel(selectorKey)) {
            continue;
        }
        ConfigMatchingProvider curCondition = configConditions.get(rule.getLabel().resolveRepositoryRelative(selectorKey));
        if (curCondition == null) {
            // This can happen if the rule is in error
            continue;
        }
        conditionLabels.add(curCondition.label());
        if (curCondition.matches()) {
            if (matchingCondition == null || curCondition.refines(matchingCondition)) {
                // A match is valid if either this is the *only* condition that matches or this is a
                // more "precise" specification of another matching condition (in which case we choose
                // the most precise one).
                matchingCondition = curCondition;
                matchingResult = new ConfigKeyAndValue<>(selectorKey, entry.getValue());
            } else if (matchingCondition.refines(curCondition)) {
            // The originally matching conditions is more precise, so keep that one.
            } else {
                throw new EvalException(rule.getAttributeLocation(attributeName), "Both " + matchingCondition.label() + " and " + curCondition.label() + " match configurable attribute \"" + attributeName + "\" in " + getLabel() + ". Multiple matches are not allowed unless one is a specialization of the other");
            }
        }
    }
    // If nothing matched, choose the default condition.
    if (matchingCondition == null) {
        if (!selector.hasDefault()) {
            String noMatchMessage = "Configurable attribute \"" + attributeName + "\" doesn't match this configuration";
            if (!selector.getNoMatchError().isEmpty()) {
                noMatchMessage += ": " + selector.getNoMatchError();
            } else {
                noMatchMessage += " (would a default condition help?).\nConditions checked:\n " + Joiner.on("\n ").join(conditionLabels);
            }
            throw new EvalException(rule.getAttributeLocation(attributeName), noMatchMessage);
        }
        matchingResult = selector.hasDefault() ? new ConfigKeyAndValue<>(Selector.DEFAULT_CONDITION_LABEL, selector.getDefault()) : null;
    }
    return matchingResult;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Label(com.google.devtools.build.lib.cmdline.Label) ConfigMatchingProvider(com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider) EvalException(com.google.devtools.build.lib.syntax.EvalException) ImmutableMap(com.google.common.collect.ImmutableMap) Map(java.util.Map) AttributeMap(com.google.devtools.build.lib.packages.AttributeMap)

Example 12 with EvalException

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

the class SkylarkRuleConfiguredTargetBuilder method parseProviderKeys.

private static void parseProviderKeys(SkylarkClassObject provider, Boolean isDefaultProvider, RuleContext ruleContext, Location loc, Artifact executable, Map<String, Class<? extends TransitiveInfoProvider>> registeredProviderTypes, RuleConfiguredTargetBuilder builder) throws EvalException {
    Runfiles statelessRunfiles = null;
    Runfiles dataRunfiles = null;
    Runfiles defaultRunfiles = null;
    for (String key : provider.getKeys()) {
        if (key.equals("files")) {
            // If we specify files_to_build we don't have the executable in it by default.
            builder.setFilesToBuild(cast("files", provider, SkylarkNestedSet.class, Artifact.class, loc).getSet(Artifact.class));
        } else if (key.equals("runfiles")) {
            statelessRunfiles = cast("runfiles", provider, Runfiles.class, loc);
        } else if (key.equals("data_runfiles")) {
            dataRunfiles = cast("data_runfiles", provider, Runfiles.class, loc);
        } else if (key.equals("default_runfiles")) {
            defaultRunfiles = cast("default_runfiles", provider, Runfiles.class, loc);
        } else if (key.equals("output_groups")) {
            addOutputGroups(provider.getValue(key), loc, builder);
        } else if (key.equals("instrumented_files")) {
            SkylarkClassObject insStruct = cast("instrumented_files", provider, SkylarkClassObject.class, loc);
            Location insLoc = insStruct.getCreationLoc();
            FileTypeSet fileTypeSet = FileTypeSet.ANY_FILE;
            if (insStruct.getKeys().contains("extensions")) {
                @SuppressWarnings("unchecked") List<String> exts = cast("extensions", insStruct, SkylarkList.class, String.class, insLoc);
                if (exts.isEmpty()) {
                    fileTypeSet = FileTypeSet.NO_FILE;
                } else {
                    FileType[] fileTypes = new FileType[exts.size()];
                    for (int i = 0; i < fileTypes.length; i++) {
                        fileTypes[i] = FileType.of(exts.get(i));
                    }
                    fileTypeSet = FileTypeSet.of(fileTypes);
                }
            }
            List<String> dependencyAttributes = Collections.emptyList();
            if (insStruct.getKeys().contains("dependency_attributes")) {
                dependencyAttributes = cast("dependency_attributes", insStruct, SkylarkList.class, String.class, insLoc);
            }
            List<String> sourceAttributes = Collections.emptyList();
            if (insStruct.getKeys().contains("source_attributes")) {
                sourceAttributes = cast("source_attributes", insStruct, SkylarkList.class, String.class, insLoc);
            }
            InstrumentationSpec instrumentationSpec = new InstrumentationSpec(fileTypeSet).withSourceAttributes(sourceAttributes.toArray(new String[0])).withDependencyAttributes(dependencyAttributes.toArray(new String[0]));
            InstrumentedFilesProvider instrumentedFilesProvider = InstrumentedFilesCollector.collect(ruleContext, instrumentationSpec, InstrumentedFilesCollector.NO_METADATA_COLLECTOR, Collections.<Artifact>emptySet());
            builder.addProvider(InstrumentedFilesProvider.class, instrumentedFilesProvider);
        } else if (registeredProviderTypes.containsKey(key)) {
            Class<? extends TransitiveInfoProvider> providerType = registeredProviderTypes.get(key);
            TransitiveInfoProvider providerField = cast(key, provider, providerType, loc);
            builder.addProvider(providerType, providerField);
        } else if (isDefaultProvider) {
            // Custom keys are not allowed for default providers
            throw new EvalException(loc, "Invalid key for default provider: " + key);
        } else if (key.equals("providers")) {
            Iterable iterable = cast(key, provider, Iterable.class, loc);
            for (Object o : iterable) {
                SkylarkClassObject declaredProvider = SkylarkType.cast(o, SkylarkClassObject.class, loc, "The value of 'providers' should be a sequence of declared providers");
                builder.addSkylarkDeclaredProvider(declaredProvider, loc);
            }
        } else if (!key.equals("executable")) {
            // We handled executable already.
            builder.addSkylarkTransitiveInfo(key, provider.getValue(key), loc);
        }
    }
    addSimpleProviders(builder, ruleContext, loc, executable, statelessRunfiles, dataRunfiles, defaultRunfiles, (isDefaultProvider ? provider : null));
}
Also used : SkylarkClassObject(com.google.devtools.build.lib.packages.SkylarkClassObject) InstrumentationSpec(com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector.InstrumentationSpec) InstrumentedFilesProvider(com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider) EvalException(com.google.devtools.build.lib.syntax.EvalException) Artifact(com.google.devtools.build.lib.actions.Artifact) Runfiles(com.google.devtools.build.lib.analysis.Runfiles) FileTypeSet(com.google.devtools.build.lib.util.FileTypeSet) SkylarkList(com.google.devtools.build.lib.syntax.SkylarkList) SkylarkList(com.google.devtools.build.lib.syntax.SkylarkList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) SkylarkClassObject(com.google.devtools.build.lib.packages.SkylarkClassObject) ClassObject(com.google.devtools.build.lib.syntax.ClassObject) TransitiveInfoProvider(com.google.devtools.build.lib.analysis.TransitiveInfoProvider) Location(com.google.devtools.build.lib.events.Location)

Example 13 with EvalException

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

the class SkylarkRuleConfiguredTargetBuilder method convertToOutputGroupValue.

public static NestedSet<Artifact> convertToOutputGroupValue(Location loc, String outputGroup, SkylarkValue objects) throws EvalException {
    NestedSet<Artifact> artifacts;
    String typeErrorMessage = "Output group '%s' is of unexpected type. " + "Should be list or set of Files, but got '%s' instead.";
    if (objects instanceof SkylarkList) {
        NestedSetBuilder<Artifact> nestedSetBuilder = NestedSetBuilder.stableOrder();
        for (Object o : (SkylarkList) objects) {
            if (o instanceof Artifact) {
                nestedSetBuilder.add((Artifact) o);
            } else {
                throw new EvalException(loc, String.format(typeErrorMessage, outputGroup, "list with an element of " + EvalUtils.getDataTypeNameFromClass(o.getClass())));
            }
        }
        artifacts = nestedSetBuilder.build();
    } else {
        artifacts = SkylarkType.cast(objects, SkylarkNestedSet.class, Artifact.class, loc, typeErrorMessage, outputGroup, EvalUtils.getDataTypeName(objects, true)).getSet(Artifact.class);
    }
    return artifacts;
}
Also used : SkylarkList(com.google.devtools.build.lib.syntax.SkylarkList) SkylarkClassObject(com.google.devtools.build.lib.packages.SkylarkClassObject) ClassObject(com.google.devtools.build.lib.syntax.ClassObject) EvalException(com.google.devtools.build.lib.syntax.EvalException) Artifact(com.google.devtools.build.lib.actions.Artifact)

Example 14 with EvalException

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

the class NewRepositoryBuildFileHandler method getBuildFileValue.

private FileValue getBuildFileValue(Rule rule, Environment env) throws RepositoryFunctionException, InterruptedException {
    WorkspaceAttributeMapper mapper = WorkspaceAttributeMapper.of(rule);
    String buildFileAttribute;
    try {
        buildFileAttribute = mapper.get("build_file", Type.STRING);
    } catch (EvalException e) {
        throw new RepositoryFunctionException(e, Transience.PERSISTENT);
    }
    RootedPath rootedBuild;
    if (LabelValidator.isAbsolute(buildFileAttribute)) {
        try {
            // Parse a label
            Label label = Label.parseAbsolute(buildFileAttribute);
            SkyKey pkgSkyKey = PackageLookupValue.key(label.getPackageIdentifier());
            PackageLookupValue pkgLookupValue = (PackageLookupValue) env.getValue(pkgSkyKey);
            if (pkgLookupValue == null) {
                return null;
            }
            if (!pkgLookupValue.packageExists()) {
                throw new RepositoryFunctionException(new EvalException(rule.getLocation(), "Unable to load package for " + buildFileAttribute + ": not found."), Transience.PERSISTENT);
            }
            // And now for the file
            Path packageRoot = pkgLookupValue.getRoot();
            rootedBuild = RootedPath.toRootedPath(packageRoot, label.toPathFragment());
        } catch (LabelSyntaxException ex) {
            throw new RepositoryFunctionException(new EvalException(rule.getLocation(), String.format("In %s the 'build_file' attribute does not specify a valid label: %s", rule, ex.getMessage())), Transience.PERSISTENT);
        }
    } else {
        // TODO(dmarting): deprecate using a path for the build_file attribute.
        PathFragment buildFile = new PathFragment(buildFileAttribute);
        Path buildFileTarget = workspacePath.getRelative(buildFile);
        if (!buildFileTarget.exists()) {
            throw new RepositoryFunctionException(new EvalException(rule.getLocation(), String.format("In %s the 'build_file' attribute does not specify an existing file " + "(%s does not exist)", rule, buildFileTarget)), Transience.PERSISTENT);
        }
        if (buildFile.isAbsolute()) {
            rootedBuild = RootedPath.toRootedPath(buildFileTarget.getParentDirectory(), new PathFragment(buildFileTarget.getBaseName()));
        } else {
            rootedBuild = RootedPath.toRootedPath(workspacePath, buildFile);
        }
    }
    SkyKey buildFileKey = FileValue.key(rootedBuild);
    FileValue buildFileValue;
    try {
        // Note that this dependency is, strictly speaking, not necessary: the symlink could simply
        // point to this FileValue and the symlink chasing could be done while loading the package
        // but this results in a nicer error message and it's correct as long as RepositoryFunctions
        // don't write to things in the file system this FileValue depends on. In theory, the latter
        // is possible if the file referenced by build_file is a symlink to somewhere under the
        // external/ directory, but if you do that, you are really asking for trouble.
        buildFileValue = (FileValue) env.getValueOrThrow(buildFileKey, IOException.class, FileSymlinkException.class, InconsistentFilesystemException.class);
        if (buildFileValue == null) {
            return null;
        }
    } catch (IOException | FileSymlinkException | InconsistentFilesystemException e) {
        throw new RepositoryFunctionException(new IOException("Cannot lookup " + buildFileAttribute + ": " + e.getMessage()), Transience.TRANSIENT);
    }
    return buildFileValue;
}
Also used : SkyKey(com.google.devtools.build.skyframe.SkyKey) PackageLookupValue(com.google.devtools.build.lib.skyframe.PackageLookupValue) RootedPath(com.google.devtools.build.lib.vfs.RootedPath) Path(com.google.devtools.build.lib.vfs.Path) FileValue(com.google.devtools.build.lib.skyframe.FileValue) LabelSyntaxException(com.google.devtools.build.lib.cmdline.LabelSyntaxException) Label(com.google.devtools.build.lib.cmdline.Label) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) EvalException(com.google.devtools.build.lib.syntax.EvalException) IOException(java.io.IOException) InconsistentFilesystemException(com.google.devtools.build.lib.skyframe.InconsistentFilesystemException) RootedPath(com.google.devtools.build.lib.vfs.RootedPath) FileSymlinkException(com.google.devtools.build.lib.skyframe.FileSymlinkException) RepositoryFunctionException(com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException)

Example 15 with EvalException

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

the class RepositoryDelegatorFunction method compute.

@Override
public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException, InterruptedException {
    RepositoryName repositoryName = (RepositoryName) skyKey.argument();
    Rule rule = RepositoryFunction.getRule(repositoryName, null, env);
    if (rule == null) {
        return null;
    }
    BlazeDirectories directories = PrecomputedValue.BLAZE_DIRECTORIES.get(env);
    if (directories == null) {
        return null;
    }
    RepositoryFunction handler;
    if (rule.getRuleClassObject().isSkylark()) {
        handler = skylarkHandler;
    } else {
        handler = handlers.get(rule.getRuleClass());
    }
    if (handler == null) {
        throw new RepositoryFunctionException(new EvalException(Location.fromFile(directories.getWorkspace().getRelative("WORKSPACE")), "Could not find handler for " + rule), Transience.PERSISTENT);
    }
    handler.setClientEnvironment(clientEnvironment);
    Path repoRoot = RepositoryFunction.getExternalRepositoryDirectory(directories).getRelative(rule.getName());
    byte[] ruleSpecificData = handler.getRuleSpecificMarkerData(rule, env);
    if (ruleSpecificData == null) {
        return null;
    }
    String ruleKey = computeRuleKey(rule, ruleSpecificData);
    Map<String, String> markerData = new TreeMap<>();
    Path markerPath = getMarkerPath(directories, rule);
    if (handler.isLocal(rule)) {
        // Local repositories are always fetched because the operation is generally fast and they do
        // not depend on non-local data, so it does not make much sense to try to cache from across
        // server instances.
        setupRepositoryRoot(repoRoot);
        RepositoryDirectoryValue.Builder localRepo = handler.fetch(rule, repoRoot, directories, env, markerData);
        if (localRepo == null) {
            return null;
        } else {
            // We write the marker file for local repository essentially for getting the digest and
            // injecting it in the RepositoryDirectoryValue.
            byte[] digest = writeMarkerFile(markerPath, markerData, ruleKey);
            return localRepo.setDigest(digest).build();
        }
    }
    // We check the repository root for existence here, but we can't depend on the FileValue,
    // because it's possible that we eventually create that directory in which case the FileValue
    // and the state of the file system would be inconsistent.
    byte[] markerHash = isFilesystemUpToDate(markerPath, rule, ruleKey, handler, env);
    if (env.valuesMissing()) {
        return null;
    }
    if (markerHash != null && repoRoot.exists()) {
        // Now that we know that it exists, we can declare a Skyframe dependency on the repository
        // root.
        RepositoryFunction.getRepositoryDirectory(repoRoot, env);
        if (env.valuesMissing()) {
            return null;
        }
        return RepositoryDirectoryValue.builder().setPath(repoRoot).setDigest(markerHash).build();
    }
    if (isFetch.get()) {
        // Fetching enabled, go ahead.
        setupRepositoryRoot(repoRoot);
        RepositoryDirectoryValue.Builder result = handler.fetch(rule, repoRoot, directories, env, markerData);
        if (env.valuesMissing()) {
            return null;
        }
        // No new Skyframe dependencies must be added between calling the repository implementation
        // and writing the marker file because if they aren't computed, it would cause a Skyframe
        // restart thus calling the possibly very slow (networking, decompression...) fetch()
        // operation again. So we write the marker file here immediately.
        byte[] digest = writeMarkerFile(markerPath, markerData, ruleKey);
        return result.setDigest(digest).build();
    }
    if (!repoRoot.exists()) {
        // The repository isn't on the file system, there is nothing we can do.
        throw new RepositoryFunctionException(new IOException("to fix, run\n\tbazel fetch //...\nExternal repository " + repositoryName + " not found and fetching repositories is disabled."), Transience.TRANSIENT);
    }
    // Declare a Skyframe dependency so that this is re-evaluated when something happens to the
    // directory.
    FileValue repoRootValue = RepositoryFunction.getRepositoryDirectory(repoRoot, env);
    if (env.valuesMissing()) {
        return null;
    }
    // Try to build with whatever is on the file system and emit a warning.
    env.getListener().handle(Event.warn(rule.getLocation(), String.format("External repository '%s' is not up-to-date and fetching is disabled. To update, " + "run the build without the '--nofetch' command line option.", rule.getName())));
    return RepositoryDirectoryValue.builder().setPath(repoRootValue.realRootedPath().asPath()).setFetchingDelayed().build();
}
Also used : Path(com.google.devtools.build.lib.vfs.Path) FileValue(com.google.devtools.build.lib.skyframe.FileValue) RepositoryName(com.google.devtools.build.lib.cmdline.RepositoryName) EvalException(com.google.devtools.build.lib.syntax.EvalException) IOException(java.io.IOException) TreeMap(java.util.TreeMap) BlazeDirectories(com.google.devtools.build.lib.analysis.BlazeDirectories) Rule(com.google.devtools.build.lib.packages.Rule) RepositoryFunctionException(com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException)

Aggregations

EvalException (com.google.devtools.build.lib.syntax.EvalException)47 IOException (java.io.IOException)15 WorkspaceAttributeMapper (com.google.devtools.build.lib.rules.repository.WorkspaceAttributeMapper)9 ClassObject (com.google.devtools.build.lib.syntax.ClassObject)9 RootedPath (com.google.devtools.build.lib.vfs.RootedPath)9 ImmutableMap (com.google.common.collect.ImmutableMap)8 Label (com.google.devtools.build.lib.cmdline.Label)8 Path (com.google.devtools.build.lib.vfs.Path)8 SkylarkClassObject (com.google.devtools.build.lib.packages.SkylarkClassObject)7 Environment (com.google.devtools.build.lib.syntax.Environment)7 Map (java.util.Map)7 LabelSyntaxException (com.google.devtools.build.lib.cmdline.LabelSyntaxException)6 RepositoryFunctionException (com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException)6 PathFragment (com.google.devtools.build.lib.vfs.PathFragment)6 SkyKey (com.google.devtools.build.skyframe.SkyKey)6 Nullable (javax.annotation.Nullable)6 FileValue (com.google.devtools.build.lib.skyframe.FileValue)5 ImmutableList (com.google.common.collect.ImmutableList)4 Artifact (com.google.devtools.build.lib.actions.Artifact)4 BaseFunction (com.google.devtools.build.lib.syntax.BaseFunction)3