CMake集成Git SHA1时遭遇链接错误:relocation against `g_GIT_SHA1'及undefined reference to `g_GIT_SHA1'的解决求助
解决CMake生成Git SHA1时的链接错误
你的链接错误根源在于C++中const全局变量默认具有internal linkage(内部链接),导致动态库中的g_GIT_SHA1符号没有被导出,主程序无法找到它。下面是具体的修复步骤:
1. 修改头文件和生成的源文件,确保符号具有外部链接性
- 你的
GitSHA1.h声明是正确的,保持不变:
extern const char g_GIT_SHA1[];
- 修改
GitSHA1.cpp.in,在定义时添加extern关键字,强制符号为外部链接:
#define GIT_SHA1 "@GIT_SHA1@" extern const char g_GIT_SHA1[] = GIT_SHA1;
这样修改后,动态库会将g_GIT_SHA1符号导出到符号表中,主程序就能正确链接到它了。
2. 额外的验证与优化步骤
如果修改后仍有问题,可以检查以下几点:
- 确认
GetGitRevisionDescription.cmake模块已正确放置在你的CMAKE_MODULE_PATH指定路径(即项目根目录),且get_git_head_revision命令正常工作。你可以直接查看构建目录下生成的GitSHA1.cpp,确认GIT_SHA1宏已被替换为实际的Git哈希字符串。 - 移除
LIB_LIST中的头文件路径,add_library仅需传入源文件,头文件通过target_include_directories暴露即可:set(LIB_LIST "${CMAKE_CURRENT_BINARY_DIR}/GitSHA1.cpp") - 尝试删除整个构建目录,重新运行CMake并编译,确保
configure_file重新生成了最新的GitSHA1.cpp文件。
问题原理补充
在C++中,const修饰的全局变量默认带有static属性(内部链接),意味着该符号仅在当前编译单元内可见。当你把它放入动态库时,编译器不会将其导出到库的符号表中,主程序链接时自然会提示"未定义引用"。添加extern关键字后,符号变为外部链接,会被导出到动态库的符号表,主程序就能顺利找到它。
内容的提问来源于stack exchange,提问作者Francesco Ciraolo
相关产品推荐
相关产品推荐

