func generateIndexerTargetGraphForRuleEntry()

in src/TulsiGenerator/PBXTargetGenerator.swift [533:681]


    func generateIndexerTargetGraphForRuleEntry(_ ruleEntry: RuleEntry) -> (NSOrderedSet) {
      if let data = processedEntries[ruleEntry] {
        return data
      }
      var frameworkSearchPaths = NSMutableOrderedSet()

      defer {
        processedEntries[ruleEntry] = (frameworkSearchPaths)
      }

      var resolvedDependecies = [RuleEntry]()
      for dep in ruleEntry.dependencies {
        guard let depEntry = ruleEntryMap.ruleEntry(buildLabel: dep, depender: ruleEntry) else {
          localizedMessageLogger.warning("UnknownTargetRule",
                                         comment: "Failure to look up a Bazel target that was expected to be present. The target label is %1$@",
                                         values: dep.value)
          continue
        }

        resolvedDependecies.append(depEntry)
        let inheritedFrameworkSearchPaths = generateIndexerTargetGraphForRuleEntry(depEntry)
        frameworkSearchPaths.union(inheritedFrameworkSearchPaths)
      }
      var defines = Set<String>()
      if let ruleDefines = ruleEntry.objcDefines {
        defines.formUnion(ruleDefines)
      }

      if !suppressCompilerDefines,
         let ruleDefines = ruleEntry.attributes[.compiler_defines] as? [String], !ruleDefines.isEmpty {
        defines.formUnion(ruleDefines)
      }

      let includes = NSMutableOrderedSet()
      addIncludes(ruleEntry, toSet: includes)

      // Search path entries are added for all framework imports, regardless of whether the
      // framework bundles are allowed by the include filters. The search path excludes the bundle
      // itself.
      ruleEntry.frameworkImports.forEach() {
        let fullPath = $0.fullPath as NSString
        let rootedPath = "$(\(PBXTargetGenerator.BazelExecutionRootSymlinkVarName))/\(fullPath.deletingLastPathComponent)"
        frameworkSearchPaths.add(rootedPath)
      }
      let sourceFileInfos = ruleEntry.sourceFiles.filter(includeFileInProject)
      let nonARCSourceFileInfos = ruleEntry.nonARCSourceFiles.filter(includeFileInProject)
      let frameworkFileInfos = ruleEntry.frameworkImports.filter(includeFileInProject)
      let nonSourceVersionedFileInfos = ruleEntry.versionedNonSourceArtifacts.filter(includeFileInProject)

      for target in ruleEntry.normalNonSourceArtifacts.filter(includeFileInProject) {
        let path = target.fullPath
        let (_, ref) = project.createGroupsAndFileReferenceForPath(path, underGroup: project.mainGroup)
        ref.isInputFile = target.targetType == .sourceFile
      }

      // Indexer targets aren't needed:
      // - if the target is a filegroup (we generate an indexer for what references the filegroup).
      // - if the target has no source files (there's nothing to index!)
      // - if the target is a test bundle (we generate proper targets for these).
      // - if the target is a direct dependency of a test target (these sources are added directly to the test target).
      if (sourceFileInfos.isEmpty &&
          nonARCSourceFileInfos.isEmpty &&
          frameworkFileInfos.isEmpty &&
          nonSourceVersionedFileInfos.isEmpty)
        || ruleEntry.pbxTargetType?.isTest ?? false
        || ruleEntry.type == "filegroup"
        || ruleEntryLabelsToSkipForIndexing.contains(ruleEntry.label) {
        addBuildFileForRule(ruleEntry)
        return (frameworkSearchPaths)
      }

      var localPreprocessorDefines = defines
      let localIncludes = includes.mutableCopy() as! NSMutableOrderedSet
      let otherCFlags = NSMutableArray()
      let swiftIncludePaths = NSMutableOrderedSet()
      let otherSwiftFlags = NSMutableArray()
      addLocalSettings(ruleEntry, localDefines: &localPreprocessorDefines, localIncludes: localIncludes,
                       otherCFlags: otherCFlags, swiftIncludePaths: swiftIncludePaths, otherSwiftFlags: otherSwiftFlags)

      addOtherSwiftFlags(ruleEntry, toArray: otherSwiftFlags)
      addSwiftIncludes(ruleEntry, toSet: swiftIncludePaths)

      let pchFile = BazelFileInfo(info: ruleEntry.attributes[.pch])
      if let pchFile = pchFile, includeFileInProject(pchFile) {
        addFileReference(pchFile)
      }

      let bridgingHeader = BazelFileInfo(info: ruleEntry.attributes[.bridging_header])
      if let bridgingHeader = bridgingHeader, includeFileInProject(bridgingHeader) {
        addFileReference(bridgingHeader)
      }
      let enableModules = (ruleEntry.attributes[.enable_modules] as? Bool) == true

      addBuildFileForRule(ruleEntry)

      let (nonARCFiles, nonARCSettings) = generateFileReferencesAndSettingsForNonARCFileInfos(nonARCSourceFileInfos)
      var fileReferences = generateFileReferencesForFileInfos(sourceFileInfos)
      fileReferences.append(contentsOf: generateFileReferencesForFileInfos(frameworkFileInfos))
      fileReferences.append(contentsOf: nonARCFiles)

      var buildPhaseReferences: [PBXReference]
      if nonSourceVersionedFileInfos.isEmpty {
        buildPhaseReferences = [PBXReference]()
      } else {
        let versionedFileReferences = createReferencesForVersionedFileTargets(nonSourceVersionedFileInfos)
        buildPhaseReferences = versionedFileReferences as [PBXReference]
      }
      buildPhaseReferences.append(contentsOf: fileReferences as [PBXReference])

      let buildPhase = createBuildPhaseForReferences(buildPhaseReferences,
                                                     withPerFileSettings: nonARCSettings)

      if !buildPhase.files.isEmpty {
        let resolvedIncludes = localIncludes.array as! [String]

        let deploymentTarget: DeploymentTarget
        if let ruleDeploymentTarget = ruleEntry.deploymentTarget {
          deploymentTarget = ruleDeploymentTarget
        } else {
          deploymentTarget = PBXTargetGenerator.defaultDeploymentTarget()
          localizedMessageLogger.warning("NoDeploymentTarget",
                                         comment: "Rule Entry for %1$@ has no DeploymentTarget set. Defaulting to iOS 9.",
                                         values: ruleEntry.label.value)
        }

        let indexerData = IndexerData(indexerNameInfo: [IndexerData.NameInfoToken(ruleEntry: ruleEntry)],
                                      dependencies: ruleEntry.dependencies,
                                      resolvedDependencies: Set(resolvedDependecies),
                                      preprocessorDefines: localPreprocessorDefines,
                                      otherCFlags: otherCFlags as! [String],
                                      otherSwiftFlags: otherSwiftFlags as! [String],
                                      includes: resolvedIncludes,
                                      frameworkSearchPaths: frameworkSearchPaths.array as! [String],
                                      swiftIncludePaths: swiftIncludePaths.array as! [String],
                                      deploymentTarget: deploymentTarget,
                                      buildPhase: buildPhase,
                                      pchFile: pchFile,
                                      bridgingHeader: bridgingHeader,
                                      enableModules: enableModules)
        let isSwiftRule = ruleEntry.attributes[.has_swift_info] as? Bool ?? false
        if (isSwiftRule) {
          frameworkIndexers[indexerData.indexerName] = indexerData
        } else {
          staticIndexers[indexerData.indexerName] = indexerData
        }
      }

      return (frameworkSearchPaths)
    }