1

我正在尝试从源代码编译 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。

欢迎任何建议和提示。

4

1 回答 1

1

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

在我看来,gtest 甚至根本不应该是一个共享库,特别是如果您对存储库中的不同项目使用不同的构建标志。还有一种替代方法,基本上只是将 gtest 源代码包含在一个文件夹中,然后将头文件和源文件包含在您的 unittestsmain.cpp中。googletest 已经为此提供了帮助程序,即src/gtest-main.cc.

这就是我将如何构建它:

  1. 将您想要的 gtest 版本作为子模块添加到 git(如果您使用 git)。这样,您就可以为 repo 中的所有项目指定一个版本,并且可以在不同的分支中对其进行更新。我将该文件夹称为“GTEST_DIR”。
  2. 将您的单元测试写在.cpp文件中,即#include <gtest/gtest.h>每个hpp您要测试的文件,#include以及您hpp的. 这强制将您的测试与其他类分开,并且可以容易地使用模拟或假对象切换依赖类。您将不需要函数,因为该函数已经在.cpptest.cppmain()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 使用您想要的标志进行编译。例如,您可以为同一个类创建 2 个单独的单元测试,一个启用异常,一个不启用。

于 2017-03-11T11:00:27.010 回答