@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()); }
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(); }