如何将动态链接库与CMake一起使用
How to use dynamic link library with CMake?
我有一个简单的程序如下:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(test LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
LINK_DIRECTORIES(${PROJECT_SOURCE_DIR})
add_executable(test main.cpp)
target_include_directories(test PRIVATE ${PROJECT_SOURCE_DIR})
target_link_libraries(test PRIVATE power.dll)
main.cpp:
#include <iostream>
#include "power.h"
using namespace std;
int main()
{
cout << "Hello World!" << endl;
power(4.);
return 0;
}
power.h:
#ifndef POWER_H
#define POWER_H
double power(double number) noexcept;
#endif // POWER_H
power.h
的实现在名为power.dll
的.dll中。如果我用MinGW 7.3.0 X64编译这个项目:
error: undefined reference to `power(double)'
如果我用MSVC 2017 X64编译它说:
error: LNK1104: cannot open file 'power.lib'
这两个错误都表明CCD_ 3不能被链接器检测到。我做了很多搜索,但没有一个解决方案对我有效!有人能帮忙吗?提前感谢!
动态库的建模在CMake和源代码级别上都是不正确的。
作为一个起点,尝试将dll构建为与消费可执行文件相同的CMake项目的一部分:
cmake_minimum_required(VERSION 3.5)
project(test LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(GenerateExportHeader)
add_library(power SHARED power_sources.cpp power.h)
generate_export_header(power)
target_include_directories(power PUBLIC ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR})
add_executable(test main.cpp)
target_link_libraries(test PRIVATE power)
请注意generate_export_header
函数的使用,它指示CMake生成宏,以便以可移植的方式导出共享库接口上的函数。由于生成的文件进入二进制目录树,因此我们必须相应地调整库的include目录。
为了确保函数正确导出,请按如下方式更改标题:
#ifndef POWER_H
#define POWER_H
#include <power_export.h>
POWER_EXPORT double power(double number) noexcept;
#endif // POWER_H
请注意,generare_export_header
允许您广泛自定义生成的导出标头。
请确保从该基线开始构建和运行项目。
如果你想从外部构建dll(这不是绝对必要的,但因为这就是你的问题所在…(,我们必须将CMake文件修改为以下内容:
cmake_minimum_required(VERSION 3.5)
project(test LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(power)
add_executable(test main.cpp)
target_link_libraries(test PRIVATE power)
这里所有的魔法都发生在find_package
调用中。这个电话现在负责提供以前由建立图书馆的线路处理的所有信息:
- 提供导入的目标
power
以供target_link_libraries
调用使用 - 导入库(
power.lib
文件(的库名称与该导入目标的关联 - 通过导入的目标公开
power.h
和power_export.h
的目录
您可以在find脚本中手动构建这样一个导入的目标,也可以让CMake为您做这件事。在第一种情况下,创建一个FindPower.cmake
脚本文件,确保它的位置是CMAKE_MODULE_PATH
的一部分,并编写用于查找库和头文件并在其中构建导入目标的代码。请注意,以可移植的方式正确处理这一问题可能非常棘手,而且远远超出了StackOverflow问题的范围。在第二种情况下,让构建power
库的CMake脚本执行一个安装步骤,在此过程中将生成一个配置文件包,然后可以由test
项目使用。请注意,如果power
库本身不是用CMake构建的,那么这种方法是不可行的,因此在这种情况下,您必须坚持使用第一个选项。
Windows中的动态链接要求使用关键字__declspec
声明外部可见的符号。您的标题"power.h"应该被修改:
#ifndef POWER_H
#define POWER_H
#if defined(__WIN32__) && !defined(__CYGWIN__)
# if (defined(_MSC_VER) || defined(__MINGW32__)) && defined(BUILD_DLL)
# define POWERAPI __declspec(dllexport)
# elif (defined(_MSC_VER) || defined(__MINGW32__))
# define POWERAPI __declspec(dllimport)
# endif
#endif
POWERAPI double power(double number) noexcept;
#endif // POWER_H
在用CMake构建DLL power.DLL的项目中,您应该定义BUILD_DL:符号
add_definitions(-DBUILD_DLL)
则当使用MSVC编译器时,它应该生成power.lib文件,当使用MINGW时,应该生成power.a文件。不要使用DLL在项目中定义BUILD_DLL,它应该可以工作。
- 将--whole archive链接器选项与CMake和具有其他库依赖项的库一起使用
- 将 OpenCV 与 CMAKE 中的项目一起构建为第三方库的正确方法
- 如何将GTest与CMake一起使用?遵循谷歌指南时的链接问题
- 如何将动态链接库与CMake一起使用
- SSE 标志应该如何与现代 CMake 一起添加?
- 将外部C++库与 CMake 一起使用时出错
- Catch2 单元测试未与 CMake 项目一起运行
- 如何将 Pybind11 与 CMAKE 一起使用以链接 2 个模块
- 如何将 c++20 模块与 CMake 一起使用
- 如何将编译的 wxwidgets 与 cmake 一起使用
- 当它们不与GCC和CMAKE一起使用时,如何解析未定义的引用
- CMake 项目结构:如何正确地将库合并在一起并将它们包含在多个可执行文件中
- 如何将库与CMAKE一起包含在OSX捆绑包中
- 当将QT创建者与CMAKE一起使用时,为什么我不必手动链接MSVC库
- 将特征与cmake一起使用
- 在将QT与Cmake一起使用时解决链接错误
- 将CMAKE与Code ::块一起使用
- 我如何配置我的cmake文件以与Google Test和CTEST一起使用
- cmake 找不到随 vcpkg 一起安装的库
- Googletest 在 bazel test 中永远不会失败(在它应该失败的地方),但与 cmake & clion 一起工作