Reputation: 149
Let's say I have a CMake project with two libraries foo
and bar
, and an executable app
:
cmake_minimum_required(VERSION 3.1)
project(app)
add_library(foo SHARED foo.cpp)
add_library(bar SHARED bar.cpp)
target_link_libraries(foo PUBLIC bar)
add_executable(app main.cpp)
target_link_libraries(app foo)
So first, when I try to compile this project on Windows, it failed with an error LNK1104 - cannot open file 'bar.lib'
. What am I doing wrong? I mean, this is like the most basic example ever, how can it fail? I am compiling with Visual Studio 15.4.2 (MSVC 14.11.25503), and CMake 3.9.1.
Next question, I want my foo.dll
and bar.dll
to be automatically copied to the folder where app.exe
will be compiled (I assume it will be $<TARGET_FILE_DIR:app>
). Can I do that by adding properties/custom commands to foo
and bar
without modifying the way that foo
and bar
are linked to app
?
In other words, I want to modify the above script so that, if I add a new target executable app2
, a simple call to target_link_libraries(app2 foo)
is all I need to have my foo.dll
and bar.dll
copied over to the destination folder of app2
.
The problem I have so far is that existing solutions involving add_custom_command( ... COMMAND ${CMAKE_COMMAND} -E copy_if_different ... )
requires to be added to the final target app
and app2
explicitly, I cannot just add_custom_command(foo ...)
because app
and app2
can end up in arbitrary folders.
I was thinking of maybe modifying the target_link_libraries(app ...)
to wrap a call to my own function (the one that copies dll) and call the old _target_link_libraries(app ...)
, but I am not sure if that's the cleanest way to go, and was wondering if there are better ways to it.
Finally, I would like whatever solution we find to also work with IMPORTED
targets and libraries that are not compiled as CMake subprojects.
Upvotes: 2
Views: 994
Reputation: 54589
So first, when I try to compile this project on Windows, it failed with an error LNK1104 - cannot open file 'bar.lib'. What am I doing wrong?
Your library does not export anything, that's why it's not creating an import library (the .lib
file that he's complaining about). Be sure your source files actually define some symbols and then be sure that those symbols are actually exported from the DLL. CMake even ships with a module that provides portable macros for exporting symbols.
Next question, I want my foo.dll and bar.dll to be automatically copied to the folder where app.exe will be compiled (I assume it will be $). Can I do that by adding properties/custom commands to foo and bar without modifying the way that foo and bar are linked to app?
Unfortunately, CMake does not have proper support for runtime dependency management at the moment. That's what prevents this from working with a simple call to target_link_libraries
. Such a feature has been discussed several times already among the CMake developers but it seems surprisingly hard to get right (I'm not too familiar with the details here though).
The most convenient method that I could come up with is having the providing library provide a CMake function
that copies all the relevant DLLs to a folder provided to it as an argument. It's still a pain, but at least you keep the details about which DLLs to copy with the providing library.
Upvotes: 2