使用catkin从源代码编译gtest

时间:2017-03-02 09:00:19

标签: cmake googletest 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版本。

欢迎任何建议和提示。

1 个答案:

答案 0 :(得分:1)

好的,所以错误信息实际上非常清楚。一个cmake"目标"是"将由构建"生成的东西,无论是库,还是可执行文件,还是其他东西。所以,问题是你正在尝试添加名为" gtest"的目标,并且catkin已经做了同样的事情。两者都会产生库" libgtest.so",当然只有一个在同一个文件夹中。你可以重命名"你的" gtest通过更改googletest/CMakelists.txt中的目标名称,但我强烈建议您不要这样做。

在我看来,gtest根本不应该是一个共享库,特别是如果你在存储库中为不同的项目使用不同的构建标志。有一个替代方案,基本上只包括文件夹中的gtest源代码,然后在单元测试main.cpp中包含头文件和源文件。 googletest已经附带了帮助,即src/gtest-main.cc

这就是我如何构建它:

  1. 将您想要的gtest版本作为子模块添加到git(如果您使用git)。这样,您拥有repo中所有项目的指定版本,并可以在其他分支中更新它。我将该文件夹称为" GTEST_DIR"。
  2. 将您的单元测试写在.cpp个文件中,#include <gtest/gtest.h>,每个hpp要测试一个,#include hppcpp 1 {} test.cpp。这会强制将测试与其他类分离,并使非常可以轻松地使用模拟或伪对象切换依赖类。您不需要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()
    
  4. 当然,你可以使这更复杂或更简单,但这是要点。当然,使用gtest作为共享库,编译时间会更长,但它实际上确保您的单元被隔离测试,这在我看来是非常有价值的。此外,您可以使用ccache来大大缩短此方案中的编译时间,因为gtest对象文件永远不会更改。此外,这将确保gtest编译完全符合您想要的标志。例如,您可以为同一个类创建2个单独的单元测试,一个启用异常,另一个不启用。