CMake构建SHARED动态库报LNK1104错误但STATIC静态库正常
错误原因
LINK : fatal error LNK1104: cannot open file 'Debug\math_lib.lib'是Windows平台使用MSVC编译器构建C++动态库的典型问题:
- 构建STATIC静态库时,编译产物只有一个
.lib文件,内部包含库的全部目标代码,链接时会直接整合进可执行文件,不需要对接口做特殊标记,因此全流程可以正常完成。 - 构建SHARED动态库时,MSVC会生成两个核心文件:一是程序运行时加载的
math_lib.dll,二是链接阶段供可执行文件定位符号用的导入库math_lib.lib。如果库代码中没有对需要对外暴露的函数、类添加导出标记,编译器不会生成这个导入库文件,后续链接可执行文件时找不到对应文件就会抛出该错误。
正确构建方案
有两种可行方案,可根据使用场景选择:
- 标准导出宏方案(生产环境推荐)
- 为math库新增头文件
math.h,定义跨平台兼容的导出宏,所有对外暴露的接口前都添加该宏标记:
// math.h #pragma once #ifdef _WIN32 #ifdef MATH_LIB_EXPORTS #define MATH_API __declspec(dllexport) #else #define MATH_API __declspec(dllimport) #endif #else #define MATH_API #endif // 示例:对外暴露的加法函数,类导出同理在class关键字后加MATH_API即可 MATH_API int add(int a, int b);- 修改CMakeLists.txt配置,为动态库添加编译宏、配置公共头文件搜索路径:
cmake_minimum_required(VERSION 3.0) project(myproject LANGUAGES CXX) // 声明动态库目标 add_library(math_lib SHARED math.cpp math.h) // 编译math_lib时定义导出宏,触发__declspec(dllexport)逻辑 target_compile_definitions(math_lib PRIVATE MATH_LIB_EXPORTS) // 将当前源码目录设为公共头文件搜索路径,所有链接math_lib的目标会自动继承该配置 target_include_directories(math_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) // 声明两个可执行文件目标 add_executable(my_exe main.cpp) add_executable(my_exe_2 main_2.cpp) // 为可执行文件链接math_lib动态库 target_link_libraries(my_exe PUBLIC math_lib) target_link_libraries(my_exe_2 PUBLIC math_lib)- 在
math.cpp中包含math.h实现对应接口,两个可执行文件的源码中直接引入math.h即可正常调用库函数。
- 为math库新增头文件
- 全局符号导出方案(仅适合学习测试场景)
如果只是编写学习demo,不想逐个给接口加导出标记,可以在add_library命令后添加一行配置,开启Windows平台自动导出所有符号的属性,无需修改C++代码即可自动生成导入库:set_target_properties(math_lib PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
运行注意:Windows下执行生成的可执行文件时,需要保证
math_lib.dll与可执行文件在同一目录,或dll所在路径已加入系统PATH环境变量。使用CMake默认生成的VS工程构建时,会自动将dll拷贝到可执行文件的输出目录,无需手动复制。
内容的提问来源于stack exchange,提问作者PetrasVestartasEPFL
相关产品推荐
相关产品推荐

