CMake配置VS2019 x64编译C++项目出现LNK2019链接错误如何解决?
核心问题定位
你遇到的LNK2019错误核心原因是引擎库的CMake配置错误导致engine.cpp根本没有被编译进nrdengine_cpp_engine库,其次存在头文件全局变量定义不规范的问题,具体排查修复步骤如下:
修复步骤
第一步:修正引擎库的源码路径配置
引擎库CMakeLists.txt中CMAKE_SOURCE_DIR指向的是整个项目最顶层CMakeLists.txt(也就是应用层的CMakeLists.txt)所在的目录,无法匹配引擎库自身的src目录,导致engine.cpp没有被加入编译。
把引擎库CMakeLists.txt中的这行:file(GLOB_RECURSE SOURCE_FILES ${CMAKE_SOURCE_DIR}/src/*.c ${CMAKE_SOURCE_DIR}/src/*.cpp)替换为:
file(GLOB_RECURSE SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)${CMAKE_CURRENT_SOURCE_DIR}才会指向当前引擎库CMakeLists.txt所在的目录。第二步:修正头文件静态全局变量的错误定义
你在头文件中定义了static Engine& Core = Engine::Ref();,static修饰的全局变量会在每个引入该头的编译单元生成独立副本,且类内定义的Ref()是inline函数,在应用层展开时会直接在应用层目标文件中查找Engine构造、析构符号,容易触发链接错误。
修复方案:- 头文件中仅保留声明:
// 替换原来的static Engine& Core = Engine::Ref(); extern Engine& Core;- 在引擎库的engine.cpp中加入变量定义:
namespace NRD { // 加在原有构造析构实现外 Engine& Core = Engine::Ref(); Engine::Engine() { // 原有实现不变 } Engine::~Engine() { // 原有实现不变 } }第三步:(可选,动态库编译场景)补充符号导出声明
如果后续要把引擎库编译为Windows动态库(DLL),需要给Engine类加导出标记:// 头文件开头加 #ifdef NRD_ENGINE_EXPORTS #define NRD_API __declspec(dllexport) #else #define NRD_API __declspec(dllimport) #endif class NRD_API Engine { // 类原有定义不变 };同时在引擎库CMakeLists.txt中加编译宏定义:
target_compile_definitions(nrdengine_cpp_engine PRIVATE NRD_ENGINE_EXPORTS)
验证方案
所有修改完成后,完全删除build目录,重新执行CMake生成项目再编译,链接错误就会消失。
额外优化建议
应用层CMakeLists.txt中的target_include_directories(nrdengine_cpp_application PUBLIC nrdengine_cpp_engine)是无效配置,nrdengine_cpp_engine是目标名不是目录,这行可以直接删除,因为你已经把引擎库的头文件目录设为PUBLIC属性,应用层链接引擎库后会自动继承头文件搜索路径。
内容的提问来源于stack exchange,提问作者kapilarny

