use of com.google.devtools.build.skyframe.SkyValue in project bazel by bazelbuild.
the class AndroidSdkRepositoryFunction method getSubdirectoryListingValues.
/** Gets DirectoryListingValues for subdirectories of the directory or returns null. */
private static ImmutableMap<PathFragment, DirectoryListingValue> getSubdirectoryListingValues(final Path root, final PathFragment path, DirectoryListingValue directory, Environment env) throws RepositoryFunctionException, InterruptedException {
Map<PathFragment, SkyKey> skyKeysForSubdirectoryLookups = Maps.transformEntries(Maps.uniqueIndex(directory.getDirents(), new Function<Dirent, PathFragment>() {
@Override
public PathFragment apply(Dirent input) {
return path.getRelative(input.getName());
}
}), new EntryTransformer<PathFragment, Dirent, SkyKey>() {
@Override
public SkyKey transformEntry(PathFragment key, Dirent value) {
return DirectoryListingValue.key(RootedPath.toRootedPath(root, root.getRelative(key)));
}
});
Map<SkyKey, ValueOrException<InconsistentFilesystemException>> values = env.getValuesOrThrow(skyKeysForSubdirectoryLookups.values(), InconsistentFilesystemException.class);
ImmutableMap.Builder<PathFragment, DirectoryListingValue> directoryListingValues = new ImmutableMap.Builder<>();
for (PathFragment pathFragment : skyKeysForSubdirectoryLookups.keySet()) {
try {
SkyValue skyValue = values.get(skyKeysForSubdirectoryLookups.get(pathFragment)).get();
if (skyValue == null) {
return null;
}
directoryListingValues.put(pathFragment, (DirectoryListingValue) skyValue);
} catch (InconsistentFilesystemException e) {
throw new RepositoryFunctionException(new IOException(e), Transience.PERSISTENT);
}
}
return directoryListingValues.build();
}
use of com.google.devtools.build.skyframe.SkyValue in project bazel by bazelbuild.
the class SkyframeExecutor method getDiff.
protected Differencer.Diff getDiff(TimestampGranularityMonitor tsgm, Iterable<PathFragment> modifiedSourceFiles, final Path pathEntry) throws InterruptedException {
if (Iterables.isEmpty(modifiedSourceFiles)) {
return new ImmutableDiff(ImmutableList.<SkyKey>of(), ImmutableMap.<SkyKey, SkyValue>of());
}
// TODO(bazel-team): change ModifiedFileSet to work with RootedPaths instead of PathFragments.
Iterable<SkyKey> dirtyFileStateSkyKeys = Iterables.transform(modifiedSourceFiles, new Function<PathFragment, SkyKey>() {
@Override
public SkyKey apply(PathFragment pathFragment) {
Preconditions.checkState(!pathFragment.isAbsolute(), "found absolute PathFragment: %s", pathFragment);
return FileStateValue.key(RootedPath.toRootedPath(pathEntry, pathFragment));
}
});
// We only need to invalidate directory values when a file has been created or deleted or
// changes type, not when it has merely been modified. Unfortunately we do not have that
// information here, so we compute it ourselves.
// TODO(bazel-team): Fancy filesystems could provide it with a hypothetically modified
// DiffAwareness interface.
LOG.info("About to recompute filesystem nodes corresponding to files that are known to have " + "changed");
FilesystemValueChecker fsvc = new FilesystemValueChecker(tsgm, null);
Map<SkyKey, SkyValue> valuesMap = memoizingEvaluator.getValues();
Differencer.DiffWithDelta diff = fsvc.getNewAndOldValues(valuesMap, dirtyFileStateSkyKeys, new FileDirtinessChecker());
Set<SkyKey> valuesToInvalidate = new HashSet<>();
Map<SkyKey, SkyValue> valuesToInject = new HashMap<>();
for (Map.Entry<SkyKey, Delta> entry : diff.changedKeysWithNewAndOldValues().entrySet()) {
SkyKey key = entry.getKey();
Preconditions.checkState(key.functionName().equals(SkyFunctions.FILE_STATE), key);
RootedPath rootedPath = (RootedPath) key.argument();
Delta delta = entry.getValue();
FileStateValue oldValue = (FileStateValue) delta.getOldValue();
FileStateValue newValue = (FileStateValue) delta.getNewValue();
if (newValue != null) {
valuesToInject.put(key, newValue);
} else {
valuesToInvalidate.add(key);
}
SkyKey dirListingStateKey = parentDirectoryListingStateKey(rootedPath);
// Invalidate the directory listing for the path's parent directory if the change was
// relevant (e.g. path turned from a symlink into a directory) OR if we don't have enough
// information to determine it was irrelevant.
boolean changedType = false;
if (newValue == null) {
changedType = true;
} else if (oldValue != null) {
changedType = !oldValue.getType().equals(newValue.getType());
} else {
DirectoryListingStateValue oldDirListingStateValue = (DirectoryListingStateValue) valuesMap.get(dirListingStateKey);
if (oldDirListingStateValue != null) {
String baseName = rootedPath.getRelativePath().getBaseName();
Dirent oldDirent = oldDirListingStateValue.getDirents().maybeGetDirent(baseName);
changedType = (oldDirent == null) || !compatibleFileTypes(oldDirent.getType(), newValue.getType());
} else {
changedType = true;
}
}
if (changedType) {
valuesToInvalidate.add(dirListingStateKey);
}
}
for (SkyKey key : diff.changedKeysWithoutNewValues()) {
Preconditions.checkState(key.functionName().equals(SkyFunctions.FILE_STATE), key);
RootedPath rootedPath = (RootedPath) key.argument();
valuesToInvalidate.add(parentDirectoryListingStateKey(rootedPath));
}
return new ImmutableDiff(valuesToInvalidate, valuesToInject);
}
use of com.google.devtools.build.skyframe.SkyValue in project bazel by bazelbuild.
the class SkyframeExecutor method getConfiguredTargetMap.
/**
* Returns a map from {@link Dependency} inputs to the {@link ConfiguredTarget}s corresponding to
* those dependencies.
*
* <p>For use for legacy support and tests calling through {@code BuildView} only.
*
* <p>If a requested configured target is in error, the corresponding value is omitted from the
* returned list.
*/
@ThreadSafety.ThreadSafe
public ImmutableMultimap<Dependency, ConfiguredTarget> getConfiguredTargetMap(ExtendedEventHandler eventHandler, BuildConfiguration originalConfig, Iterable<Dependency> keys, boolean useOriginalConfig) {
checkActive();
Multimap<Dependency, BuildConfiguration> configs;
if (originalConfig != null) {
if (useOriginalConfig) {
// This flag is used because of some unfortunate complexity in the configuration machinery:
// Most callers of this method pass a <Label, Configuration> pair to directly create a
// ConfiguredTarget from, but happen to use the Dependency data structure to pass that
// info (even though the data has nothing to do with dependencies). If this configuration
// includes a split transition, a dynamic configuration created from it will *not*
// include that transition (because dynamic configurations don't embed transitions to
// other configurations. In that case, we need to preserve the original configuration.
// TODO(bazel-team); make this unnecessary once split transition logic is properly ported
// out of configurations.
configs = ArrayListMultimap.<Dependency, BuildConfiguration>create();
configs.put(Iterables.getOnlyElement(keys), originalConfig);
} else {
configs = getConfigurations(eventHandler, originalConfig.getOptions(), keys);
}
} else {
configs = ArrayListMultimap.<Dependency, BuildConfiguration>create();
for (Dependency key : keys) {
configs.put(key, null);
}
}
final List<SkyKey> skyKeys = new ArrayList<>();
for (Dependency key : keys) {
if (!configs.containsKey(key)) {
// it couldn't be loaded). Exclude it from the results.
continue;
}
for (BuildConfiguration depConfig : configs.get(key)) {
skyKeys.add(ConfiguredTargetValue.key(key.getLabel(), depConfig));
for (AspectDescriptor aspectDescriptor : key.getAspects().getAllAspects()) {
skyKeys.add(ActionLookupValue.key(AspectValue.createAspectKey(key.getLabel(), depConfig, aspectDescriptor, depConfig)));
}
}
}
EvaluationResult<SkyValue> result = evaluateSkyKeys(eventHandler, skyKeys);
for (Map.Entry<SkyKey, ErrorInfo> entry : result.errorMap().entrySet()) {
reportCycles(eventHandler, entry.getValue().getCycleInfo(), entry.getKey());
}
ImmutableMultimap.Builder<Dependency, ConfiguredTarget> cts = ImmutableMultimap.<Dependency, ConfiguredTarget>builder();
DependentNodeLoop: for (Dependency key : keys) {
if (!configs.containsKey(key)) {
// it couldn't be loaded). Exclude it from the results.
continue;
}
for (BuildConfiguration depConfig : configs.get(key)) {
SkyKey configuredTargetKey = ConfiguredTargetValue.key(key.getLabel(), depConfig);
if (result.get(configuredTargetKey) == null) {
continue;
}
ConfiguredTarget configuredTarget = ((ConfiguredTargetValue) result.get(configuredTargetKey)).getConfiguredTarget();
List<ConfiguredAspect> configuredAspects = new ArrayList<>();
for (AspectDescriptor aspectDescriptor : key.getAspects().getAllAspects()) {
SkyKey aspectKey = ActionLookupValue.key(AspectValue.createAspectKey(key.getLabel(), depConfig, aspectDescriptor, depConfig));
if (result.get(aspectKey) == null) {
continue DependentNodeLoop;
}
configuredAspects.add(((AspectValue) result.get(aspectKey)).getConfiguredAspect());
}
try {
cts.put(key, MergedConfiguredTarget.of(configuredTarget, configuredAspects));
} catch (DuplicateException e) {
throw new IllegalStateException(String.format("Error creating %s", configuredTarget.getTarget().getLabel()), e);
}
}
}
return cts.build();
}
use of com.google.devtools.build.skyframe.SkyValue 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.skyframe.SkyValue in project bazel by bazelbuild.
the class TargetPatternPhaseFunction method determineTests.
/**
* Interpret test target labels from the command-line arguments and return the corresponding set
* of targets, handling the filter flags, and expanding test suites.
*
* @param targetPatterns the list of command-line target patterns specified by the user
* @param testFilter the test filter
*/
private static ResolvedTargets<Target> determineTests(Environment env, List<String> targetPatterns, String offset, TestFilter testFilter) throws InterruptedException {
List<SkyKey> patternSkyKeys = new ArrayList<>();
for (TargetPatternSkyKeyOrException keyOrException : TargetPatternValue.keys(targetPatterns, FilteringPolicies.FILTER_TESTS, offset)) {
try {
patternSkyKeys.add(keyOrException.getSkyKey());
} catch (TargetParsingException e) {
// Skip.
}
}
Map<SkyKey, ValueOrException<TargetParsingException>> resolvedPatterns = env.getValuesOrThrow(patternSkyKeys, TargetParsingException.class);
if (env.valuesMissing()) {
return null;
}
List<SkyKey> expandedSuiteKeys = new ArrayList<>();
for (SkyKey key : patternSkyKeys) {
TargetPatternValue value;
try {
value = (TargetPatternValue) resolvedPatterns.get(key).get();
} catch (TargetParsingException e) {
// Skip.
continue;
}
expandedSuiteKeys.add(TestSuiteExpansionValue.key(value.getTargets().getTargets()));
}
Map<SkyKey, SkyValue> expandedSuites = env.getValues(expandedSuiteKeys);
if (env.valuesMissing()) {
return null;
}
ResolvedTargets.Builder<Target> testTargetsBuilder = ResolvedTargets.builder();
for (SkyKey key : patternSkyKeys) {
TargetPatternKey pattern = (TargetPatternKey) key.argument();
TargetPatternValue value;
try {
value = (TargetPatternValue) resolvedPatterns.get(key).get();
} catch (TargetParsingException e) {
// This was already reported in getTargetsToBuild (maybe merge the two code paths?).
continue;
}
TestSuiteExpansionValue expandedSuitesValue = (TestSuiteExpansionValue) expandedSuites.get(TestSuiteExpansionValue.key(value.getTargets().getTargets()));
if (pattern.isNegative()) {
ResolvedTargets<Target> negativeTargets = expandedSuitesValue.getTargets();
testTargetsBuilder.filter(Predicates.not(Predicates.in(negativeTargets.getTargets())));
testTargetsBuilder.mergeError(negativeTargets.hasError());
} else {
ResolvedTargets<Target> positiveTargets = expandedSuitesValue.getTargets();
testTargetsBuilder.addAll(positiveTargets.getTargets());
testTargetsBuilder.mergeError(positiveTargets.hasError());
}
}
testTargetsBuilder.filter(testFilter);
return testTargetsBuilder.build();
}
Aggregations