[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