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;
}
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));
}
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;
}
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;
}
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();
}
Aggregations