如何配置Bazel与Google Test解决bazel test链接错误
解决Bazel+Google Test测试DLL内部类的链接错误问题
问题根源
你碰到的LNK2019错误,说白了就是:你的core库被构建成Windows DLL时,只有标记为导出的符号会被放进DLL的导入库里。而你要测试的CallbackLogger::registerLogInfo属于库的内部实现,没被导出,所以测试程序链接时找不到这个符号。
解决方案
方案1:给核心库加静态库目标(推荐用于单元测试)
在core/BUILD里新增一个静态库目标,专门给测试用,这样测试能直接链接静态库,访问所有内部符号:
- 修改
core/BUILD:
# 原来的DLL目标(给生产可执行文件用) load(":windows_dll_library.bzl", "windows_dll_library") windows_dll_library( name = "core", srcs = [ "logger/callback_logger.cpp", # 其他源文件... ], hdrs = [ "logger/callback_logger.h", # 其他头文件... ], # 原来的DLL配置... ) # 新增静态库目标(只给测试用) cc_library( name = "core_static", srcs = [ "logger/callback_logger.cpp", # 和DLL目标用一样的源文件列表 ], hdrs = [ "logger/callback_logger.h", # 和DLL目标用一样的头文件列表 ], copts = [ # 如果有DLL导出宏,这里要取消导出,比如: # "-DCORE_LIB_STATIC" ], visibility = ["//test:__pkg__"], # 只允许test包访问这个目标 )
- 修改
test/BUILD,让测试依赖静态库而非DLL:
cc_test( name = "test", srcs = ["callback_logger_test.cpp"], deps = [ "//core:core_static", # 把原来的//core:core换成静态库目标 "@com_google_googletest//:gtest_main", ], )
方案2:调整DLL导出逻辑,让测试能访问内部符号
如果不想维护两个库目标,可以通过预编译宏控制符号导出,测试时让所有符号都可见:
- 在
callback_logger.h里调整导出宏:
#ifdef CORE_LIB_EXPORTS #define CORE_API __declspec(dllexport) #elif defined(CORE_LIB_STATIC) #define CORE_API #else #define CORE_API __declspec(dllimport) #endif class CORE_API CallbackLogger { // 原来可能只有对外类加了导出,现在测试时CORE_LIB_STATIC会让这个宏为空,所有符号都能被访问 public: void registerLogInfo(void (*callback)(const char*, int)); // 其他成员... };
- 修改
windows_dll_library.bzl,构建DLL时定义CORE_LIB_EXPORTS:
def windows_dll_library(name, srcs, hdrs, **kwargs): cc_binary( name = name + ".dll", srcs = srcs + hdrs, linkshared = True, copts = kwargs.pop("copts", []) + ["-DCORE_LIB_EXPORTS"], **kwargs ) cc_import( name = name, shared_library = name + ".dll", interface_library = name + ".lib", **kwargs )
- 修改
test/BUILD,测试时定义CORE_LIB_STATIC:
cc_test( name = "test", srcs = ["callback_logger_test.cpp"], deps = [ "//core:core", "@com_google_googletest//:gtest_main", ], copts = ["-DCORE_LIB_STATIC"], )
验证
运行测试命令:
bazel test --test_output=all //test:test
内容的提问来源于stack exchange,提问作者Daniel Vernall
相关产品推荐
相关产品推荐

