[lld] r219039 - [mach-o] Add support for -dependency_info command line option

Nick Kledzik kledzik at apple.com
Fri Oct 3 17:16:13 PDT 2014


Author: kledzik
Date: Fri Oct  3 19:16:13 2014
New Revision: 219039

URL: http://llvm.org/viewvc/llvm-project?rev=219039&view=rev
Log:
[mach-o] Add support for -dependency_info command line option

This option is added by Xcode when it runs the linker.  It produces a binary
file which contains the file the linker used.  Xcode uses the info to
dynamically update it dependency tracking.

To check the content of the binary file, the test case uses a python script
to dump the binary file as text which FileCheck can check.

Added:
    lld/trunk/test/mach-o/Inputs/DependencyDump.py   (with props)
    lld/trunk/test/mach-o/dependency_info.yaml
Modified:
    lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
    lld/trunk/lib/Driver/DarwinInputGraph.cpp
    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=219039&r1=219038&r2=219039&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Fri Oct  3 19:16:13 2014
@@ -99,7 +99,12 @@ public:
   void setKeepPrivateExterns(bool v) { _keepPrivateExterns = v; }
   bool demangleSymbols() const { return _demangle; }
   void setDemangleSymbols(bool d) { _demangle = d; }
-
+  /// Create file at specified path which will contain a binary encoding
+  /// of all input and output file paths.
+  std::error_code createDependencyFile(StringRef path);
+  void addInputFileDependency(StringRef path) const;
+  void addInputFileNotFound(StringRef path) const;
+  void addOutputFileDependency(StringRef path) const;
 
   bool minOS(StringRef mac, StringRef iOS) const;
   void setDoNothing(bool value) { _doNothing = value; }
@@ -123,6 +128,9 @@ public:
   /// instead of the actual filesystem.
   bool pathExists(StringRef path) const;
 
+  /// Like pathExists() but only used on files - not directories.
+  bool fileExists(StringRef path) const;
+
   /// \brief Adds any library search paths derived from the given base, possibly
   /// modified by -syslibroots.
   ///
@@ -304,6 +312,7 @@ private:
   mutable std::vector<std::unique_ptr<class MachOFileNode>> _indirectDylibs;
   ExportMode _exportMode;
   llvm::StringSet<> _exportedSymbols;
+  std::unique_ptr<llvm::raw_fd_ostream> _dependencyInfo;
 };
 
 } // end namespace lld

Modified: lld/trunk/lib/Driver/DarwinInputGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinInputGraph.cpp?rev=219039&r1=219038&r2=219039&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinInputGraph.cpp (original)
+++ lld/trunk/lib/Driver/DarwinInputGraph.cpp Fri Oct  3 19:16:13 2014
@@ -30,6 +30,7 @@ std::error_code MachOFileNode::parse(con
   if (std::error_code ec = getBuffer(*filePath))
     return ec;
 
+  _context.addInputFileDependency(*filePath);
   if (ctx.logInputFiles())
     diagnostics << *filePath << "\n";
 

Modified: lld/trunk/lib/Driver/DarwinLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=219039&r1=219038&r2=219039&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/DarwinLdDriver.cpp Fri Oct  3 19:16:13 2014
@@ -100,6 +100,7 @@ static std::error_code parseExportsList(
                                    MemoryBuffer::getFileOrSTDIN(exportFilePath);
   if (std::error_code ec = mb.getError())
     return ec;
+  ctx.addInputFileDependency(exportFilePath);
   StringRef buffer = mb->get()->getBuffer();
   while (!buffer.empty()) {
     // Split off each line in the file.
@@ -134,6 +135,7 @@ static std::error_code parseFileList(Str
   std::pair<StringRef, StringRef> opt = fileListPath.split(',');
   StringRef filePath = opt.first;
   StringRef dirName = opt.second;
+  ctx.addInputFileDependency(filePath);
   // Map in file list file.
   ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
                                         MemoryBuffer::getFileOrSTDIN(filePath);
@@ -436,6 +438,16 @@ bool DarwinLdDriver::parse(int argc, con
       diagnostics << "warning: -keep_private_externs only used in -r mode\n";
   }
 
+  // Handle -dependency_info <path> used by Xcode.
+  if (llvm::opt::Arg *depInfo = parsedArgs->getLastArg(OPT_dependency_info)) {
+    if (std::error_code ec = ctx.createDependencyFile(depInfo->getValue())) {
+      diagnostics << "warning: " << ec.message()
+                  << ", processing '-dependency_info "
+                  << depInfo->getValue()
+                  << "'\n";
+    }
+  }
+
   // In -test_file_usage 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

Modified: lld/trunk/lib/Driver/DarwinLdOptions.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdOptions.td?rev=219039&r1=219038&r2=219039&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdOptions.td (original)
+++ lld/trunk/lib/Driver/DarwinLdOptions.td Fri Oct  3 19:16:13 2014
@@ -146,6 +146,9 @@ def image_base : Separate<["-"], "image_
 def seg1addr : Separate<["-"], "seg1addr">, Alias<image_base>;
 def demangle : Flag<["-"], "demangle">,
      HelpText<"Demangles symbol names in errors and warnings">;
+def dependency_info : Separate<["-"], "dependency_info">,
+     MetaVarName<"<file>">,
+     HelpText<"Write binary list of files used during link">;
 
 def t : Flag<["-"], "t">,
      HelpText<"Print the names of the input files as ld processes them">;

Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=219039&r1=219038&r2=219039&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Fri Oct  3 19:16:13 2014
@@ -357,6 +357,19 @@ bool MachOLinkingContext::pathExists(Str
   return _existingPaths.find(key) != _existingPaths.end();
 }
 
+bool MachOLinkingContext::fileExists(StringRef path) const {
+  bool found = pathExists(path);
+  // Log search misses.
+  if (!found)
+    addInputFileNotFound(path);
+
+  // When testing, file is never opened, so logging is done here.
+  if (_testingFileUsage && found)
+    addInputFileDependency(path);
+
+  return found;
+}
+
 void MachOLinkingContext::setSysLibRoots(const StringRefVector &paths) {
   _syslibRoots = paths;
 }
@@ -426,7 +439,7 @@ MachOLinkingContext::searchDirForLibrary
     // 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))
+    if (fileExists(fullPath))
       return fullPath.str().copy(_allocator);
     return make_error_code(llvm::errc::no_such_file_or_directory);
   }
@@ -434,13 +447,13 @@ MachOLinkingContext::searchDirForLibrary
   // Search for dynamic library
   fullPath.assign(path);
   llvm::sys::path::append(fullPath, Twine("lib") + libName + ".dylib");
-  if (pathExists(fullPath))
+  if (fileExists(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))
+  if (fileExists(fullPath))
     return fullPath.str().copy(_allocator);
 
   return make_error_code(llvm::errc::no_such_file_or_directory);
@@ -465,7 +478,7 @@ ErrorOr<StringRef> MachOLinkingContext::
   for (StringRef dir : frameworkDirs()) {
     fullPath.assign(dir);
     llvm::sys::path::append(fullPath, Twine(fwName) + ".framework", fwName);
-    if (pathExists(fullPath))
+    if (fileExists(fullPath))
       return fullPath.str().copy(_allocator);
   }
 
@@ -520,6 +533,8 @@ bool MachOLinkingContext::validateImpl(r
     }
   }
 
+  addOutputFileDependency(outputPath());
+
   return true;
 }
 
@@ -692,5 +707,52 @@ std::string MachOLinkingContext::demangl
   return symbolName;
 }
 
+std::error_code MachOLinkingContext::createDependencyFile(StringRef path) {
+  std::error_code ec;
+  _dependencyInfo = std::unique_ptr<llvm::raw_fd_ostream>(new
+                         llvm::raw_fd_ostream(path, ec, llvm::sys::fs::F_None));
+  if (ec) {
+    _dependencyInfo.reset();
+    return ec;
+  }
+
+  char linkerVersionOpcode = 0x00;
+  *_dependencyInfo << linkerVersionOpcode;
+  *_dependencyInfo << "lld";     // FIXME
+  *_dependencyInfo << '\0';
+
+  return std::error_code();
+}
+
+void MachOLinkingContext::addInputFileDependency(StringRef path) const {
+  if (!_dependencyInfo)
+    return;
+
+  char inputFileOpcode = 0x10;
+  *_dependencyInfo << inputFileOpcode;
+  *_dependencyInfo << path;
+  *_dependencyInfo << '\0';
+}
+
+void MachOLinkingContext::addInputFileNotFound(StringRef path) const {
+  if (!_dependencyInfo)
+    return;
+
+  char inputFileOpcode = 0x11;
+  *_dependencyInfo << inputFileOpcode;
+  *_dependencyInfo << path;
+  *_dependencyInfo << '\0';
+}
+
+void MachOLinkingContext::addOutputFileDependency(StringRef path) const {
+  if (!_dependencyInfo)
+    return;
+
+  char outputFileOpcode = 0x40;
+  *_dependencyInfo << outputFileOpcode;
+  *_dependencyInfo << path;
+  *_dependencyInfo << '\0';
+}
+
 
 } // end namespace lld

Added: lld/trunk/test/mach-o/Inputs/DependencyDump.py
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/Inputs/DependencyDump.py?rev=219039&view=auto
==============================================================================
--- lld/trunk/test/mach-o/Inputs/DependencyDump.py (added)
+++ lld/trunk/test/mach-o/Inputs/DependencyDump.py Fri Oct  3 19:16:13 2014
@@ -0,0 +1,30 @@
+# -*- Python -*-
+
+
+#
+# Dump out Xcode binary dependency file.
+#
+
+import sys
+
+f = open(sys.argv[1], "rb")
+byte = f.read(1)
+while byte != '':
+    if byte == '\000':
+        sys.stdout.write("linker-vers: ")
+    elif byte == '\020':
+        sys.stdout.write("input-file:  ")
+    elif byte == '\021':
+        sys.stdout.write("not-found:   ")
+    elif byte == '\100':
+        sys.stdout.write("output-file: ")
+    byte = f.read(1)
+    while byte != '\000':
+        if byte != '\012':
+            sys.stdout.write(byte)
+        byte = f.read(1)
+    sys.stdout.write("\n")
+    byte = f.read(1)
+
+f.close()
+

Propchange: lld/trunk/test/mach-o/Inputs/DependencyDump.py
------------------------------------------------------------------------------
    svn:executable = *

Added: lld/trunk/test/mach-o/dependency_info.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/dependency_info.yaml?rev=219039&view=auto
==============================================================================
--- lld/trunk/test/mach-o/dependency_info.yaml (added)
+++ lld/trunk/test/mach-o/dependency_info.yaml Fri Oct  3 19:16:13 2014
@@ -0,0 +1,21 @@
+#
+# Test -dependency_info option
+#
+# RUN: lld -flavor darwin -arch x86_64 -test_file_usage  \
+# RUN:        -dependency_info %t.info \
+# RUN:        -path_exists /System/Library/Frameworks \
+# RUN:        -path_exists /System/Library/Frameworks/Foo.framework/Foo \
+# RUN:        -path_exists /Custom/Frameworks \
+# RUN:        -path_exists /Custom/Frameworks/Bar.framework/Bar \
+# RUN:        -F/Custom/Frameworks \
+# RUN:        -framework Bar \
+# RUN:        -framework Foo
+# RUN: python %p/Inputs/DependencyDump.py %t.info | FileCheck %s
+
+
+# CHECK: linker-vers: lld
+# CHECK: input-file:  /Custom/Frameworks/Bar.framework/Bar
+# CHECK: not-found:   /Custom/Frameworks/Foo.framework/Foo
+# CHECK: input-file:  /System/Library/Frameworks/Foo.framework/Foo
+# CHECK: output-file: a.out
+





More information about the llvm-commits mailing list