<div dir="ltr">

I was very excited to see that CMake 3.12rc1 now has support for linking object libraries, making usage requirements propagate to top level targets that use these libraries. However, I'm having trouble putting the concept into practice to build a DLL on Windows 10 using Visual Studio 2017's compiler (MSVC 19.x I think).<br><br>There's a minimal self-contained example here:<br><br><a href="https://gitlab.com/detly/cmake-dll-ex">https://gitlab.com/detly/cmake-dll-ex</a><br><br>The point is to make a DLL of "module2" that exports the "module2()" function. This is the "module2_dll" target in modules/module2/CMakeLists.txt. If you don't want to pore over that project, basically I have this structure:<br><br>  /<br>    - common<br>    - modules/<br>      - module1 (depends on "common")<br>      - module2 (depends on "common" and "module1", exports "module2()")<br><br>In common/CMakeLists.txt I have 'add_library(common OBJECT "common.c")'. Similarly for module1 and module2, and module1 also has 'target_link_libraries(module1 PUBLIC common)' and module2 has 'target_link_libraries(module2 PUBLIC module1 common)'. (I am aware that some build systems don't like build targets without source files, but adding "module2.c" doesn't change things.)<br><br>Finally there's a DLL target:<br><br>add_library(module2_dll SHARED)<br>target_link_libraries(module2_dll module2)<br><br>I build this by doing:<br><br>    mkdir build<br>    cd build<br>    cmake ..<br>    cmake --build . --target module2_dll<br><br>The toolchain information shows:<br><br>-- Building for: Visual Studio 15 2017<br>-- The C compiler identification is MSVC 19.13.26129.0<br>-- The CXX compiler identification is MSVC 19.13.26129.0<br>-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.13.26128/bin/Hostx86/x86/cl.exe<br>-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.13.26128/bin/Hostx86/x86/cl.exe -- works<br><br>Now I would expect that building the module2_dll target would build .obj files for all dependencies and link them all together as a DLL. But it ultimately fails with:<br><br>"C:\Users\heerij\Code\cmake-dll-ex\build\modules\module2\module2_dll.vcxproj" (default target) (1) -><br>(Link target) -><br>  module2.obj : error LNK2019: unresolved external symbol _common referenced in function _module2 [C:\Users\heerij\Code \cmake-dll-ex\build\modules\module2\module2_dll.vcxproj]<br>  module2.obj : error LNK2019: unresolved external symbol _module1 referenced in function _module2 [C:\Users\heerij\Cod e\cmake-dll-ex\build\modules\module2\module2_dll.vcxproj]<br>  C:\Users\heerij\Code\cmake-dll-ex\build\modules\module2\Debug\module2_dll.dll : fatal error LNK1120: 2 unresolved ext ernals [C:\Users\heerij\Code\cmake-dll-ex\build\modules\module2\module2_dll.vcxproj]<br><br>If I remove the "SHARED" option from 'add_library(module2_dll)', it builds a .lib file just fine. If I build the module2 target (not module2_dll), it builds a .lib file as well. But I want a DLL.<br><br>I was surprised to see two things:<br><br>1. The final link command only runs on module2.obj, not module1.obj or common.obj. If I were doing it by hand I'd link all three as the final step.<br><br>2. The intermediate commands build both .obj and .lib files. Are the .lib files required? I don't know enough about Windows build mechanics to know.<br><br>Example output for #1:<br><br>Link:<br>  C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\bin\HostX86\x86\link.exe /ERR<br>  ORREPORT:QUEUE /OUT:"C:\Users\heerij\Code\cmake-dll-ex\build\modules\module2\Debug\module2_dll.dll" /INCREMENTAL /NOL<br>  OGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.<br>  lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /DEBUG /PDB:"C:/Users/heerij/Code/cma<br>  ke-dll-ex/build/modules/module2/Debug/module2_dll.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"C:<br>  /Users/heerij/Code/cmake-dll-ex/build/modules/module2/Debug/module2_dll.lib" /MACHINE:X86 /SAFESEH  /machine:X86 /DLL<br>   "C:\Users\heerij\Code\cmake-dll-ex\build\modules\module2\module2.dir\Debug\module2.obj"<br><br>Example output for #2:<br><br>ClCompile:<br>  C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\bin\HostX86\x86\CL.exe /c /I"<br>  C:\Users\heerij\Code\cmake-dll-ex\modules\module2" /I"C:\Users\heerij\Code\cmake-dll-ex\common" /I"C:\Users\heerij\Co<br>  de\cmake-dll-ex\modules\module1" /Zi /nologo /W3 /WX- /diagnostics:classic /Od /Ob0 /Oy- /D WIN32 /D _WINDOWS /D "CMA<br>  KE_INTDIR=\"Debug\"" /D _MBCS /Gm- /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"module2.dir\Deb<br>  ug\\" /Fd"module2.dir\Debug\module2.pdb" /Gd /TC /analyze- /FC /errorReport:queue "C:\Users\heerij\Code\cmake-dll-ex\<br>  modules\module2\module2.c"<br>  module2.c<br>Lib:<br>  C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\bin\HostX86\x86\Lib.exe /OUT:<br>  "module2.dir\Debug\module2.lib" /NOLOGO  /machine:X86 module2.dir\Debug\module2.obj<br>  "C:\Users\heerij\Code\cmake-dll-ex\build\common\common.dir\Debug\common.obj"<br>  "C:\Users\heerij\Code\cmake-dll-ex\build\modules\module1\module1.dir\Debug\module1.obj"<br>  module2.vcxproj -> C:\Users\heerij\Code\cmake-dll-ex\build\modules\module2\module2.dir\Debug\module2.lib<br><br>I didn't want to dump the entire MSVC output here because there's a tonne of it. But if you don't want to try this yourself, the output is here:<br><br><a href="https://gitlab.com/snippets/1728169">https://gitlab.com/snippets/1728169</a><br><br>Have I misunderstood how object library usage requirements and dependencies propagate? I would appreciate any pointers on this.<br><br>- Jason Heeris</div>