diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -860,14 +860,37 @@ // files. static DylibFile *findDylib(StringRef path, DylibFile *umbrella, const InterfaceFile *currentTopLevelTapi) { + // Search order: + // 1. Install name basename in -F / -L directories. + { + StringRef stem = path::stem(path); + SmallString<128> frameworkName; + path::append(frameworkName, stem + ".framework", stem); + bool isFramework = path.endswith(frameworkName); + if (isFramework) { + for (StringRef dir : config->frameworkSearchPaths) { + SmallString<128> candidate = dir; + path::append(candidate, frameworkName); + if (Optional dylibPath = resolveDylibPath(candidate)) + return loadDylib(*dylibPath, umbrella); + } + } else if (Optional dylibPath = findPathCombination( + stem, config->librarySearchPaths, {".tbd", ".dylib"})) + return loadDylib(*dylibPath, umbrella); + } + + // 2. As absolute path. if (path::is_absolute(path, path::Style::posix)) for (StringRef root : config->systemLibraryRoots) if (Optional dylibPath = resolveDylibPath((root + path).str())) return loadDylib(*dylibPath, umbrella); + // 3. As relative path. + // TODO: Handle -dylib_file + // Replace @executable_path, @loader_path, @rpath prefixes in install name. SmallString<128> newPath; if (config->outputType == MH_EXECUTE && path.consume_front("@executable_path/")) { @@ -894,6 +917,7 @@ } } + // FIXME: Should this be further up? if (currentTopLevelTapi) { for (InterfaceFile &child : make_pointee_range(currentTopLevelTapi->documents())) { diff --git a/lld/test/MachO/sub-library.s b/lld/test/MachO/sub-library.s --- a/lld/test/MachO/sub-library.s +++ b/lld/test/MachO/sub-library.s @@ -86,6 +86,36 @@ # RUN: -o %t/libgoodbye.dylib 2>&1 | FileCheck %s --check-prefix=MISSING-FRAMEWORK # MISSING-FRAMEWORK: error: -sub_umbrella libhello does not match a supplied dylib + +## Check that -F (but not -L) can override the search path in install_name for +## frameworks. +# RUN: mkdir -p %t/Hello2.framework +# RUN: %lld -dylib %t/libhello.o \ +# RUN: -install_name /path/to/Hello2.framework/Hello2 \ +# RUN: -o %t/Hello2.framework/Hello2 +# RUN: %lld -dylib -o %t/libgoodbye4.dylib %t/libgoodbye.o \ +# RUN: -reexport_library %t/Hello2.framework/Hello2 +# RUN: not %lld -lSystem -o %t/hello %t/libgoodbye4.dylib %t/sub-library.o 2>&1 \ +# RUN: | FileCheck %s --check-prefix=NOTFOUND +# RUN: not %lld -lSystem -o %t/hello -L%t %t/libgoodbye4.dylib %t/sub-library.o 2>&1 \ +# RUN: | FileCheck %s --check-prefix=NOTFOUND +# NOTFOUND: unable to locate re-export with install name /path/to/Hello2.framework/Hello2 +# RUN: %lld -lSystem -o %t/hello -F%t %t/libgoodbye4.dylib %t/sub-library.o + +## Check that -L (but not -F) can override the search path in install_name for +## libraries. +# RUN: %lld -dylib %t/libhello.o \ +# RUN: -install_name /path/to/libhello2.dylib \ +# RUN: -o %t/libhello2.dylib +# RUN: %lld -dylib -o %t/libgoodbye5.dylib %t/libgoodbye.o \ +# RUN: -reexport_library %t/libhello2.dylib +# RUN: not %lld -lSystem -o %t/hello %t/libgoodbye5.dylib %t/sub-library.o 2>&1 \ +# RUN: | FileCheck %s --check-prefix=NOTFOUND2 +# RUN: not %lld -lSystem -o %t/hello -F%t %t/libgoodbye5.dylib %t/sub-library.o 2>&1 \ +# RUN: | FileCheck %s --check-prefix=NOTFOUND2 +# NOTFOUND2: unable to locate re-export with install name /path/to/libhello2.dylib +# RUN: %lld -lSystem -o %t/hello -L%t %t/libgoodbye5.dylib %t/sub-library.o + .text .globl _main