public BuildRule createBuildRule()

in src/com/facebook/buck/cxx/CxxTestDescription.java [155:339]


  public BuildRule createBuildRule(
      BuildRuleCreationContextWithTargetGraph context,
      BuildTarget inputBuildTarget,
      BuildRuleParams params,
      CxxTestDescriptionArg args) {
    Optional<StripStyle> flavoredStripStyle = StripStyle.FLAVOR_DOMAIN.getValue(inputBuildTarget);
    Optional<LinkerMapMode> flavoredLinkerMapMode =
        LinkerMapMode.FLAVOR_DOMAIN.getValue(inputBuildTarget);
    inputBuildTarget =
        CxxStrip.removeStripStyleFlavorInTarget(inputBuildTarget, flavoredStripStyle);
    inputBuildTarget =
        LinkerMapMode.removeLinkerMapModeFlavorInTarget(inputBuildTarget, flavoredLinkerMapMode);
    BuildTarget buildTarget = inputBuildTarget;

    ActionGraphBuilder graphBuilder = context.getActionGraphBuilder();
    args.checkDuplicateSources(graphBuilder.getSourcePathResolver());
    CxxPlatform cxxPlatform =
        getCxxPlatform(buildTarget, args)
            .resolve(graphBuilder, buildTarget.getTargetConfiguration());
    ProjectFilesystem projectFilesystem = context.getProjectFilesystem();
    CellPathResolver cellRoots = context.getCellPathResolver();

    if (buildTarget.getFlavors().contains(CxxCompilationDatabase.COMPILATION_DATABASE)) {
      CxxLinkAndCompileRules cxxLinkAndCompileRules =
          CxxDescriptionEnhancer.createBuildRulesForCxxBinaryDescriptionArg(
              context.getTargetGraph(),
              buildTarget.withoutFlavors(CxxCompilationDatabase.COMPILATION_DATABASE),
              projectFilesystem,
              graphBuilder,
              cellRoots,
              cxxBuckConfig,
              cxxPlatform,
              args,
              getImplicitFrameworkDeps(buildTarget.getTargetConfiguration(), args),
              flavoredStripStyle,
              flavoredLinkerMapMode);
      return CxxCompilationDatabase.createCompilationDatabase(
          buildTarget, projectFilesystem, cxxLinkAndCompileRules.compileRules);
    }

    if (buildTarget.getFlavors().contains(CxxCompilationDatabase.UBER_COMPILATION_DATABASE)) {
      return CxxDescriptionEnhancer.createUberCompilationDatabase(
          getCxxPlatformsProvider(buildTarget.getTargetConfiguration())
                  .getUnresolvedCxxPlatforms()
                  .getValue(buildTarget)
                  .isPresent()
              ? buildTarget
              : buildTarget.withAppendedFlavors(cxxPlatform.getFlavor()),
          projectFilesystem,
          graphBuilder);
    }

    // Generate the link rule that builds the test binary.
    CxxLinkAndCompileRules cxxLinkAndCompileRules =
        CxxDescriptionEnhancer.createBuildRulesForCxxBinaryDescriptionArg(
            context.getTargetGraph(),
            buildTarget,
            projectFilesystem,
            graphBuilder,
            cellRoots,
            cxxBuckConfig,
            cxxPlatform,
            args,
            getImplicitFrameworkDeps(buildTarget.getTargetConfiguration(), args),
            flavoredStripStyle,
            flavoredLinkerMapMode);

    // Construct the actual build params we'll use, notably with an added dependency on the
    // CxxLink rule above which builds the test binary.
    BuildTarget testBuildTarget =
        CxxStrip.restoreStripStyleFlavorInTarget(buildTarget, flavoredStripStyle);
    testBuildTarget =
        LinkerMapMode.restoreLinkerMapModeFlavorInTarget(testBuildTarget, flavoredLinkerMapMode);
    BuildRuleParams testParams =
        params
            .withDeclaredDeps(cxxLinkAndCompileRules.deps)
            .copyAppendingExtraDeps(
                BuildableSupport.getDepsCollection(
                    cxxLinkAndCompileRules.executable, graphBuilder));

    StringWithMacrosConverter macrosConverter =
        StringWithMacrosConverter.of(
            buildTarget,
            cellRoots.getCellNameResolver(),
            graphBuilder,
            ImmutableList.of(LocationMacroExpander.INSTANCE));

    // Supplier which expands macros in the passed in test environment.
    ImmutableMap<String, Arg> testEnv =
        ImmutableMap.copyOf(Maps.transformValues(args.getEnv(), macrosConverter::convert));

    ImmutableList<Arg> testArgs =
        args.getArgs().stream()
            .map(macrosConverter::convert)
            .collect(ImmutableList.toImmutableList());

    Function<SourcePathRuleFinder, ImmutableSortedSet<BuildRule>> additionalDeps =
        ruleFinderInner -> {
          ImmutableSortedSet.Builder<BuildRule> deps = ImmutableSortedSet.naturalOrder();

          // It's not uncommon for users to add dependencies onto other binaries that they run
          // during the test, so make sure to add them as runtime deps.
          deps.addAll(
              Sets.difference(
                  params.getBuildDeps(), cxxLinkAndCompileRules.getBinaryRule().getBuildDeps()));

          // Add any build-time from any macros embedded in the `env` or `args` parameter.
          for (Arg part : Iterables.concat(testArgs, testEnv.values())) {
            deps.addAll(BuildableSupport.getDepsCollection(part, ruleFinderInner));
          }

          return deps.build();
        };

    CxxTest test;

    CxxTestType type = args.getFramework().orElse(getDefaultTestType());
    switch (type) {
      case GTEST:
        {
          test =
              new CxxGtestTest(
                  testBuildTarget,
                  projectFilesystem,
                  testParams,
                  cxxLinkAndCompileRules.getBinaryRule(),
                  cxxLinkAndCompileRules.executable,
                  testEnv,
                  testArgs,
                  FluentIterable.from(args.getResources())
                      .transform(p -> PathSourcePath.of(projectFilesystem, p))
                      .toSortedSet(Ordering.natural()),
                  args.getAdditionalCoverageTargets(),
                  additionalDeps,
                  args.getLabels(),
                  args.getContacts(),
                  args.getRunTestSeparately().orElse(false),
                  args.getTestRuleTimeoutMs()
                      .map(Optional::of)
                      .orElse(
                          cxxBuckConfig
                              .getDelegate()
                              .getView(TestBuckConfig.class)
                              .getDefaultTestRuleTimeoutMs()),
                  cxxBuckConfig.getMaximumTestOutputSize(),
                  cxxBuckConfig.checkGTestTestList());
          break;
        }
      case BOOST:
        {
          test =
              new CxxBoostTest(
                  testBuildTarget,
                  projectFilesystem,
                  testParams,
                  cxxLinkAndCompileRules.getBinaryRule(),
                  cxxLinkAndCompileRules.executable,
                  testEnv,
                  testArgs,
                  FluentIterable.from(args.getResources())
                      .transform(p -> PathSourcePath.of(projectFilesystem, p))
                      .toSortedSet(Ordering.natural()),
                  args.getAdditionalCoverageTargets(),
                  additionalDeps,
                  args.getLabels(),
                  args.getContacts(),
                  args.getRunTestSeparately().orElse(false),
                  args.getTestRuleTimeoutMs()
                      .map(Optional::of)
                      .orElse(
                          cxxBuckConfig
                              .getDelegate()
                              .getView(TestBuckConfig.class)
                              .getDefaultTestRuleTimeoutMs()));
          break;
        }
      default:
        {
          Preconditions.checkState(false, "Unhandled C++ test type: %s", type);
          throw new RuntimeException();
        }
    }

    return test;
  }