예제 #1
0
  @Override
  public NativeLinkableInput getNativeLinkableInput(
      CxxPlatform cxxPlatform, Linker.LinkableDepType type) throws NoSuchBuildTargetException {
    // Build the library path and linker arguments that we pass through the
    // {@link NativeLinkable} interface for linking.
    ImmutableList.Builder<Arg> linkerArgsBuilder = ImmutableList.builder();
    linkerArgsBuilder.addAll(
        StringArg.from(Preconditions.checkNotNull(exportedLinkerFlags.apply(cxxPlatform))));
    if (!headerOnly) {
      if (type == Linker.LinkableDepType.SHARED) {
        Preconditions.checkState(getPreferredLinkage(cxxPlatform) != Linkage.STATIC);
        final SourcePath sharedLibrary = requireSharedLibrary(cxxPlatform);
        if (linkWithoutSoname) {
          if (!(sharedLibrary instanceof PathSourcePath)) {
            throw new HumanReadableException(
                "%s: can only link prebuilt DSOs without sonames", getBuildTarget());
          }
          linkerArgsBuilder.add(new RelativeLinkArg((PathSourcePath) sharedLibrary));
        } else {
          linkerArgsBuilder.add(
              new SourcePathArg(getResolver(), requireSharedLibrary(cxxPlatform)));
        }
      } else {
        Preconditions.checkState(getPreferredLinkage(cxxPlatform) != Linkage.SHARED);
        Path staticLibraryPath =
            type == Linker.LinkableDepType.STATIC_PIC
                ? getStaticPicLibrary(cxxPlatform).get()
                : PrebuiltCxxLibraryDescription.getStaticLibraryPath(
                    getBuildTarget(),
                    params.getCellRoots(),
                    ruleResolver,
                    cxxPlatform,
                    libDir,
                    libName);
        SourcePathArg staticLibrary =
            new SourcePathArg(
                getResolver(), new PathSourcePath(getProjectFilesystem(), staticLibraryPath));
        if (linkWhole) {
          Linker linker = cxxPlatform.getLd();
          linkerArgsBuilder.addAll(linker.linkWhole(staticLibrary));
        } else {
          linkerArgsBuilder.add(staticLibrary);
        }
      }
    }
    final ImmutableList<Arg> linkerArgs = linkerArgsBuilder.build();

    return NativeLinkableInput.of(
        linkerArgs, ImmutableSet.<FrameworkPath>of(), ImmutableSet.<FrameworkPath>of());
  }
예제 #2
0
  public static CxxLinkAndCompileRules createBuildRulesForCxxBinary(
      TargetGraph targetGraph,
      BuildRuleParams params,
      BuildRuleResolver resolver,
      CxxPlatform cxxPlatform,
      ImmutableMap<String, CxxSource> srcs,
      ImmutableMap<Path, SourcePath> headers,
      ImmutableMap<String, SourcePath> lexSrcs,
      ImmutableMap<String, SourcePath> yaccSrcs,
      CxxPreprocessMode preprocessMode,
      Linker.LinkableDepType linkStyle,
      Optional<ImmutableList<String>> preprocessorFlags,
      Optional<PatternMatchedCollection<ImmutableList<String>>> platformPreprocessorFlags,
      Optional<ImmutableMap<CxxSource.Type, ImmutableList<String>>> langPreprocessorFlags,
      Optional<ImmutableSortedSet<FrameworkPath>> frameworks,
      Optional<ImmutableList<String>> compilerFlags,
      Optional<PatternMatchedCollection<ImmutableList<String>>> platformCompilerFlags,
      Optional<SourcePath> prefixHeader,
      Optional<ImmutableList<String>> linkerFlags,
      Optional<PatternMatchedCollection<ImmutableList<String>>> platformLinkerFlags,
      Optional<Linker.CxxRuntimeType> cxxRuntimeType) {
    SourcePathResolver sourcePathResolver = new SourcePathResolver(resolver);
    Path linkOutput = getLinkOutputPath(params.getBuildTarget());
    ImmutableList.Builder<Arg> argsBuilder = ImmutableList.builder();
    CommandTool.Builder executableBuilder = new CommandTool.Builder();

    // Setup the rules to run lex/yacc.
    CxxHeaderSourceSpec lexYaccSources =
        requireLexYaccSources(params, resolver, sourcePathResolver, cxxPlatform, lexSrcs, yaccSrcs);

    // Setup the header symlink tree and combine all the preprocessor input from this rule
    // and all dependencies.
    HeaderSymlinkTree headerSymlinkTree =
        requireHeaderSymlinkTree(
            params,
            resolver,
            sourcePathResolver,
            cxxPlatform,
            /* includeLexYaccHeaders */ true,
            lexSrcs,
            yaccSrcs,
            headers,
            HeaderVisibility.PRIVATE);
    ImmutableList<CxxPreprocessorInput> cxxPreprocessorInput =
        collectCxxPreprocessorInput(
            targetGraph,
            params,
            cxxPlatform,
            CxxFlags.getLanguageFlags(
                preprocessorFlags, platformPreprocessorFlags, langPreprocessorFlags, cxxPlatform),
            ImmutableList.of(headerSymlinkTree),
            getFrameworkSearchPaths(frameworks, cxxPlatform, new SourcePathResolver(resolver)),
            CxxPreprocessables.getTransitiveCxxPreprocessorInput(
                targetGraph,
                cxxPlatform,
                FluentIterable.from(params.getDeps())
                    .filter(Predicates.instanceOf(CxxPreprocessorDep.class))));

    // The complete list of input sources.
    ImmutableMap<String, CxxSource> sources =
        ImmutableMap.<String, CxxSource>builder()
            .putAll(srcs)
            .putAll(lexYaccSources.getCxxSources())
            .build();

    // Generate and add all the build rules to preprocess and compile the source to the
    // resolver and get the `SourcePath`s representing the generated object files.
    ImmutableMap<CxxPreprocessAndCompile, SourcePath> objects =
        CxxSourceRuleFactory.requirePreprocessAndCompileRules(
            params,
            resolver,
            sourcePathResolver,
            cxxPlatform,
            cxxPreprocessorInput,
            CxxFlags.getFlags(compilerFlags, platformCompilerFlags, cxxPlatform),
            prefixHeader,
            preprocessMode,
            sources,
            linkStyle == Linker.LinkableDepType.STATIC
                ? CxxSourceRuleFactory.PicType.PDC
                : CxxSourceRuleFactory.PicType.PIC);

    // Build up the linker flags, which support macro expansion.
    ImmutableList<String> resolvedLinkerFlags =
        CxxFlags.getFlags(linkerFlags, platformLinkerFlags, cxxPlatform);
    argsBuilder.addAll(
        FluentIterable.from(resolvedLinkerFlags)
            .transform(
                MacroArg.toMacroArgFunction(
                    MACRO_HANDLER,
                    params.getBuildTarget(),
                    params.getCellRoots(),
                    resolver,
                    params.getProjectFilesystem())));

    // Special handling for dynamically linked binaries.
    if (linkStyle == Linker.LinkableDepType.SHARED) {

      // Create a symlink tree with for all shared libraries needed by this binary.
      SymlinkTree sharedLibraries =
          resolver.addToIndex(
              createSharedLibrarySymlinkTree(
                  targetGraph,
                  params,
                  sourcePathResolver,
                  cxxPlatform,
                  Predicates.instanceOf(NativeLinkable.class)));

      // Embed a origin-relative library path into the binary so it can find the shared libraries.
      argsBuilder.addAll(
          StringArg.from(
              Linkers.iXlinker(
                  "-rpath",
                  String.format(
                      "%s/%s",
                      cxxPlatform.getLd().origin(),
                      linkOutput.getParent().relativize(sharedLibraries.getRoot()).toString()))));

      // Add all the shared libraries and the symlink tree as inputs to the tool that represents
      // this binary, so that users can attach the proper deps.
      executableBuilder.addDep(sharedLibraries);
      executableBuilder.addInputs(sharedLibraries.getLinks().values());
    }

    // Add object files into the args.
    argsBuilder.addAll(SourcePathArg.from(sourcePathResolver, objects.values()));

    // Generate the final link rule.  We use the top-level target as the link rule's
    // target, so that it corresponds to the actual binary we build.
    CxxLink cxxLink =
        CxxLinkableEnhancer.createCxxLinkableBuildRule(
            targetGraph,
            cxxPlatform,
            params,
            sourcePathResolver,
            createCxxLinkTarget(params.getBuildTarget()),
            Linker.LinkType.EXECUTABLE,
            Optional.<String>absent(),
            linkOutput,
            argsBuilder.build(),
            linkStyle,
            params.getDeps(),
            cxxRuntimeType,
            Optional.<SourcePath>absent(),
            ImmutableSet.<BuildTarget>of());
    resolver.addToIndex(cxxLink);

    // Add the output of the link as the lone argument needed to invoke this binary as a tool.
    executableBuilder.addArg(new BuildTargetSourcePath(cxxLink.getBuildTarget()));

    return new CxxLinkAndCompileRules(
        cxxLink, ImmutableSortedSet.copyOf(objects.keySet()), executableBuilder.build());
  }
  private ImmutableList<com.facebook.buck.rules.args.Arg> getExtensionArgs(
      BuildRuleParams params,
      BuildRuleResolver ruleResolver,
      SourcePathResolver pathResolver,
      CxxPlatform cxxPlatform,
      Arg args)
      throws NoSuchBuildTargetException {

    // Extract all C/C++ sources from the constructor arg.
    ImmutableMap<String, CxxSource> srcs =
        CxxDescriptionEnhancer.parseCxxSources(
            params.getBuildTarget(), pathResolver, cxxPlatform, args);
    ImmutableMap<Path, SourcePath> headers =
        CxxDescriptionEnhancer.parseHeaders(
            params.getBuildTarget(), pathResolver, Optional.of(cxxPlatform), args);

    // Setup the header symlink tree and combine all the preprocessor input from this rule
    // and all dependencies.
    HeaderSymlinkTree headerSymlinkTree =
        CxxDescriptionEnhancer.requireHeaderSymlinkTree(
            params,
            ruleResolver,
            new SourcePathResolver(ruleResolver),
            cxxPlatform,
            headers,
            HeaderVisibility.PRIVATE);
    ImmutableList<CxxPreprocessorInput> cxxPreprocessorInput =
        CxxDescriptionEnhancer.collectCxxPreprocessorInput(
            params,
            cxxPlatform,
            CxxFlags.getLanguageFlags(
                args.preprocessorFlags,
                args.platformPreprocessorFlags,
                args.langPreprocessorFlags,
                cxxPlatform),
            ImmutableList.of(headerSymlinkTree),
            ImmutableSet.<FrameworkPath>of(),
            CxxPreprocessables.getTransitiveCxxPreprocessorInput(cxxPlatform, params.getDeps()));

    // Generate rule to build the object files.
    ImmutableMap<CxxPreprocessAndCompile, SourcePath> picObjects =
        CxxSourceRuleFactory.requirePreprocessAndCompileRules(
            params,
            ruleResolver,
            pathResolver,
            cxxBuckConfig,
            cxxPlatform,
            cxxPreprocessorInput,
            CxxFlags.getLanguageFlags(
                args.compilerFlags,
                args.platformCompilerFlags,
                args.langCompilerFlags,
                cxxPlatform),
            args.prefixHeader,
            cxxBuckConfig.getPreprocessMode(),
            srcs,
            CxxSourceRuleFactory.PicType.PIC);

    ImmutableList.Builder<com.facebook.buck.rules.args.Arg> argsBuilder = ImmutableList.builder();
    argsBuilder.addAll(
        StringArg.from(CxxFlags.getFlags(args.linkerFlags, args.platformLinkerFlags, cxxPlatform)));

    // Embed a origin-relative library path into the binary so it can find the shared libraries.
    argsBuilder.addAll(
        StringArg.from(
            Linkers.iXlinker(
                "-rpath",
                String.format("%s/", cxxPlatform.getLd().resolve(ruleResolver).libOrigin()))));

    // Add object files into the args.
    argsBuilder.addAll(SourcePathArg.from(pathResolver, picObjects.values()));

    return argsBuilder.build();
  }