Search in sources :

Example 31 with TransitiveInfoCollection

use of com.google.devtools.build.lib.analysis.TransitiveInfoCollection in project bazel by bazelbuild.

the class ConstraintSemantics method checkConstraints.

/**
   * Performs constraint checking on the given rule's dependencies and reports any errors. This
   * includes:
   *
   * <ul>
   *   <li>Static environment checking: if this rule supports environment E, all deps outside
   *     selects must also support E
   *   <li>Refined environment computation: this rule's refined environments are its static
   *     environments intersected with the refined environments of all dependencies (including
   *     chosen deps in selects)
   *   <li>Refined environment checking: no environment groups can be "emptied" due to refinement
   * </ul>
   *
   * @param ruleContext the rule to analyze
   * @param staticEnvironments the rule's supported environments, as defined by the return
   *     value of {@link #getSupportedEnvironments}. In particular, for any environment group that's
   *     not in this collection, the rule is assumed to support the defaults for that group.
   * @param refinedEnvironments a builder for populating this rule's refined environments
   * @param removedEnvironmentCulprits a builder for populating the core dependencies that trigger
   *     pruning away environments through refinement. If multiple dependencies qualify (e.g.
   *     two direct deps under the current rule), one is arbitrarily chosen.
   */
public static void checkConstraints(RuleContext ruleContext, EnvironmentCollection staticEnvironments, EnvironmentCollection.Builder refinedEnvironments, Map<Label, Target> removedEnvironmentCulprits) {
    Set<EnvironmentWithGroup> refinedEnvironmentsSoFar = new LinkedHashSet<>();
    // Start with the full set of static environments:
    refinedEnvironmentsSoFar.addAll(staticEnvironments.getGroupedEnvironments());
    Set<EnvironmentGroup> groupsWithEnvironmentsRemoved = new LinkedHashSet<>();
    // Maps the label results of getUnsupportedEnvironments() to EnvironmentWithGroups. We can't
    // have that method just return EnvironmentWithGroups because it also collects group defaults,
    // which we only have labels for.
    Map<Label, EnvironmentWithGroup> labelsToEnvironments = new HashMap<>();
    for (EnvironmentWithGroup envWithGroup : staticEnvironments.getGroupedEnvironments()) {
        labelsToEnvironments.put(envWithGroup.environment(), envWithGroup);
    }
    DepsToCheck depsToCheck = getConstraintCheckedDependencies(ruleContext);
    for (TransitiveInfoCollection dep : depsToCheck.allDeps()) {
        SupportedEnvironmentsProvider depEnvironments = dep.getProvider(SupportedEnvironmentsProvider.class);
        if (!depsToCheck.isSelectOnly(dep)) {
            // TODO(bazel-team): support static constraint checking for selects. A selectable constraint
            // is valid if the union of all deps in the select includes all of this rule's static
            // environments. Determining that requires following the select paths that don't get chosen,
            // which means we won't have ConfiguredTargets for those deps and need to find another
            // way to get their environments.
            Collection<Label> unsupportedEnvironments = getUnsupportedEnvironments(depEnvironments.getStaticEnvironments(), staticEnvironments);
            if (!unsupportedEnvironments.isEmpty()) {
                ruleContext.ruleError("dependency " + dep.getLabel() + " doesn't support expected environment" + (unsupportedEnvironments.size() == 1 ? "" : "s") + ": " + Joiner.on(", ").join(unsupportedEnvironments));
            }
        }
        // Refine this rule's environments by intersecting with the dep's refined environments:
        for (Label refinedEnvironmentToPrune : getUnsupportedEnvironments(depEnvironments.getRefinedEnvironments(), staticEnvironments)) {
            EnvironmentWithGroup envToPrune = labelsToEnvironments.get(refinedEnvironmentToPrune);
            if (envToPrune == null) {
                // set before trying to remove specific items.
                for (EnvironmentWithGroup defaultEnv : getDefaults(refinedEnvironmentToPrune, depEnvironments.getRefinedEnvironments())) {
                    refinedEnvironmentsSoFar.add(defaultEnv);
                    labelsToEnvironments.put(defaultEnv.environment(), defaultEnv);
                }
                envToPrune = Verify.verifyNotNull(labelsToEnvironments.get(refinedEnvironmentToPrune));
            }
            refinedEnvironmentsSoFar.remove(envToPrune);
            groupsWithEnvironmentsRemoved.add(envToPrune.group());
            removedEnvironmentCulprits.put(envToPrune.environment(), findOriginalRefiner(ruleContext, depEnvironments, envToPrune));
        }
    }
    checkRefinedEnvironmentConstraints(ruleContext, groupsWithEnvironmentsRemoved, refinedEnvironmentsSoFar, refinedEnvironments, removedEnvironmentCulprits);
}
Also used : LinkedHashSet(java.util.LinkedHashSet) EnvironmentGroup(com.google.devtools.build.lib.packages.EnvironmentGroup) EnvironmentWithGroup(com.google.devtools.build.lib.analysis.constraints.EnvironmentCollection.EnvironmentWithGroup) HashMap(java.util.HashMap) Label(com.google.devtools.build.lib.cmdline.Label) TransitiveInfoCollection(com.google.devtools.build.lib.analysis.TransitiveInfoCollection)

Example 32 with TransitiveInfoCollection

use of com.google.devtools.build.lib.analysis.TransitiveInfoCollection in project bazel by bazelbuild.

the class BazelJavaSemantics method addRunfilesForBinary.

@Override
public void addRunfilesForBinary(RuleContext ruleContext, Artifact launcher, Runfiles.Builder runfilesBuilder) {
    TransitiveInfoCollection testSupport = getTestSupport(ruleContext);
    if (testSupport != null) {
        runfilesBuilder.addTarget(testSupport, JavaRunfilesProvider.TO_RUNFILES);
        runfilesBuilder.addTarget(testSupport, RunfilesProvider.DEFAULT_RUNFILES);
    }
}
Also used : TransitiveInfoCollection(com.google.devtools.build.lib.analysis.TransitiveInfoCollection)

Example 33 with TransitiveInfoCollection

use of com.google.devtools.build.lib.analysis.TransitiveInfoCollection in project bazel by bazelbuild.

the class ConstraintSemantics method getConstraintCheckedDependencies.

/**
   * Returns all dependencies that should be constraint-checked against the current rule,
   * including both "uncoditional" deps (outside selects) and deps that only appear in selects.
   */
private static DepsToCheck getConstraintCheckedDependencies(RuleContext ruleContext) {
    Set<TransitiveInfoCollection> depsToCheck = new LinkedHashSet<>();
    Set<TransitiveInfoCollection> selectOnlyDeps = new LinkedHashSet<>();
    Set<TransitiveInfoCollection> depsOutsideSelects = new LinkedHashSet<>();
    AttributeMap attributes = ruleContext.attributes();
    for (String attr : attributes.getAttributeNames()) {
        Attribute attrDef = attributes.getAttributeDefinition(attr);
        if (attrDef.getType().getLabelClass() != LabelClass.DEPENDENCY || attrDef.skipConstraintsOverride()) {
            continue;
        }
        if (!attrDef.checkConstraintsOverride()) {
            // determine exactly which rules need to be constraint-annotated for depot migrations.
            if (!DependencyFilter.NO_IMPLICIT_DEPS.apply(ruleContext.getRule(), attrDef) || // because --nodistinct_host_configuration subverts that call.
            attrDef.getConfigurationTransition() == Attribute.ConfigurationTransition.HOST) {
                continue;
            }
        }
        Set<Label> selectOnlyDepsForThisAttribute = getDepsOnlyInSelects(ruleContext, attr, attributes.getAttributeType(attr));
        for (TransitiveInfoCollection dep : ruleContext.getPrerequisites(attr, RuleConfiguredTarget.Mode.DONT_CHECK)) {
            // Output files inherit the environment spec of their generating rule.
            if (dep instanceof OutputFileConfiguredTarget) {
                // Note this reassignment means constraint violation errors reference the generating
                // rule, not the file. This makes the source of the environmental mismatch more clear.
                dep = ((OutputFileConfiguredTarget) dep).getGeneratingRule();
            }
            // checking, but for now just pass them by.
            if (dep.getProvider(SupportedEnvironmentsProvider.class) != null) {
                depsToCheck.add(dep);
                if (!selectOnlyDepsForThisAttribute.contains(dep.getLabel())) {
                    depsOutsideSelects.add(dep);
                }
            }
        }
    }
    for (TransitiveInfoCollection dep : depsToCheck) {
        if (!depsOutsideSelects.contains(dep)) {
            selectOnlyDeps.add(dep);
        }
    }
    return new DepsToCheck(depsToCheck, selectOnlyDeps);
}
Also used : LinkedHashSet(java.util.LinkedHashSet) AttributeMap(com.google.devtools.build.lib.packages.AttributeMap) Attribute(com.google.devtools.build.lib.packages.Attribute) Label(com.google.devtools.build.lib.cmdline.Label) TransitiveInfoCollection(com.google.devtools.build.lib.analysis.TransitiveInfoCollection) OutputFileConfiguredTarget(com.google.devtools.build.lib.analysis.OutputFileConfiguredTarget)

Example 34 with TransitiveInfoCollection

use of com.google.devtools.build.lib.analysis.TransitiveInfoCollection in project bazel by bazelbuild.

the class AndroidStudioInfoAspect method processDependencies.

private DependenciesResult processDependencies(ConfiguredTarget base, RuleContext ruleContext, AndroidStudioInfoFilesProvider.Builder providerBuilder) {
    // Calculate direct dependencies
    ImmutableList.Builder<TransitiveInfoCollection> directDepsBuilder = ImmutableList.builder();
    for (PrerequisiteAttr prerequisiteAttr : prerequisiteAttrs) {
        if (ruleContext.attributes().has(prerequisiteAttr.name, prerequisiteAttr.type)) {
            Mode mode = ruleContext.getAttributeMode(prerequisiteAttr.name);
            if (mode == Mode.TARGET || mode == Mode.SPLIT) {
                directDepsBuilder.addAll(ruleContext.getPrerequisites(prerequisiteAttr.name, Mode.TARGET));
            }
        }
    }
    List<TransitiveInfoCollection> directDeps = directDepsBuilder.build();
    // Add exports from direct dependencies
    NestedSetBuilder<Label> dependenciesBuilder = NestedSetBuilder.stableOrder();
    for (AndroidStudioInfoFilesProvider depProvider : AnalysisUtils.getProviders(directDeps, AndroidStudioInfoFilesProvider.class)) {
        dependenciesBuilder.addTransitive(depProvider.getExportedDeps());
    }
    for (TransitiveInfoCollection dep : directDeps) {
        dependenciesBuilder.add(dep.getLabel());
    }
    NestedSet<Label> dependencies = dependenciesBuilder.build();
    // Propagate my own exports
    JavaExportsProvider javaExportsProvider = base.getProvider(JavaExportsProvider.class);
    if (javaExportsProvider != null) {
        providerBuilder.exportedDepsBuilder().addTransitive(javaExportsProvider.getTransitiveExports());
    }
    // android_library without sources exports all its deps
    if (ruleContext.getRule().getRuleClass().equals("android_library")) {
        JavaSourceInfoProvider sourceInfoProvider = base.getProvider(JavaSourceInfoProvider.class);
        boolean hasSources = sourceInfoProvider != null && !sourceInfoProvider.getSourceFiles().isEmpty();
        if (!hasSources) {
            for (TransitiveInfoCollection dep : directDeps) {
                providerBuilder.exportedDepsBuilder().add(dep.getLabel());
            }
        }
    }
    // runtime_deps
    List<? extends TransitiveInfoCollection> runtimeDeps = ImmutableList.of();
    NestedSetBuilder<Label> runtimeDepsBuilder = NestedSetBuilder.stableOrder();
    if (ruleContext.attributes().has("runtime_deps", BuildType.LABEL_LIST)) {
        runtimeDeps = ruleContext.getPrerequisites("runtime_deps", Mode.TARGET);
        for (TransitiveInfoCollection dep : runtimeDeps) {
            runtimeDepsBuilder.add(dep.getLabel());
        }
    }
    // resources
    @Nullable TransitiveInfoCollection resources = ruleContext.attributes().has("resources", BuildType.LABEL) ? ruleContext.getPrerequisite("resources", Mode.TARGET) : null;
    // Propagate providers from all prerequisites (deps + runtime_deps)
    ImmutableList.Builder<TransitiveInfoCollection> prerequisitesBuilder = ImmutableList.builder();
    prerequisitesBuilder.addAll(directDeps);
    prerequisitesBuilder.addAll(runtimeDeps);
    if (resources != null) {
        prerequisitesBuilder.add(resources);
    }
    List<TransitiveInfoCollection> prerequisites = prerequisitesBuilder.build();
    for (AndroidStudioInfoFilesProvider depProvider : AnalysisUtils.getProviders(prerequisites, AndroidStudioInfoFilesProvider.class)) {
        providerBuilder.ideInfoFilesBuilder().addTransitive(depProvider.getIdeInfoFiles());
        providerBuilder.ideInfoTextFilesBuilder().addTransitive(depProvider.getIdeInfoTextFiles());
        providerBuilder.ideResolveFilesBuilder().addTransitive(depProvider.getIdeResolveFiles());
    }
    return new DependenciesResult(dependencies, runtimeDepsBuilder.build(), resources != null ? resources.getLabel() : null);
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) Mode(com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode) Label(com.google.devtools.build.lib.cmdline.Label) JavaExportsProvider(com.google.devtools.build.lib.rules.java.JavaExportsProvider) JavaSourceInfoProvider(com.google.devtools.build.lib.rules.java.JavaSourceInfoProvider) TransitiveInfoCollection(com.google.devtools.build.lib.analysis.TransitiveInfoCollection) Nullable(javax.annotation.Nullable)

Example 35 with TransitiveInfoCollection

use of com.google.devtools.build.lib.analysis.TransitiveInfoCollection in project bazel by bazelbuild.

the class SkylarkRuleContext method buildAttributesCollection.

private static SkylarkRuleAttributesCollection buildAttributesCollection(Collection<Attribute> attributes, RuleContext ruleContext, Function<Attribute, Object> attributeValueExtractor) {
    Builder<String, Object> attrBuilder = new Builder<>();
    Builder<String, Object> executableBuilder = new Builder<>();
    Builder<Artifact, FilesToRunProvider> executableRunfilesbuilder = new Builder<>();
    Builder<String, Object> fileBuilder = new Builder<>();
    Builder<String, Object> filesBuilder = new Builder<>();
    HashSet<Artifact> seenExecutables = new HashSet<>();
    for (Attribute a : attributes) {
        Type<?> type = a.getType();
        Object val = attributeValueExtractor.apply(a);
        // Skylark as a Map<String, Label>; this special case preserves that behavior temporarily.
        if (type.getLabelClass() != LabelClass.DEPENDENCY || type == BuildType.LABEL_DICT_UNARY) {
            attrBuilder.put(a.getPublicName(), val == null ? Runtime.NONE : // Attribute values should be type safe
            SkylarkType.convertToSkylark(val, null));
            continue;
        }
        String skyname = a.getPublicName();
        if (a.isExecutable()) {
            // In Skylark only label (not label list) type attributes can have the Executable flag.
            FilesToRunProvider provider = ruleContext.getExecutablePrerequisite(a.getName(), Mode.DONT_CHECK);
            if (provider != null && provider.getExecutable() != null) {
                Artifact executable = provider.getExecutable();
                executableBuilder.put(skyname, executable);
                if (!seenExecutables.contains(executable)) {
                    // todo(dslomov,laurentlb): In general, this is incorrect.
                    // We associate the first encountered FilesToRunProvider with
                    // the executable (this provider is later used to build the spawn).
                    // However ideally we should associate a provider with the attribute name,
                    // and pass the correct FilesToRunProvider to the spawn depending on
                    // what attribute is used to access the executable.
                    executableRunfilesbuilder.put(executable, provider);
                    seenExecutables.add(executable);
                }
            } else {
                executableBuilder.put(skyname, Runtime.NONE);
            }
        }
        if (a.isSingleArtifact()) {
            // In Skylark only label (not label list) type attributes can have the SingleArtifact flag.
            Artifact artifact = ruleContext.getPrerequisiteArtifact(a.getName(), Mode.DONT_CHECK);
            if (artifact != null) {
                fileBuilder.put(skyname, artifact);
            } else {
                fileBuilder.put(skyname, Runtime.NONE);
            }
        }
        filesBuilder.put(skyname, ruleContext.getPrerequisiteArtifacts(a.getName(), Mode.DONT_CHECK).list());
        if (type == BuildType.LABEL && !a.hasSplitConfigurationTransition()) {
            Object prereq = ruleContext.getPrerequisite(a.getName(), Mode.DONT_CHECK);
            if (prereq == null) {
                prereq = Runtime.NONE;
            }
            attrBuilder.put(skyname, prereq);
        } else if (type == BuildType.LABEL_LIST || (type == BuildType.LABEL && a.hasSplitConfigurationTransition())) {
            List<?> allPrereq = ruleContext.getPrerequisites(a.getName(), Mode.DONT_CHECK);
            attrBuilder.put(skyname, SkylarkList.createImmutable(allPrereq));
        } else if (type == BuildType.LABEL_KEYED_STRING_DICT) {
            ImmutableMap.Builder<TransitiveInfoCollection, String> builder = new ImmutableMap.Builder<>();
            Map<Label, String> original = BuildType.LABEL_KEYED_STRING_DICT.cast(val);
            List<? extends TransitiveInfoCollection> allPrereq = ruleContext.getPrerequisites(a.getName(), Mode.DONT_CHECK);
            for (TransitiveInfoCollection prereq : allPrereq) {
                builder.put(prereq, original.get(prereq.getLabel()));
            }
            attrBuilder.put(skyname, SkylarkType.convertToSkylark(builder.build(), null));
        } else if (type == BuildType.LABEL_DICT_UNARY) {
            Map<Label, TransitiveInfoCollection> prereqsByLabel = new LinkedHashMap<>();
            for (TransitiveInfoCollection target : ruleContext.getPrerequisites(a.getName(), Mode.DONT_CHECK)) {
                prereqsByLabel.put(target.getLabel(), target);
            }
            ImmutableMap.Builder<String, TransitiveInfoCollection> attrValue = new ImmutableMap.Builder<>();
            for (Map.Entry<String, Label> entry : ((Map<String, Label>) val).entrySet()) {
                attrValue.put(entry.getKey(), prereqsByLabel.get(entry.getValue()));
            }
            attrBuilder.put(skyname, attrValue.build());
        } else {
            throw new IllegalArgumentException("Can't transform attribute " + a.getName() + " of type " + type + " to a Skylark object");
        }
    }
    return new SkylarkRuleAttributesCollection(ruleContext.getRule().getRuleClass(), attrBuilder.build(), executableBuilder.build(), fileBuilder.build(), filesBuilder.build(), executableRunfilesbuilder.build());
}
Also used : FilesToRunProvider(com.google.devtools.build.lib.analysis.FilesToRunProvider) Attribute(com.google.devtools.build.lib.packages.Attribute) Builder(com.google.common.collect.ImmutableMap.Builder) Label(com.google.devtools.build.lib.cmdline.Label) Artifact(com.google.devtools.build.lib.actions.Artifact) ImmutableMap(com.google.common.collect.ImmutableMap) Entry(java.util.Map.Entry) SkylarkClassObject(com.google.devtools.build.lib.packages.SkylarkClassObject) List(java.util.List) SkylarkList(com.google.devtools.build.lib.syntax.SkylarkList) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) LinkedList(java.util.LinkedList) TransitiveInfoCollection(com.google.devtools.build.lib.analysis.TransitiveInfoCollection) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) HashSet(java.util.HashSet)

Aggregations

TransitiveInfoCollection (com.google.devtools.build.lib.analysis.TransitiveInfoCollection)54 Artifact (com.google.devtools.build.lib.actions.Artifact)27 RuleConfiguredTargetBuilder (com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder)14 FileProvider (com.google.devtools.build.lib.analysis.FileProvider)11 NestedSetBuilder (com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder)11 Label (com.google.devtools.build.lib.cmdline.Label)10 ImmutableList (com.google.common.collect.ImmutableList)8 ArrayList (java.util.ArrayList)8 Runfiles (com.google.devtools.build.lib.analysis.Runfiles)7 BuildConfiguration (com.google.devtools.build.lib.analysis.config.BuildConfiguration)5 Test (org.junit.Test)5 ImmutableMap (com.google.common.collect.ImmutableMap)4 FilesToRunProvider (com.google.devtools.build.lib.analysis.FilesToRunProvider)4 RunfilesProvider (com.google.devtools.build.lib.analysis.RunfilesProvider)4 SkylarkClassObject (com.google.devtools.build.lib.packages.SkylarkClassObject)4 Pair (com.google.devtools.build.lib.util.Pair)4 PathFragment (com.google.devtools.build.lib.vfs.PathFragment)4 Map (java.util.Map)4 CustomCommandLine (com.google.devtools.build.lib.analysis.actions.CustomCommandLine)3 CcLinkParamsProvider (com.google.devtools.build.lib.rules.cpp.CcLinkParamsProvider)3