public BuildRule createBuildRule()

in src/com/facebook/buck/apple/AppleTestDescription.java [188:467]


  public BuildRule createBuildRule(
      BuildRuleCreationContextWithTargetGraph context,
      BuildTarget buildTarget,
      BuildRuleParams params,
      AppleTestDescriptionArg args) {
    ActionGraphBuilder graphBuilder = context.getActionGraphBuilder();
    args.checkDuplicateSources(graphBuilder.getSourcePathResolver());
    ProjectFilesystem projectFilesystem = context.getProjectFilesystem();
    CxxPlatformsProvider cxxPlatformsProvider =
        getCxxPlatformsProvider(buildTarget.getTargetConfiguration());
    if (buildTarget.getFlavors().contains(COMPILE_DEPS)) {
      return createCompileDepsRule(
          cxxPlatformsProvider, buildTarget, graphBuilder, context, params, args);
    }
    if (!appleConfig.shouldUseSwiftDelegate()) {
      Optional<BuildRule> buildRule =
          appleLibraryDescription.createSwiftBuildRule(
              buildTarget,
              projectFilesystem,
              graphBuilder,
              context.getCellPathResolver(),
              args,
              Optional.of(this));

      if (buildRule.isPresent()) {
        return buildRule.get();
      }
    }

    if (args.getUiTestTargetApp().isPresent() && !args.getIsUiTest()) {
      throw new HumanReadableException(
          "Invalid configuration for %s with 'ui_test_target_app' specified, but 'is_ui_test' set to false or 'test_host_app' not specified",
          buildTarget);
    }

    AppleDebugFormat debugFormat =
        AppleDebugFormat.FLAVOR_DOMAIN
            .getValue(buildTarget)
            .orElse(appleConfig.getDefaultDebugInfoFormatForTests());
    if (buildTarget.getFlavors().contains(debugFormat.getFlavor())) {
      buildTarget = buildTarget.withoutFlavors(debugFormat.getFlavor());
    }

    boolean createBundle =
        Sets.intersection(buildTarget.getFlavors().getSet(), AUXILIARY_LIBRARY_FLAVORS).isEmpty();
    // Flavors pertaining to the library targets that are generated.
    Sets.SetView<Flavor> libraryFlavors =
        Sets.difference(buildTarget.getFlavors().getSet(), AUXILIARY_LIBRARY_FLAVORS);
    boolean addDefaultPlatform = libraryFlavors.isEmpty();
    ImmutableSet.Builder<Flavor> extraFlavorsBuilder = ImmutableSet.builder();
    if (createBundle) {
      extraFlavorsBuilder.add(LIBRARY_FLAVOR, CxxDescriptionEnhancer.MACH_O_BUNDLE_FLAVOR);
    }
    extraFlavorsBuilder.add(debugFormat.getFlavor());
    if (addDefaultPlatform) {
      Flavor defaultCxxFlavor =
          args.getDefaultPlatform()
              .orElse(cxxPlatformsProvider.getDefaultUnresolvedCxxPlatform().getFlavor());
      extraFlavorsBuilder.add(defaultCxxFlavor);
    }

    FlavorDomain<UnresolvedAppleCxxPlatform> appleCxxPlatformFlavorDomain =
        getAppleCxxPlatformsFlavorDomain(buildTarget.getTargetConfiguration());

    Optional<MultiarchFileInfo> multiarchFileInfo =
        MultiarchFileInfos.create(appleCxxPlatformFlavorDomain, buildTarget);
    AppleCxxPlatform appleCxxPlatform;
    ImmutableList<CxxPlatform> cxxPlatforms;
    TargetConfiguration targetConfiguration = buildTarget.getTargetConfiguration();
    if (multiarchFileInfo.isPresent()) {
      FlavorDomain<UnresolvedCxxPlatform> cxxPlatformFlavorDomain =
          cxxPlatformsProvider.getUnresolvedCxxPlatforms();
      ImmutableList.Builder<CxxPlatform> cxxPlatformBuilder = ImmutableList.builder();
      for (BuildTarget thinTarget : multiarchFileInfo.get().getThinTargets()) {
        cxxPlatformBuilder.add(
            cxxPlatformFlavorDomain
                .getValue(thinTarget)
                .get()
                .resolve(graphBuilder, targetConfiguration));
      }
      cxxPlatforms = cxxPlatformBuilder.build();
      appleCxxPlatform =
          appleCxxPlatformFlavorDomain
              .getValue(multiarchFileInfo.get().getRepresentativePlatformFlavor())
              .resolve(graphBuilder);
    } else {
      CxxPlatform cxxPlatform =
          ApplePlatforms.getCxxPlatformForBuildTarget(
                  cxxPlatformsProvider, buildTarget, args.getDefaultPlatform())
              .resolve(graphBuilder, buildTarget.getTargetConfiguration());
      cxxPlatforms = ImmutableList.of(cxxPlatform);
      appleCxxPlatform =
          verifyAppleCxxPlatform(appleCxxPlatformFlavorDomain, cxxPlatform, buildTarget)
              .resolve(graphBuilder);
    }

    Optional<TestHostInfo> testHostWithTargetApp = Optional.empty();
    if (args.getTestHostApp().isPresent()) {
      testHostWithTargetApp =
          Optional.of(
              createTestHostInfo(
                  buildTarget,
                  args.getIsUiTest(),
                  graphBuilder,
                  args.getTestHostApp().get(),
                  args.getUiTestTargetApp(),
                  debugFormat,
                  libraryFlavors,
                  cxxPlatforms));
    }

    BuildTarget libraryTarget =
        buildTarget
            .withAppendedFlavors(extraFlavorsBuilder.build())
            .withAppendedFlavors(debugFormat.getFlavor())
            .withAppendedFlavors(LinkerMapMode.NO_LINKER_MAP.getFlavor());
    BuildRule library =
        createTestLibraryRule(
            context,
            params,
            graphBuilder,
            args,
            testHostWithTargetApp.flatMap(TestHostInfo::getTestHostAppBinarySourcePath),
            testHostWithTargetApp.map(TestHostInfo::getBlacklist).orElse(ImmutableSet.of()),
            libraryTarget,
            RichStream.from(args.getTestHostApp()).toImmutableSortedSet(Ordering.natural()));
    if (!createBundle || SwiftLibraryDescription.isSwiftTarget(libraryTarget)) {
      return library;
    }

    String platformName = appleCxxPlatform.getAppleSdk().getApplePlatform().getName();

    BuildTarget appleBundleBuildTarget =
        buildTarget.withAppendedFlavors(
            BUNDLE_FLAVOR,
            debugFormat.getFlavor(),
            LinkerMapMode.NO_LINKER_MAP.getFlavor(),
            AppleDescriptions.NO_INCLUDE_FRAMEWORKS_FLAVOR);
    AppleBundle bundle =
        AppleBundle.class.cast(
            graphBuilder.computeIfAbsent(
                appleBundleBuildTarget,
                ignored ->
                    AppleDescriptions.createAppleBundle(
                        xcodeDescriptions,
                        getCxxPlatformsProvider(targetConfiguration),
                        appleCxxPlatformFlavorDomain,
                        context.getTargetGraph(),
                        appleBundleBuildTarget,
                        projectFilesystem,
                        params.withDeclaredDeps(
                            ImmutableSortedSet.<BuildRule>naturalOrder()
                                .add(library)
                                .addAll(params.getDeclaredDeps().get())
                                .build()),
                        graphBuilder,
                        toolchainProvider.getByName(
                            CodeSignIdentityStore.DEFAULT_NAME,
                            targetConfiguration,
                            CodeSignIdentityStore.class),
                        toolchainProvider.getByName(
                            ProvisioningProfileStore.DEFAULT_NAME,
                            targetConfiguration,
                            ProvisioningProfileStore.class),
                        Optional.of(library.getBuildTarget()),
                        Optional.empty(),
                        args.getDefaultPlatform(),
                        args.getExtension(),
                        Optional.empty(),
                        args.getInfoPlist(),
                        args.getInfoPlistSubstitutions(),
                        args.getDeps(),
                        args.getTests(),
                        debugFormat,
                        appleConfig.useDryRunCodeSigning(),
                        appleConfig.cacheBundlesAndPackages(),
                        appleConfig.shouldVerifyBundleResources(),
                        appleConfig.assetCatalogValidation(),
                        args.getAssetCatalogsCompilationOptions(),
                        args.getCodesignFlags(),
                        args.getCodesignIdentity(),
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty(),
                        appleConfig.getCodesignTimeout(),
                        swiftBuckConfig.getCopyStdlibToFrameworks(),
                        swiftBuckConfig.getUseLipoThin(),
                        cxxBuckConfig.shouldCacheStrip(),
                        appleConfig.useEntitlementsWhenAdhocCodeSigning(),
                        Predicates.alwaysTrue(),
                        Optional.empty())));

    Optional<SourcePath> xctool =
        getXctool(projectFilesystem, params, targetConfiguration, graphBuilder);

    if (args.getSpecs().isPresent()) {
      UserVerify.verify(
          args.getRunner().isPresent(),
          "runner should be specified for rules implementing test protocol");
      BuildRule runnerRule = graphBuilder.requireRule(args.getRunner().get());
      UserVerify.verify(
          runnerRule instanceof ExternalTestRunner,
          "runner should be an external_test_runner for apple_test");

      ExternalTestRunner runner = (ExternalTestRunner) runnerRule;

      StringWithMacrosConverter macrosConverter =
          StringWithMacrosConverter.of(
              buildTarget,
              context.getCellPathResolver().getCellNameResolver(),
              graphBuilder,
              ImmutableList.of(
                  LocationMacroExpander.INSTANCE, AbsoluteOutputMacroExpander.INSTANCE));

      return new AppleTestX(
          runner.getBinary(),
          TestRunnerSpecCoercer.coerce(args.getSpecs().get(), macrosConverter),
          xctool,
          appleConfig.getXctoolStutterTimeoutMs(),
          appleCxxPlatform.getXctest(),
          appleConfig.getXctestPlatformNames().contains(platformName),
          platformName,
          appleConfig.getXctoolDefaultDestinationSpecifier(),
          buildTarget,
          projectFilesystem,
          params.withDeclaredDeps(ImmutableSortedSet.of(bundle)).withoutExtraDeps(),
          bundle,
          testHostWithTargetApp.map(TestHostInfo::getTestHostApp),
          testHostWithTargetApp.flatMap(TestHostInfo::getUiTestTargetApp),
          args.getContacts(),
          args.getLabels(),
          toolchainProvider.getByName(
              AppleDeveloperDirectoryForTestsProvider.DEFAULT_NAME,
              targetConfiguration,
              AppleDeveloperDirectoryForTestsProvider.class),
          args.getIsUiTest(),
          args.getSnapshotReferenceImagesPath(),
          args.getSnapshotImagesDiffPath(),
          appleConfig.useIdb(),
          appleConfig.getIdbPath());
    }

    return new AppleTest(
        xctool,
        appleConfig.getXctoolStutterTimeoutMs(),
        appleCxxPlatform.getXctest(),
        appleConfig.getXctestPlatformNames().contains(platformName),
        platformName,
        appleConfig.getXctoolDefaultDestinationSpecifier(),
        Optional.of(args.getDestinationSpecifier()),
        buildTarget,
        projectFilesystem,
        params.withDeclaredDeps(ImmutableSortedSet.of(bundle)).withoutExtraDeps(),
        bundle,
        testHostWithTargetApp.map(TestHostInfo::getTestHostApp),
        testHostWithTargetApp.flatMap(TestHostInfo::getUiTestTargetApp),
        args.getContacts(),
        args.getLabels(),
        args.getRunTestSeparately(),
        toolchainProvider.getByName(
            AppleDeveloperDirectoryForTestsProvider.DEFAULT_NAME,
            targetConfiguration,
            AppleDeveloperDirectoryForTestsProvider.class),
        appleConfig.getTestLogDirectoryEnvironmentVariable(),
        appleConfig.getTestLogLevelEnvironmentVariable(),
        appleConfig.getTestLogLevel(),
        args.getTestRuleTimeoutMs()
            .map(Optional::of)
            .orElse(
                appleConfig
                    .getDelegate()
                    .getView(TestBuckConfig.class)
                    .getDefaultTestRuleTimeoutMs()),
        args.getIsUiTest(),
        args.getSnapshotReferenceImagesPath(),
        args.getSnapshotImagesDiffPath(),
        args.getEnv(),
        appleConfig.useIdb(),
        appleConfig.getIdbPath());
  }