[lld] r311424 - Integrate manifest merging library into LLD.

Eric Beckmann via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 21 20:15:28 PDT 2017


Author: ecbeckmann
Date: Mon Aug 21 20:15:28 2017
New Revision: 311424

URL: http://llvm.org/viewvc/llvm-project?rev=311424&view=rev
Log:
Integrate manifest merging library into LLD.

Summary: Now that the llvm-mt manifest merging libraries are complete, we may use them to merge manifests instead of needing to shell out to mt.exe.

Subscribers: mgorny, llvm-commits

Differential Revision: https://reviews.llvm.org/D36255

Modified:
    lld/trunk/COFF/CMakeLists.txt
    lld/trunk/COFF/DriverUtils.cpp
    lld/trunk/test/COFF/manifestinput.test
    lld/trunk/test/lit.cfg
    lld/trunk/test/lit.site.cfg.in

Modified: lld/trunk/COFF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/CMakeLists.txt?rev=311424&r1=311423&r2=311424&view=diff
==============================================================================
--- lld/trunk/COFF/CMakeLists.txt (original)
+++ lld/trunk/COFF/CMakeLists.txt Mon Aug 21 20:15:28 2017
@@ -39,6 +39,7 @@ add_lld_library(lldCOFF
   Target
   Option
   Support
+  WindowsManifest
 
   LINK_LIBS
   lldCore

Modified: lld/trunk/COFF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DriverUtils.cpp?rev=311424&r1=311423&r2=311424&view=diff
==============================================================================
--- lld/trunk/COFF/DriverUtils.cpp (original)
+++ lld/trunk/COFF/DriverUtils.cpp Mon Aug 21 20:15:28 2017
@@ -20,6 +20,7 @@
 #include "Symbols.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
 #include "llvm/BinaryFormat/COFF.h"
 #include "llvm/Object/COFF.h"
 #include "llvm/Object/WindowsResource.h"
@@ -32,6 +33,7 @@
 #include "llvm/Support/Process.h"
 #include "llvm/Support/Program.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/WindowsManifest/WindowsManifestMerger.h"
 #include <memory>
 
 using namespace llvm::COFF;
@@ -328,16 +330,9 @@ public:
 };
 }
 
-// Create the default manifest file as a temporary file.
-TemporaryFile createDefaultXml() {
-  // Create a temporary file.
-  TemporaryFile File("defaultxml", "manifest");
-
-  // Open the temporary file for writing.
-  std::error_code EC;
-  raw_fd_ostream OS(File.Path, EC, sys::fs::F_Text);
-  if (EC)
-    fatal(EC, "failed to open " + File.Path);
+static std::string createDefaultXml() {
+  std::string Ret;
+  raw_string_ostream OS(Ret);
 
   // Emit the XML. Note that we do *not* verify that the XML attributes are
   // syntactically correct. This is intentional for link.exe compatibility.
@@ -362,37 +357,83 @@ TemporaryFile createDefaultXml() {
        << "  </dependency>\n";
   }
   OS << "</assembly>\n";
-  OS.close();
-  return File;
+  return Ret;
 }
 
-static std::string readFile(StringRef Path) {
-  std::unique_ptr<MemoryBuffer> MB =
-      check(MemoryBuffer::getFile(Path), "could not open " + Path);
-  return MB->getBuffer();
+static Expected<std::unique_ptr<MemoryBuffer>>
+createManifestXmlWithInternalMt(std::string &DefaultXml) {
+  std::unique_ptr<MemoryBuffer> DefaultXmlCopy =
+      MemoryBuffer::getMemBufferCopy(DefaultXml);
+
+  windows_manifest::WindowsManifestMerger Merger;
+  if (auto E = Merger.merge(*DefaultXmlCopy.get()))
+    return std::move(E);
+
+  for (StringRef Filename : Config->ManifestInput) {
+    std::unique_ptr<MemoryBuffer> Manifest =
+        check(MemoryBuffer::getFile(Filename));
+    if (auto E = Merger.merge(*Manifest.get())) {
+      warn("internal manifest tool failed on file " + Filename);
+      return std::move(E);
+    }
+  }
+
+  return Merger.getMergedManifest();
 }
 
-static std::string createManifestXml() {
-  // Create the default manifest file.
-  TemporaryFile File1 = createDefaultXml();
-  if (Config->ManifestInput.empty())
-    return readFile(File1.Path);
+static std::unique_ptr<MemoryBuffer>
+createManifestXmlWithExternalMt(std::string &DefaultXml) {
+  const Triple HostTriple(Triple::normalize(LLVM_HOST_TRIPLE));
+  if (!HostTriple.isOSWindows())
+    fatal("manifest ignored because no external manifest tool available");
+  // Create the default manifest file as a temporary file.
+  TemporaryFile Default("defaultxml", "manifest");
+  std::error_code EC;
+  raw_fd_ostream OS(Default.Path, EC, sys::fs::F_Text);
+  if (EC)
+    fatal(EC, "failed to open " + Default.Path);
+  OS << DefaultXml;
+  OS.close();
 
-  // If manifest files are supplied by the user using /MANIFESTINPUT
-  // option, we need to merge them with the default manifest.
-  TemporaryFile File2("user", "manifest");
+  // Merge user-supplied manifests if they are given.  Since libxml2 is not
+  // enabled, we must shell out to Microsoft's mt.exe tool.
+  TemporaryFile User("user", "manifest");
 
   Executor E("mt.exe");
   E.add("/manifest");
-  E.add(File1.Path);
+  E.add(Default.Path);
   for (StringRef Filename : Config->ManifestInput) {
     E.add("/manifest");
     E.add(Filename);
   }
   E.add("/nologo");
-  E.add("/out:" + StringRef(File2.Path));
+  E.add("/out:" + StringRef(User.Path));
   E.run();
-  return readFile(File2.Path);
+
+  return check(MemoryBuffer::getFile(User.Path), "could not open " + User.Path);
+}
+
+static std::string createManifestXml() {
+  std::string DefaultXml = createDefaultXml();
+  if (Config->ManifestInput.empty())
+    return DefaultXml;
+
+  // If manifest files are supplied by the user using /MANIFESTINPUT
+  // option, we need to merge them with the default manifest. If libxml2
+  // is enabled, we may merge them with LLVM's own library.
+  Expected<std::unique_ptr<MemoryBuffer>> OutputBufferOrError =
+      createManifestXmlWithInternalMt(DefaultXml);
+  if (OutputBufferOrError)
+    return OutputBufferOrError.get()->getBuffer();
+  // Using built-in library failed, possibly because libxml2 is not installed.
+  // Shell out to mt.exe instead.
+  handleAllErrors(std::move(OutputBufferOrError.takeError()),
+                  [&](ErrorInfoBase &EIB) {
+                    warn("error with internal manifest tool: " + EIB.message());
+                  });
+  std::unique_ptr<MemoryBuffer> OutputBuffer;
+  OutputBuffer = createManifestXmlWithExternalMt(DefaultXml);
+  return OutputBuffer->getBuffer();
 }
 
 static std::unique_ptr<MemoryBuffer>

Modified: lld/trunk/test/COFF/manifestinput.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/manifestinput.test?rev=311424&r1=311423&r2=311424&view=diff
==============================================================================
--- lld/trunk/test/COFF/manifestinput.test (original)
+++ lld/trunk/test/COFF/manifestinput.test Mon Aug 21 20:15:28 2017
@@ -1,4 +1,4 @@
-# REQUIRES: win_mt
+# REQUIRES: manifest_tool
 
 # RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj
 # RUN: lld-link /out:%t.exe /entry:main \

Modified: lld/trunk/test/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/lit.cfg?rev=311424&r1=311423&r2=311424&view=diff
==============================================================================
--- lld/trunk/test/lit.cfg (original)
+++ lld/trunk/test/lit.cfg Mon Aug 21 20:15:28 2017
@@ -265,6 +265,8 @@ llvm_config_cmd.wait()
 config.environment['LLD_VERSION'] = 'LLD 1.0'
 
 # Indirectly check if the mt.exe Microsoft utility exists by searching for
-# cvtres, which always accompanies it.
-if lit.util.which('cvtres', config.environment['PATH']):
-    config.available_features.add('win_mt')
+# cvtres, which always accompanies it.  Alternatively, check if we can use
+# libxml2 to merge manifests.
+if (lit.util.which('cvtres', config.environment['PATH'])) or \
+ (config.llvm_libxml2_enabled == "1"):
+    config.available_features.add('manifest_tool')

Modified: lld/trunk/test/lit.site.cfg.in
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/lit.site.cfg.in?rev=311424&r1=311423&r2=311424&view=diff
==============================================================================
--- lld/trunk/test/lit.site.cfg.in (original)
+++ lld/trunk/test/lit.site.cfg.in Mon Aug 21 20:15:28 2017
@@ -4,6 +4,7 @@ config.llvm_src_root = "@LLVM_SOURCE_DIR
 config.llvm_obj_root = "@LLVM_BINARY_DIR@"
 config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
 config.llvm_libs_dir = "@LLVM_LIBS_DIR@"
+config.llvm_libxml2_enabled = "@LLVM_LIBXML2_ENABLED@"
 config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
 config.lld_obj_root = "@LLD_BINARY_DIR@"
 config.lld_libs_dir = "@LLVM_LIBRARY_OUTPUT_INTDIR@"




More information about the llvm-commits mailing list