在CMake项目中传递复制dll

时间:2017-11-06 14:39:07

标签: c++ dll cmake shared-libraries visual-studio-2017

假设我有一个包含两个库foobar的CMake项目,以及一个可执行文件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添加属性/自定义命令而不修改foobarapp相关联的方式来实现

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

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

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

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

1 个答案:

答案 0 :(得分:2)

  

首先,当我尝试在Windows上编译此项目时,它失败了   错误LNK1104 - 无法打开文件&#39; bar.lib&#39;。我在做什么   错?

您的图书馆不会导出任何内容,这就是为什么它没有创建导入库(他正在抱怨的.lib文件)。确保您的源文件实际定义了一些符号,然后确保这些符号实际上是从DLL导出的。 CMake甚至随a module that provides portable macros for exporting symbols一起发货。

  

接下来的问题,我希望我的foo.dll和bar.dll能够自动生成   复制到app.exe将被编译的文件夹(我假设它会   是$)。我可以通过添加属性/自定义来实现   命令foo和bar而不修改foo和bar的方式   链接到app?

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

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