/** Constructs the RuleConfiguredTarget instance based on the values set for this Builder. */
  public ConfiguredTarget build() {
    if (ruleContext.getConfiguration().enforceConstraints()) {
      checkConstraints();
    }
    if (ruleContext.hasErrors()) {
      return null;
    }

    FilesToRunProvider filesToRunProvider =
        new FilesToRunProvider(
            ruleContext.getLabel(),
            RuleContext.getFilesToRun(runfilesSupport, filesToBuild),
            runfilesSupport,
            executable);
    add(FileProvider.class, new FileProvider(ruleContext.getLabel(), filesToBuild));
    add(FilesToRunProvider.class, filesToRunProvider);

    if (runfilesSupport != null) {
      // If a binary is built, build its runfiles, too
      addOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL, runfilesSupport.getRunfilesMiddleman());
    } else if (providers.get(RunfilesProvider.class) != null) {
      // If we don't have a RunfilesSupport (probably because this is not a binary rule), we still
      // want to build the files this rule contributes to runfiles of dependent rules so that we
      // report an error if one of these is broken.
      //
      // Note that this is a best-effort thing: there is .getDataRunfiles() and all the language-
      // specific *RunfilesProvider classes, which we don't add here for reasons that are lost in
      // the mists of time.
      addOutputGroup(
          OutputGroupProvider.HIDDEN_TOP_LEVEL,
          ((RunfilesProvider) providers.get(RunfilesProvider.class))
              .getDefaultRunfiles()
              .getAllArtifacts());
    }

    // Create test action and artifacts if target was successfully initialized
    // and is a test.
    if (TargetUtils.isTestRule(ruleContext.getTarget())) {
      Preconditions.checkState(runfilesSupport != null);
      add(TestProvider.class, initializeTestProvider(filesToRunProvider));
    }
    add(ExtraActionArtifactsProvider.class, initializeExtraActions());
    if (!outputGroupBuilders.isEmpty()) {
      ImmutableMap.Builder<String, NestedSet<Artifact>> outputGroups = ImmutableMap.builder();
      for (Map.Entry<String, NestedSetBuilder<Artifact>> entry : outputGroupBuilders.entrySet()) {
        outputGroups.put(entry.getKey(), entry.getValue().build());
      }

      add(OutputGroupProvider.class, new OutputGroupProvider(outputGroups.build()));
    }

    return new RuleConfiguredTarget(
        ruleContext, mandatoryStampFiles, skylarkProviders.build(), providers);
  }
 /**
  * Invokes Blaze's constraint enforcement system: checks that this rule's dependencies support its
  * environments and reports appropriate errors if violations are found. Also publishes this rule's
  * supported environments for the rules that depend on it.
  */
 private void checkConstraints() {
   if (!ruleContext.getRule().getRuleClassObject().supportsConstraintChecking()) {
     return;
   }
   EnvironmentCollection supportedEnvironments =
       ConstraintSemantics.getSupportedEnvironments(ruleContext);
   if (supportedEnvironments != null) {
     add(SupportedEnvironmentsProvider.class, new SupportedEnvironments(supportedEnvironments));
     ConstraintSemantics.checkConstraints(ruleContext, supportedEnvironments);
   }
 }
Exemplo n.º 3
0
  @Override
  public ConfiguredTarget create(RuleContext ruleContext)
      throws RuleErrorException, InterruptedException {
    TransitiveInfoCollection lipoContextCollector =
        ruleContext.getPrerequisite(":lipo_context_collector", Mode.DONT_CHECK);
    if (lipoContextCollector != null
        && lipoContextCollector.getProvider(LipoContextProvider.class) == null) {
      ruleContext.ruleError("--lipo_context must point to a cc_binary or a cc_test rule");
      return null;
    }

    CppConfiguration cppConfiguration =
        Preconditions.checkNotNull(ruleContext.getFragment(CppConfiguration.class));
    Path fdoZip =
        ruleContext.getConfiguration().getCompilationMode() == CompilationMode.OPT
            ? cppConfiguration.getFdoZip()
            : null;
    SkyKey fdoKey =
        FdoSupportValue.key(
            cppConfiguration.getLipoMode(), fdoZip, cppConfiguration.getFdoInstrument());

    SkyFunction.Environment skyframeEnv = ruleContext.getAnalysisEnvironment().getSkyframeEnv();
    FdoSupportValue fdoSupport;
    try {
      fdoSupport =
          (FdoSupportValue)
              skyframeEnv.getValueOrThrow(fdoKey, FdoException.class, IOException.class);
    } catch (FdoException | IOException e) {
      ruleContext.ruleError("cannot initialize FDO: " + e.getMessage());
      return null;
    }

    if (skyframeEnv.valuesMissing()) {
      return null;
    }

    final Label label = ruleContext.getLabel();
    final NestedSet<Artifact> crosstool =
        ruleContext
            .getPrerequisite("all_files", Mode.HOST)
            .getProvider(FileProvider.class)
            .getFilesToBuild();
    final NestedSet<Artifact> crosstoolMiddleman = getFiles(ruleContext, "all_files");
    final NestedSet<Artifact> compile = getFiles(ruleContext, "compiler_files");
    final NestedSet<Artifact> strip = getFiles(ruleContext, "strip_files");
    final NestedSet<Artifact> objcopy = getFiles(ruleContext, "objcopy_files");
    final NestedSet<Artifact> link = getFiles(ruleContext, "linker_files");
    final NestedSet<Artifact> dwp = getFiles(ruleContext, "dwp_files");
    final NestedSet<Artifact> libcLink = inputsForLibc(ruleContext);
    String purposePrefix = Actions.escapeLabel(label) + "_";
    String runtimeSolibDirBase = "_solib_" + "_" + Actions.escapeLabel(label);
    final PathFragment runtimeSolibDir =
        ruleContext.getConfiguration().getBinFragment().getRelative(runtimeSolibDirBase);

    // Static runtime inputs.
    TransitiveInfoCollection staticRuntimeLibDep =
        selectDep(ruleContext, "static_runtime_libs", cppConfiguration.getStaticRuntimeLibsLabel());
    final NestedSet<Artifact> staticRuntimeLinkInputs;
    final Artifact staticRuntimeLinkMiddleman;
    if (cppConfiguration.supportsEmbeddedRuntimes()) {
      staticRuntimeLinkInputs =
          staticRuntimeLibDep.getProvider(FileProvider.class).getFilesToBuild();
    } else {
      staticRuntimeLinkInputs = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
    }

    if (!staticRuntimeLinkInputs.isEmpty()) {
      NestedSet<Artifact> staticRuntimeLinkMiddlemanSet =
          CompilationHelper.getAggregatingMiddleman(
              ruleContext, purposePrefix + "static_runtime_link", staticRuntimeLibDep);
      staticRuntimeLinkMiddleman =
          staticRuntimeLinkMiddlemanSet.isEmpty()
              ? null
              : Iterables.getOnlyElement(staticRuntimeLinkMiddlemanSet);
    } else {
      staticRuntimeLinkMiddleman = null;
    }

    Preconditions.checkState(
        (staticRuntimeLinkMiddleman == null) == staticRuntimeLinkInputs.isEmpty());

    // Dynamic runtime inputs.
    TransitiveInfoCollection dynamicRuntimeLibDep =
        selectDep(
            ruleContext, "dynamic_runtime_libs", cppConfiguration.getDynamicRuntimeLibsLabel());
    final NestedSet<Artifact> dynamicRuntimeLinkInputs;
    final Artifact dynamicRuntimeLinkMiddleman;
    if (cppConfiguration.supportsEmbeddedRuntimes()) {
      NestedSetBuilder<Artifact> dynamicRuntimeLinkInputsBuilder = NestedSetBuilder.stableOrder();
      for (Artifact artifact :
          dynamicRuntimeLibDep.getProvider(FileProvider.class).getFilesToBuild()) {
        if (CppHelper.SHARED_LIBRARY_FILETYPES.matches(artifact.getFilename())) {
          dynamicRuntimeLinkInputsBuilder.add(
              SolibSymlinkAction.getCppRuntimeSymlink(
                  ruleContext, artifact, runtimeSolibDirBase, ruleContext.getConfiguration()));
        } else {
          dynamicRuntimeLinkInputsBuilder.add(artifact);
        }
      }
      dynamicRuntimeLinkInputs = dynamicRuntimeLinkInputsBuilder.build();
    } else {
      dynamicRuntimeLinkInputs = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
    }

    if (!dynamicRuntimeLinkInputs.isEmpty()) {
      List<Artifact> dynamicRuntimeLinkMiddlemanSet =
          CppHelper.getAggregatingMiddlemanForCppRuntimes(
              ruleContext,
              purposePrefix + "dynamic_runtime_link",
              dynamicRuntimeLibDep,
              runtimeSolibDirBase,
              ruleContext.getConfiguration());
      dynamicRuntimeLinkMiddleman =
          dynamicRuntimeLinkMiddlemanSet.isEmpty()
              ? null
              : Iterables.getOnlyElement(dynamicRuntimeLinkMiddlemanSet);
    } else {
      dynamicRuntimeLinkMiddleman = null;
    }

    Preconditions.checkState(
        (dynamicRuntimeLinkMiddleman == null) == dynamicRuntimeLinkInputs.isEmpty());

    CppCompilationContext.Builder contextBuilder = new CppCompilationContext.Builder(ruleContext);
    CppModuleMap moduleMap = createCrosstoolModuleMap(ruleContext);
    if (moduleMap != null) {
      contextBuilder.setCppModuleMap(moduleMap);
    }
    final CppCompilationContext context = contextBuilder.build();
    boolean supportsParamFiles = ruleContext.attributes().get("supports_param_files", BOOLEAN);
    boolean supportsHeaderParsing =
        ruleContext.attributes().get("supports_header_parsing", BOOLEAN);

    NestedSetBuilder<Pair<String, String>> coverageEnvironment = NestedSetBuilder.compileOrder();

    coverageEnvironment.add(
        Pair.of("COVERAGE_GCOV_PATH", cppConfiguration.getGcovExecutable().getPathString()));
    if (cppConfiguration.getFdoInstrument() != null) {
      coverageEnvironment.add(
          Pair.of("FDO_DIR", cppConfiguration.getFdoInstrument().getPathString()));
    }

    CcToolchainProvider provider =
        new CcToolchainProvider(
            cppConfiguration,
            crosstool,
            fullInputsForCrosstool(ruleContext, crosstoolMiddleman),
            compile,
            strip,
            objcopy,
            fullInputsForLink(ruleContext, link),
            dwp,
            libcLink,
            staticRuntimeLinkInputs,
            staticRuntimeLinkMiddleman,
            dynamicRuntimeLinkInputs,
            dynamicRuntimeLinkMiddleman,
            runtimeSolibDir,
            context,
            supportsParamFiles,
            supportsHeaderParsing,
            getBuildVariables(ruleContext),
            getBuiltinIncludes(ruleContext),
            coverageEnvironment.build());
    RuleConfiguredTargetBuilder builder =
        new RuleConfiguredTargetBuilder(ruleContext)
            .add(CcToolchainProvider.class, provider)
            .add(FdoSupportProvider.class, new FdoSupportProvider(fdoSupport.getFdoSupport()))
            .setFilesToBuild(new NestedSetBuilder<Artifact>(Order.STABLE_ORDER).build())
            .add(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY));

    // If output_license is specified on the cc_toolchain rule, override the transitive licenses
    // with that one. This is necessary because cc_toolchain is used in the target configuration,
    // but it is sort-of-kind-of a tool, but various parts of it are linked into the output...
    // ...so we trust the judgment of the author of the cc_toolchain rule to figure out what
    // licenses should be propagated to C++ targets.
    License outputLicense = ruleContext.getRule().getToolOutputLicense(ruleContext.attributes());
    if (outputLicense != null && outputLicense != License.NO_LICENSE) {
      final NestedSet<TargetLicense> license =
          NestedSetBuilder.create(
              Order.STABLE_ORDER, new TargetLicense(ruleContext.getLabel(), outputLicense));
      LicensesProvider licensesProvider =
          new LicensesProvider() {
            @Override
            public NestedSet<TargetLicense> getTransitiveLicenses() {
              return license;
            }
          };

      builder.add(LicensesProvider.class, licensesProvider);
    }

    return builder.build();
  }
 public RuleConfiguredTargetBuilder(RuleContext ruleContext) {
   this.ruleContext = ruleContext;
   add(LicensesProvider.class, initializeLicensesProvider());
   add(VisibilityProvider.class, new VisibilityProviderImpl(ruleContext.getVisibility()));
 }