Index: include/lld/ReaderWriter/MachOLinkingContext.h =================================================================== --- include/lld/ReaderWriter/MachOLinkingContext.h +++ include/lld/ReaderWriter/MachOLinkingContext.h @@ -79,6 +79,12 @@ bool doNothing() const { return _doNothing; } bool printAtoms() const { return _printAtoms; } + ErrorOr searchPathForLibrary(StringRef path, + StringRef libName) const; + + /// Searches directories for a match on the input File + ErrorOr searchLibrary(StringRef libName) const; + /// \brief The dylib's binary compatibility version, in the raw uint32 format. /// /// When building a dynamic library, this is the compatibility version that @@ -125,6 +131,8 @@ } void setBundleLoader(StringRef loader) { _bundleLoader = loader; } void setPrintAtoms(bool value=true) { _printAtoms = value; } + void setSyslibRoot(StringRef path) { _syslibRoot = path; } + StringRef dyldPath() const { return "/usr/lib/dyld"; } static Arch archFromCpuType(uint32_t cputype, uint32_t cpusubtype); @@ -153,6 +161,7 @@ static ArchInfo _s_archInfos[]; + StringRef _syslibRoot; HeaderFileType _outputMachOType; // e.g MH_EXECUTE bool _outputMachOTypeStatic; // Disambiguate static vs dynamic prog bool _doNothing; // for -help and -v which just print info Index: lib/Driver/DarwinLdDriver.cpp =================================================================== --- lib/Driver/DarwinLdDriver.cpp +++ lib/Driver/DarwinLdDriver.cpp @@ -268,12 +268,31 @@ std::unique_ptr inputGraph(new InputGraph()); + if (llvm::opt::Arg *syslibRoot = parsedArgs->getLastArg(OPT_syslibroot)) { + ctx.setSyslibRoot(syslibRoot->getValue()); + } + // Handle input files - for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_INPUT), - ie = parsedArgs->filtered_end(); - it != ie; ++it) { + for (auto &arg : *parsedArgs) { + StringRef inputPath; + switch (arg->getOption().getID()) { + default: + continue; + case OPT_INPUT: + inputPath = arg->getValue(); + break; + case OPT_l: { + ErrorOr resolvedPath = ctx.searchLibrary(arg->getValue()); + if (!resolvedPath) { + diagnostics << "Unable to find library -l" << arg->getValue() << "\n"; + return false; + } + inputPath = resolvedPath.get(); + break; + } + } inputGraph->addInputElement(std::unique_ptr( - new MachOFileNode(ctx, (*it)->getValue(), globalWholeArchive))); + new MachOFileNode(ctx, inputPath, globalWholeArchive))); } if (!inputGraph->size()) { Index: lib/Driver/DarwinLdOptions.td =================================================================== --- lib/Driver/DarwinLdOptions.td +++ lib/Driver/DarwinLdOptions.td @@ -69,9 +69,16 @@ def all_load : Flag<["-"], "all_load">, HelpText<"Forces all members of all static libraries to be loaded">, Group; +def syslibroot : Separate<["-"], "syslibroot">, + HelpText<"Add prefix to all system library search paths">, + Group; + +// Input options +def l : Joined<["-"], "l">, + HelpText<"Root name of library to searchf for">; // test case options -def print_atoms : Flag<["-"], "print_atoms">, +def print_atoms : Flag<["-"], "print_atoms">, HelpText<"Emit output as yaml atoms">; // general options Index: lib/ReaderWriter/MachO/MachOLinkingContext.cpp =================================================================== --- lib/ReaderWriter/MachO/MachOLinkingContext.cpp +++ lib/ReaderWriter/MachO/MachOLinkingContext.cpp @@ -20,8 +20,10 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/Host.h" #include "llvm/Support/MachO.h" +#include "llvm/Support/Path.h" using lld::mach_o::KindHandler; using namespace llvm::MachO; @@ -262,6 +264,49 @@ } } +ErrorOr +MachOLinkingContext::searchPathForLibrary(StringRef path, + StringRef libName) const { + SmallString<128> fullPath; + if (libName.endswith(".o")) { + // A request ending in .o is special: just search for the file directly. + fullPath.assign(path); + llvm::sys::path::append(fullPath, libName); + if (llvm::sys::fs::exists(fullPath.str())) + return StringRef(*new (_allocator) std::string(fullPath.str())); + return make_error_code(llvm::errc::no_such_file_or_directory); + } + + // Search for dynamic library + fullPath.assign(path); + llvm::sys::path::append(fullPath, Twine("lib") + libName + ".dylib"); + if (llvm::sys::fs::exists(fullPath.str())) + return StringRef(*new (_allocator) std::string(fullPath.str())); + + // If not, try for a static library + fullPath.assign(path); + llvm::sys::path::append(fullPath, Twine("lib") + libName + ".a"); + if (llvm::sys::fs::exists(fullPath.str())) + return StringRef(*new (_allocator) std::string(fullPath.str())); + + return make_error_code(llvm::errc::no_such_file_or_directory); +} + +ErrorOr MachOLinkingContext::searchLibrary(StringRef libName) const { + SmallString<128> path; + static const char *syslibPaths[] = {"/usr/lib", "/usr/local/lib"}; + for (StringRef dir : syslibPaths) { + path.assign(_syslibRoot); + llvm::sys::path::append(path, dir); + + ErrorOr ec = searchPathForLibrary(path, libName); + if (ec) + return ec; + } + + return make_error_code(llvm::errc::no_such_file_or_directory); +} + bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) { // TODO: if -arch not specified, look at arch of first .o file. Index: test/mach-o/lib-search-paths.yaml =================================================================== --- /dev/null +++ test/mach-o/lib-search-paths.yaml @@ -0,0 +1,16 @@ +# RUN: lld -flavor darwin -arch x86_64 %s -syslibroot %p/Inputs/lib-search-paths -lmyshared -lmystatic -lfile.o -print_atoms 2>&1 -r | FileCheck %s + +--- !native +undefined-atoms: + - name: _from_myshared + - name: _from_mystatic + - name: _from_fileo + +# CHECK: defined-atoms: +# CHECK: - name: _from_mystatic +# CHECK: content: [ 02, 00, 00, 00 ] +# CHECK: - name: _from_fileo +# CHECK: content: [ 2A, 00, 00, 00 ] +# CHECK: shared-library-atoms: +# CHECK: - name: _from_myshared +# CHECK: load-name: libmyshared.dylib