llvm.org GIT mirror llvm / c152744
Implement parsing and writing of a single xml manifest file. Summary: Implement parsing and writing of a single xml manifest file. Subscribers: mgorny, llvm-commits, hiraditya Differential Revision: https://reviews.llvm.org/D35425 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@308679 91177308-0d34-0410-b5e6-96231b3b80d8 Eric Beckmann 2 years ago
16 changed file(s) with 251 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
362362
363363 option(LLVM_ENABLE_TERMINFO "Use terminfo database if available." ON)
364364
365 option(LLVM_ENABLE_LIBXML2 "Use libxml2 if available." ON)
366
365367 option(LLVM_ENABLE_LIBEDIT "Use libedit if available." ON)
366368
367369 option(LLVM_ENABLE_THREADS "Use threads if available." ON)
153153 endforeach()
154154 else()
155155 set(HAVE_TERMINFO 0)
156 endif()
157
158 set(LLVM_LIBXML2_ENABLED 0)
159 set(LIBXML2_FOUND 0)
160 if(LLVM_ENABLE_LIBXML2)
161 find_package(LibXml2)
162 if (LIBXML2_FOUND)
163 set(LLVM_LIBXML2_ENABLED 1)
164 include_directories(${LIBXML2_INCLUDE_DIR})
165 set(LIBXML2_LIBS "xml2")
166 endif()
156167 endif()
157168 endif()
158169
382382 /* LLVM version string */
383383 #define LLVM_VERSION_STRING "${PACKAGE_VERSION}"
384384
385 /* Define if libxml2 is supported on this platform. */
386 #cmakedefine LLVM_LIBXML2_ENABLED ${LLVM_LIBXML2_ENABLED}
387
385388 /* Define to the extension used for shared libraries, say, ".so". */
386389 #cmakedefine LTDL_SHLIB_EXT "${LTDL_SHLIB_EXT}"
387390
0 //===-- WindowsManifestMerger.h ---------------------------------*- C++-*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===---------------------------------------------------------------------===//
8 //
9 // This file provides a utility for merging Microsoft .manifest files. These
10 // files are xml documents which contain meta-information about applications,
11 // such as whether or not admin access is required, system compatibility,
12 // versions, etc. Part of the linking process of an executable may require
13 // merging several of these .manifest files using a tree-merge following
14 // specific rules. Unfortunately, these rules are not documented well
15 // anywhere. However, a careful investigation of the behavior of the original
16 // Microsoft Manifest Tool (mt.exe) revealed the rules of this merge. As the
17 // saying goes, code is the best documentation, so please look below if you are
18 // interested in the exact merging requirements.
19 //
20 // Ref:
21 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa374191(v=vs.85).aspx
22 //
23 //===---------------------------------------------------------------------===//
24
25 #ifndef LLVM_INCLUDE_LLVM_SUPPORT_WINDOWS_MANIFEST_MERGER_H
26 #define LLVM_INCLUDE_LLVM_SUPPORT_WINDOWS_MANIFEST_MERGER_H
27
28 #include "llvm/Config/config.h"
29 #include "llvm/Support/Error.h"
30
31 #if LLVM_LIBXML2_ENABLED
32 #include
33 #endif
34
35 namespace llvm {
36
37 class MemoryBuffer;
38
39 #if LLVM_LIBXML2_ENABLED
40 typedef xmlDocPtr XMLDocumentImpl;
41 typedef xmlNodePtr XMLNodeImpl;
42 #else
43 typedef void *XMLDocumentImpl;
44 typedef void *XMLNodeImpl;
45 #endif
46
47 class WindowsManifestError : public ErrorInfo {
48 public:
49 static char ID;
50 WindowsManifestError(const Twine &Msg);
51 void log(raw_ostream &OS) const override;
52
53 private:
54 std::string Msg;
55 };
56
57 class WindowsManifestMerger {
58 public:
59 Error merge(const MemoryBuffer &Manifest);
60
61 // Returns vector containing merged xml manifest, or uninitialized vector for
62 // empty manifest.
63 std::unique_ptr getMergedManifest();
64
65 private:
66 static void errorCallback(void *Ctx, const char *Format, ...);
67 Error getParseError();
68
69 XMLNodeImpl CombinedRoot = nullptr;
70 bool ParseErrorOccurred = false;
71 };
72
73 } // namespace llvm
74 #endif
2525 endif()
2626 if( UNIX AND NOT (BEOS OR HAIKU) )
2727 set(system_libs ${system_libs} m)
28 endif()
29 if( LLVM_LIBXML2_ENABLED )
30 set(system_libs ${system_libs} ${LIBXML2_LIBS})
2831 endif()
2932 endif( MSVC OR MINGW )
3033
109112 Triple.cpp
110113 Twine.cpp
111114 Unicode.cpp
115 WindowsManifestMerger.cpp
112116 YAMLParser.cpp
113117 YAMLTraits.cpp
114118 raw_os_ostream.cpp
0 //===-- WindowsManifestMerger.cpp ------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===---------------------------------------------------------------------===//
8 //
9 // This file implements the .manifest merger class.
10 //
11 //===---------------------------------------------------------------------===//
12
13 #include "llvm/Support/WindowsManifestMerger.h"
14 #include "llvm/Support/MemoryBuffer.h"
15
16 #include
17
18 namespace llvm {
19
20 char WindowsManifestError::ID = 0;
21
22 WindowsManifestError::WindowsManifestError(const Twine &Msg) : Msg(Msg.str()) {}
23
24 void WindowsManifestError::log(raw_ostream &OS) const { OS << Msg; }
25
26 Error WindowsManifestMerger::merge(const MemoryBuffer &Manifest) {
27 #if LLVM_LIBXML2_ENABLED
28 xmlSetGenericErrorFunc((void *)this, WindowsManifestMerger::errorCallback);
29 XMLDocumentImpl ManifestXML =
30 xmlReadMemory(Manifest.getBufferStart(), Manifest.getBufferSize(),
31 "manifest.xml", nullptr, 0);
32 xmlSetGenericErrorFunc(nullptr, nullptr);
33 if (auto E = getParseError())
34 return E;
35 CombinedRoot = xmlDocGetRootElement(ManifestXML);
36 #endif
37 return Error::success();
38 }
39
40 std::unique_ptr WindowsManifestMerger::getMergedManifest() {
41 #if LLVM_LIBXML2_ENABLED
42 unsigned char *XmlBuff;
43 int BufferSize = 0;
44 if (CombinedRoot) {
45 std::unique_ptr OutputDoc(xmlNewDoc((const unsigned char *)"1.0"));
46 xmlDocSetRootElement(OutputDoc.get(), CombinedRoot);
47 xmlDocDumpMemory(OutputDoc.get(), &XmlBuff, &BufferSize);
48 }
49 if (BufferSize == 0)
50 return nullptr;
51 return MemoryBuffer::getMemBuffer(
52 StringRef(reinterpret_cast(XmlBuff), (size_t)BufferSize));
53 #else
54 return nullptr;
55 #endif
56 }
57
58 void WindowsManifestMerger::errorCallback(void *Ctx, const char *Format, ...) {
59 auto *Merger = (WindowsManifestMerger *)Ctx;
60 Merger->ParseErrorOccurred = true;
61 }
62
63 Error WindowsManifestMerger::getParseError() {
64 if (!ParseErrorOccurred)
65 return Error::success();
66 return make_error("invalid xml document");
67 }
68
69 } // namespace llvm
5858 llvm-mc
5959 llvm-mcmarkup
6060 llvm-modextract
61 llvm-mt
6261 llvm-nm
6362 llvm-objdump
6463 llvm-opt-report
139138 )
140139 endif()
141140
141 if (LLVM_LIBXML2_ENABLED)
142 set(LLVM_TEST_DEPENDS ${LLVM_TEST_DEPENDS}
143 llvm-mt
144 )
145 endif()
146
142147 add_custom_target(llvm-test-depends DEPENDS ${LLVM_TEST_DEPENDS})
143148 set_target_properties(llvm-test-depends PROPERTIES FOLDER "Tests")
144149
287287 r"\bllvm-config\b",
288288 r"\bllvm-cov\b",
289289 r"\bllvm-cxxdump\b",
290 r"\bllvm-cvtres\b",
290291 r"\bllvm-diff\b",
291292 r"\bllvm-dis\b",
292293 r"\bllvm-dsymutil\b",
336337 # For tools that are optional depending on the config, we won't warn
337338 # if they're missing.
338339 for pattern in [r"\bllvm-go\b",
340 r"\bllvm-mt\b",
339341 r"\bKaleidoscope-Ch3\b",
340342 r"\bKaleidoscope-Ch4\b",
341343 r"\bKaleidoscope-Ch5\b",
549551
550552 if config.enable_abi_breaking_checks == "1":
551553 config.available_features.add('abi-breaking-checks')
554
555 if config.llvm_disable_libxml2 == "OFF" and config.have_libxml2 == "TRUE":
556 config.available_features.add('libxml2')
557
3939 config.have_dia_sdk = @LLVM_ENABLE_DIA_SDK@
4040 config.enable_ffi = @LLVM_ENABLE_FFI@
4141 config.build_shared_libs = @BUILD_SHARED_LIBS@
42 config.llvm_disable_libxml2 = "@LLVM_DISABLE_LIBXML2@"
43 config.have_libxml2 = "@LIBXML2_FOUND@"
4244
4345 # Support substitution of the tools_dir with user parameters. This is
4446 # used when we can't determine the tool dir at configuration time.
0 RUN: llvm-mt /h | FileCheck %s -check-prefix=HELP
11
2 RUN: llvm-mt /inputresource:foo.res /manifest foo.manifest | FileCheck %s -check-prefix=NOT_SUPPORTED
3
42 HELP: OVERVIEW: Manifest Tool
5
6 NOT_SUPPORTED: llvm-mt: ignoring unsupported 'inputresource:' option
0 REQUIRES: libxml2
1 UNSUPPORTED: windows
2
3 RUN: llvm-mt /manifest %p/Inputs/test_manifest.manifest /out:%t
4 RUN: diff %p/Inputs/test_manifest.manifest %t
0 REQUIRES: libxml2
1 UNSUPPORTED: windows
2
3 RUN: not llvm-mt /manifest %p/Inputs/bad.manifest 2>&1 >/dev/null | FileCheck %s
4
5 CHECK: llvm-mt error: invalid xml document
6
7 RUN: llvm-mt /inputresource:foo.res /manifest \
8 RUN: %p/Inputs/test_manifest.manifest | FileCheck %s -check-prefix=NOT_SUPPORTED
9
10 NOT_SUPPORTED: llvm-mt: ignoring unsupported 'inputresource:' option
3737 llvm-mc
3838 llvm-mcmarkup
3939 llvm-modextract
40 llvm-mt
4041 llvm-nm
4142 llvm-objdump
4243 llvm-pdbutil
1515 #include "llvm/Option/ArgList.h"
1616 #include "llvm/Option/Option.h"
1717 #include "llvm/Support/Error.h"
18 #include "llvm/Support/FileOutputBuffer.h"
1819 #include "llvm/Support/ManagedStatic.h"
1920 #include "llvm/Support/Path.h"
2021 #include "llvm/Support/PrettyStackTrace.h"
2122 #include "llvm/Support/Process.h"
2223 #include "llvm/Support/Signals.h"
24 #include "llvm/Support/WindowsManifestMerger.h"
2325 #include "llvm/Support/raw_ostream.h"
2426
2527 #include
6668 exit(1);
6769 }
6870
71 static void reportError(StringRef Input, std::error_code EC) {
72 reportError(Twine(Input) + ": " + EC.message());
73 }
74
75 void error(std::error_code EC) {
76 if (EC)
77 reportError(EC.message());
78 }
79
80 void error(Error EC) {
81 if (EC)
82 handleAllErrors(std::move(EC), [&](const ErrorInfoBase &EI) {
83 reportError(EI.message());
84 });
85 }
86
6987 int main(int argc, const char **argv) {
7088 sys::PrintStackTraceOnErrorSignal(argv[0]);
7189 PrettyStackTraceProgram X(argc, argv);
103121 }
104122
105123 StringRef OutputFile;
106
107124 if (InputArgs.hasArg(OPT_out)) {
108125 OutputFile = InputArgs.getLastArgValue(OPT_out);
109126 } else if (InputFiles.size() == 1) {
112129 reportError("no output file specified");
113130 }
114131
132 WindowsManifestMerger Merger;
133
134 for (const auto &File : InputFiles) {
135 ErrorOr> ManifestOrErr =
136 MemoryBuffer::getFile(File);
137 if (!ManifestOrErr)
138 reportError(File, ManifestOrErr.getError());
139 MemoryBuffer &Manifest = *ManifestOrErr.get();
140 error(Merger.merge(Manifest));
141 }
142
143 std::unique_ptr OutputBuffer = Merger.getMergedManifest();
144 if (!OutputBuffer)
145 reportError("empty manifest not written");
146 ErrorOr> FileOrErr =
147 FileOutputBuffer::create(OutputFile, OutputBuffer->getBufferSize());
148 if (!FileOrErr)
149 reportError(OutputFile, FileOrErr.getError());
150 std::unique_ptr FileBuffer = std::move(*FileOrErr);
151 std::copy(OutputBuffer->getBufferStart(), OutputBuffer->getBufferEnd(),
152 FileBuffer->getBufferStart());
153 error(FileBuffer->commit());
115154 return 0;
116155 }