使用bazel

时间:2018-12-27 20:20:11

标签: c bazel

我有一个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并不完全陌生,但我也不是专家,花了很多时间尝试失败后。关于如何使它起作用的任何建议?

2 个答案:

答案 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)) 来注释您的“正常”功能。应该在所有目标中选择“假”函数而不是“正常”函数,其中存在函数(假函数)的强符号