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());
  }
  TestTargetExecutionSettings(
      RuleContext ruleContext,
      RunfilesSupport runfiles,
      Artifact executable,
      Artifact instrumentedFileManifest,
      int shards) {
    Preconditions.checkArgument(TargetUtils.isTestRule(ruleContext.getRule()));
    Preconditions.checkArgument(shards >= 0);
    BuildConfiguration config = ruleContext.getConfiguration();

    List<String> targetArgs = runfiles.getArgs();
    testArguments =
        targetArgs.isEmpty()
            ? config.getTestArguments()
            : ImmutableList.copyOf(Iterables.concat(targetArgs, config.getTestArguments()));

    totalShards = shards;
    runUnder = config.getRunUnder();
    runUnderExecutable = getRunUnderExecutable(ruleContext);

    this.testFilter = config.getTestFilter();
    this.executable = executable;
    this.runfilesManifest = runfiles.getRunfilesManifest();
    this.runfilesInputManifest = runfiles.getRunfilesInputManifest();
    this.instrumentedFileManifest = instrumentedFileManifest;
  }
Exemple #3
0
 /**
  * Returns the host configuration trimmed to the same fragments as the input configuration. If the
  * input is null, returns the top-level host configuration.
  *
  * <p>For static configurations, this unconditionally returns the (sole) top-level configuration.
  *
  * <p>This may only be called after {@link #setTopLevelHostConfiguration} has set the correct host
  * configuration at the top-level.
  */
 public BuildConfiguration getHostConfiguration(BuildConfiguration config) {
   if (config == null || !config.useDynamicConfigurations()) {
     return topLevelHostConfiguration;
   }
   // TODO(bazel-team): have the fragment classes be those required by the consuming target's
   // transitive closure. This isn't the same as the input configuration's fragment classes -
   // the latter may be a proper subset of the former.
   //
   // ConfigurationFactory.getConfiguration provides the reason why: if a declared required
   // fragment is evaluated and returns null, it never gets added to the configuration. So if we
   // use the configuration's fragments as the source of truth, that excludes required fragments
   // that never made it in.
   //
   // If we're just trimming an existing configuration, this is no big deal (if the original
   // configuration doesn't need the fragment, the trimmed one doesn't either). But this method
   // trims a host configuration to the same scope as a target configuration. Since their options
   // are different, the host instance may actually be able to produce the fragment. So it's
   // wrong and potentially dangerous to unilaterally exclude it.
   Set<Class<? extends BuildConfiguration.Fragment>> fragmentClasses = config.fragmentClasses();
   BuildConfiguration hostConfig = hostConfigurationCache.get(fragmentClasses);
   if (hostConfig != null) {
     return hostConfig;
   }
   BuildConfiguration trimmedConfig =
       topLevelHostConfiguration.clone(fragmentClasses, ruleClassProvider);
   hostConfigurationCache.put(fragmentClasses, trimmedConfig);
   return trimmedConfig;
 }
 @Nullable
 private static CppConfiguration getCppConfiguration(ConfiguredTarget base) {
   BuildConfiguration configuration = base.getConfiguration();
   if (configuration != null) {
     return configuration.getFragment(CppConfiguration.class);
   }
   return null;
 }
  private Artifact scopedArtifact(PathFragment scopeRelative, boolean inGenfiles) {
    Root root =
        inGenfiles
            ? buildConfiguration.getGenfilesDirectory(ruleContext.getRule().getRepository())
            : buildConfiguration.getBinDirectory(ruleContext.getRule().getRepository());

    // The path of this artifact will be RULE_PACKAGE/SCOPERELATIVE
    return ruleContext.getPackageRelativeArtifact(scopeRelative, root);
  }
  private static Artifact derivedArtifact(
      ConfiguredTarget base, RuleContext ruleContext, String suffix) {
    BuildConfiguration configuration = ruleContext.getConfiguration();
    assert configuration != null;
    Root genfilesDirectory = configuration.getGenfilesDirectory();

    PathFragment derivedFilePath = getOutputFilePath(base, ruleContext, suffix);

    return ruleContext
        .getAnalysisEnvironment()
        .getDerivedArtifact(derivedFilePath, genfilesDirectory);
  }
Exemple #7
0
  /**
   * Takes a set of configured targets, and checks if the distribution methods declared for the
   * targets are compatible with the constraints imposed by their prerequisites' licenses.
   *
   * @param configuredTargets the targets to check
   * @param keepGoing if false, and a licensing error is encountered, both generates an error
   *     message on the reporter, <em>and</em> throws an exception. If true, then just generates a
   *     message on the reporter.
   * @throws ViewCreationFailedException if the license checking failed (and not --keep_going)
   */
  private void validateLicensingForTargets(
      Iterable<ConfiguredTarget> configuredTargets, boolean keepGoing)
      throws ViewCreationFailedException {
    for (ConfiguredTarget configuredTarget : configuredTargets) {
      final Target target = configuredTarget.getTarget();

      if (TargetUtils.isTestRule(target)) {
        continue; // Tests are exempt from license checking
      }

      final Set<DistributionType> distribs = target.getDistributions();
      BuildConfiguration config = configuredTarget.getConfiguration();
      boolean staticallyLinked = (config != null) && config.performsStaticLink();
      staticallyLinked |=
          (config != null)
              && (target instanceof Rule)
              && ((Rule) target).getRuleClassObject().hasAttr("linkopts", Type.STRING_LIST)
              && ConfiguredAttributeMapper.of((RuleConfiguredTarget) configuredTarget)
                  .get("linkopts", Type.STRING_LIST)
                  .contains("-static");

      LicensesProvider provider = configuredTarget.getProvider(LicensesProvider.class);
      if (provider != null) {
        NestedSet<TargetLicense> licenses = provider.getTransitiveLicenses();
        for (TargetLicense targetLicense : licenses) {
          if (!targetLicense
              .getLicense()
              .checkCompatibility(
                  distribs, target, targetLicense.getLabel(), getReporter(), staticallyLinked)) {
            if (!keepGoing) {
              throw new ViewCreationFailedException("Build aborted due to licensing error");
            }
          }
        }
      } else if (configuredTarget.getTarget() instanceof InputFile) {
        // Input file targets do not provide licenses because they do not
        // depend on the rule where their license is taken from. This is usually
        // not a problem, because the transitive collection of licenses always
        // hits the rule they come from, except when the input file is a
        // top-level target. Thus, we need to handle that case specially here.
        //
        // See FileTarget#getLicense for more information about the handling of
        // license issues with File targets.
        License license = configuredTarget.getTarget().getLicense();
        if (!license.checkCompatibility(
            distribs, target, configuredTarget.getLabel(), getReporter(), staticallyLinked)) {
          if (!keepGoing) {
            throw new ViewCreationFailedException("Build aborted due to licensing error");
          }
        }
      }
    }
  }
Exemple #8
0
 /**
  * Returns the host configuration trimmed to the same fragments as the input configuration. If the
  * input is null, returns the top-level host configuration.
  *
  * <p>For static configurations, this unconditionally returns the (sole) top-level configuration.
  *
  * <p>This may only be called after {@link #setTopLevelHostConfiguration} has set the correct host
  * configuration at the top-level.
  */
 public BuildConfiguration getHostConfiguration(BuildConfiguration config) {
   if (config == null || !config.useDynamicConfigurations()) {
     return topLevelHostConfiguration;
   }
   Set<Class<? extends BuildConfiguration.Fragment>> fragmentClasses = config.fragmentClasses();
   BuildConfiguration hostConfig = hostConfigurationCache.get(fragmentClasses);
   if (hostConfig != null) {
     return hostConfig;
   }
   BuildConfiguration trimmedConfig =
       topLevelHostConfiguration.clone(fragmentClasses, ruleClassProvider);
   hostConfigurationCache.put(fragmentClasses, trimmedConfig);
   return trimmedConfig;
 }
 public CppCompileActionBuilder setDotdFile(PathFragment outputName, String extension) {
   if (CppFileTypes.mustProduceDotdFile(outputName.toString())) {
     if (configuration.getFragment(CppConfiguration.class).getInmemoryDotdFiles()) {
       // Just set the path, no artifact is constructed
       PathFragment file = FileSystemUtils.replaceExtension(outputName, extension);
       Root root = configuration.getBinDirectory();
       dotdFile = new DotdFile(root.getExecPath().getRelative(file));
     } else {
       dotdFile = new DotdFile(ruleContext.getRelatedArtifact(outputName, extension));
     }
   } else {
     dotdFile = null;
   }
   return this;
 }
Exemple #10
0
 /** Returns true iff code coverage is enabled for the given target. */
 private boolean isCodeCoverageEnabled() {
   if (configuration.isCodeCoverageEnabled()) {
     // If rule is matched by the instrumentation filter, enable instrumentation
     if (InstrumentedFilesCollector.shouldIncludeLocalSources(ruleContext)) {
       return true;
     }
     // At this point the rule itself is not matched by the instrumentation filter. However, we
     // might still want to instrument C++ rules if one of the targets listed in "deps" is
     // instrumented and, therefore, can supply header files that we would want to collect code
     // coverage for. For example, think about cc_test rule that tests functionality defined in a
     // header file that is supplied by the cc_library.
     //
     // Note that we only check direct prerequisites and not the transitive closure. This is done
     // for two reasons:
     // a) It is a good practice to declare libraries which you directly rely on. Including headers
     //    from a library hidden deep inside the transitive closure makes build dependencies less
     //    readable and can lead to unexpected breakage.
     // b) Traversing the transitive closure for each C++ compile action would require more complex
     //    implementation (with caching results of this method) to avoid O(N^2) slowdown.
     if (ruleContext.getRule().isAttrDefined("deps", BuildType.LABEL_LIST)) {
       for (TransitiveInfoCollection dep : ruleContext.getPrerequisites("deps", Mode.TARGET)) {
         if (dep.getProvider(CppCompilationContext.class) != null
             && InstrumentedFilesCollector.shouldIncludeLocalSources(configuration, dep)) {
           return true;
         }
       }
     }
   }
   return false;
 }
Exemple #11
0
 /**
  * Sets the host configuration consisting of all fragments that will be used by the top level
  * targets' transitive closures.
  *
  * <p>This is used to power {@link #getHostConfiguration} during analysis, which computes
  * fragment-trimmed host configurations from the top-level one.
  */
 private void setTopLevelHostConfiguration(BuildConfiguration topLevelHostConfiguration) {
   if (topLevelHostConfiguration.equals(this.topLevelHostConfiguration)) {
     return;
   }
   hostConfigurationCache.clear();
   this.topLevelHostConfiguration = topLevelHostConfiguration;
 }
Exemple #12
0
 @Override
 public Label getDefault(Rule rule, BuildConfiguration configuration) {
   // If --proguard_top is not specified, null is returned. AndroidSdk will take care of
   // using
   // android_sdk.proguard then.
   return configuration.getFragment(AndroidConfiguration.class).getProguardLabel();
 }
  /**
   * 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());
  }
 /**
  * Returns a derived artifact in the bin directory obtained by appending some extension to the
  * main label name; the result artifact is placed in a unique "entitlements" directory. For
  * example, if this artifact is for a target Foo with extension ".extension", the result artifact
  * will be located at {target_base_path}/entitlements/Foo.extension.
  */
 public Artifact appendExtensionForEntitlementArtifact(String extension) {
   PathFragment entitlementsDirectory = ruleContext.getUniqueDirectory("entitlements");
   Artifact artifact =
       ruleContext.getDerivedArtifact(
           entitlementsDirectory.replaceName(
               addOutputPrefix(entitlementsDirectory.getBaseName(), extension)),
           buildConfiguration.getBinDirectory(ruleContext.getRule().getRepository()));
   return artifact;
 }
Exemple #15
0
  /**
   * Checks that if this is an environment-restricted build, all top-level targets support the
   * expected environments.
   *
   * @param topLevelTargets the build's top-level targets
   * @throws ViewCreationFailedException if constraint enforcement is on, the build declares
   *     environment-restricted top level configurations, and any top-level target doesn't support
   *     the expected environments
   */
  private void checkTargetEnvironmentRestrictions(
      Iterable<ConfiguredTarget> topLevelTargets, PackageManager packageManager)
      throws ViewCreationFailedException {
    for (ConfiguredTarget topLevelTarget : topLevelTargets) {
      BuildConfiguration config = topLevelTarget.getConfiguration();
      if (config == null) {
        // TODO(bazel-team): support file targets (they should apply package-default constraints).
        continue;
      } else if (!config.enforceConstraints() || config.getTargetEnvironments().isEmpty()) {
        continue;
      }

      // Parse and collect this configuration's environments.
      EnvironmentCollection.Builder builder = new EnvironmentCollection.Builder();
      for (Label envLabel : config.getTargetEnvironments()) {
        try {
          Target env = packageManager.getLoadedTarget(envLabel);
          builder.put(ConstraintSemantics.getEnvironmentGroup(env), envLabel);
        } catch (NoSuchPackageException
            | NoSuchTargetException
            | ConstraintSemantics.EnvironmentLookupException e) {
          throw new ViewCreationFailedException("invalid target environment", e);
        }
      }
      EnvironmentCollection expectedEnvironments = builder.build();

      // Now check the target against those environments.
      SupportedEnvironmentsProvider provider =
          Verify.verifyNotNull(topLevelTarget.getProvider(SupportedEnvironmentsProvider.class));
      Collection<Label> missingEnvironments =
          ConstraintSemantics.getUnsupportedEnvironments(
              provider.getEnvironments(), expectedEnvironments);
      if (!missingEnvironments.isEmpty()) {
        throw new ViewCreationFailedException(
            String.format(
                "This is a restricted-environment build. %s does not support"
                    + " required environment%s %s",
                topLevelTarget.getLabel(),
                missingEnvironments.size() == 1 ? "" : "s",
                Joiner.on(", ").join(missingEnvironments)));
      }
    }
  }
 /**
  * Adds the given targets as dependencies - this can include explicit dependencies on other rules
  * (like from a "deps" attribute) and also implicit dependencies on runtime libraries.
  */
 public CcLibraryHelper addDeps(Iterable<? extends TransitiveInfoCollection> deps) {
   for (TransitiveInfoCollection dep : deps) {
     Preconditions.checkArgument(
         dep.getConfiguration() == null
             || configuration.equalsOrIsSupersetOf(dep.getConfiguration()),
         "dep " + dep.getLabel() + " has a different config than " + ruleContext.getLabel());
     this.deps.add(dep);
   }
   return this;
 }
Exemple #17
0
 @Override
 public List<Label> resolve(
     Rule rule, AttributeMap attributes, BuildConfiguration configuration) {
   // action_listeners are special rules; they tell the build system to add extra_actions to
   // existing rules. As such they need an edge to every ConfiguredTarget with the limitation
   // that they only run on the target configuration and should not operate on
   // action_listeners
   // and extra_actions themselves (to avoid cycles).
   return configuration.getActionListeners();
 }
Exemple #18
0
 @Override
 public boolean equals(Object other) {
   if (!(other instanceof Dependency)) {
     return false;
   }
   Dependency otherDep = (Dependency) other;
   return label.equals(otherDep.label)
       && (configuration == otherDep.configuration
           || (configuration != null && configuration.equals(otherDep.configuration)))
       && aspects.equals(otherDep.aspects);
 }
 public void assertConfigurationsHaveUniqueOutputDirectories(
     BuildConfigurationCollection configCollection) throws Exception {
   Collection<BuildConfiguration> allConfigs = configCollection.getAllConfigurations();
   Map<Root, BuildConfiguration> outputPaths = new HashMap<>();
   for (BuildConfiguration config : allConfigs) {
     if (config.isActionsEnabled()) {
       BuildConfiguration otherConfig = outputPaths.get(config.getOutputDirectory());
       if (otherConfig != null) {
         throw new IllegalStateException(
             "The output path '"
                 + config.getOutputDirectory()
                 + "' is the same for configurations '"
                 + config
                 + "' and '"
                 + otherConfig
                 + "'");
       } else {
         outputPaths.put(config.getOutputDirectory(), config);
       }
     }
   }
 }
Exemple #20
0
 /** Returns null if any build-info values are not ready. */
 @Nullable
 CachingAnalysisEnvironment createAnalysisEnvironment(
     ArtifactOwner owner,
     boolean isSystemEnv,
     EventHandler eventHandler,
     Environment env,
     BuildConfiguration config) {
   if (config != null && !getWorkspaceStatusValues(env, config)) {
     return null;
   }
   boolean extendedSanityChecks = config != null && config.extendedSanityChecks();
   boolean allowRegisteringActions = config == null || config.isActionsEnabled();
   return new CachingAnalysisEnvironment(
       artifactFactory,
       owner,
       isSystemEnv,
       extendedSanityChecks,
       eventHandler,
       env,
       allowRegisteringActions,
       binTools);
 }
 /**
  * Checks that the implicit labels are reachable from the loaded labels. The loaded labels are
  * those returned from {@link BuildOptions#getAllLabels()}, and the implicit ones are those that
  * need to be available for late-bound attributes.
  */
 private void sanityCheckImplicitLabels(
     Collection<Label> reachableLabels, BuildConfiguration config)
     throws InvalidConfigurationException {
   for (Map.Entry<String, Label> entry : config.getImplicitLabels().entries()) {
     if (!reachableLabels.contains(entry.getValue())) {
       throw new InvalidConfigurationException(
           "The required "
               + entry.getKey()
               + " target is not transitively reachable from a command-line option: '"
               + entry.getValue()
               + "'");
     }
   }
 }
  /**
   * Returns a raw link command for the given link invocation, including both command and arguments
   * (argv). After any further usage-specific processing, this can be passed to {@link
   * #finalizeWithLinkstampCommands} to give the final command line.
   *
   * @return raw link command line.
   */
  public List<String> getRawLinkArgv() {
    List<String> argv = new ArrayList<>();

    switch (linkTargetType) {
      case EXECUTABLE:
        argv.add(cppConfiguration.getCppExecutable().getPathString());
        argv.addAll(featureConfiguration.getCommandLine(actionName, variables));
        argv.addAll(noWholeArchiveFlags);
        addToolchainFlags(argv);
        break;

      case DYNAMIC_LIBRARY:
        if (interfaceOutput != null) {
          argv.add(configuration.getShExecutable().getPathString());
          argv.add("-c");
          argv.add(
              "build_iface_so=\"$0\"; impl=\"$1\"; iface=\"$2\"; cmd=\"$3\"; shift 3; "
                  + "\"$cmd\" \"$@\" && \"$build_iface_so\" \"$impl\" \"$iface\"");
          argv.add(interfaceSoBuilder.getExecPathString());
          argv.add(output.getExecPathString());
          argv.add(interfaceOutput.getExecPathString());
        }
        argv.add(cppConfiguration.getCppExecutable().getPathString());
        argv.addAll(featureConfiguration.getCommandLine(actionName, variables));
        argv.addAll(noWholeArchiveFlags);
        addToolchainFlags(argv);
        break;

      case STATIC_LIBRARY:
      case PIC_STATIC_LIBRARY:
      case ALWAYS_LINK_STATIC_LIBRARY:
      case ALWAYS_LINK_PIC_STATIC_LIBRARY:
        // The static library link command follows this template:
        // ar <cmd> <output_archive> <input_files...>
        argv.add(cppConfiguration.getArExecutable().getPathString());
        argv.addAll(
            cppConfiguration.getArFlags(cppConfiguration.archiveType() == Link.ArchiveType.THIN));
        argv.add(output.getExecPathString());
        argv.addAll(featureConfiguration.getCommandLine(actionName, variables));
        argv.addAll(noWholeArchiveFlags);
        break;

      default:
        throw new IllegalArgumentException();
    }

    return argv;
  }
Exemple #23
0
  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);
        }
      }
    }
  }
 /**
  * Creates a builder for an owner that is not required to be rule.
  *
  * <p>If errors are found when creating the {@code CppCompileAction}, builders constructed this
  * way will throw a runtime exception.
  */
 @VisibleForTesting
 public CppCompileActionBuilder(
     ActionOwner owner,
     AnalysisEnvironment analysisEnvironment,
     Artifact sourceFile,
     Label sourceLabel,
     BuildConfiguration configuration) {
   this.owner = owner;
   this.actionContext = CppCompileActionContext.class;
   this.cppConfiguration = configuration.getFragment(CppConfiguration.class);
   this.analysisEnvironment = analysisEnvironment;
   this.sourceFile = sourceFile;
   this.sourceLabel = sourceLabel;
   this.configuration = configuration;
   this.mandatoryInputsBuilder = NestedSetBuilder.stableOrder();
   this.pluginInputsBuilder = NestedSetBuilder.stableOrder();
   this.lipoScannableMap = ImmutableMap.of();
 }
 @Override
 public List<Label> getDefault(Rule rule, BuildConfiguration configuration) {
   return ImmutableList.copyOf(configuration.getPlugins());
 }
 @Override
 public Label getDefault(Rule rule, BuildConfiguration configuration) {
   return configuration.getFragment(JavaConfiguration.class).getProguardBinary();
 }
 @Override
 public List<Label> getDefault(Rule rule, BuildConfiguration configuration) {
   return ImmutableList.copyOf(
       configuration.getFragment(JavaConfiguration.class).getExtraProguardSpecs());
 }
 @Override
 public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) {
   return configuration.getFragment(AndroidConfiguration.class).getSdk();
 }
 @Override
 public Label getDefault(Rule rule, BuildConfiguration configuration) {
   return configuration.getFragment(JavaConfiguration.class).getToolchainLabel();
 }
Exemple #30
0
  private void resolveLateBoundAttributes(
      Rule rule,
      BuildConfiguration configuration,
      BuildConfiguration hostConfiguration,
      AttributeMap attributeMap,
      Iterable<Attribute> attributes,
      ImmutableSortedKeyListMultimap.Builder<Attribute, LabelAndConfiguration> builder)
      throws EvalException, InterruptedException {
    for (Attribute attribute : attributes) {
      if (!attribute.isLateBound() || !attribute.getCondition().apply(attributeMap)) {
        continue;
      }

      List<BuildConfiguration> actualConfigurations = ImmutableList.of(configuration);
      if (attribute.getConfigurationTransition() instanceof SplitTransition<?>) {
        Preconditions.checkState(attribute.getConfigurator() == null);
        // TODO(bazel-team): This ends up applying the split transition twice, both here and in the
        // visitRule method below - this is not currently a problem, because the configuration graph
        // never contains nested split transitions, so the second application is idempotent.
        actualConfigurations =
            configuration.getSplitConfigurations(
                (SplitTransition<?>) attribute.getConfigurationTransition());
      }

      for (BuildConfiguration actualConfig : actualConfigurations) {
        @SuppressWarnings("unchecked")
        LateBoundDefault<BuildConfiguration> lateBoundDefault =
            (LateBoundDefault<BuildConfiguration>) attribute.getLateBoundDefault();
        if (lateBoundDefault.useHostConfiguration()) {
          actualConfig = hostConfiguration;
        }
        // TODO(bazel-team): This might be too expensive - can we cache this somehow?
        if (!lateBoundDefault.getRequiredConfigurationFragments().isEmpty()) {
          if (!actualConfig.hasAllFragments(lateBoundDefault.getRequiredConfigurationFragments())) {
            continue;
          }
        }

        // TODO(bazel-team): We should check if the implementation tries to access an undeclared
        // fragment.
        Object actualValue = lateBoundDefault.getDefault(rule, actualConfig);
        if (EvalUtils.isNullOrNone(actualValue)) {
          continue;
        }
        try {
          if (attribute.getType() == BuildType.LABEL) {
            Label label = BuildType.LABEL.cast(actualValue);
            builder.put(attribute, LabelAndConfiguration.of(label, actualConfig));
          } else if (attribute.getType() == BuildType.LABEL_LIST) {
            for (Label label : BuildType.LABEL_LIST.cast(actualValue)) {
              builder.put(attribute, LabelAndConfiguration.of(label, actualConfig));
            }
          } else {
            throw new IllegalStateException(
                String.format(
                    "Late bound attribute '%s' is not a label or a label list",
                    attribute.getName()));
          }
        } catch (ClassCastException e) {
          throw new EvalException(
              rule.getLocation(),
              String.format(
                  "When computing the default value of %s, expected '%s', got '%s'",
                  attribute.getName(),
                  attribute.getType(),
                  EvalUtils.getDataTypeName(actualValue, true)));
        }
      }
    }
  }