<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p>On 03/06/2021 23:09, Martin Storsjö wrote:<br>
    </p>
    <blockquote type="cite" cite="mid:3f8cc3f0-d3e4-3558-8d24-91f1b2f683d8@martin.st">On Sun,
      30 May 2021, Cristian Adam via llvm-dev wrote:
      <br>
      <br>
      <blockquote type="cite">Due to the nature of MSVC regarding
        default visibility of symbols (hidden by
        <br>
        default, whereas MinGW has visible by default), one needs to
        generate a .def
        <br>
        file with the symbols needed to be exported.
        <br>
        <br>
        This is done already in two cases for LLVM_BUILD_LLVM_C_DYLIB
        <br>
        (llvm/tools/llvm-shlib/gen-msvc-exports.py) and for
        <br>
        LLVM_EXPORT_SYMBOLS_FOR_PLUGINS (llvm/utils/extract_symbols.py).
        <br>
        <br>
        I've put together a patch that enables LLVM_DYLIB and
        CLANG_DYLIB for MSVC.
        <br>
        <br>
        I tested with clang-cl from the official Clang 12 x64 Windows
        binary
        <br>
        release:
        <br>
        <br>
         *  Normal build: 1,42 GB
        <br>
         *  shlib build: 536 MB
        <br>
        <br>
        The shlib release build compiled and linked fine with LLVM.dll
        and
        <br>
        clang-cpp.dll, unfortunately it crashes at runtime.
        <br>
      </blockquote>
      <br>
      Without digging into the scripts, I have one hunch:
      <br>
      <br>
      Does the def generator script differentiate between code and data
      symbols?
      <br>
      <br>
    </blockquote>
    <p>No. The CMake script just calls <font face="monospace">llvm-nm</font>,
      exports the symbols and filters some out.</p>
    <p><font face="monospace">llvm-nm</font> needs to exist beforehand.
      I tried using <font face="monospace">dumpbin</font>, but it's
      slower than llvm-nm. CMake's <font face="monospace">__create_def</font>
      also works, but it's not exporting all symbols needed to proper
      link.<br>
    </p>
    <blockquote type="cite" cite="mid:3f8cc3f0-d3e4-3558-8d24-91f1b2f683d8@martin.st">For the
      cases where accessing a data symbol from another DLL, the caller
      would have to have seen a declaration with the dllimport
      attribute. For functions, it doesn't matter (it just does an extra
      hop via the import thunk), but for data variables it matters. If
      the def file would have proper DATA annotations for such symbols,
      you would end up with linker errors (where you'd have an undefined
      reference to dataSymbol, where the import library only provides
      __imp_dataSymbol).
      <br>
      <br>
      This is fixed up by the autoimport feature when linking in mingw
      mode (which, in general, requires you to link against the mingw
      runtime too); for cases where the caller references dataSymbol but
      you only have __imp_dataSymbol available, the linker adds an entry
      to a list of pseudo relocations, which the mingw runtime handles
      when loaded, which then maps sections as writable and patches up
      the addresses to where they are located in another DLL.
      <br>
      <br>
      So to avoid this, we would either need to actually provide proper
      dllimport declarations at least for all data symbols, or avoid
      cross-DLL data accesses (by using e.g. accessor functions
      instead).
      <br>
      <br>
      <br>
    </blockquote>
    <p>According to <a moz-do-not-send="true" href="https://docs.microsoft.com/en-us/cpp/build/reference/exports?view=msvc-160">https://docs.microsoft.com/en-us/cpp/build/reference/exports?view=msvc-160 </a>
      you need to:</p>
    <blockquote>
      <p><i>When you export a variable from a DLL by using a .DEF file,
          you do not have to specify __declspec(dllexport) on the
          variable. However, in any file that uses the DLL, you must
          still use __declspec(dllimport) on the declaration of data.</i><i><br>
        </i></p>
    </blockquote>
    <p>Then tested it out in a small project <a moz-do-not-send="true" href="https://github.com/cristianadam/test-dll-def/">https://github.com/cristianadam/test-dll-def/</a>.
      <br>
    </p>
    <p>Then proceeded to add dllimport declarations for <font face="monospace">llvm::cl::TopLevelSubCommand</font> and <font face="monospace">llvm::cl::AllSubCommands</font> as seen in the
      updated patch:<br>
      <a moz-do-not-send="true" href="https://github.com/cristianadam/llvm-project/commit/56ecad41992bd9345702fccaf3805ab186dca25c">https://github.com/cristianadam/llvm-project/commit/56ecad41992bd9345702fccaf3805ab186dca25c</a></p>
    <p>Now <font face="monospace">llvm-nm</font> doesn't crash anymore!
      <br>
    </p>
    <p>Adding the dllimport declaration for the exported data symbols
      should be less work than doing proper dllimport declaration for
      everything that uses <font face="monospace">LLVM.dll</font> and<font face="monospace"> clang-cpp.dll</font>. Now I <i>just </i>need
      to find out which data variables I need to update. <br>
    </p>
    <p>Thank you!</p>
    <p>Cheers,<br>
      Cristian.<br>
    </p>
  </body>
</html>