使用 catkin 从源代码编译 gtest

Compile gtest from source with catkin

我正在尝试从源代码编译 gtest(而不是使用现有的已安装版本)。我正在做一个基于 catkin 的 cmake 项目。

我已将 https://github.com/google/googletest 中的源代码添加到我的工作区,并将文件夹包含在 add_subdirectory 中。

但是,我遇到了与现有 gtest 的名称冲突:

CMake Error at src/test_env/GTest/googletest/cmake/internal_utils.cmake:151 (add_library):
  add_library cannot create target "gtest" because another target with the
  same name already exists.  The existing target is a shared library created
  in source directory "/usr/src/gtest".  See documentation for policy CMP0002
  for more details.

从其他帖子和 googletest 说明本身 (https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project) 我了解到这应该没有问题。

我认为问题可能在于catkin如何处理gtest。而且,诚然,通常我只能使用已安装的版本。但我想确保每个人都使用相同(捆绑)版本的 gtest。

欢迎任何建议和提示。

好的,所以错误信息其实很清楚。 cmake "target" 是 "something that will be produced by the build",无论是库、可执行文件还是其他东西。所以,问题是您正在尝试添加一个名为 "gtest" 的目标,而 catkin 已经做了同样的事情。两者都会产生库 "libgtest.so",当然同一文件夹中只能有一个。您可以通过更改 googletest/CMakelists.txt 中的目标名称来重命名 "your" gtest,但我强烈建议您不要这样做。

在我看来,gtest 根本不应该是一个共享库,尤其是当您对存储库中的不同项目使用不同的构建标志时。有一个替代方案,基本上只将 gtest 源代码包含在一个文件夹中,然后将头文件和源文件包含在您的单元测试 main.cpp 中。 googletest 已经为此提供了帮助程序,即 src/gtest-main.cc.

这就是我的结构:

  1. 将你想要的 gtest 版本作为子模块添加到 git(以防你使用 git)。这样,您就可以为存储库中的所有项目指定一个版本,并且可以在不同的分支中更新它。我将调用该文件夹 "GTEST_DIR".
  2. .cpp 文件中编写你的单元测试,即 #include <gtest/gtest.h>,每个 hpp 你想测试一个,#include hppcpp 在你的 test.cpp 中。这强制将您的测试与其他 classes 分开,并使 非常 容易切换出依赖 classes 与模拟或假对象。您不需要 main() 函数,因为该函数已经在 gtest-main.cc.
  3. 像这样写一个cmake宏:

    macro(add_gtest NAME FILES)
    add_executable(my_gtest_$NAME
      $FILES
      GTEST_DIR/src/gtest.cc
      GTEST_DIR/src/gtest-death-test.cc
      GTEST_DIR/src/gtest-filepath.cc
      GTEST_DIR/src/gtest-port.cc
      GTEST_DIR/src/gtest-printers.cc
      GTEST_DIR/src/gtest-test-part.cc
      GTEST_DIR/src/gtest-typed-test.cc
      GTEST_DIR/src/gtest-main.cc
    )
    target_include_directories(my_gtest_$NAME GTEST_DIR/include)
    endmacro()
    

当然,您可以使它更复杂或更简单,但这就是要点。当然,与将 gtest 用作共享库相比,这种方式的编译时间会更长,但它实际上可以确保您的单元得到隔离测试,这在我看来非常有价值。此外,在这种情况下,您可以使用 ccache 来大大缩短编译时间,因为 gtest 目标文件永远不会更改。此外,这将确保 gtest 是用您想要的标志编译的。例如,您可以为同一个 class 创建 2 个单独的单元测试,一个启用异常,一个不启用。