[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