/** * Returns the configurable attribute conditions necessary to evaluate the given configured * target, or null if not all dependencies have yet been SkyFrame-evaluated. */ @Nullable private Set<ConfigMatchingProvider> getConfigurableAttributeConditions( TargetAndConfiguration ctg, Environment env) { if (!(ctg.getTarget() instanceof Rule)) { return ImmutableSet.of(); } Rule rule = (Rule) ctg.getTarget(); RawAttributeMapper mapper = RawAttributeMapper.of(rule); Set<SkyKey> depKeys = new LinkedHashSet<>(); for (Attribute attribute : rule.getAttributes()) { for (Label label : mapper.getConfigurabilityKeys(attribute.getName(), attribute.getType())) { if (!BuildType.Selector.isReservedLabel(label)) { depKeys.add(ConfiguredTargetValue.key(label, ctg.getConfiguration())); } } } Map<SkyKey, SkyValue> cts = env.getValues(depKeys); if (env.valuesMissing()) { return null; } ImmutableSet.Builder<ConfigMatchingProvider> conditions = ImmutableSet.builder(); for (SkyValue ctValue : cts.values()) { ConfiguredTarget ct = ((ConfiguredTargetValue) ctValue).getConfiguredTarget(); conditions.add(Preconditions.checkNotNull(ct.getProvider(ConfigMatchingProvider.class))); } return conditions.build(); }
@Nullable @Override public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException, InterruptedException { ImmutableMap<Action, ConflictException> badActions = PrecomputedValue.BAD_ACTIONS.get(env); ConfiguredTargetValue ctValue = (ConfiguredTargetValue) env.getValue(ConfiguredTargetValue.key((ConfiguredTargetKey) skyKey.argument())); SkyframeDependencyResolver resolver = buildViewProvider.getSkyframeBuildView().createDependencyResolver(env); if (env.valuesMissing()) { return null; } for (Action action : ctValue.getActions()) { if (badActions.containsKey(action)) { throw new ActionConflictFunctionException(badActions.get(action)); } } ConfiguredTarget ct = ctValue.getConfiguredTarget(); TargetAndConfiguration ctgValue = new TargetAndConfiguration(ct.getTarget(), ct.getConfiguration()); Set<ConfigMatchingProvider> configConditions = getConfigurableAttributeConditions(ctgValue, env); if (configConditions == null) { return null; } ListMultimap<Attribute, Dependency> deps; try { BuildConfiguration hostConfiguration = buildViewProvider.getSkyframeBuildView().getHostConfiguration(ct.getConfiguration()); deps = resolver.dependentNodeMap( ctgValue, hostConfiguration, /*aspect=*/ null, configConditions); if (ct.getConfiguration() != null && ct.getConfiguration().useDynamicConfigurations()) { deps = ConfiguredTargetFunction.trimConfigurations( env, ctgValue, deps, hostConfiguration, ruleClassProvider); } } catch (EvalException e) { throw new PostConfiguredTargetFunctionException(e); } catch (ConfiguredTargetFunction.DependencyEvaluationException e) { throw new PostConfiguredTargetFunctionException(e); } env.getValues(Iterables.transform(deps.values(), TO_KEYS)); if (env.valuesMissing()) { return null; } return new PostConfiguredTargetValue(ct); }
/** * Requests Skyframe to compute the dependent values and returns them. * * <p>The keys must all be {@link SkyFunctions#RECURSIVE_FILESYSTEM_TRAVERSAL} keys. */ private static Collection<RecursiveFilesystemTraversalValue> traverseChildren( Environment env, Iterable<SkyKey> keys) throws MissingDepException { Map<SkyKey, SkyValue> values = env.getValues(keys); if (env.valuesMissing()) { throw new MissingDepException(); } return Collections2.transform( values.values(), new Function<SkyValue, RecursiveFilesystemTraversalValue>() { @Override public RecursiveFilesystemTraversalValue apply(SkyValue input) { return (RecursiveFilesystemTraversalValue) input; } }); }
SkyValue computeInternal( SkyKey skyKey, Environment env, @Nullable Set<SkyKey> visitedKeysForCycle) throws SkyFunctionException, InterruptedException { PackageIdentifier arg = (PackageIdentifier) skyKey.argument(); PathFragment file = arg.getPackageFragment(); ASTFileLookupValue astLookupValue = null; try { SkyKey astLookupKey = ASTFileLookupValue.key(arg); astLookupValue = (ASTFileLookupValue) env.getValueOrThrow( astLookupKey, ErrorReadingSkylarkExtensionException.class, InconsistentFilesystemException.class); } catch (ErrorReadingSkylarkExtensionException e) { throw new SkylarkImportLookupFunctionException( SkylarkImportFailedException.errorReadingFile(file, e.getMessage())); } catch (InconsistentFilesystemException e) { throw new SkylarkImportLookupFunctionException(e, Transience.PERSISTENT); } if (astLookupValue == null) { return null; } if (astLookupValue.getAST() == null) { // Skylark import files have to exist. throw new SkylarkImportLookupFunctionException(SkylarkImportFailedException.noFile(file)); } BuildFileAST ast = astLookupValue.getAST(); if (ast.containsErrors()) { throw new SkylarkImportLookupFunctionException( SkylarkImportFailedException.skylarkErrors(file)); } Label label = pathFragmentToLabel(arg.getRepository(), file, env); if (label == null) { Preconditions.checkState(env.valuesMissing(), "null label with no missing %s", file); return null; } Map<Location, PathFragment> astImports = ast.getImports(); Map<PathFragment, Extension> importMap = Maps.newHashMapWithExpectedSize(astImports.size()); ImmutableList.Builder<SkylarkFileDependency> fileDependencies = ImmutableList.builder(); Map<SkyKey, PathFragment> skylarkImports = Maps.newHashMapWithExpectedSize(astImports.size()); for (Map.Entry<Location, PathFragment> entry : ast.getImports().entrySet()) { try { skylarkImports.put( PackageFunction.getImportKey(entry, ruleClassProvider.getPreludePath(), file, arg), entry.getValue()); } catch (ASTLookupInputException e) { throw new SkylarkImportLookupFunctionException(e, Transience.PERSISTENT); } } Map<SkyKey, SkyValue> skylarkImportMap; boolean valuesMissing = false; if (visitedKeysForCycle == null) { // Not inlining. skylarkImportMap = env.getValues(skylarkImports.keySet()); valuesMissing = env.valuesMissing(); } else { // inlining calls to SkylarkImportLookupFunction. if (!visitedKeysForCycle.add(skyKey)) { ImmutableList<SkyKey> cycle = CycleUtils.splitIntoPathAndChain(Predicates.equalTo(skyKey), visitedKeysForCycle) .second; if (env.getValue(SkylarkImportUniqueCycleValue.key(cycle)) == null) { return null; } throw new SkylarkImportLookupFunctionException( new SkylarkImportFailedException("Skylark import cycle")); } skylarkImportMap = Maps.newHashMapWithExpectedSize(astImports.size()); for (SkyKey skylarkImport : skylarkImports.keySet()) { SkyValue skyValue = this.computeWithInlineCalls(skylarkImport, env, visitedKeysForCycle); if (skyValue == null) { Preconditions.checkState( env.valuesMissing(), "no skylark import value for %s", skylarkImport); // Don't give up on computing. This is against the Skyframe contract, but we don't want to // pay the price of serializing all these calls, since they are fundamentally independent. valuesMissing = true; } else { skylarkImportMap.put(skylarkImport, skyValue); } } // All imports traversed, this key can no longer be part of a cycle. visitedKeysForCycle.remove(skyKey); } if (valuesMissing) { // This means some imports are unavailable. return null; } for (Map.Entry<SkyKey, SkyValue> entry : skylarkImportMap.entrySet()) { SkylarkImportLookupValue importLookupValue = (SkylarkImportLookupValue) entry.getValue(); importMap.put( skylarkImports.get(entry.getKey()), 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, file, importMap, env); return new SkylarkImportLookupValue( extension, new SkylarkFileDependency(label, fileDependencies.build())); }
@Override public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException, InterruptedException { PackageIdentifier arg = (PackageIdentifier) skyKey.argument(); PathFragment file = arg.getPackageFragment(); ASTFileLookupValue astLookupValue = null; try { SkyKey astLookupKey = ASTFileLookupValue.key(arg); astLookupValue = (ASTFileLookupValue) env.getValueOrThrow( astLookupKey, ErrorReadingSkylarkExtensionException.class, InconsistentFilesystemException.class); } catch (ErrorReadingSkylarkExtensionException e) { throw new SkylarkImportLookupFunctionException( SkylarkImportFailedException.errorReadingFile(file, e.getMessage())); } catch (InconsistentFilesystemException e) { throw new SkylarkImportLookupFunctionException(e, Transience.PERSISTENT); } if (astLookupValue == null) { return null; } if (astLookupValue.getAST() == null) { // Skylark import files have to exist. throw new SkylarkImportLookupFunctionException(SkylarkImportFailedException.noFile(file)); } BuildFileAST ast = astLookupValue.getAST(); if (ast.containsErrors()) { throw new SkylarkImportLookupFunctionException( SkylarkImportFailedException.skylarkErrors(file)); } Map<Location, PathFragment> astImports = ast.getImports(); Map<PathFragment, Extension> importMap = Maps.newHashMapWithExpectedSize(astImports.size()); ImmutableList.Builder<SkylarkFileDependency> fileDependencies = ImmutableList.builder(); Map<SkyKey, PathFragment> skylarkImports = Maps.newHashMapWithExpectedSize(astImports.size()); for (Map.Entry<Location, PathFragment> entry : ast.getImports().entrySet()) { try { skylarkImports.put( PackageFunction.getImportKey(entry, ruleClassProvider.getPreludePath(), file, arg), entry.getValue()); } catch (ASTLookupInputException e) { throw new SkylarkImportLookupFunctionException(e, Transience.PERSISTENT); } } Map<SkyKey, SkyValue> skylarkImportMap = env.getValues(skylarkImports.keySet()); if (env.valuesMissing()) { // This means some imports are unavailable. return null; } for (Map.Entry<SkyKey, SkyValue> entry : skylarkImportMap.entrySet()) { SkylarkImportLookupValue importLookupValue = (SkylarkImportLookupValue) entry.getValue(); importMap.put( skylarkImports.get(entry.getKey()), importLookupValue.getEnvironmentExtension()); fileDependencies.add(importLookupValue.getDependency()); } Label label = pathFragmentToLabel(arg.getRepository(), file, env); if (label == null) { Preconditions.checkState(env.valuesMissing(), "label null but no missing for %s", file); return null; } // 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, file, importMap, env); return new SkylarkImportLookupValue( extension, new SkylarkFileDependency(label, fileDependencies.build())); }