[lld] r306618 - Revert "Replace trivial use of external rc.exe by writing our own .res file."

Eric Beckmann via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 28 17:17:26 PDT 2017


Author: ecbeckmann
Date: Wed Jun 28 17:17:26 2017
New Revision: 306618

URL: http://llvm.org/viewvc/llvm-project?rev=306618&view=rev
Log:
Revert "Replace trivial use of external rc.exe by writing our own .res file."

This reverts commit d4c7e9fc63c10dbab0c30186ef8575474a704496.

This is done in order to address the failure of CrWinClangLLD etc. bots.
These throw an error of "side-by-side configuration is incorrect" during
compilation, which sounds suspiciously related to these manifest
changes.

Revert "Switch external cvtres.exe for llvm's own resource library."

This reverts commit 71fe8ef283a9dab9a3f21432c98466cbc23990d1.

Modified:
    lld/trunk/COFF/DriverUtils.cpp
    lld/trunk/test/COFF/combined-resources.test
    lld/trunk/test/COFF/def-name.test
    lld/trunk/test/COFF/dll.test
    lld/trunk/test/COFF/dllimport-gc.test
    lld/trunk/test/COFF/manifestinput.test
    lld/trunk/test/COFF/noentry.test
    lld/trunk/test/COFF/out.test
    lld/trunk/test/COFF/resource.test
    lld/trunk/test/lit.cfg

Modified: lld/trunk/COFF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DriverUtils.cpp?rev=306618&r1=306617&r2=306618&view=diff
==============================================================================
--- lld/trunk/COFF/DriverUtils.cpp (original)
+++ lld/trunk/COFF/DriverUtils.cpp Wed Jun 28 17:17:26 2017
@@ -20,15 +20,12 @@
 #include "Symbols.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringSwitch.h"
-#include "llvm/BinaryFormat/COFF.h"
 #include "llvm/Object/COFF.h"
-#include "llvm/Object/WindowsResource.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/MathExtras.h"
 #include "llvm/Support/Process.h"
 #include "llvm/Support/Program.h"
 #include "llvm/Support/raw_ostream.h"
@@ -44,9 +41,6 @@ namespace lld {
 namespace coff {
 namespace {
 
-const uint16_t SUBLANG_ENGLISH_US = 0x0409;
-const uint16_t RT_MANIFEST = 24;
-
 class Executor {
 public:
   explicit Executor(StringRef S) : Prog(Saver.save(S)) {}
@@ -263,6 +257,26 @@ void parseManifestUAC(StringRef Arg) {
   }
 }
 
+// Quote each line with "". Existing double-quote is converted
+// to two double-quotes.
+static void quoteAndPrint(raw_ostream &Out, StringRef S) {
+  while (!S.empty()) {
+    StringRef Line;
+    std::tie(Line, S) = S.split("\n");
+    if (Line.empty())
+      continue;
+    Out << '\"';
+    for (int I = 0, E = Line.size(); I != E; ++I) {
+      if (Line[I] == '\"') {
+        Out << "\"\"";
+      } else {
+        Out << Line[I];
+      }
+    }
+    Out << "\"\n";
+  }
+}
+
 // An RAII temporary file class that automatically removes a temporary file.
 namespace {
 class TemporaryFile {
@@ -376,64 +390,38 @@ static std::string createManifestXml() {
   return readFile(File2.Path);
 }
 
-static std::unique_ptr<MemoryBuffer>
-createMemoryBufferForManifestRes(size_t ManifestSize) {
-  size_t ResSize = alignTo(object::WIN_RES_MAGIC_SIZE +
-                           object::WIN_RES_NULL_ENTRY_SIZE +
-                           sizeof(object::WinResHeaderPrefix) +
-                           sizeof(object::WinResIDs) +
-                           sizeof(object::WinResHeaderSuffix) +
-                           ManifestSize,
-                           object::WIN_RES_DATA_ALIGNMENT);
-  return MemoryBuffer::getNewMemBuffer(ResSize);
-}
-
-static void writeResFileHeader(char *&Buf) {
-  memcpy(Buf, COFF::WinResMagic, sizeof(COFF::WinResMagic));
-  Buf += sizeof(COFF::WinResMagic);
-  memset(Buf, 0, object::WIN_RES_NULL_ENTRY_SIZE);
-  Buf += object::WIN_RES_NULL_ENTRY_SIZE;
-}
-
-static void writeResEntryHeader(char *&Buf, size_t ManifestSize) {
-  // Write the prefix.
-  auto *Prefix = reinterpret_cast<object::WinResHeaderPrefix *>(Buf);
-  Prefix->DataSize = ManifestSize;
-  Prefix->HeaderSize = sizeof(object::WinResHeaderPrefix) +
-                       sizeof(object::WinResIDs) +
-                       sizeof(object::WinResHeaderSuffix);
-  Buf += sizeof(object::WinResHeaderPrefix);
-
-  // Write the Type/Name IDs.
-  auto *IDs = reinterpret_cast<object::WinResIDs *>(Buf);
-  IDs->setType(RT_MANIFEST);
-  IDs->setName(Config->ManifestID);
-  Buf += sizeof(object::WinResIDs);
-
-  // Write the suffix.
-  auto *Suffix = reinterpret_cast<object::WinResHeaderSuffix *>(Buf);
-  Suffix->DataVersion = 0;
-  Suffix->MemoryFlags = object::WIN_RES_PURE_MOVEABLE;
-  Suffix->Language = SUBLANG_ENGLISH_US;
-  Suffix->Version = 0;
-  Suffix->Characteristics = 0;
-  Buf += sizeof(object::WinResHeaderSuffix);
-}
-
 // Create a resource file containing a manifest XML.
 std::unique_ptr<MemoryBuffer> createManifestRes() {
-  std::string Manifest = createManifestXml();
+  // Create a temporary file for the resource script file.
+  TemporaryFile RCFile("manifest", "rc");
 
-  std::unique_ptr<MemoryBuffer> Res =
-      createMemoryBufferForManifestRes(Manifest.size());
+  // Open the temporary file for writing.
+  std::error_code EC;
+  raw_fd_ostream Out(RCFile.Path, EC, sys::fs::F_Text);
+  if (EC)
+    fatal(EC, "failed to open " + RCFile.Path);
 
-  char *Buf = const_cast<char *>(Res->getBufferStart());
-  writeResFileHeader(Buf);
-  writeResEntryHeader(Buf, Manifest.size());
-
-  // Copy the manifest data into the .res file.
-  std::copy(Manifest.begin(), Manifest.end(), Buf);
-  return Res;
+  // Write resource script to the RC file.
+  Out << "#define LANG_ENGLISH 9\n"
+      << "#define SUBLANG_DEFAULT 1\n"
+      << "#define APP_MANIFEST " << Config->ManifestID << "\n"
+      << "#define RT_MANIFEST 24\n"
+      << "LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT\n"
+      << "APP_MANIFEST RT_MANIFEST {\n";
+  quoteAndPrint(Out, createManifestXml());
+  Out << "}\n";
+  Out.close();
+
+  // Create output resource file.
+  TemporaryFile ResFile("output-resource", "res");
+
+  Executor E("rc.exe");
+  E.add("/fo");
+  E.add(ResFile.Path);
+  E.add("/nologo");
+  E.add(RCFile.Path);
+  E.run();
+  return ResFile.getMemoryBuffer();
 }
 
 void createSideBySideManifest() {
@@ -604,22 +592,40 @@ void checkFailIfMismatch(StringRef Arg)
 // using cvtres.exe.
 std::unique_ptr<MemoryBuffer>
 convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) {
-  object::WindowsResourceParser Parser;
+  // Create an output file path.
+  TemporaryFile File("resource-file", "obj");
 
+  // Execute cvtres.exe.
+  Executor E("cvtres.exe");
+  E.add("/machine:" + machineToStr(Config->Machine));
+  E.add("/readonly");
+  E.add("/nologo");
+  E.add("/out:" + Twine(File.Path));
+
+  // We must create new files because the memory buffers we have may have no
+  // underlying file still existing on the disk.
+  // It happens if it was created from a TemporaryFile, which usually delete
+  // the file just after creating the MemoryBuffer.
+  std::vector<TemporaryFile> ResFiles;
+  ResFiles.reserve(MBs.size());
   for (MemoryBufferRef MB : MBs) {
-    std::unique_ptr<object::Binary> Bin = check(object::createBinary(MB));
-    object::WindowsResource *RF = dyn_cast<object::WindowsResource>(Bin.get());
-    if (!RF)
-      fatal("cannot compile non-resource file as resource");
-    if (auto EC = Parser.parse(RF))
-      fatal(EC, "failed to parse .res file");
+    // We store the temporary file in a vector to avoid deletion
+    // before running cvtres
+    ResFiles.emplace_back("resource-file", "res");
+    TemporaryFile& ResFile = ResFiles.back();
+    // Write the content of the resource in a temporary file
+    std::error_code EC;
+    raw_fd_ostream OS(ResFile.Path, EC, sys::fs::F_None);
+    if (EC)
+      fatal(EC, "failed to open " + ResFile.Path);
+    OS << MB.getBuffer();
+    OS.close();
+
+    E.add(ResFile.Path);
   }
 
-  Expected<std::unique_ptr<MemoryBuffer>> E =
-      llvm::object::writeWindowsResourceCOFF(Config->Machine, Parser);
-  if (!E)
-    fatal(errorToErrorCode(E.takeError()), "failed to write .res to COFF");
-  return std::move(E.get());
+  E.run();
+  return File.getMemoryBuffer();
 }
 
 // Run MSVC link.exe for given in-memory object files.

Modified: lld/trunk/test/COFF/combined-resources.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/combined-resources.test?rev=306618&r1=306617&r2=306618&view=diff
==============================================================================
--- lld/trunk/test/COFF/combined-resources.test (original)
+++ lld/trunk/test/COFF/combined-resources.test Wed Jun 28 17:17:26 2017
@@ -4,6 +4,8 @@
 // > rc /fo combined-resources.res /nologo combined-resources.rc
 // > rc /fo combined-resources-2.res /nologo combined-resources-2.rc
 
+# REQUIRES: winres
+
 # RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
 # RUN: lld-link /out:%t.exe /entry:main %t.obj %p/Inputs/resource.res \
 # RUN:   %p/Inputs/combined-resources.res %p/Inputs/combined-resources-2.res

Modified: lld/trunk/test/COFF/def-name.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/def-name.test?rev=306618&r1=306617&r2=306618&view=diff
==============================================================================
--- lld/trunk/test/COFF/def-name.test (original)
+++ lld/trunk/test/COFF/def-name.test Wed Jun 28 17:17:26 2017
@@ -1,3 +1,5 @@
+# REQUIRES: winres
+
 # RUN: rm -rf %t
 # RUN: mkdir -p %t
 # RUN: cd %t

Modified: lld/trunk/test/COFF/dll.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/dll.test?rev=306618&r1=306617&r2=306618&view=diff
==============================================================================
--- lld/trunk/test/COFF/dll.test (original)
+++ lld/trunk/test/COFF/dll.test Wed Jun 28 17:17:26 2017
@@ -1,3 +1,5 @@
+# REQUIRES: winres
+
 # RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj
 # RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2 \
 # RUN:   /export:mangled

Modified: lld/trunk/test/COFF/dllimport-gc.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/dllimport-gc.test?rev=306618&r1=306617&r2=306618&view=diff
==============================================================================
--- lld/trunk/test/COFF/dllimport-gc.test (original)
+++ lld/trunk/test/COFF/dllimport-gc.test Wed Jun 28 17:17:26 2017
@@ -1,3 +1,5 @@
+# REQUIRES: winres
+
 # RUN: yaml2obj < %p/Inputs/export.yaml > %t-lib.obj
 # RUN: lld-link /out:%t.dll /dll %t-lib.obj /implib:%t.lib /export:exportfn1
 

Modified: lld/trunk/test/COFF/manifestinput.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/manifestinput.test?rev=306618&r1=306617&r2=306618&view=diff
==============================================================================
--- lld/trunk/test/COFF/manifestinput.test (original)
+++ lld/trunk/test/COFF/manifestinput.test Wed Jun 28 17:17:26 2017
@@ -1,4 +1,4 @@
-# REQUIRES: win_mt
+# REQUIRES: winres
 
 # RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj
 # RUN: lld-link /out:%t.exe /entry:main \
@@ -8,28 +8,3 @@
 
 CHECK: <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 CHECK: <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity></dependentAssembly></dependency><trustInfo><security><requestedPrivileges><requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security></trustInfo></assembly>
-
-# RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj
-# RUN: lld-link /out:%t.exe /entry:main \
-# RUN:   /manifest:embed \
-# RUN:   /manifestuac:"level='requireAdministrator'" \
-# RUN:   /manifestinput:%p/Inputs/manifestinput.test %t.obj
-# RUN: llvm-readobj -coff-resources -file-headers %t.exe | FileCheck %s \
-# RUN:   -check-prefix TEST_EMBED
-
-TEST_EMBED:          ResourceTableRVA: 0x1000
-TEST_EMBED-NEXT:     ResourceTableSize: 0x298
-TEST_EMBED-DAG:      Resources [
-TEST_EMBED-NEXT:       Total Number of Resources: 1 
-TEST_EMBED-DAG:        Number of String Entries: 0
-TEST_EMBED-NEXT:       Number of ID Entries: 1
-TEST_EMBED-NEXT:       Type: kRT_MANIFEST (ID 24) [
-TEST_EMBED-NEXT:         Table Offset: 0x18
-TEST_EMBED-NEXT:         Number of String Entries: 0
-TEST_EMBED-NEXT:         Number of ID Entries: 1
-TEST_EMBED-NEXT:         Name: (ID 1) [
-TEST_EMBED-NEXT:           Table Offset: 0x30
-TEST_EMBED-NEXT:           Number of String Entries: 0
-TEST_EMBED-NEXT:           Number of ID Entries: 1
-TEST_EMBED-NEXT:           Language: (ID 1033) [
-TEST_EMBED-NEXT:             Entry Offset: 0x48

Modified: lld/trunk/test/COFF/noentry.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/noentry.test?rev=306618&r1=306617&r2=306618&view=diff
==============================================================================
--- lld/trunk/test/COFF/noentry.test (original)
+++ lld/trunk/test/COFF/noentry.test Wed Jun 28 17:17:26 2017
@@ -1,3 +1,5 @@
+# REQUIRES: winres
+
 # RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj
 # RUN: lld-link /out:%t.dll /dll %t.obj
 # RUN: llvm-readobj -file-headers %t.dll | FileCheck -check-prefix=ENTRY %s

Modified: lld/trunk/test/COFF/out.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/out.test?rev=306618&r1=306617&r2=306618&view=diff
==============================================================================
--- lld/trunk/test/COFF/out.test (original)
+++ lld/trunk/test/COFF/out.test Wed Jun 28 17:17:26 2017
@@ -1,3 +1,4 @@
+# REQUIRES: winres
 # RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
 
 # RUN: mkdir -p %T/out/tmp

Modified: lld/trunk/test/COFF/resource.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/resource.test?rev=306618&r1=306617&r2=306618&view=diff
==============================================================================
--- lld/trunk/test/COFF/resource.test (original)
+++ lld/trunk/test/COFF/resource.test Wed Jun 28 17:17:26 2017
@@ -1,3 +1,5 @@
+# REQUIRES: winres
+
 # RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
 # RUN: lld-link /out:%t.exe /entry:main %t.obj %p/Inputs/resource.res
 

Modified: lld/trunk/test/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/lit.cfg?rev=306618&r1=306617&r2=306618&view=diff
==============================================================================
--- lld/trunk/test/lit.cfg (original)
+++ lld/trunk/test/lit.cfg Wed Jun 28 17:17:26 2017
@@ -264,7 +264,8 @@ llvm_config_cmd.wait()
 # Set a fake constant version so that we get consitent output.
 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')
+# Check if Windows resource file compiler exists.
+cvtres = lit.util.which('cvtres', config.environment['PATH'])
+rc = lit.util.which('rc', config.environment['PATH'])
+if cvtres and rc:
+    config.available_features.add('winres')




More information about the llvm-commits mailing list