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 @@ -30,6 +30,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" @@ -86,7 +87,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); @@ -110,13 +111,42 @@ } } -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(StringRef option, 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 void getSearchPaths(std::vector &paths, unsigned optionCode, + opt::InputArgList &args, + const SmallVector &systemPaths) { + StringRef optionLetter{(optionCode == OPT_F ? "F" : "L")}; + for (auto const &path : args::getStrings(args, optionCode)) { + if (isDirectory(optionLetter, path)) + paths.push_back(path); } - return ret; + if (!args.hasArg(OPT_Z) && Triple(sys::getProcessTriple()).isOSDarwin()) { + for (auto const &path : systemPaths) { + if (isDirectory(optionLetter, path)) + paths.push_back(path); + } + } +} + +static void getLibrarySearchPaths(std::vector &paths, + opt::InputArgList &args) { + getSearchPaths(paths, OPT_L, args, {"/usr/lib", "/usr/local/lib"}); +} + +static void getFrameworkSearchPaths(std::vector &paths, + opt::InputArgList &args) { + getSearchPaths(paths, OPT_F, args, + {"/Library/Frameworks", "/System/Library/Frameworks"}); } static void addFile(StringRef path) { @@ -330,14 +360,20 @@ config->outputFile = args.getLastArgValue(OPT_o, "a.out"); config->installName = args.getLastArgValue(OPT_install_name, config->outputFile); - config->searchPaths = getSearchPaths(args); + getLibrarySearchPaths(config->librarySearchPaths, args); + getFrameworkSearchPaths(config->frameworkSearchPaths, 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.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 -v -L%t 2>&1 | FileCheck -DDIR=%t %s +RUN: mkdir -p %t1 %t2 + +RUN: lld -flavor darwinnew -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 -v -L%t -Z 2>&1 | FileCheck -DDIR=%t --check-prefix=CHECK_Z %s +RUN: lld -flavor darwinnew -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]]