public static BuildRule create()

in src/com/facebook/buck/features/go/CGoLibrary.java [95:320]


  public static BuildRule create(
      BuildRuleParams params,
      BuildTarget buildTarget,
      ProjectFilesystem projectFilesystem,
      ActionGraphBuilder graphBuilder,
      CellPathResolver cellRoots,
      CxxBuckConfig cxxBuckConfig,
      GoPlatform platform,
      CgoLibraryDescriptionArg args,
      Iterable<BuildTarget> cxxDeps,
      Tool cgo) {

    CxxDeps allDeps =
        CxxDeps.builder().addDeps(cxxDeps).addPlatformDeps(args.getPlatformDeps()).build();

    // build cxxPreprocessorInputs and collect include flags (used by cgo
    // compiler)
    ImmutableList<BuildRule> cxxDepsRules =
        Streams.stream(cxxDeps)
            .map(graphBuilder::requireRule)
            .collect(ImmutableList.toImmutableList());

    Collection<CxxPreprocessorInput> cxxPreprocessorInputs =
        CxxPreprocessables.getTransitiveCxxPreprocessorInputFromDeps(
            platform.getCxxPlatform(), graphBuilder, cxxDepsRules);

    PreprocessorFlags.Builder ppFlagsBuilder = PreprocessorFlags.builder();
    for (CxxPreprocessorInput input : cxxPreprocessorInputs) {
      ppFlagsBuilder.addAllIncludes(input.getIncludes());
    }
    PreprocessorFlags ppFlags = ppFlagsBuilder.build();

    // generate C sources with cgo tool (go build writes c files to _obj dir)
    ImmutableMap<Path, SourcePath> headers =
        CxxDescriptionEnhancer.parseHeaders(
            buildTarget,
            graphBuilder,
            projectFilesystem,
            Optional.of(platform.getCxxPlatform()),
            args);

    HeaderSymlinkTree headerSymlinkTree =
        getHeaderSymlinkTree(
            buildTarget,
            projectFilesystem,
            graphBuilder,
            platform.getCxxPlatform(),
            cxxPreprocessorInputs,
            headers);

    SourcePathResolverAdapter pathResolver = graphBuilder.getSourcePathResolver();

    ImmutableSet.Builder<SourcePath> cxxSourcesFromArg = ImmutableSet.builder();
    ImmutableSet.Builder<SourcePath> goSourcesFromArg = ImmutableSet.builder();

    for (SourceWithFlags srcWithFlags : args.getSrcs()) {
      SourcePath pth = srcWithFlags.getSourcePath();
      String ext = Files.getFileExtension(pathResolver.getAbsolutePath(pth).toString());
      Optional<CxxSource.Type> srcType = CxxSource.Type.fromExtension(ext);

      if (srcType.equals(Optional.of(CxxSource.Type.C))
          || srcType.equals(Optional.of(CxxSource.Type.CXX))) {
        cxxSourcesFromArg.add(pth);
      } else if (ext.equals("go")) {
        goSourcesFromArg.add(pth);
      }
    }

    CGoGenSource genSource =
        (CGoGenSource)
            graphBuilder.computeIfAbsent(
                buildTarget.withAppendedFlavors(InternalFlavor.of("cgo-gen-sources")),
                target ->
                    new CGoGenSource(
                        target,
                        projectFilesystem,
                        graphBuilder,
                        CxxSourceTypes.getPreprocessor(platform.getCxxPlatform(), CxxSource.Type.C)
                            .resolve(graphBuilder, target.getTargetConfiguration()),
                        goSourcesFromArg.build(),
                        headerSymlinkTree,
                        cgo,
                        args.getCgoCompilerFlags(),
                        ppFlags,
                        platform
                            .getCxxPlatform()
                            .getCpp()
                            .resolve(graphBuilder, buildTarget.getTargetConfiguration()),
                        platform));

    // generated c files needs to be compiled and linked into a single object
    // file (equivalent of (_cgo_.o), includes:
    //   * _cgo_export.o
    //   * _cgo_main.o
    //   * all of the *.cgo2.o
    CxxLink cgoBin =
        (CxxLink)
            graphBuilder.computeIfAbsent(
                buildTarget.withAppendedFlavors(InternalFlavor.of("cgo-first-step")),
                target ->
                    nativeBinCompilation(
                        target,
                        projectFilesystem,
                        graphBuilder,
                        cellRoots,
                        cxxBuckConfig,
                        platform.getCxxPlatform(),
                        args,
                        new ImmutableList.Builder<BuildRule>()
                            .add(genSource)
                            .addAll(allDeps.get(graphBuilder, platform.getCxxPlatform()))
                            .build(),
                        new ImmutableMap.Builder<Path, SourcePath>()
                            .putAll(headers)
                            .put(
                                pathResolver
                                    .getAbsolutePath(genSource.getExportHeader())
                                    .getFileName(),
                                genSource.getExportHeader())
                            .build(),
                        new ImmutableList.Builder<SourcePath>()
                            .addAll(cxxSourcesFromArg.build())
                            .addAll(genSource.getCFiles())
                            .addAll(genSource.getCgoFiles())
                            .build(),
                        args.getLinkerFlags()));

    // generate cgo_import.h with previously generated object file (_cgo.o)
    BuildRule cgoImport =
        graphBuilder.computeIfAbsent(
            buildTarget.withAppendedFlavors(InternalFlavor.of("cgo-gen-import")),
            target ->
                new CGoGenImport(
                    target,
                    projectFilesystem,
                    graphBuilder,
                    cgo,
                    platform,
                    // take first source file in the list to infer the package
                    // name via go list
                    goSourcesFromArg.build().iterator().next(),
                    Objects.requireNonNull(cgoBin.getSourcePathToOutput())));

    // filter out compiled object only for the sources we are interested in
    ImmutableList<String> linkableObjectFiles =
        Stream.concat(
                cxxSourcesFromArg.build().stream()
                    .map(x -> pathResolver.getAbsolutePath(x).getFileName().toString()),
                ImmutableList.of(".cgo2.c", "_cgo_export.c").stream())
            .collect(ImmutableList.toImmutableList());

    // generate final object file (equivalent of _all.o) which includes:
    //  * _cgo_export.o
    //  * all of the *.cgo2.o files
    ImmutableList<Arg> cxxArgs =
        ImmutableList.<Arg>builder()
            .addAll(StringArg.from("-r", "-nostdlib"))
            .addAll(
                cgoBin.getArgs().stream()
                    .filter(FileListableLinkerInputArg.class::isInstance)
                    .map(FileListableLinkerInputArg.class::cast)
                    .filter(
                        arg -> {
                          Path pth = pathResolver.getAbsolutePath(arg.getPath());
                          String fileName = pth.getFileName().toString();
                          return pth.toString().contains("cgo-first-step")
                              && linkableObjectFiles.stream().anyMatch(x -> fileName.contains(x));
                        })
                    .collect(ImmutableList.toImmutableList()))
            .build();

    CxxLink cgoAllBin =
        (CxxLink)
            graphBuilder.computeIfAbsent(
                buildTarget.withAppendedFlavors(InternalFlavor.of("cgo-second-step")),
                target ->
                    CxxLinkableEnhancer.createCxxLinkableBuildRule(
                        cellRoots,
                        cxxBuckConfig,
                        platform.getCxxPlatform(),
                        projectFilesystem,
                        graphBuilder,
                        target,
                        BuildTargetPaths.getGenPath(projectFilesystem, target, "%s/_all.o"),
                        ImmutableMap.of(),
                        cxxArgs, // collection of selected object files
                        args.getLinkStyle().orElse(Linker.LinkableDepType.STATIC_PIC),
                        CxxLinkOptions.of(),
                        Optional.empty()));

    // output (referenced later on by GoCompile) provides:
    // * _cgo_gotypes.go
    // * _cgo_import.go
    // * all of the *.cgo1.go files
    //
    // the go sources should be appended to sources list and _all.o file should
    // be appended to the output binary (pack step)
    return graphBuilder.computeIfAbsent(
        buildTarget,
        target ->
            new CGoLibrary(
                params
                    .withDeclaredDeps(
                        ImmutableSortedSet.<BuildRule>naturalOrder()
                            .addAll(
                                graphBuilder.filterBuildRuleInputs(
                                    cgoAllBin.getSourcePathToOutput()))
                            .addAll(
                                graphBuilder.filterBuildRuleInputs(
                                    new Builder<SourcePath>()
                                        .addAll(genSource.getGoFiles())
                                        .add(
                                            Objects.requireNonNull(
                                                cgoImport.getSourcePathToOutput()))
                                        .build()))
                            .build())
                    .withoutExtraDeps(),
                target,
                projectFilesystem,
                new Builder<SourcePath>()
                    .addAll(genSource.getGoFiles())
                    .add(Objects.requireNonNull(cgoImport.getSourcePathToOutput()))
                    .build(),
                Objects.requireNonNull(cgoAllBin.getSourcePathToOutput()),
                Objects.requireNonNull(allDeps.get(graphBuilder, platform.getCxxPlatform()))));
  }