0

I'm a bit puzzled by the way that CMake deals with library linking on Windows machine. Below I have a simple CMakeLists.txt file:

cmake_minimum_required (VERSION 3.10)
project (sample)

add_library (quad SHARED quad.cpp)

add_executable (run main.cpp)
target_link_libraries (run PRIVATE quad)

On a Linux/Mac machine, CMake correctly builds the *.so/*.dylib libraries and links the executable against the *.so/*.dylib files. However on a Windows machine it builds the *.dll file and then attempts to link against a *.lib file.

Underneath the hood CMake executes the following command:

>------ Build started: Project: CMakeLists, Configuration: Debug ------
[1/4] C:\PROGRA~2\MICROS~1\2017\COMMUN~1\VC\Tools\MSVC\1415~1.267\bin\HostX64\x64\cl.exe  /nologo /TP -Dquad_EXPORTS  /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MDd /Zi /Ob0 /Od /RTC1 /showIncludes /FoCMakeFiles\quad.dir\quad.cpp.obj /FdCMakeFiles\quad.dir\ /FS -c C:\Users\UX\Workspace\sample\quad.cpp
[2/4] C:\PROGRA~2\MICROS~1\2017\COMMUN~1\VC\Tools\MSVC\1415~1.267\bin\HostX64\x64\cl.exe  /nologo /TP   /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MDd /Zi /Ob0 /Od /RTC1 /showIncludes /FoCMakeFiles\run.dir\main.cpp.obj /FdCMakeFiles\run.dir\ /FS -c C:\Users\UX\Workspace\sample\main.cpp
[3/4] cmd.exe /C "cd . && "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E vs_link_dll --intdir=CMakeFiles\quad.dir --manifests  -- C:\PROGRA~2\MICROS~1\2017\COMMUN~1\VC\Tools\MSVC\1415~1.267\bin\Hostx64\x64\link.exe /nologo CMakeFiles\quad.dir\quad.cpp.obj  /out:quad.dll /implib:quad.lib /pdb:quad.pdb /dll /version:0.0 /machine:x64 /debug /INCREMENTAL  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib  && cd ."
[4/4] cmd.exe /C "cd . && "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\run.dir --manifests  -- C:\PROGRA~2\MICROS~1\2017\COMMUN~1\VC\Tools\MSVC\1415~1.267\bin\Hostx64\x64\link.exe /nologo CMakeFiles\run.dir\main.cpp.obj  /out:run.exe /implib:run.lib /pdb:run.pdb /version:0.0  /machine:x64 /debug /INCREMENTAL /subsystem:console  quad.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
FAILED: run.exe 
cmd.exe /C "cd . && "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\run.dir --manifests  -- C:\PROGRA~2\MICROS~1\2017\COMMUN~1\VC\Tools\MSVC\1415~1.267\bin\Hostx64\x64\link.exe /nologo CMakeFiles\run.dir\main.cpp.obj  /out:run.exe /implib:run.lib /pdb:run.pdb /version:0.0  /machine:x64 /debug /INCREMENTAL /subsystem:console  quad.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
LINK Pass 1: command "C:\PROGRA~2\MICROS~1\2017\COMMUN~1\VC\Tools\MSVC\1415~1.267\bin\Hostx64\x64\link.exe /nologo CMakeFiles\run.dir\main.cpp.obj /out:run.exe /implib:run.lib /pdb:run.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console quad.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\run.dir/intermediate.manifest CMakeFiles\run.dir/manifest.res" failed (exit code 1104) with the following output:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\LINK : fatal error LNK1104: cannot open file 'quad.lib'
ninja: build stopped: subcommand failed.

Build failed.

My question is why does it fail on Windows when the CMake documentation states the following:

target_link_libraries(<target>
                  <PRIVATE|PUBLIC|INTERFACE> <item>...
                 [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)

Where item can be A library target name? Shouldn't it have enough information from the target's properties to identify the full path to the compiled library as well as its type (i.e. SHARED) to be able to properly link the executable?

1 Answers1

0

This is how linking works in Windows. You need a foo.lib file to link to foo.dll library. This .lib is produced when .dll itself is linked. You have to distribute .lib files together with library headers.

arrowd
  • 33,231
  • 8
  • 79
  • 110