diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -27,7 +27,8 @@ llvm::StringRef installName; llvm::StringRef outputFile; llvm::MachO::HeaderFileType outputType; - std::vector searchPaths; + std::vector librarySearchPaths; + 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 @@ -83,7 +83,7 @@ // This is for -lfoo. We'll look for libfoo.dylib from search paths. static Optional findDylib(StringRef name) { - for (StringRef dir : config->searchPaths) { + for (StringRef dir : config->librarySearchPaths) { std::string path = (dir + "/lib" + name + ".dylib").str(); if (fs::exists(path)) return path; @@ -99,8 +99,18 @@ return createX86_64TargetInfo(); } -static std::vector getSearchPaths(opt::InputArgList &args) { +static void checkSearchDirs(StringRef option, std::vector &paths) { + for (const auto &path : paths) { + if (!fs::exists(path)) + warn("directory not found for option -" + option + path); + else if (!fs::is_directory(path)) + warn("option -" + option + path + " references a non-directory path"); + } +} + +static std::vector getLibrarySearchPaths(opt::InputArgList &args) { std::vector ret{args::getStrings(args, OPT_L)}; + checkSearchDirs("L", ret); if (!args.hasArg(OPT_Z)) { ret.push_back("/usr/lib"); ret.push_back("/usr/local/lib"); @@ -108,6 +118,16 @@ return ret; } +static std::vector getFrameworkSearchPaths(opt::InputArgList &args) { + std::vector ret{args::getStrings(args, OPT_F)}; + checkSearchDirs("F", ret); + if (!args.hasArg(OPT_Z)) { + ret.push_back("/Library/Frameworks"); + ret.push_back("/System/Library/Frameworks"); + } + return ret; +} + static void addFile(StringRef path) { Optional buffer = readFile(path); if (!buffer) @@ -378,14 +398,16 @@ 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("Library search paths:\n\t" + + llvm::join(config->librarySearchPaths, "\n\t")); + message("Framework search paths:\n\t" + + llvm::join(config->frameworkSearchPaths, "\n\t")); freeArena(); return !errorCount(); } @@ -396,6 +418,8 @@ switch (opt.getID()) { case OPT_o: case OPT_dylib: + case OPT_L: + case OPT_F: // handled elsewhere ... break; default: 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,45 @@ -RUN: mkdir -p %t - -RUN: lld -flavor darwinnew -v -L%t 2>&1 | FileCheck -DDIR=%t %s -CHECK: Library search paths: -CHECK-NEXT: [[DIR]] -CHECK-NEXT: /usr/lib -CHECK-NEXT: /usr/local/lib - -RUN: lld -flavor darwinnew -v -L%t -Z 2>&1 | FileCheck -DDIR=%t --check-prefix=CHECK_Z %s -CHECK_Z: Library search paths: -CHECK_Z-NEXT: [[DIR]] -CHECK_Z-NOT: /usr/ +RUN: mkdir -p %t1 %t2 %t5 %t6 +RUN: rm -fr %t3 %t4 +RUN: touch %t3 %t4 + +RUN: lld -flavor darwinnew -v -L%t1 -L %t2 -L%t3 -L %t4 -F%t5 -F %t6 -F%t7 -F %t8 2>&1 \ +RUN: | FileCheck -DT1=%t1 -DT2=%t2 -DT3=%t3 -DT4=%t4 -DT5=%t5 -DT6=%t6 -DT7=%t7 -DT8=%t8 --check-prefix=CHECK_noZ %s + +CHECK_noZ: warning: option -L[[T3]] references a non-directory path +CHECK_noZ-NEXT: warning: option -L[[T4]] references a non-directory path +CHECK_noZ-NEXT: warning: directory not found for option -F[[T7]] +CHECK_noZ-NEXT: warning: directory not found for option -F[[T8]] +CHECK_noZ-NEXT: LLD {{[0-9.]+ .*}} +CHECK_noZ-NEXT: Library search paths: +CHECK_noZ-NEXT: [[T1]] +CHECK_noZ-NEXT: [[T2]] +CHECK_noZ-NEXT: [[T3]] +CHECK_noZ-NEXT: [[T4]] +CHECK_noZ-NEXT: /usr/lib +CHECK_noZ-NEXT: /usr/local/lib +CHECK_noZ-NEXT: Framework search paths: +CHECK_noZ-NEXT: [[T5]] +CHECK_noZ-NEXT: [[T6]] +CHECK_noZ-NEXT: [[T7]] +CHECK_noZ-NEXT: [[T8]] +CHECK_noZ-NEXT: /Library/Frameworks +CHECK_noZ-NEXT: /System/Library/Frameworks + +RUN: lld -flavor darwinnew -v -L%t1 -L %t2 -L%t3 -L %t4 -F%t5 -F %t6 -F%t7 -F %t8 -Z 2>&1 \ +RUN: | FileCheck -DT1=%t1 -DT2=%t2 -DT3=%t3 -DT4=%t4 -DT5=%t5 -DT6=%t6 -DT7=%t7 -DT8=%t8 --check-prefix=CHECK_Z %s + +CHECK_Z: warning: option -L[[T3]] references a non-directory path +CHECK_Z-NEXT: warning: option -L[[T4]] references a non-directory path +CHECK_Z-NEXT: warning: directory not found for option -F[[T7]] +CHECK_Z-NEXT: warning: directory not found for option -F[[T8]] +CHECK_Z-NEXT: LLD {{[0-9.]+ .*}} +CHECK_Z-NEXT: Library search paths: +CHECK_Z-NEXT: [[T1]] +CHECK_Z-NEXT: [[T2]] +CHECK_Z-NEXT: [[T3]] +CHECK_Z-NEXT: [[T4]] +CHECK_Z-NEXT: Framework search paths: +CHECK_Z-NEXT: [[T5]] +CHECK_Z-NEXT: [[T6]] +CHECK_Z-NEXT: [[T7]] +CHECK_Z-NEXT: [[T8]]