Note that there are some explanatory texts on larger screens.

plurals
  1. POLinking Windows DLL files from static libraries using CMake without hand-crafting unresolved symbol names
    primarykey
    data
    text
    <h1>The Situation</h1> <p>I'm using Visual&nbsp;Studio&nbsp;2008 SP1 (Professional Edition, both for 32-bit and 64-bit builds). I'm seeking a workaround to what I believe is a very unhelpful "<a href="http://support.microsoft.com/kb/141459" rel="nofollow noreferrer">limitation</a>" in Visual Studio. </p> <p>I find it quite surprising that the Visual Studio linker and compiler does not do this right at DLL file creation time, to automatically scan all specified static libraries for all exported symbols in the same manner given in <em><a href="http://msdn.microsoft.com/en-us/library/0b9xe492.aspx" rel="nofollow noreferrer">Building an Import Library and Export File</a></em> and in <em><a href="https://stackoverflow.com/questions/366228/def-files-c-c-dlls/376784#376784">a StackOverflow comment</a></em>. I confirmed that it is not sufficient to simply apply <code>__declspec(dllexport)</code> and <code>__declspec(dllimport)</code> attributes to class, function, and data declarations in the files that comprise the static libraries. </p> <p>The linker does not scan all of the static libraries for exported symbols and so won't pull them into the DLL file (the symbols have to be referenced by <code>.obj</code> files on the DLL link command-line or by other means I show below). Without explicit references to each exported symbol, the DLL file may still be created, but its associated import library file is not created.</p> <p>From what I can gather, Microsoft is recommending using <a href="http://msdn.microsoft.com/en-us/library/0b9xe492.aspx" rel="nofollow noreferrer">LIB.EXE</a> to create the <a href="http://msdn.microsoft.com/en-us/library/28d6s79h(VS.80).aspx" rel="nofollow noreferrer">DEF</a> file, but unfortunately, the <a href="http://msdn.microsoft.com/en-us/library/0b9xe492.aspx" rel="nofollow noreferrer">LIB.EXE</a> page applies a constraint:</p> <blockquote> <p>Note that if you create your import library in a preliminary step, before creating your <code>.dll</code>, you must pass the same set of object files when building the <code>.dll</code>, as you passed when building the import library.</p> </blockquote> <p>That is an unfortunate constraint given that I am also using <a href="http://en.wikipedia.org/wiki/CMake" rel="nofollow noreferrer">CMake</a> in my new build environment. CMake hides the details of what is actually passed to the linker (and I deem that to be a good thing in 99% of the time), but in this case I need to get access to some of that information at CMake execution time, not afterwards using hand-crafted scripts or other fragile <a href="http://en.wiktionary.org/wiki/skulduggery#Noun" rel="nofollow noreferrer">skulduggery</a>.</p> <h1>The Questions:</h1> <p>How do I go about forcing the DLL linker to resolve all exported symbols in all static libraries that comprise the DLL file, that isn't going to result in fragility and additional build logic maintenance chores? Think in terms of full-automation here, and keep in mind that I need to do this multiple times for multiple different DLL's.</p> <p>My questions are:</p> <ol> <li><p>How do I obtain the set of object files and static libraries used on the final DLL link command line using CMake syntax alone? </p></li> <li><p>Does the order of files listed on <a href="http://msdn.microsoft.com/en-us/library/0b9xe492.aspx" rel="nofollow noreferrer">LIB.EXE</a> line (the one used to generate the <a href="http://msdn.microsoft.com/en-us/library/28d6s79h(VS.80).aspx" rel="nofollow noreferrer">DEF</a> file) have to match exactly that order used on the DLL link line?</p></li> <li><p>Are there other difficulties that I might encounter from the use of the <a href="http://msdn.microsoft.com/en-us/library/0b9xe492.aspx" rel="nofollow noreferrer">LIB.EXE</a> approach to generate the <a href="http://msdn.microsoft.com/en-us/library/28d6s79h(VS.80).aspx" rel="nofollow noreferrer">DEF</a> file?</p></li> <li><p>Is there a better way to go about this that does not require calling a separate utility, such LIB.EXE, <strong>before</strong> calling the final link? I'm concerned about the added build overhead beyond the link itself for LIB.EXE to rescan <strong>all</strong> of the static libraries <em>again</em> even though it just wrote them out in separate executions.</p></li> </ol> <h1>The Non-Answers:</h1> <p>The following are solutions that I cannot consider right now:</p> <ol> <li><p>Manually specifying the unreferenced symbols anywhere other than in the original <code>.h</code> or <code>.cpp</code> files, as doing that is going to break each time a developer forgets to update the file that lists the (quite possibly name-mangled) symbol name. And it will break with non-user-friendly linker errors about unresolved symbols which will be costly for developers to debug. This non-answer includes the following approaches:</p> <ol> <li><p>Explicitly added <code>.obj</code> files to the DLL link command-line, (variants of this include adding "fake" <code>.obj</code> files that have dummy references to the otherwise unreferenced but exported symbols (and note that this is what my old build environment does today, and it stinks)), and,</p></li> <li><p>Handcrafting <a href="http://msdn.microsoft.com/en-us/library/28d6s79h(VS.80).aspx" rel="nofollow noreferrer">DEF</a> files to include the unreferenced but exported symbols, and,</p></li> <li><p>Linker command-line options that specifically reference the unreferenced but exported symbols symbols.</p></li> </ol></li> <li><p>Stop using static libraries altogether. I cannot do that in the short-term, as it is too much of a structural change from the old build environment I am moving away from. It is quite likely I will take this route in the future, once all remnants of the old build environment are in the "trash bin", but that is not my focus here.</p></li> </ol> <h1>Reference material:</h1> <ul> <li><a href="http://msdn.microsoft.com/en-us/library/d91k01sh(VS.80).aspx" rel="nofollow noreferrer">Exporting from a DLL Using DEF Files</a></li> <li><a href="http://msdn.microsoft.com/en-us/library/28d6s79h(VS.80).aspx" rel="nofollow noreferrer">Module Definition (.def) Files</a></li> <li><a href="http://support.microsoft.com/kb/141459" rel="nofollow noreferrer">PRB: Can't Export from Static Libraries w/_declspec(dllexport)</a></li> <li><a href="http://msdn.microsoft.com/en-us/library/30e78zd0.aspx" rel="nofollow noreferrer">dumpbin.exe /symbols option</a></li> <li><a href="http://msdn.microsoft.com/en-us/library/0xb6w1f8.aspx" rel="nofollow noreferrer">lib.exe options</a></li> <li><a href="http://msdn.microsoft.com/en-us/library/0b9xe492.aspx" rel="nofollow noreferrer">Building an Import Library and Export File</a></li> <li><a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#prop_tgt:LINK_FLAGS" rel="nofollow noreferrer">CMake LINK_FLAGS target property</a></li> </ul>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload