[lld] r215680 - [mach-o] Support -F and -framework options in darwin driver
Nick Kledzik
kledzik at apple.com
Thu Aug 14 15:20:41 PDT 2014
Author: kledzik
Date: Thu Aug 14 17:20:41 2014
New Revision: 215680
URL: http://llvm.org/viewvc/llvm-project?rev=215680&view=rev
Log:
[mach-o] Support -F and -framework options in darwin driver
Darwin has a packaging mechanism for shared libraries and headers called
frameworks. A directory Foo.framework contains a shared library binary file
"Foo" and a subdirectory "Headers". Most OS frameworks are all in one
directory /System/Library/Frameworks/. As a linking convenience, the linker
option "-framework Foo" means search the framework directories specified
with -F (analogous to -L) looking for a shared library Foo.framework/Foo.
Added:
lld/trunk/test/mach-o/framework-user-paths.yaml
Modified:
lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
lld/trunk/lib/Driver/DarwinLdDriver.cpp
lld/trunk/lib/Driver/DarwinLdOptions.td
lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
Modified: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=215680&r1=215679&r2=215680&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Thu Aug 14 17:20:41 2014
@@ -85,7 +85,8 @@ public:
bool printAtoms() const { return _printAtoms; }
bool testingLibResolution() const { return _testingLibResolution; }
const StringRefVector &searchDirs() const { return _searchDirs; }
- void addSysLibRoot(StringRef sysPath) { _syslibRoots.push_back(sysPath); }
+ const StringRefVector &frameworkDirs() const { return _frameworkDirs; }
+ void setSysLibRoots(const StringRefVector &paths);
const StringRefVector &sysLibRoots() const { return _syslibRoots; }
/// \brief Checks whether a given path on the filesystem exists.
@@ -112,10 +113,18 @@ public:
ErrorOr<StringRef> searchDirForLibrary(StringRef path,
StringRef libName) const;
- /// \brief Iterates through all search path entries lookinf for libName (as
+ /// \brief Iterates through all search path entries looking for libName (as
/// specified by -lFoo).
ErrorOr<StringRef> searchLibrary(StringRef libName) const;
+ /// Add a framework search path. Internally, this method may be prepended
+ /// the path with syslibroot.
+ void addFrameworkSearchDir(StringRef fwPath, bool isSystemPath = false);
+
+ /// \brief Iterates through all framework directories looking for
+ /// Foo.framework/Foo (when fwName = "Foo").
+ ErrorOr<StringRef> findPathForFramework(StringRef fwName) const;
+
/// \brief The dylib's binary compatibility version, in the raw uint32 format.
///
/// When building a dynamic library, this is the compatibility version that
@@ -231,6 +240,7 @@ private:
std::set<StringRef> _existingPaths; // For testing only.
StringRefVector _searchDirs;
StringRefVector _syslibRoots;
+ StringRefVector _frameworkDirs;
HeaderFileType _outputMachOType; // e.g MH_EXECUTE
bool _outputMachOTypeStatic; // Disambiguate static vs dynamic prog
bool _doNothing; // for -help and -v which just print info
Modified: lld/trunk/lib/Driver/DarwinLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=215680&r1=215679&r2=215680&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/DarwinLdDriver.cpp Thu Aug 14 17:20:41 2014
@@ -321,8 +321,14 @@ bool DarwinLdDriver::parse(int argc, con
// skipped.
// 3. If the last -syslibroot is "/", all of them are ignored entirely.
// 4. If { syslibroots } x path == {}, the original path is kept.
+ std::vector<StringRef> sysLibRoots;
for (auto syslibRoot : parsedArgs->filtered(OPT_syslibroot)) {
- ctx.addSysLibRoot(syslibRoot->getValue());
+ sysLibRoots.push_back(syslibRoot->getValue());
+ }
+ if (!sysLibRoots.empty()) {
+ // Ignore all if last -syslibroot is "/".
+ if (sysLibRoots.back() != "/")
+ ctx.setSysLibRoots(sysLibRoots);
}
// Paths specified with -L come first, and are not considered system paths for
@@ -331,10 +337,17 @@ bool DarwinLdDriver::parse(int argc, con
ctx.addModifiedSearchDir(libPath->getValue());
}
+ // Process -F directories (where to look for frameworks).
+ for (auto fwPath : parsedArgs->filtered(OPT_F)) {
+ ctx.addFrameworkSearchDir(fwPath->getValue());
+ }
+
// -Z suppresses the standard search paths.
if (!parsedArgs->hasArg(OPT_Z)) {
ctx.addModifiedSearchDir("/usr/lib", true);
ctx.addModifiedSearchDir("/usr/local/lib", true);
+ ctx.addFrameworkSearchDir("/Library/Frameworks", true);
+ ctx.addFrameworkSearchDir("/System/Library/Frameworks", true);
}
// Now that we've constructed the final set of search paths, print out what
@@ -344,6 +357,10 @@ bool DarwinLdDriver::parse(int argc, con
for (auto path : ctx.searchDirs()) {
diagnostics << " " << path << '\n';
}
+ diagnostics << "Framework search paths:\n";
+ for (auto path : ctx.frameworkDirs()) {
+ diagnostics << " " << path << '\n';
+ }
}
// Handle input files
@@ -370,6 +387,21 @@ bool DarwinLdDriver::parse(int argc, con
inputPath = resolvedPath.get();
break;
}
+ case OPT_framework: {
+ ErrorOr<StringRef> fullPath = ctx.findPathForFramework(arg->getValue());
+ if (!fullPath) {
+ diagnostics << "Unable to find -framework " << arg->getValue() << "\n";
+ return false;
+ } else if (ctx.testingLibResolution()) {
+ // Test may be running on Windows. Canonicalize the path
+ // separator to '/' to get consistent outputs for tests.
+ std::string path = fullPath.get();
+ std::replace(path.begin(), path.end(), '\\', '/');
+ diagnostics << "Found framework " << path << '\n';
+ }
+ inputPath = fullPath.get();
+ break;
+ }
}
inputGraph->addInputElement(std::unique_ptr<InputElement>(
new MachOFileNode(inputPath, globalWholeArchive)));
Modified: lld/trunk/lib/Driver/DarwinLdOptions.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdOptions.td?rev=215680&r1=215679&r2=215680&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdOptions.td (original)
+++ lld/trunk/lib/Driver/DarwinLdOptions.td Thu Aug 14 17:20:41 2014
@@ -66,6 +66,8 @@ def bundle_loader : Separate<["-"], "bun
def grp_libs : OptionGroup<"libs">, HelpText<"LIBRARY OPTIONS">;
def L : JoinedOrSeparate<["-"], "L">,
HelpText<"Add directory to library search path">, Group<grp_libs>;
+def F : JoinedOrSeparate<["-"], "F">,
+ HelpText<"Add directory to framework search path">, Group<grp_libs>;
def Z : Flag<["-"], "Z">,
HelpText<"Do not search standard directories for libraries or frameworks">;
def all_load : Flag<["-"], "all_load">,
@@ -78,6 +80,8 @@ def syslibroot : Separate<["-"], "syslib
// Input options
def l : Joined<["-"], "l">,
HelpText<"Base name of library searched for in -L directories">;
+def framework : Separate<["-"], "framework">,
+ HelpText<"Base name of framework searched for in -F directories">;
// test case options
def print_atoms : Flag<["-"], "print_atoms">,
Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=215680&r1=215679&r2=215680&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Thu Aug 14 17:20:41 2014
@@ -307,15 +307,16 @@ bool MachOLinkingContext::pathExists(Str
return _existingPaths.find(key) != _existingPaths.end();
}
+void MachOLinkingContext::setSysLibRoots(const StringRefVector &paths) {
+ _syslibRoots = paths;
+}
+
void MachOLinkingContext::addModifiedSearchDir(StringRef libPath,
bool isSystemPath) {
bool addedModifiedPath = false;
- // Two cases to consider here:
- // + If the last -syslibroot is "/", all of them are ignored (don't ask).
- // + -syslibroot only applies to absolute paths.
- if (!_syslibRoots.empty() && _syslibRoots.back() != "/" &&
- libPath.startswith("/")) {
+ // -syslibroot only applies to absolute paths.
+ if (libPath.startswith("/")) {
for (auto syslibRoot : _syslibRoots) {
SmallString<256> path(syslibRoot);
llvm::sys::path::append(path, libPath);
@@ -338,6 +339,35 @@ void MachOLinkingContext::addModifiedSea
}
}
+void MachOLinkingContext::addFrameworkSearchDir(StringRef fwPath,
+ bool isSystemPath) {
+ bool pathAdded = false;
+
+ // -syslibroot only used with to absolute framework search paths.
+ if (fwPath.startswith("/")) {
+ for (auto syslibRoot : _syslibRoots) {
+ SmallString<256> path(syslibRoot);
+ llvm::sys::path::append(path, fwPath);
+ if (pathExists(path)) {
+ _frameworkDirs.push_back(path.str().copy(_allocator));
+ pathAdded = true;
+ }
+ }
+ }
+ // If fwPath found in any -syslibroot, then done.
+ if (pathAdded)
+ return;
+
+ // If only one -syslibroot, system paths not in that SDK are suppressed.
+ if (isSystemPath && (_syslibRoots.size() == 1))
+ return;
+
+ // Only use raw fwPath if that directory exists.
+ if (pathExists(fwPath))
+ _frameworkDirs.push_back(fwPath);
+}
+
+
ErrorOr<StringRef>
MachOLinkingContext::searchDirForLibrary(StringRef path,
StringRef libName) const {
@@ -377,6 +407,19 @@ ErrorOr<StringRef> MachOLinkingContext::
}
return make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
+
+ErrorOr<StringRef> MachOLinkingContext::findPathForFramework(StringRef fwName) const{
+ SmallString<256> fullPath;
+ for (StringRef dir : frameworkDirs()) {
+ fullPath.assign(dir);
+ llvm::sys::path::append(fullPath, Twine(fwName) + ".framework", fwName);
+ if (pathExists(fullPath))
+ return fullPath.str().copy(_allocator);
+ }
+
+ return make_error_code(llvm::errc::no_such_file_or_directory);
}
bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
Added: lld/trunk/test/mach-o/framework-user-paths.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/framework-user-paths.yaml?rev=215680&view=auto
==============================================================================
--- lld/trunk/test/mach-o/framework-user-paths.yaml (added)
+++ lld/trunk/test/mach-o/framework-user-paths.yaml Thu Aug 14 17:20:41 2014
@@ -0,0 +1,41 @@
+#
+# Test framework and SDK search paths.
+# myFrameworks is not an absolute path, so it should not by found in SDK
+# /Custom/Frameworks should be found in SDK
+# /opt/Frameworks should not be found in SDK
+# /System/Library/Frameworks is implicit and should be in SDK
+#
+# RUN: lld -flavor darwin -arch x86_64 -r -test_libresolution \
+# RUN: -path_exists myFrameworks \
+# RUN: -path_exists myFrameworks/my.framework/my \
+# RUN: -path_exists /opt/Frameworks \
+# RUN: -path_exists /opt/Frameworks/other.framework/other \
+# RUN: -path_exists /Custom/Frameworks \
+# RUN: -path_exists /Custom/Frameworks/Bar.framework/Bar \
+# RUN: -path_exists /System/Library/Frameworks \
+# RUN: -path_exists /System/Library/Frameworks/Foo.framework/Foo \
+# RUN: -path_exists /SDK/myFrameworks \
+# RUN: -path_exists /SDK/myFrameworks/my.framework/my \
+# RUN: -path_exists /SDK/Custom/Frameworks \
+# RUN: -path_exists /SDK/Custom/Frameworks/Bar.framework/Bar \
+# RUN: -path_exists /SDK/System/Library/Frameworks \
+# RUN: -path_exists /SDK/System/Library/Frameworks/Foo.framework/Foo \
+# RUN: -syslibroot /SDK \
+# RUN: -FmyFrameworks \
+# RUN: -F/Custom/Frameworks \
+# RUN: -F/opt/Frameworks \
+# RUN: -framework my \
+# RUN: -framework Bar \
+# RUN: -framework Foo \
+# RUN: -framework other \
+# RUN: 2>&1 | FileCheck %s
+
+# CHECK: Framework search paths:
+# CHECK-NEXT: myFrameworks
+# CHECK-NEXT: /SDK/Custom/Frameworks
+# CHECK-NEXT: /opt/Frameworks
+# CHECK-NEXT: /SDK/System/Library/Frameworks
+# CHECK: Found framework myFrameworks/my.framework/my
+# CHECK: Found framework /SDK/Custom/Frameworks/Bar.framework/Bar
+# CHECK: Found framework /SDK/System/Library/Frameworks/Foo.framework/Foo
+# CHECK: Found framework /opt/Frameworks/other.framework/other
More information about the llvm-commits
mailing list