我有一个C语言代码库,正在尝试用Bazel构建。该代码库包含使用fff库在C语言中生成函数模拟的单元测试。尽管实际的库并不重要,但我对函数模拟的整个概念有疑问。
现在,我有一个makefile,可以链接并运行测试。在构建测试时,我编译并链接了要测试的库和测试源本身。此测试还为库的依赖项定义了模拟。链接后,模拟符号将解析为模拟实现,并且一切都按预期工作。但是这样做的原因是我不链接实际的依赖库,我仅链接测试源中定义的模拟符号。
主要问题是:如何用Bazel做到这一点?当为cc_test
目标链接二进制文件时,Bazel会编译并链接所有传递依赖项。由于受测试的库(通过deps
)依赖于符号的实际实现,因此该真实定义与模拟对象一起链接,因此我自然会遇到此错误:multiple definition of XXX
。
示例:
cc_library(
name = "a",
# a.cc has the real version of "void some_function()".
srcs = ["a.cc"],
hdrs = ["a.h"],
)
# This test is working just fine.
cc_test(
name = "a_test",
srcs = ["a_test.cpp"],
deps = [":a"],
)
cc_library(
name = "b",
# b.cc includes a.h and uses "void some_function()".
srcs = ["b.cc"],
hdrs = ["b.h"],
deps = [":a"],
)
# This test has two definitions for "void some_function()":
# the real one and the mock one.
cc_test(
name = "b_test",
# b_test.cpp has the mock version of "void some_function()".
srcs = ["b_test.cpp"],
deps = [":b"],
)
我对Bazel并不完全陌生,但我也不是专家,花了很多时间尝试失败后。关于如何使它起作用的任何建议?
答案 0 :(得分:0)
您的问题可能是一个非常基本的问题,与名称空间和/或扩展类有关。
c根据定义没有命名空间,但是可以通过以下方式对其进行仿真:
https://stackoverflow.com/a/28535585/1019850
但是您可能使用c ++而不用c,所以可以直接使用名称空间。
具体的问题是,您使用相同的函数使用命名空间a.some_function()
和b.some_function()
表示的函数是原来的两倍。
在Bazel中,有几种解决方法,我只发布了简短复制的摘录,您必须在链接的页面上阅读详细信息。
deps = [
"@gtest//:main",
"//lib:hello-greet",
],
链接:https://docs.bazel.build/versions/master/cpp-use-cases.html
那里的代码段也用于测试,但我认为与您的问题无关紧要。
然后在Bazel中存在工具链,这是一个示例:
config_setting(
name = "on_linux",
constraint_values = [
"@bazel_tools//platforms:linux",
],
)
config_setting(
name = "on_windows",
constraint_values = [
"@bazel_tools//platforms:windows",
],
)
bar_binary(
name = "myprog",
srcs = ["mysrc.bar"],
compiler = select({
":on_linux": "//bar_tools:barc_linux",
":on_windows": "//bar_tools:barc_windows",
}),
)
链接:https://docs.bazel.build/versions/master/toolchains.html
由于我不是用c或c ++编程,通常需要花费一些时间来挖掘足够的信息以发布解决方案,所以我必须保留它而不是真正的解决方案,但是我希望问题和解决方法解决它变得更清晰了。
我会首先尝试第二个链接,位于上面的第一个代码段的下方。
答案 1 :(得分:0)
我在 Bazel 本身中没有看到任何好的解决方案。在 C++ 的情况下,Bazel 尝试创建一个简单明了的依赖管理系统来减少所有恶作剧,这可以在 C/C++ 编译/链接系统中完成。而且你的情况很不寻常。
我看到的唯一解决方案是使用 weak symbols 将负担转移到链接器。您可以使用 __attribute__((weak))
来注释您的“正常”功能。应该在所有目标中选择“假”函数而不是“正常”函数,其中存在函数(假函数)的强符号