diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -29,7 +29,9 @@ llvm::StringRef outputFile; llvm::MachO::Architecture arch; llvm::MachO::HeaderFileType outputType; - std::vector searchPaths; + std::vector librarySearchPaths; + // TODO: use the framework search paths + std::vector frameworkSearchPaths; llvm::DenseMap priorities; }; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -31,6 +31,7 @@ #include "llvm/Object/Archive.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" +#include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" @@ -87,7 +88,7 @@ std::string archive = (llvm::Twine("lib") + name + ".a").str(); llvm::SmallString<260> location; - for (StringRef dir : config->searchPaths) { + for (StringRef dir : config->librarySearchPaths) { for (StringRef library : {stub, shared, archive}) { location = dir; llvm::sys::path::append(location, library); @@ -111,13 +112,49 @@ } } -static std::vector getSearchPaths(opt::InputArgList &args) { - std::vector ret{args::getStrings(args, OPT_L)}; - if (!args.hasArg(OPT_Z)) { - ret.push_back("/usr/lib"); - ret.push_back("/usr/local/lib"); +static bool isDirectory(const StringRef &option, const StringRef &path) { + if (!fs::exists(path)) { + warn("directory not found for option -" + option + path); + return false; + } else if (!fs::is_directory(path)) { + warn("option -" + option + path + " references a non-directory path"); + return false; + } + return true; +} + +static std::vector getLibrarySearchPaths(opt::InputArgList &args) { + std::vector paths; + for (auto const &path : args::getStrings(args, OPT_L)) { + if (isDirectory("L", path)) + paths.push_back(path); + } + if (!args.hasArg(OPT_Z) && Triple(sys::getProcessTriple()).isOSDarwin()) { + StringRef usrLib("/usr/lib"); + StringRef usrLocalLib("/usr/local/lib"); + if (isDirectory("L", usrLib)) + paths.push_back(usrLib); + if (isDirectory("L", usrLocalLib)) + paths.push_back(usrLocalLib); + } + return paths; +} + +static std::vector getFrameworkSearchPaths(opt::InputArgList &args) { + std::vector paths; + for (auto const &path : args::getStrings(args, OPT_F)) { + if (isDirectory("F", path)) + paths.push_back(path); + } + if (!args.hasArg(OPT_Z) && Triple(sys::getProcessTriple()).isOSDarwin()) { + StringRef libFrames("/Library/Frameworks"); + StringRef sysLibFrames("/System/Library/Frameworks"); + if (isDirectory("F", libFrames)) + paths.push_back(libFrames); + if (isDirectory("F", sysLibFrames)) + paths.push_back(sysLibFrames); } - return ret; + return paths; } static void addFile(StringRef path) { @@ -331,14 +368,20 @@ config->outputFile = args.getLastArgValue(OPT_o, "a.out"); config->installName = args.getLastArgValue(OPT_install_name, config->outputFile); - config->searchPaths = getSearchPaths(args); + config->librarySearchPaths = getLibrarySearchPaths(args); + config->frameworkSearchPaths = getFrameworkSearchPaths(args); config->outputType = args.hasArg(OPT_dylib) ? MH_DYLIB : MH_EXECUTE; if (args.hasArg(OPT_v)) { message(getLLDVersion()); - std::vector &searchPaths = config->searchPaths; - message("Library search paths:\n" + - llvm::join(searchPaths.begin(), searchPaths.end(), "\n")); + message(StringRef("Library search paths:") + + (config->librarySearchPaths.size() + ? "\n\t" + llvm::join(config->librarySearchPaths, "\n\t") + : "")); + message(StringRef("Framework search paths:") + + (config->frameworkSearchPaths.size() + ? "\n\t" + llvm::join(config->frameworkSearchPaths, "\n\t") + : "")); freeArena(); return !errorCount(); } diff --git a/lld/test/MachO/search-paths-darwin.test b/lld/test/MachO/search-paths-darwin.test new file mode 100644 --- /dev/null +++ b/lld/test/MachO/search-paths-darwin.test @@ -0,0 +1,20 @@ +REQUIRES: x86 +REQUIRES: darwin + +RUN: mkdir -p %t1 %t2 + +RUN: lld -flavor darwinnew -arch x86_64 -v -L%t1 -F%t2 2>&1 | FileCheck -DLDIR=%t1 -DFDIR=%t2 %s +CHECK: Library search paths: +CHECK-NEXT: [[LDIR]] +CHECK-NEXT: /usr/lib +CHECK-NEXT: /usr/local/lib +CHECK-NEXT: Framework search paths: +CHECK-NEXT: [[FDIR]] +CHECK-NEXT: /Library/Frameworks +CHECK-NEXT: /System/Library/Frameworks + +RUN: lld -flavor darwinnew -arch x86_64 -v -L%t1 -F%t2 -Z 2>&1 | FileCheck -DLDIR=%t1 -DFDIR=%t2 --check-prefix=CHECK_Z %s +CHECK_Z: Library search paths: +CHECK_Z-NEXT: [[LDIR]] +CHECK_Z-NEXT: Framework search paths: +CHECK_Z-NEXT: [[FDIR]] diff --git a/lld/test/MachO/search-paths.test b/lld/test/MachO/search-paths.test --- a/lld/test/MachO/search-paths.test +++ b/lld/test/MachO/search-paths.test @@ -1,12 +1,15 @@ -RUN: mkdir -p %t +UNSUPPORTED: darwin -RUN: lld -flavor darwinnew -arch x86_64 -v -L%t 2>&1 | FileCheck -DDIR=%t %s +RUN: mkdir -p %t1 %t2 + +RUN: lld -flavor darwinnew -arch x86_64 -v -L%t1 -F%t2 2>&1 | FileCheck -DLDIR=%t1 -DFDIR=%t2 %s CHECK: Library search paths: -CHECK-NEXT: [[DIR]] -CHECK-NEXT: /usr/lib -CHECK-NEXT: /usr/local/lib +CHECK-NEXT: [[LDIR]] +CHECK-NEXT: Framework search paths: +CHECK-NEXT: [[FDIR]] -RUN: lld -flavor darwinnew -arch x86_64 -v -L%t -Z 2>&1 | FileCheck -DDIR=%t --check-prefix=CHECK_Z %s +RUN: lld -flavor darwinnew -arch x86_64 -v -L%t1 -F%t2 -Z 2>&1 | FileCheck -DLDIR=%t1 -DFDIR=%t2 --check-prefix=CHECK_Z %s CHECK_Z: Library search paths: -CHECK_Z-NEXT: [[DIR]] -CHECK_Z-NOT: /usr/ +CHECK_Z-NEXT: [[LDIR]] +CHECK_Z-NEXT: Framework search paths: +CHECK_Z-NEXT: [[FDIR]]