[llvm] r309070 - Move manifest utils into separate lib, to reduce libxml2 deps.

Eric Beckmann via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 25 18:21:55 PDT 2017


Author: ecbeckmann
Date: Tue Jul 25 18:21:55 2017
New Revision: 309070

URL: http://llvm.org/viewvc/llvm-project?rev=309070&view=rev
Log:
Move manifest utils into separate lib, to reduce libxml2 deps.

Summary:
Previously were in support.  Since many many things depend on support,
were all forced to also depend on libxml2, which we only want in a few cases.
This puts all the libxml2 deps in a separate lib to be used only in a few
places.

Reviewers: ruiu, thakis, rnk

Subscribers: mgorny, hiraditya, llvm-commits

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

Added:
    llvm/trunk/include/llvm/WindowsManifest/
    llvm/trunk/include/llvm/WindowsManifest/WindowsManifestMerger.h
    llvm/trunk/lib/WindowsManifest/
    llvm/trunk/lib/WindowsManifest/CMakeLists.txt
    llvm/trunk/lib/WindowsManifest/LLVMBuild.txt
    llvm/trunk/lib/WindowsManifest/WindowsManifestMerger.cpp
Removed:
    llvm/trunk/include/llvm/Support/WindowsManifestMerger.h
    llvm/trunk/lib/Support/WindowsManifestMerger.cpp
Modified:
    llvm/trunk/include/llvm/module.modulemap
    llvm/trunk/lib/CMakeLists.txt
    llvm/trunk/lib/LLVMBuild.txt
    llvm/trunk/lib/Support/CMakeLists.txt
    llvm/trunk/tools/llvm-mt/CMakeLists.txt
    llvm/trunk/tools/llvm-mt/LLVMBuild.txt
    llvm/trunk/tools/llvm-mt/llvm-mt.cpp

Removed: llvm/trunk/include/llvm/Support/WindowsManifestMerger.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/WindowsManifestMerger.h?rev=309069&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Support/WindowsManifestMerger.h (original)
+++ llvm/trunk/include/llvm/Support/WindowsManifestMerger.h (removed)
@@ -1,80 +0,0 @@
-//===-- WindowsManifestMerger.h ---------------------------------*- C++-*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===---------------------------------------------------------------------===//
-//
-// This file provides a utility for merging Microsoft .manifest files.  These
-// files are xml documents which contain meta-information about applications,
-// such as whether or not admin access is required, system compatibility,
-// versions, etc.  Part of the linking process of an executable may require
-// merging several of these .manifest files using a tree-merge following
-// specific rules.  Unfortunately, these rules are not documented well
-// anywhere.  However, a careful investigation of the behavior of the original
-// Microsoft Manifest Tool (mt.exe) revealed the rules of this merge.  As the
-// saying goes, code is the best documentation, so please look below if you are
-// interested in the exact merging requirements.
-//
-// Ref:
-// https://msdn.microsoft.com/en-us/library/windows/desktop/aa374191(v=vs.85).aspx
-//
-//===---------------------------------------------------------------------===//
-
-#ifndef LLVM_INCLUDE_LLVM_SUPPORT_WINDOWS_MANIFEST_MERGER_H
-#define LLVM_INCLUDE_LLVM_SUPPORT_WINDOWS_MANIFEST_MERGER_H
-
-#include "llvm/Config/config.h"
-#include "llvm/Support/Error.h"
-
-#if LLVM_LIBXML2_ENABLED
-#include <libxml/xmlreader.h>
-#endif
-
-namespace llvm {
-
-class MemoryBuffer;
-
-#if LLVM_LIBXML2_ENABLED
-typedef xmlDocPtr XMLDocumentImpl;
-typedef xmlNodePtr XMLNodeImpl;
-#else
-typedef void *XMLDocumentImpl;
-typedef void *XMLNodeImpl;
-#endif
-
-class WindowsManifestError : public ErrorInfo<WindowsManifestError, ECError> {
-public:
-  static char ID;
-  WindowsManifestError(const Twine &Msg);
-  void log(raw_ostream &OS) const override;
-
-private:
-  std::string Msg;
-};
-
-class WindowsManifestMerger {
-public:
-  ~WindowsManifestMerger();
-
-  Error merge(const MemoryBuffer &Manifest);
-
-  // Returns vector containing merged xml manifest, or uninitialized vector for
-  // empty manifest.
-  std::unique_ptr<MemoryBuffer> getMergedManifest();
-
-private:
-  static void errorCallback(void *Ctx, const char *Format, ...);
-  Error getParseError();
-
-#if LLVM_LIBXML2_ENABLED
-  XMLDocumentImpl CombinedDoc = nullptr;
-  std::vector<XMLDocumentImpl> MergedDocs;
-#endif
-  bool ParseErrorOccurred = false;
-};
-
-} // namespace llvm
-#endif

Added: llvm/trunk/include/llvm/WindowsManifest/WindowsManifestMerger.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/WindowsManifest/WindowsManifestMerger.h?rev=309070&view=auto
==============================================================================
--- llvm/trunk/include/llvm/WindowsManifest/WindowsManifestMerger.h (added)
+++ llvm/trunk/include/llvm/WindowsManifest/WindowsManifestMerger.h Tue Jul 25 18:21:55 2017
@@ -0,0 +1,80 @@
+//===-- WindowsManifestMerger.h ---------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// This file provides a utility for merging Microsoft .manifest files.  These
+// files are xml documents which contain meta-information about applications,
+// such as whether or not admin access is required, system compatibility,
+// versions, etc.  Part of the linking process of an executable may require
+// merging several of these .manifest files using a tree-merge following
+// specific rules.  Unfortunately, these rules are not documented well
+// anywhere.  However, a careful investigation of the behavior of the original
+// Microsoft Manifest Tool (mt.exe) revealed the rules of this merge.  As the
+// saying goes, code is the best documentation, so please look below if you are
+// interested in the exact merging requirements.
+//
+// Ref:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa374191(v=vs.85).aspx
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef LLVM_INCLUDE_LLVM_SUPPORT_WINDOWS_MANIFEST_MERGER_H
+#define LLVM_INCLUDE_LLVM_SUPPORT_WINDOWS_MANIFEST_MERGER_H
+
+#include "llvm/Config/config.h"
+#include "llvm/Support/Error.h"
+
+#if LLVM_LIBXML2_ENABLED
+#include <libxml/xmlreader.h>
+#endif
+
+namespace llvm {
+
+class MemoryBuffer;
+
+#if LLVM_LIBXML2_ENABLED
+typedef xmlDocPtr XMLDocumentImpl;
+typedef xmlNodePtr XMLNodeImpl;
+#else
+typedef void *XMLDocumentImpl;
+typedef void *XMLNodeImpl;
+#endif
+
+class WindowsManifestError : public ErrorInfo<WindowsManifestError, ECError> {
+public:
+  static char ID;
+  WindowsManifestError(const Twine &Msg);
+  void log(raw_ostream &OS) const override;
+
+private:
+  std::string Msg;
+};
+
+class WindowsManifestMerger {
+public:
+  ~WindowsManifestMerger();
+
+  Error merge(const MemoryBuffer &Manifest);
+
+  // Returns vector containing merged xml manifest, or uninitialized vector for
+  // empty manifest.
+  std::unique_ptr<MemoryBuffer> getMergedManifest();
+
+private:
+  static void errorCallback(void *Ctx, const char *Format, ...);
+  Error getParseError();
+
+#if LLVM_LIBXML2_ENABLED
+  XMLDocumentImpl CombinedDoc = nullptr;
+  std::vector<XMLDocumentImpl> MergedDocs;
+#endif
+  bool ParseErrorOccurred = false;
+};
+
+} // namespace llvm
+#endif

Modified: llvm/trunk/include/llvm/module.modulemap
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/module.modulemap?rev=309070&r1=309069&r2=309070&view=diff
==============================================================================
--- llvm/trunk/include/llvm/module.modulemap (original)
+++ llvm/trunk/include/llvm/module.modulemap Tue Jul 25 18:21:55 2017
@@ -306,3 +306,9 @@ module LLVM_Support_DataTypes_Src {
   header "llvm/Support/DataTypes.h"
   export *
 }
+
+module LLVM_WindowsManifest {
+  requires cplusplus
+  umbrella "WindowsManifest"
+  module * { export * }
+}

Modified: llvm/trunk/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CMakeLists.txt?rev=309070&r1=309069&r2=309070&view=diff
==============================================================================
--- llvm/trunk/lib/CMakeLists.txt (original)
+++ llvm/trunk/lib/CMakeLists.txt Tue Jul 25 18:21:55 2017
@@ -25,3 +25,4 @@ add_subdirectory(Passes)
 add_subdirectory(ToolDrivers)
 add_subdirectory(XRay)
 add_subdirectory(Testing)
+add_subdirectory(WindowsManifest)

Modified: llvm/trunk/lib/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LLVMBuild.txt?rev=309070&r1=309069&r2=309070&view=diff
==============================================================================
--- llvm/trunk/lib/LLVMBuild.txt (original)
+++ llvm/trunk/lib/LLVMBuild.txt Tue Jul 25 18:21:55 2017
@@ -42,6 +42,7 @@ subdirectories =
  Testing
  ToolDrivers
  Transforms
+ WindowsManifest
 
 [component_0]
 type = Group

Modified: llvm/trunk/lib/Support/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CMakeLists.txt?rev=309070&r1=309069&r2=309070&view=diff
==============================================================================
--- llvm/trunk/lib/Support/CMakeLists.txt (original)
+++ llvm/trunk/lib/Support/CMakeLists.txt Tue Jul 25 18:21:55 2017
@@ -27,9 +27,6 @@ elseif( CMAKE_HOST_UNIX )
   if( UNIX AND NOT (BEOS OR HAIKU) )
     set(system_libs ${system_libs} m)
   endif()
-  if( LLVM_LIBXML2_ENABLED )
-    set(system_libs ${system_libs} ${LIBXML2_LIBS})
-  endif()
 endif( MSVC OR MINGW )
 
 add_llvm_library(LLVMSupport
@@ -113,7 +110,6 @@ add_llvm_library(LLVMSupport
   Triple.cpp
   Twine.cpp
   Unicode.cpp
-  WindowsManifestMerger.cpp
   YAMLParser.cpp
   YAMLTraits.cpp
   raw_os_ostream.cpp

Removed: llvm/trunk/lib/Support/WindowsManifestMerger.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/WindowsManifestMerger.cpp?rev=309069&view=auto
==============================================================================
--- llvm/trunk/lib/Support/WindowsManifestMerger.cpp (original)
+++ llvm/trunk/lib/Support/WindowsManifestMerger.cpp (removed)
@@ -1,212 +0,0 @@
-//===-- WindowsManifestMerger.cpp ------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===---------------------------------------------------------------------===//
-//
-// This file implements the .manifest merger class.
-//
-//===---------------------------------------------------------------------===//
-
-#include "llvm/Support/WindowsManifestMerger.h"
-#include "llvm/Support/MemoryBuffer.h"
-
-#include <stdarg.h>
-
-#define TO_XML_CHAR(X) reinterpret_cast<const unsigned char *>(X)
-#define FROM_XML_CHAR(X) reinterpret_cast<const char *>(X)
-
-using namespace llvm;
-
-namespace llvm {
-
-char WindowsManifestError::ID = 0;
-
-WindowsManifestError::WindowsManifestError(const Twine &Msg) : Msg(Msg.str()) {}
-
-void WindowsManifestError::log(raw_ostream &OS) const { OS << Msg; }
-
-#if LLVM_LIBXML2_ENABLED
-static bool xmlStringsEqual(const unsigned char *A, const unsigned char *B) {
-  return strcmp(FROM_XML_CHAR(A), FROM_XML_CHAR(B)) == 0;
-}
-#endif
-
-bool isMergeableElement(const unsigned char *ElementName) {
-  for (StringRef S : {"application", "assembly", "assemblyIdentity",
-                      "compatibility", "noInherit", "requestedExecutionLevel",
-                      "requestedPrivileges", "security", "trustInfo"}) {
-    if (S == FROM_XML_CHAR(ElementName))
-      return true;
-  }
-  return false;
-}
-
-XMLNodeImpl getChildWithName(XMLNodeImpl Parent,
-                             const unsigned char *ElementName) {
-#if LLVM_LIBXML2_ENABLED
-  for (XMLNodeImpl Child = Parent->children; Child; Child = Child->next)
-    if (xmlStringsEqual(Child->name, ElementName)) {
-      return Child;
-    }
-#endif
-  return nullptr;
-}
-
-const unsigned char *getAttribute(XMLNodeImpl Node,
-                                  const unsigned char *AttributeName) {
-#if LLVM_LIBXML2_ENABLED
-  for (xmlAttrPtr Attribute = Node->properties; Attribute != nullptr;
-       Attribute = Attribute->next) {
-    if (xmlStringsEqual(Attribute->name, AttributeName))
-      return Attribute->children->content;
-  }
-#endif
-  return nullptr;
-}
-
-Error mergeAttributes(XMLNodeImpl OriginalNode, XMLNodeImpl AdditionalNode) {
-#if LLVM_LIBXML2_ENABLED
-  for (xmlAttrPtr Attribute = AdditionalNode->properties; Attribute != nullptr;
-       Attribute = Attribute->next) {
-    if (const unsigned char *OriginalValue =
-            getAttribute(OriginalNode, Attribute->name)) {
-      // Attributes of the same name must also have the same value.  Otherwise
-      // an error is thrown.
-      if (!xmlStringsEqual(OriginalValue, Attribute->children->content))
-        return make_error<WindowsManifestError>(
-            Twine("conflicting attributes for ") +
-            FROM_XML_CHAR(OriginalNode->name));
-    } else {
-      char *NameCopy = strdup(FROM_XML_CHAR(Attribute->name));
-      char *ContentCopy = strdup(FROM_XML_CHAR(Attribute->children->content));
-      xmlNewProp(OriginalNode, TO_XML_CHAR(NameCopy), TO_XML_CHAR(ContentCopy));
-    }
-  }
-#endif
-  return Error::success();
-}
-
-Error treeMerge(XMLNodeImpl OriginalRoot, XMLNodeImpl AdditionalRoot) {
-#if LLVM_LIBXML2_ENABLED
-  XMLNodeImpl AdditionalFirstChild = AdditionalRoot->children;
-  for (XMLNodeImpl Child = AdditionalFirstChild; Child; Child = Child->next) {
-    XMLNodeImpl OriginalChildWithName;
-    if (!isMergeableElement(Child->name) ||
-        !(OriginalChildWithName =
-              getChildWithName(OriginalRoot, Child->name))) {
-      XMLNodeImpl NewChild = xmlCopyNode(Child, 1);
-      if (!NewChild)
-        return make_error<WindowsManifestError>(Twine("error when copying ") +
-                                                FROM_XML_CHAR(Child->name));
-      if (NewChild->ns)
-        xmlFreeNs(NewChild->ns); // xmlCopyNode explicitly defines default
-                                 // namespace, undo this here.
-      if (!xmlAddChild(OriginalRoot, NewChild))
-        return make_error<WindowsManifestError>(Twine("could not merge ") +
-                                                FROM_XML_CHAR(NewChild->name));
-    } else if (auto E = treeMerge(OriginalChildWithName, Child)) {
-      return E;
-    }
-  }
-  if (auto E = mergeAttributes(OriginalRoot, AdditionalRoot))
-    return E;
-#endif
-  return Error::success();
-}
-
-void stripCommentsAndText(XMLNodeImpl Root) {
-#if LLVM_LIBXML2_ENABLED
-  xmlNode StoreNext;
-  for (XMLNodeImpl Child = Root->children; Child; Child = Child->next) {
-    if (!xmlStringsEqual(Child->name, TO_XML_CHAR("text")) &&
-        !xmlStringsEqual(Child->name, TO_XML_CHAR("comment"))) {
-      stripCommentsAndText(Child);
-    } else {
-      StoreNext.next = Child->next;
-      XMLNodeImpl Remove = Child;
-      Child = &StoreNext;
-      xmlUnlinkNode(Remove);
-      xmlFreeNode(Remove);
-    }
-  }
-#endif
-}
-
-WindowsManifestMerger::~WindowsManifestMerger() {
-#if LLVM_LIBXML2_ENABLED
-  for (auto &Doc : MergedDocs)
-    xmlFreeDoc(Doc);
-#endif
-}
-
-Error WindowsManifestMerger::merge(const MemoryBuffer &Manifest) {
-#if LLVM_LIBXML2_ENABLED
-  if (Manifest.getBufferSize() == 0)
-    return make_error<WindowsManifestError>(
-        "attempted to merge empty manifest");
-  xmlSetGenericErrorFunc((void *)this, WindowsManifestMerger::errorCallback);
-  XMLDocumentImpl ManifestXML =
-      xmlReadMemory(Manifest.getBufferStart(), Manifest.getBufferSize(),
-                    "manifest.xml", nullptr, XML_PARSE_NOBLANKS);
-  xmlSetGenericErrorFunc(nullptr, nullptr);
-  if (auto E = getParseError())
-    return E;
-  XMLNodeImpl AdditionalRoot = xmlDocGetRootElement(ManifestXML);
-  stripCommentsAndText(AdditionalRoot);
-  if (CombinedDoc == nullptr) {
-    CombinedDoc = ManifestXML;
-  } else {
-    XMLNodeImpl CombinedRoot = xmlDocGetRootElement(CombinedDoc);
-    if (xmlStringsEqual(CombinedRoot->name, AdditionalRoot->name) &&
-        isMergeableElement(AdditionalRoot->name)) {
-      if (auto E = treeMerge(CombinedRoot, AdditionalRoot)) {
-        return E;
-      }
-    } else {
-      XMLNodeImpl NewChild = xmlCopyNode(AdditionalRoot, 1);
-      if (!NewChild)
-        return make_error<WindowsManifestError>("could not copy manifest");
-      if (!xmlAddChild(CombinedRoot, NewChild))
-        return make_error<WindowsManifestError>("could not append manifest");
-    }
-  }
-  MergedDocs.push_back(ManifestXML);
-#endif
-  return Error::success();
-}
-
-std::unique_ptr<MemoryBuffer> WindowsManifestMerger::getMergedManifest() {
-#if LLVM_LIBXML2_ENABLED
-  unsigned char *XmlBuff;
-  int BufferSize = 0;
-  if (CombinedDoc) {
-    std::unique_ptr<xmlDoc> OutputDoc(xmlNewDoc((const unsigned char *)"1.0"));
-    xmlDocSetRootElement(OutputDoc.get(), xmlDocGetRootElement(CombinedDoc));
-    xmlKeepBlanksDefault(0);
-    xmlDocDumpFormatMemory(OutputDoc.get(), &XmlBuff, &BufferSize, 1);
-  }
-  if (BufferSize == 0)
-    return nullptr;
-  return MemoryBuffer::getMemBuffer(
-      StringRef(FROM_XML_CHAR(XmlBuff), (size_t)BufferSize));
-#else
-  return nullptr;
-#endif
-}
-
-void WindowsManifestMerger::errorCallback(void *Ctx, const char *Format, ...) {
-  auto *Merger = (WindowsManifestMerger *)Ctx;
-  Merger->ParseErrorOccurred = true;
-}
-
-Error WindowsManifestMerger::getParseError() {
-  if (!ParseErrorOccurred)
-    return Error::success();
-  return make_error<WindowsManifestError>("invalid xml document");
-}
-
-} // namespace llvm

Added: llvm/trunk/lib/WindowsManifest/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/WindowsManifest/CMakeLists.txt?rev=309070&view=auto
==============================================================================
--- llvm/trunk/lib/WindowsManifest/CMakeLists.txt (added)
+++ llvm/trunk/lib/WindowsManifest/CMakeLists.txt Tue Jul 25 18:21:55 2017
@@ -0,0 +1,18 @@
+set(system_libs)
+if( CMAKE_HOST_UNIX )
+  if( LLVM_LIBXML2_ENABLED )
+    set(system_libs ${system_libs} ${LIBXML2_LIBS})
+  endif()
+endif()
+
+add_llvm_library(LLVMWindowsManifest
+  WindowsManifestMerger.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${LLVM_MAIN_INCLUDE_DIR}/llvm/WindowsManifest
+  ${Backtrace_INCLUDE_DIRS}
+
+  LINK_LIBS ${system_libs}
+  )
+
+set_property(TARGET LLVMWindowsManifest PROPERTY LLVM_SYSTEM_LIBS "${system_libs}")

Added: llvm/trunk/lib/WindowsManifest/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/WindowsManifest/LLVMBuild.txt?rev=309070&view=auto
==============================================================================
--- llvm/trunk/lib/WindowsManifest/LLVMBuild.txt (added)
+++ llvm/trunk/lib/WindowsManifest/LLVMBuild.txt Tue Jul 25 18:21:55 2017
@@ -0,0 +1,22 @@
+;===- ./lib/WindowsManifest/LLVMBuild.txt ----------------------*- Conf -*--===;
+;
+;                     The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+;   http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = WindowsManifest
+parent = Libraries
+required_libraries = Support

Added: llvm/trunk/lib/WindowsManifest/WindowsManifestMerger.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/WindowsManifest/WindowsManifestMerger.cpp?rev=309070&view=auto
==============================================================================
--- llvm/trunk/lib/WindowsManifest/WindowsManifestMerger.cpp (added)
+++ llvm/trunk/lib/WindowsManifest/WindowsManifestMerger.cpp Tue Jul 25 18:21:55 2017
@@ -0,0 +1,212 @@
+//===-- WindowsManifestMerger.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// This file implements the .manifest merger class.
+//
+//===---------------------------------------------------------------------===//
+
+#include "llvm/WindowsManifest/WindowsManifestMerger.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include <stdarg.h>
+
+#define TO_XML_CHAR(X) reinterpret_cast<const unsigned char *>(X)
+#define FROM_XML_CHAR(X) reinterpret_cast<const char *>(X)
+
+using namespace llvm;
+
+namespace llvm {
+
+char WindowsManifestError::ID = 0;
+
+WindowsManifestError::WindowsManifestError(const Twine &Msg) : Msg(Msg.str()) {}
+
+void WindowsManifestError::log(raw_ostream &OS) const { OS << Msg; }
+
+#if LLVM_LIBXML2_ENABLED
+static bool xmlStringsEqual(const unsigned char *A, const unsigned char *B) {
+  return strcmp(FROM_XML_CHAR(A), FROM_XML_CHAR(B)) == 0;
+}
+#endif
+
+bool isMergeableElement(const unsigned char *ElementName) {
+  for (StringRef S : {"application", "assembly", "assemblyIdentity",
+                      "compatibility", "noInherit", "requestedExecutionLevel",
+                      "requestedPrivileges", "security", "trustInfo"}) {
+    if (S == FROM_XML_CHAR(ElementName))
+      return true;
+  }
+  return false;
+}
+
+XMLNodeImpl getChildWithName(XMLNodeImpl Parent,
+                             const unsigned char *ElementName) {
+#if LLVM_LIBXML2_ENABLED
+  for (XMLNodeImpl Child = Parent->children; Child; Child = Child->next)
+    if (xmlStringsEqual(Child->name, ElementName)) {
+      return Child;
+    }
+#endif
+  return nullptr;
+}
+
+const unsigned char *getAttribute(XMLNodeImpl Node,
+                                  const unsigned char *AttributeName) {
+#if LLVM_LIBXML2_ENABLED
+  for (xmlAttrPtr Attribute = Node->properties; Attribute != nullptr;
+       Attribute = Attribute->next) {
+    if (xmlStringsEqual(Attribute->name, AttributeName))
+      return Attribute->children->content;
+  }
+#endif
+  return nullptr;
+}
+
+Error mergeAttributes(XMLNodeImpl OriginalNode, XMLNodeImpl AdditionalNode) {
+#if LLVM_LIBXML2_ENABLED
+  for (xmlAttrPtr Attribute = AdditionalNode->properties; Attribute != nullptr;
+       Attribute = Attribute->next) {
+    if (const unsigned char *OriginalValue =
+            getAttribute(OriginalNode, Attribute->name)) {
+      // Attributes of the same name must also have the same value.  Otherwise
+      // an error is thrown.
+      if (!xmlStringsEqual(OriginalValue, Attribute->children->content))
+        return make_error<WindowsManifestError>(
+            Twine("conflicting attributes for ") +
+            FROM_XML_CHAR(OriginalNode->name));
+    } else {
+      char *NameCopy = strdup(FROM_XML_CHAR(Attribute->name));
+      char *ContentCopy = strdup(FROM_XML_CHAR(Attribute->children->content));
+      xmlNewProp(OriginalNode, TO_XML_CHAR(NameCopy), TO_XML_CHAR(ContentCopy));
+    }
+  }
+#endif
+  return Error::success();
+}
+
+Error treeMerge(XMLNodeImpl OriginalRoot, XMLNodeImpl AdditionalRoot) {
+#if LLVM_LIBXML2_ENABLED
+  XMLNodeImpl AdditionalFirstChild = AdditionalRoot->children;
+  for (XMLNodeImpl Child = AdditionalFirstChild; Child; Child = Child->next) {
+    XMLNodeImpl OriginalChildWithName;
+    if (!isMergeableElement(Child->name) ||
+        !(OriginalChildWithName =
+              getChildWithName(OriginalRoot, Child->name))) {
+      XMLNodeImpl NewChild = xmlCopyNode(Child, 1);
+      if (!NewChild)
+        return make_error<WindowsManifestError>(Twine("error when copying ") +
+                                                FROM_XML_CHAR(Child->name));
+      if (NewChild->ns)
+        xmlFreeNs(NewChild->ns); // xmlCopyNode explicitly defines default
+                                 // namespace, undo this here.
+      if (!xmlAddChild(OriginalRoot, NewChild))
+        return make_error<WindowsManifestError>(Twine("could not merge ") +
+                                                FROM_XML_CHAR(NewChild->name));
+    } else if (auto E = treeMerge(OriginalChildWithName, Child)) {
+      return E;
+    }
+  }
+  if (auto E = mergeAttributes(OriginalRoot, AdditionalRoot))
+    return E;
+#endif
+  return Error::success();
+}
+
+void stripCommentsAndText(XMLNodeImpl Root) {
+#if LLVM_LIBXML2_ENABLED
+  xmlNode StoreNext;
+  for (XMLNodeImpl Child = Root->children; Child; Child = Child->next) {
+    if (!xmlStringsEqual(Child->name, TO_XML_CHAR("text")) &&
+        !xmlStringsEqual(Child->name, TO_XML_CHAR("comment"))) {
+      stripCommentsAndText(Child);
+    } else {
+      StoreNext.next = Child->next;
+      XMLNodeImpl Remove = Child;
+      Child = &StoreNext;
+      xmlUnlinkNode(Remove);
+      xmlFreeNode(Remove);
+    }
+  }
+#endif
+}
+
+WindowsManifestMerger::~WindowsManifestMerger() {
+#if LLVM_LIBXML2_ENABLED
+  for (auto &Doc : MergedDocs)
+    xmlFreeDoc(Doc);
+#endif
+}
+
+Error WindowsManifestMerger::merge(const MemoryBuffer &Manifest) {
+#if LLVM_LIBXML2_ENABLED
+  if (Manifest.getBufferSize() == 0)
+    return make_error<WindowsManifestError>(
+        "attempted to merge empty manifest");
+  xmlSetGenericErrorFunc((void *)this, WindowsManifestMerger::errorCallback);
+  XMLDocumentImpl ManifestXML =
+      xmlReadMemory(Manifest.getBufferStart(), Manifest.getBufferSize(),
+                    "manifest.xml", nullptr, XML_PARSE_NOBLANKS);
+  xmlSetGenericErrorFunc(nullptr, nullptr);
+  if (auto E = getParseError())
+    return E;
+  XMLNodeImpl AdditionalRoot = xmlDocGetRootElement(ManifestXML);
+  stripCommentsAndText(AdditionalRoot);
+  if (CombinedDoc == nullptr) {
+    CombinedDoc = ManifestXML;
+  } else {
+    XMLNodeImpl CombinedRoot = xmlDocGetRootElement(CombinedDoc);
+    if (xmlStringsEqual(CombinedRoot->name, AdditionalRoot->name) &&
+        isMergeableElement(AdditionalRoot->name)) {
+      if (auto E = treeMerge(CombinedRoot, AdditionalRoot)) {
+        return E;
+      }
+    } else {
+      XMLNodeImpl NewChild = xmlCopyNode(AdditionalRoot, 1);
+      if (!NewChild)
+        return make_error<WindowsManifestError>("could not copy manifest");
+      if (!xmlAddChild(CombinedRoot, NewChild))
+        return make_error<WindowsManifestError>("could not append manifest");
+    }
+  }
+  MergedDocs.push_back(ManifestXML);
+#endif
+  return Error::success();
+}
+
+std::unique_ptr<MemoryBuffer> WindowsManifestMerger::getMergedManifest() {
+#if LLVM_LIBXML2_ENABLED
+  unsigned char *XmlBuff;
+  int BufferSize = 0;
+  if (CombinedDoc) {
+    std::unique_ptr<xmlDoc> OutputDoc(xmlNewDoc((const unsigned char *)"1.0"));
+    xmlDocSetRootElement(OutputDoc.get(), xmlDocGetRootElement(CombinedDoc));
+    xmlKeepBlanksDefault(0);
+    xmlDocDumpFormatMemory(OutputDoc.get(), &XmlBuff, &BufferSize, 1);
+  }
+  if (BufferSize == 0)
+    return nullptr;
+  return MemoryBuffer::getMemBuffer(
+      StringRef(FROM_XML_CHAR(XmlBuff), (size_t)BufferSize));
+#else
+  return nullptr;
+#endif
+}
+
+void WindowsManifestMerger::errorCallback(void *Ctx, const char *Format, ...) {
+  auto *Merger = (WindowsManifestMerger *)Ctx;
+  Merger->ParseErrorOccurred = true;
+}
+
+Error WindowsManifestMerger::getParseError() {
+  if (!ParseErrorOccurred)
+    return Error::success();
+  return make_error<WindowsManifestError>("invalid xml document");
+}
+
+} // namespace llvm

Modified: llvm/trunk/tools/llvm-mt/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mt/CMakeLists.txt?rev=309070&r1=309069&r2=309070&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mt/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-mt/CMakeLists.txt Tue Jul 25 18:21:55 2017
@@ -1,6 +1,7 @@
 set(LLVM_LINK_COMPONENTS
   Option
   Support
+  WindowsManifest
   )
 
 set(LLVM_TARGET_DEFINITIONS Opts.td)

Modified: llvm/trunk/tools/llvm-mt/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mt/LLVMBuild.txt?rev=309070&r1=309069&r2=309070&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mt/LLVMBuild.txt (original)
+++ llvm/trunk/tools/llvm-mt/LLVMBuild.txt Tue Jul 25 18:21:55 2017
@@ -19,4 +19,4 @@
 type = Tool
 name = llvm-mt
 parent = Tools
-required_libraries = Option Support
+required_libraries = Option Support WindowsManifest

Modified: llvm/trunk/tools/llvm-mt/llvm-mt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mt/llvm-mt.cpp?rev=309070&r1=309069&r2=309070&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mt/llvm-mt.cpp (original)
+++ llvm/trunk/tools/llvm-mt/llvm-mt.cpp Tue Jul 25 18:21:55 2017
@@ -22,8 +22,8 @@
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Process.h"
 #include "llvm/Support/Signals.h"
-#include "llvm/Support/WindowsManifestMerger.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/WindowsManifest/WindowsManifestMerger.h"
 
 #include <system_error>
 




More information about the llvm-commits mailing list