假设我有一个包含两个库foo
和bar
的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.dll
和bar.dll
会自动复制到将编译app.exe
的文件夹中(我假设它将是$<TARGET_FILE_DIR:app>
)。我是否可以通过向foo
和bar
添加属性/自定义命令而不修改foo
和bar
与app
相关联的方式来实现?
换句话说,我想修改上面的脚本,这样,如果我添加一个新的目标可执行文件app2
,对target_link_libraries(app2 foo)
的简单调用就是我需要的所有将foo.dll
和bar.dll
复制到app2
的目标文件夹。
我目前遇到的问题是涉及add_custom_command( ... COMMAND ${CMAKE_COMMAND} -E copy_if_different ... )
的现有解决方案需要明确添加到最终目标app
和app2
,我不能只是add_custom_command(foo ...)
因为app
和app2
最终会出现在任意文件夹中。
我在考虑修改target_link_libraries(app ...)
以包含对我自己的函数(复制dll的函数)的调用并调用旧的_target_link_libraries(app ...)
,但我不确定这是否是最干净的方式去,并想知道是否有更好的方法。
最后,我希望我们发现的任何解决方案也适用于未编译为CMake子项目的IMPORTED
目标和库。
答案 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的详细信息。