private LicensesProvider initializeLicensesProvider() { if (!ruleContext.getConfiguration().checkLicenses()) { return LicensesProviderImpl.EMPTY; } NestedSetBuilder<TargetLicense> builder = NestedSetBuilder.linkOrder(); BuildConfiguration configuration = ruleContext.getConfiguration(); Rule rule = ruleContext.getRule(); License toolOutputLicense = rule.getToolOutputLicense(ruleContext.attributes()); if (configuration.isHostConfiguration() && toolOutputLicense != null) { if (toolOutputLicense != License.NO_LICENSE) { builder.add(new TargetLicense(rule.getLabel(), toolOutputLicense)); } } else { if (rule.getLicense() != License.NO_LICENSE) { builder.add(new TargetLicense(rule.getLabel(), rule.getLicense())); } for (TransitiveInfoCollection dep : ruleContext.getConfiguredTargetMap().values()) { LicensesProvider provider = dep.getProvider(LicensesProvider.class); if (provider != null) { builder.addTransitive(provider.getTransitiveLicenses()); } } } return new LicensesProviderImpl(builder.build()); }
private void visitRule( Rule rule, AspectDefinition aspect, AspectParameters aspectParameters, ListMultimap<Attribute, LabelAndConfiguration> labelMap, ListMultimap<Attribute, Dependency> outgoingEdges) { Preconditions.checkNotNull(labelMap); for (Map.Entry<Attribute, Collection<LabelAndConfiguration>> entry : labelMap.asMap().entrySet()) { Attribute attribute = entry.getKey(); for (LabelAndConfiguration dep : entry.getValue()) { Label label = dep.getLabel(); BuildConfiguration config = dep.getConfiguration(); Target toTarget; try { toTarget = getTarget(label); } catch (NoSuchThingException e) { throw new IllegalStateException( "not found: " + label + " from " + rule + " in " + attribute.getName()); } if (toTarget == null) { continue; } BuildConfiguration.TransitionApplier transitionApplier = config.getTransitionApplier(); if (config.useDynamicConfigurations() && config.isHostConfiguration() && !BuildConfiguration.usesNullConfiguration(toTarget)) { // This condition is needed because resolveLateBoundAttributes may switch config to // the host configuration, which is the only case DependencyResolver applies a // configuration transition outside of this method. We need to reflect that // transition in the results of this method, but config.evaluateTransition is hard-set // to return a NONE transition when the input is a host config. Since the outside // caller originally passed the *original* value of config (before the possible // switch), it can mistakenly interpret the result as a NONE transition from the // original value of config. This condition fixes that. Another fix would be to have // config.evaluateTransition return a HOST transition when the input config is a host, // but since this blemish is specific to DependencyResolver it seems best to keep the // fix here. // TODO(bazel-team): eliminate this special case by passing transitionApplier to // resolveLateBoundAttributes, so that method uses the same interface for transitions. transitionApplier.applyTransition(Attribute.ConfigurationTransition.HOST); } else { config.evaluateTransition(rule, attribute, toTarget, transitionApplier); } for (Dependency dependency : transitionApplier.getDependencies( label, requiredAspects(aspect, aspectParameters, attribute, toTarget, rule))) { outgoingEdges.put(entry.getKey(), dependency); } } } }
/** * Scans {@code action_listeners} associated with this build to see if any {@code extra_actions} * should be added to this configured target. If any action_listeners are present, a partial visit * of the artifact/action graph is performed (for as long as actions found are owned by this * {@link ConfiguredTarget}). Any actions that match the {@code action_listener} get an {@code * extra_action} associated. The output artifacts of the extra_action are reported to the {@link * AnalysisEnvironment} for bookkeeping. */ private ExtraActionArtifactsProvider initializeExtraActions() { BuildConfiguration configuration = ruleContext.getConfiguration(); if (configuration.isHostConfiguration()) { return ExtraActionArtifactsProvider.EMPTY; } ImmutableList<Artifact> extraActionArtifacts = ImmutableList.of(); NestedSetBuilder<ExtraArtifactSet> builder = NestedSetBuilder.stableOrder(); List<Label> actionListenerLabels = configuration.getActionListeners(); if (!actionListenerLabels.isEmpty() && ruleContext.getRule().getAttributeDefinition(":action_listener") != null) { ExtraActionsVisitor visitor = new ExtraActionsVisitor(ruleContext, computeMnemonicsToExtraActionMap()); // The action list is modified within the body of the loop by the addExtraAction() call, // thus the copy for (Action action : ImmutableList.copyOf(ruleContext.getAnalysisEnvironment().getRegisteredActions())) { if (!actionsWithoutExtraAction.contains(action)) { visitor.addExtraAction(action); } } extraActionArtifacts = visitor.getAndResetExtraArtifacts(); if (!extraActionArtifacts.isEmpty()) { builder.add(ExtraArtifactSet.of(ruleContext.getLabel(), extraActionArtifacts)); } } // Add extra action artifacts from dependencies for (TransitiveInfoCollection dep : ruleContext.getConfiguredTargetMap().values()) { ExtraActionArtifactsProvider provider = dep.getProvider(ExtraActionArtifactsProvider.class); if (provider != null) { builder.addTransitive(provider.getTransitiveExtraActionArtifacts()); } } if (mandatoryStampFiles != null && !mandatoryStampFiles.isEmpty()) { builder.add(ExtraArtifactSet.of(ruleContext.getLabel(), mandatoryStampFiles)); } if (extraActionArtifacts.isEmpty() && builder.isEmpty()) { return ExtraActionArtifactsProvider.EMPTY; } return new ExtraActionArtifactsProvider(extraActionArtifacts, builder.build()); }
static BuildConfiguration setupTransitions( BuildConfiguration targetConfiguration, BuildConfiguration dataConfiguration, BuildConfiguration hostConfiguration, ListMultimap<SplitTransition<?>, BuildConfiguration> splitTransitionsTable) { Set<BuildConfiguration> allConfigurations = new LinkedHashSet<>(); allConfigurations.add(targetConfiguration); allConfigurations.add(dataConfiguration); allConfigurations.add(hostConfiguration); allConfigurations.addAll(splitTransitionsTable.values()); Table<BuildConfiguration, Transition, ConfigurationHolder> transitionBuilder = HashBasedTable.create(); for (BuildConfiguration from : allConfigurations) { for (ConfigurationTransition transition : ConfigurationTransition.values()) { BuildConfiguration to; if (transition == ConfigurationTransition.HOST) { to = hostConfiguration; } else if (transition == ConfigurationTransition.DATA && from == targetConfiguration) { to = dataConfiguration; } else { to = from; } transitionBuilder.put(from, transition, new ConfigurationHolder(to)); } } // TODO(bazel-team): This makes LIPO totally not work. Just a band-aid until we get around to // implementing a way for the C++ rules to contribute this transition to the configuration // collection. for (BuildConfiguration config : allConfigurations) { transitionBuilder.put(config, CppTransition.LIPO_COLLECTOR, new ConfigurationHolder(config)); transitionBuilder.put( config, CppTransition.TARGET_CONFIG_FOR_LIPO, new ConfigurationHolder(config.isHostConfiguration() ? null : config)); } for (BuildConfiguration config : allConfigurations) { Transitions outgoingTransitions = new BazelTransitions( config, transitionBuilder.row(config), // Split transitions must not have their own split transitions because then they // would be applied twice due to a quirk in DependencyResolver. See the comment in // DependencyResolver.resolveLateBoundAttributes(). splitTransitionsTable.values().contains(config) ? ImmutableListMultimap.<SplitTransition<?>, BuildConfiguration>of() : splitTransitionsTable); // We allow host configurations to be shared between target configurations. In that case, the // transitions may already be set. // TODO(bazel-team): Check that the transitions are identical, or even better, change the // code to set the host configuration transitions before we even create the target // configuration. if (config.isHostConfiguration() && config.getTransitions() != null) { continue; } config.setConfigurationTransitions(outgoingTransitions); } return targetConfiguration; }