[lld] r212706 - [mach-o]: support -syslibroot and -l options

Tim Northover tnorthover at apple.com
Thu Jul 10 04:21:06 PDT 2014


Author: tnorthover
Date: Thu Jul 10 06:21:06 2014
New Revision: 212706

URL: http://llvm.org/viewvc/llvm-project?rev=212706&view=rev
Log:
[mach-o]: support -syslibroot and -l options

These behave slightly idiosyncratically in the best of cases, and have
additional hacks layered on top of that for compatibility with badly behaved
build systems (via ld64).

For -lXYZ:
  + If XYZ is actually XY.o then search all library paths for XY.o
  + Otherwise search all library paths, first for libXYZ.dylib, then libXYZ.a
  + By default the library paths are /usr/lib and /usr/local/lib in that order.

For -syslibroot:
  + -syslibroot options apply to absolute paths in the search order.
  + All -syslibroot prefixes that exist are added to the search path *instead*
    of the original.
  + If no -syslibroot prefixed path exists, the original is kept.
  + Hacks^WExceptions:
      + If only 1 -syslibroot is given and doesn't contain /usr/lib or
        /usr/local/lib, that path is dropped entirely. (rdar://problem/6438270).
      + If the last -syslibroot is "/", all of them are ignored entirely.
        (rdar://problem/5829579).

At least, that's my best interpretation of what ld64 does in buildSearchPaths.

Added:
    lld/trunk/test/mach-o/Inputs/lib-search-paths/
    lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/
    lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/lib/
    lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/lib/libmyshared.dylib   (with props)
    lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/lib/libmystatic.a
    lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/local/
    lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/local/lib/
    lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/local/lib/file.o
    lld/trunk/test/mach-o/lib-search-paths.yaml
    lld/trunk/test/mach-o/libresolve-bizarre-root-override.yaml
    lld/trunk/test/mach-o/libresolve-multiple-syslibroots.yaml
    lld/trunk/test/mach-o/libresolve-one-syslibroot.yaml
    lld/trunk/test/mach-o/libresolve-simple.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=212706&r1=212705&r2=212706&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Thu Jul 10 06:21:06 2014
@@ -17,6 +17,8 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MachO.h"
 
+#include <set>
+
 using llvm::MachO::HeaderFileType;
 
 namespace lld {
@@ -78,6 +80,38 @@ public:
   void setDoNothing(bool value) { _doNothing = value; }
   bool doNothing() const { return _doNothing; }
   bool printAtoms() const { return _printAtoms; }
+  bool testingLibResolution() const { return _testingLibResolution; }
+  const StringRefVector &searchDirs() const { return _searchDirs; }
+
+  /// \brief Checks whether a given path on the filesystem exists.
+  ///
+  /// When running in -test_libresolution mode, this method consults an
+  /// internally maintained list of files that exist (provided by -path_exists)
+  /// instead of the actual filesystem.
+  bool pathExists(StringRef path) const;
+
+  /// \brief Adds any library search paths derived from the given base, possibly
+  /// modified by -syslibroots.
+  ///
+  /// The set of paths added consists of approximately all syslibroot-prepended
+  /// versions of libPath that exist, or the original libPath if there are none
+  /// for whatever reason. With various edge-cases for compatibility.
+  void addModifiedSearchDir(StringRef libPath,
+                            const StringRefVector &syslibRoots,
+                            bool isSystemPath = false);
+
+  /// \brief Determine whether -lFoo can be resolve within the given path, and
+  /// return the filename if so.
+  ///
+  /// The -lFoo option is documented to search for libFoo.dylib and libFoo.a in
+  /// that order, unless Foo ends in ".o", in which case only the exact file
+  /// matches (e.g. -lfoo.o would only find foo.o).
+  ErrorOr<StringRef> searchDirForLibrary(StringRef path,
+                                         StringRef libName) const;
+
+  /// \brief Iterates through all search path entries lookinf for libName (as
+  /// specified by -lFoo).
+  ErrorOr<StringRef> searchLibrary(StringRef libName) const;
 
   /// \brief The dylib's binary compatibility version, in the raw uint32 format.
   ///
@@ -125,6 +159,13 @@ public:
   }
   void setBundleLoader(StringRef loader) { _bundleLoader = loader; }
   void setPrintAtoms(bool value=true) { _printAtoms = value; }
+  void setTestingLibResolution(bool value = true) {
+    _testingLibResolution = value;
+  }
+  void addExistingPathForDebug(StringRef path) {
+    _existingPaths.insert(path);
+  }
+
   StringRef dyldPath() const { return "/usr/lib/dyld"; }
 
   static Arch archFromCpuType(uint32_t cputype, uint32_t cpusubtype);
@@ -153,6 +194,8 @@ private:
 
   static ArchInfo _s_archInfos[];
 
+  std::set<StringRef> _existingPaths; // For testing only.
+  StringRefVector _searchDirs;
   HeaderFileType _outputMachOType;   // e.g MH_EXECUTE
   bool _outputMachOTypeStatic; // Disambiguate static vs dynamic prog
   bool _doNothing;            // for -help and -v which just print info
@@ -166,6 +209,7 @@ private:
   StringRef _installName;
   bool _deadStrippableDylib;
   bool _printAtoms;
+  bool _testingLibResolution;
   StringRef _bundleLoader;
   mutable std::unique_ptr<mach_o::KindHandler> _kindHandler;
   mutable std::unique_ptr<Writer> _writer;

Modified: lld/trunk/lib/Driver/DarwinLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=212706&r1=212705&r2=212706&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/DarwinLdDriver.cpp Thu Jul 10 06:21:06 2014
@@ -263,12 +263,76 @@ bool DarwinLdDriver::parse(int argc, con
   if (parsedArgs->getLastArg(OPT_print_atoms))
     ctx.setPrintAtoms();
 
+  // In -test_libresolution mode, we'll be given an explicit list of paths that
+  // exist. We'll also be expected to print out information about how we located
+  // libraries and so on that the user specified, but not to actually do any
+  // linking.
+  if (parsedArgs->getLastArg(OPT_test_libresolution)) {
+    ctx.setTestingLibResolution();
+
+    // With paths existing by fiat, linking is not going to end well.
+    ctx.setDoNothing(true);
+
+    // Only bother looking for an existence override if we're going to use it.
+    for (auto existingPath : parsedArgs->filtered(OPT_path_exists)) {
+      ctx.addExistingPathForDebug(existingPath->getValue());
+    }
+  }
+
   std::unique_ptr<InputGraph> inputGraph(new InputGraph());
 
+  // Now construct the set of library search directories, following ld64's
+  // baroque set of accumulated hacks. Mostly, the algorithm constructs
+  //     { syslibroots } x { libpaths }
+  //
+  // Unfortunately, there are numerous exceptions:
+  //   1. Only absolute paths get modified by syslibroot options.
+  //   2. If there is just 1 -syslibroot, system paths not found in it are
+  //      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)) {
+    syslibRoots.push_back(syslibRoot->getValue());
+  }
+
+  // FIXME: handle -L options: these get added *before* the default paths,
+  // possibly modified by any syslibroot options.
+  ctx.addModifiedSearchDir("/usr/lib", syslibRoots, true);
+  ctx.addModifiedSearchDir("/usr/local/lib", syslibRoots, true);
+
+  // Now that we've constructed the final set of search paths, print out what
+  // we'll be using for testing purposes.
+  if (ctx.testingLibResolution()) {
+    diagnostics << "Library search paths:\n";
+    for (auto path : ctx.searchDirs()) {
+      diagnostics << "    " << path << '\n';
+    }
+  }
+
   // Handle input files
-  for (auto &inputFile : parsedArgs->filtered(OPT_INPUT)) {
+  for (auto &arg : *parsedArgs) {
+    StringRef inputPath;
+    switch (arg->getOption().getID()) {
+    default:
+      continue;
+    case OPT_INPUT:
+      inputPath = arg->getValue();
+      break;
+    case OPT_l: {
+      ErrorOr<StringRef> resolvedPath = ctx.searchLibrary(arg->getValue());
+      if (!resolvedPath) {
+        diagnostics << "Unable to find library -l" << arg->getValue() << "\n";
+        return false;
+      } else if (ctx.testingLibResolution()) {
+        diagnostics << "Found library " << resolvedPath.get() << '\n';
+      }
+      inputPath = resolvedPath.get();
+      break;
+    }
+    }
     inputGraph->addInputElement(std::unique_ptr<InputElement>(
-        new MachOFileNode(ctx, inputFile->getValue(), globalWholeArchive)));
+        new MachOFileNode(ctx, inputPath, globalWholeArchive)));
   }
 
   if (!inputGraph->size()) {

Modified: lld/trunk/lib/Driver/DarwinLdOptions.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdOptions.td?rev=212706&r1=212705&r2=212706&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdOptions.td (original)
+++ lld/trunk/lib/Driver/DarwinLdOptions.td Thu Jul 10 06:21:06 2014
@@ -69,10 +69,23 @@ def L : Joined<["-"], "L">,
 def all_load : Flag<["-"], "all_load">,
         HelpText<"Forces all members of all static libraries to be loaded">,
         Group<grp_libs>;
+def syslibroot : Separate<["-"], "syslibroot">,
+        HelpText<"Add path to SDK to all absolute library search paths">,
+        Group<grp_libs>;
+
+// Input options
+def l : Joined<["-"], "l">,
+        HelpText<"Base name of library searched for in -L directories">;
 
 // test case options
-def print_atoms : Flag<["-"], "print_atoms">, 
+def print_atoms : Flag<["-"], "print_atoms">,
         HelpText<"Emit output as yaml atoms">;
+def test_libresolution : Flag<["-"], "test_libresolution">,
+        HelpText<"Only files specified by -file_exists are considered to exist."
+                 " Print debugging information during resolution">;
+def path_exists : Separate<["-"], "path_exists">,
+        HelpText<"When used with -test_libresolution, only these paths exist">;
+
 
 // general options
 def output : Separate<["-"], "o">, HelpText<"Output file path">;

Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=212706&r1=212705&r2=212706&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Thu Jul 10 06:21:06 2014
@@ -20,8 +20,10 @@
 
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/Support/Errc.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/MachO.h"
+#include "llvm/Support/Path.h"
 
 using lld::mach_o::KindHandler;
 using namespace llvm::MachO;
@@ -123,7 +125,7 @@ MachOLinkingContext::MachOLinkingContext
       _doNothing(false), _arch(arch_unknown), _os(OS::macOSX), _osMinVersion(0),
       _pageZeroSize(0), _pageSize(4096), _compatibilityVersion(0),
       _currentVersion(0), _deadStrippableDylib(false), _printAtoms(false),
-      _kindHandler(nullptr) {}
+      _testingLibResolution(false), _kindHandler(nullptr) {}
 
 MachOLinkingContext::~MachOLinkingContext() {}
 
@@ -262,6 +264,87 @@ bool MachOLinkingContext::addUnixThreadL
   }
 }
 
+bool MachOLinkingContext::pathExists(StringRef path) const {
+  if (!testingLibResolution())
+    return llvm::sys::fs::exists(path.str());
+
+  // Otherwise, we're in test mode: only files explicitly provided on the
+  // command-line exist.
+  return _existingPaths.find(path) != _existingPaths.end();
+}
+
+void MachOLinkingContext::addModifiedSearchDir(
+    StringRef libPath, const StringRefVector &syslibRoots, 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() != "/" &&
+      llvm::sys::path::is_absolute(libPath)) {
+    for (auto syslibRoot : syslibRoots) {
+      SmallString<256> path(syslibRoot);
+      llvm::sys::path::append(path, libPath);
+      if (pathExists(path)) {
+        _searchDirs.push_back(path.str().copy(_allocator));
+        addedModifiedPath = true;
+      }
+    }
+  }
+
+  if (addedModifiedPath)
+    return;
+
+  // Finally, if only one -syslibroot is given, system paths which aren't in it
+  // get suppressed.
+  if (syslibRoots.size() != 1 || !isSystemPath) {
+    if (pathExists(libPath)) {
+      _searchDirs.push_back(libPath);
+    }
+  }
+}
+
+ErrorOr<StringRef>
+MachOLinkingContext::searchDirForLibrary(StringRef path,
+                                         StringRef libName) const {
+  SmallString<256> fullPath;
+  if (libName.endswith(".o")) {
+    // A request ending in .o is special: just search for the file directly.
+    fullPath.assign(path);
+    llvm::sys::path::append(fullPath, libName);
+    if (pathExists(fullPath))
+      return fullPath.str().copy(_allocator);
+    return make_error_code(llvm::errc::no_such_file_or_directory);
+  }
+
+  // Search for dynamic library
+  fullPath.assign(path);
+  llvm::sys::path::append(fullPath, Twine("lib") + libName + ".dylib");
+  if (pathExists(fullPath))
+    return fullPath.str().copy(_allocator);
+
+  // If not, try for a static library
+  fullPath.assign(path);
+  llvm::sys::path::append(fullPath, Twine("lib") + libName + ".a");
+  if (pathExists(fullPath))
+    return fullPath.str().copy(_allocator);
+
+  return make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
+
+
+ErrorOr<StringRef> MachOLinkingContext::searchLibrary(StringRef libName) const {
+  SmallString<256> path;
+  for (StringRef dir : searchDirs()) {
+    ErrorOr<StringRef> ec = searchDirForLibrary(dir, libName);
+    if (ec)
+      return ec;
+  }
+
+  return make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
 bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
   // TODO: if -arch not specified, look at arch of first .o file.
 

Added: lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/lib/libmyshared.dylib
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/lib/libmyshared.dylib?rev=212706&view=auto
==============================================================================
Binary files lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/lib/libmyshared.dylib (added) and lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/lib/libmyshared.dylib Thu Jul 10 06:21:06 2014 differ

Propchange: lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/lib/libmyshared.dylib
------------------------------------------------------------------------------
    svn:executable = *

Added: lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/lib/libmystatic.a
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/lib/libmystatic.a?rev=212706&view=auto
==============================================================================
Binary files lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/lib/libmystatic.a (added) and lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/lib/libmystatic.a Thu Jul 10 06:21:06 2014 differ

Added: lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/local/lib/file.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/local/lib/file.o?rev=212706&view=auto
==============================================================================
Binary files lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/local/lib/file.o (added) and lld/trunk/test/mach-o/Inputs/lib-search-paths/usr/local/lib/file.o Thu Jul 10 06:21:06 2014 differ

Added: lld/trunk/test/mach-o/lib-search-paths.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/lib-search-paths.yaml?rev=212706&view=auto
==============================================================================
--- lld/trunk/test/mach-o/lib-search-paths.yaml (added)
+++ lld/trunk/test/mach-o/lib-search-paths.yaml Thu Jul 10 06:21:06 2014
@@ -0,0 +1,16 @@
+# RUN: lld -flavor darwin -arch x86_64 %s -syslibroot %p/Inputs/lib-search-paths -lmyshared -lmystatic -lfile.o -print_atoms 2>&1 -r | FileCheck %s
+
+--- !native
+undefined-atoms:
+    - name: _from_myshared
+    - name: _from_mystatic
+    - name: _from_fileo
+
+# CHECK: defined-atoms:
+# CHECK:   - name:            _from_mystatic
+# CHECK:     content:         [ 02, 00, 00, 00 ]
+# CHECK:   - name:            _from_fileo
+# CHECK:     content:         [ 2A, 00, 00, 00 ]
+# CHECK: shared-library-atoms:
+# CHECK:   - name:            _from_myshared
+# CHECK:     load-name:       libmyshared.dylib

Added: lld/trunk/test/mach-o/libresolve-bizarre-root-override.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/libresolve-bizarre-root-override.yaml?rev=212706&view=auto
==============================================================================
--- lld/trunk/test/mach-o/libresolve-bizarre-root-override.yaml (added)
+++ lld/trunk/test/mach-o/libresolve-bizarre-root-override.yaml Thu Jul 10 06:21:06 2014
@@ -0,0 +1,17 @@
+# RUN: not lld -flavor darwin -test_libresolution \
+# RUN:        -path_exists /usr/lib \
+# RUN:        -path_exists /Applications/MySDK/usr/local/lib \
+# RUN:        -path_exists /Applications/MySDK/usr/lib \
+# RUN:        -path_exists /Applications/MySDK/usr/lib/libSystem.dylib \
+# RUN:        -syslibroot /Applications/MySDK \
+# RUN:        -syslibroot / \
+# RUN:        -lSystem \
+# RUN: 2>&1 | FileCheck %s
+
+# When the last -syslibroot is simply "/", all of them get discarded. So in this
+# case, only /usr/lib should show up.
+
+# CHECK: Library search paths:
+# CHECK:     /usr/lib
+# CHECK-NOT:     /usr/local/lib
+# CHECK: Unable to find library -lSystem

Added: lld/trunk/test/mach-o/libresolve-multiple-syslibroots.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/libresolve-multiple-syslibroots.yaml?rev=212706&view=auto
==============================================================================
--- lld/trunk/test/mach-o/libresolve-multiple-syslibroots.yaml (added)
+++ lld/trunk/test/mach-o/libresolve-multiple-syslibroots.yaml Thu Jul 10 06:21:06 2014
@@ -0,0 +1,17 @@
+# RUN: lld -flavor darwin -test_libresolution \
+# RUN:        -path_exists /usr/lib \
+# RUN:        -path_exists /Applications/MyFirstSDK/usr/local/lib \
+# RUN:        -path_exists /Applications/MySecondSDK/usr/local/lib \
+# RUN:        -path_exists /Applications/MyFirstSDK/usr/local/lib/libSystem.a \
+# RUN:        -path_exists /Applications/MySecondSDK/usr/local/lib/libSystem.a \
+# RUN:        -syslibroot /Applications/MyFirstSDK \
+# RUN:        -syslibroot /Applications/MySecondSDK \
+# RUN:        -lSystem \
+# RUN: 2>&1 | FileCheck %s
+
+
+# CHECK: Library search paths:
+# CHECK:     /usr/lib
+# CHECK:     /Applications/MyFirstSDK/usr/local/lib
+# CHECK:     /Applications/MySecondSDK/usr/local/lib
+# CHECK: Found library /Applications/MyFirstSDK/usr/local/lib/libSystem.a

Added: lld/trunk/test/mach-o/libresolve-one-syslibroot.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/libresolve-one-syslibroot.yaml?rev=212706&view=auto
==============================================================================
--- lld/trunk/test/mach-o/libresolve-one-syslibroot.yaml (added)
+++ lld/trunk/test/mach-o/libresolve-one-syslibroot.yaml Thu Jul 10 06:21:06 2014
@@ -0,0 +1,19 @@
+# RUN: lld -flavor darwin -test_libresolution \
+# RUN:        -path_exists /usr/lib \
+# RUN:        -path_exists /Applications/MySDK/usr/local/lib \
+# RUN:        -path_exists /Applications/MySDK/usr/local/lib/libSystem.a \
+# RUN:        -syslibroot /Applications/MySDK \
+# RUN:        -lSystem \
+# RUN: 2>&1 | FileCheck %s
+
+# When just one -syslibroot is specified, we apparently want to skip *system*
+# paths that aren't found. User ones should still get added. In this case
+# /usr/lib exists, but not the equivalent in the -syslibroot, so there should be
+# no mention of /usr/lib.
+
+# CHECK: Library search paths:
+# CHECK-NOT:     /usr/lib
+# CHECK-NOT:     /usr/local/lib
+# CHECK:     /Applications/MySDK/usr/local/lib
+# CHECK-NOT:     /usr/local/lib
+# CHECK: Found library /Applications/MySDK/usr/local/lib/libSystem.a

Added: lld/trunk/test/mach-o/libresolve-simple.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/libresolve-simple.yaml?rev=212706&view=auto
==============================================================================
--- lld/trunk/test/mach-o/libresolve-simple.yaml (added)
+++ lld/trunk/test/mach-o/libresolve-simple.yaml Thu Jul 10 06:21:06 2014
@@ -0,0 +1,11 @@
+# RUN: lld -flavor darwin -arch x86_64 -r -test_libresolution \
+# RUN:        -path_exists /usr/lib \
+# RUN:        -path_exists /usr/local/lib \
+# RUN:        -path_exists /usr/lib/libSystem.dylib \
+# RUN:        -lSystem \
+# RUN: 2>&1 | FileCheck %s
+
+# CHECK: Library search paths:
+# CHECK:     /usr/lib
+# CHECK:     /usr/local/lib
+# CHECK: Found library /usr/lib/libSystem.dylib





More information about the llvm-commits mailing list