在 CMake 项目中传递复制 dll

Transitively copy dlls in a CMake project

假设我有一个 CMake 项目,其中包含两个库 foobar,以及一个可执行文件 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)

所以首先,当我尝试在 Windows 上编译这个项目时,它因错误 LNK1104 - cannot open file 'bar.lib' 而失败。我究竟做错了什么?我的意思是,这就像有史以来最基本的例子,它怎么会失败呢?我正在使用 Visual Studio 15.4.2 (MSVC 14.11.25503) 和 CMake 3.9.1.

进行编译

下一个问题,我想让我的foo.dllbar.dll自动复制到编译app.exe的文件夹中(我假设是$<TARGET_FILE_DIR:app>) .我可以通过向 foobar 添加 properties/custom 命令而不修改 foobar 链接到 [= 的方式来做到这一点 13=]?

换句话说,我想修改上面的脚本,这样,如果我添加一个新的目标可执行文件 app2,我只需要对 target_link_libraries(app2 foo) 的简单调用 将我的 foo.dllbar.dll 复制到 app2 的目标文件夹。

我目前遇到的问题是涉及 add_custom_command( ... COMMAND ${CMAKE_COMMAND} -E copy_if_different ... ) 的现有解决方案需要添加到 final 目标 appapp2明确地说,我不能只是 add_custom_command(foo ...) 因为 appapp2 可以在任意文件夹中结束。

我正在考虑修改 target_link_libraries(app ...) 以包装对我自己的函数(复制 dll 的函数)的调用并调用旧的 _target_link_libraries(app ...),但我不确定那是否是最干净的方法,想知道是否有更好的方法。

最后,我希望我们找到的任何解决方案也适用于 IMPORTED 未编译为 CMake 子项目的目标和库。

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?

您的库不导出任何内容,这就是它不创建导入库(他抱怨的 .lib 文件)的原因。确保您的源文件确实定义了一些符号,然后确保这些符号实际上是从 DLL 中导出的。 CMake 甚至附带 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?

不幸的是,CMake 目前没有对运行时依赖管理的适当支持。这就是阻止它与对 target_link_libraries 的简单调用一起工作的原因。 CMake 开发人员已经多次讨论过这样的功能,但似乎很难做到正确(不过我对这里的细节不太熟悉)。

我能想到的最方便的方法是让提供库提供一个 CMake function,它将所有相关的 DLL 复制到作为参数提供给它的文件夹中。这仍然很痛苦,但至少您保留了有关要使用提供的库复制哪些 DLL 的详细信息。