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