c++ - 为什么谷歌测试可以编译但看不到我的项目源代码?

标签 c++ cmake googletest

为什么谷歌测试可以编译但看不到我的项目源代码?

这是我收到的错误:

$ cmake . && make && make test
-- Configuring done
-- Generating done
-- Build files have been written to: mars_rover
Scanning dependencies of target mars_rover
[  8%] Building CXX object CMakeFiles/mars_rover.dir/src/rover.cpp.o
Linking CXX executable build/bin/mars_rover
[ 33%] Built target mars_rover
[ 41%] Built target gtest
[ 50%] Built target gtest_main
Scanning dependencies of target mars_rover_TEST
[ 58%] Building CXX object CMakeFiles/mars_rover_TEST.dir/test/test_mars_rover.cpp.o
mars_rover/test/test_mars_rover.cpp:2:10: fatal error: 'src/directions.h' file not found
#include "src/directions.h"
         ^
1 error generated.
make[2]: *** [CMakeFiles/mars_rover_TEST.dir/test/test_mars_rover.cpp.o] Error 1
make[1]: *** [CMakeFiles/mars_rover_TEST.dir/all] Error 2
make: *** [all] Error 2

以下是我的项目布局:

$ tree {src,test,lib} -L 1
    src
    ├── directions.cpp
    ├── directions.h
    ├── main.cpp
    ├── plateau.cpp
    ├── plateau.h
    ├── point.h
    ├── rover.cpp
    └── rover.h
    test
    ├── input1
    ├── output1
    ├── test_main.cpp
    └── test_mars_rover.cpp
    lib
    ├── CMakeLists.txt
    └── gtest-1.7.0

这是我的 CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

# Options. Turn on with 'cmake -Dtest=ON'.
option(test "Build all tests." ON)

set(PROJECT_NAME mars_rover CXX)
project(${PROJECT_NAME})

set(CMAKE_CXX_FLAGS "-g -Wall -Werror")

file(GLOB_RECURSE PROJECT_SOURCES ${CMAKE_SOURCE_DIR}/src/*.cpp)
add_executable(${PROJECT_NAME} ${PROJECT_SOURCES})
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/build/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/build/lib)

if (test)

  add_subdirectory(lib/gtest-1.7.0)
  enable_testing()
  include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})

  # finding test sources
  file(GLOB_RECURSE TEST_SOURCES ${CMAKE_SOURCE_DIR}/test/*.cpp ${CMAKE_SOURCE_DIR}/src/*.cpp)
  add_executable(${PROJECT_NAME}_TEST ${TEST_SOURCES})

  # link to gtest
  target_link_libraries(${PROJECT_NAME}_TEST gtest gtest_main)

  add_test(CardinalDirectionTests ${EXECUTABLE_OUTPUT_PATH}/${PROJECT_NAME}_TEST --gtest_filter=MarsRoverTest.CardinalDirectionTests)
  add_test(RelativeDirectionTests ${EXECUTABLE_OUTPUT_PATH}/${PROJECT_NAME}_TEST --gtest_filter=MarsRoverTest.RelativeDirectionTests)

endif()

最佳答案

您的测试可执行文件找不到“src/directions.h”,因为其父级 (${CMAKE_SOURCE_DIR}) 尚未添加到 include_directories 调用中。只需添加它就可以了。

但是,我可以在您的设置中看到其他一些小点。运行您的 CMakeLists.txt,以下是我要做的更改:

cmake_minimum_required(VERSION 2.8.12)

如果您可以指定 2.8.12 作为最小值,您就可以访问更有用的 target_include_directories命令。 include_directories 是一种有点错误的方法,而 target_include_directories 允许您仅为该特定目标指定搜索路径。如果您将这些指定为 PUBLICINTERFACE,则链接到该目标的后续目标也将自动继承这些搜索路径。

以类似的方式,您可以考虑使用 target_compile_definitionstarget_compile_options .


设置(PROJECT_NAME mars_rover CXX)
项目(${PROJECT_NAME})

项目(mars_rover)

project 命令设置变量PROJECT_NAME,因此您的set 命令在这里几乎没有用处。 CMake 会根据源文件后缀检测到这是一个 C++ 项目。


通过将所有源代码包含在两个单独的目标(主 exe 和测试 exe)中,这些都将被编译两次。为了避免这种低效率,我会在“/src”中创建一个包含除“main.cpp”之外的所有源代码的库,然后创建一个具有 main.cpp 并链接到该库的 exe。

此外,不鼓励使用 file(GLOB ...)file(GLOB_RECURSE ...) 作为收集源列表的方法。

set(CMAKE_CXX_FLAGS "-g -Wall -Werror")
文件(GLOB_RECURSE PROJECT_SOURCES ${CMAKE_SOURCE_DIR}/src/*.cpp) add_executable(${PROJECT_NAME} ${PROJECT_SOURCES})

# No need to include .h files, but they show up in IDEs like Xcode if you do.
set(libSources
    src/directions.cpp src/directions.h
    src/plateau.cpp src/plateau.h
    src/point.h
    src/rover.cpp src/rover.h
    )
add_library(${PROJECT_NAME}_LIB ${libSources})

# Anything linking to this will automatically have ${PROJECT_SOURCE_DIR}
# added to the compiler's search paths since it is PUBLIC.  Prefer
# ${PROJECT_SOURCE_DIR} to ${CMAKE_SOURCE_DIR} in case this project is not
# the top-level one.
target_include_directories(${PROJECT_NAME}_LIB PUBLIC ${PROJECT_SOURCE_DIR})

# Use generator expressions to conditionally apply the flags to Unix and Debug
# builds.  Anything linking to this will automatically have these flags also
# applied since they are PUBLIC.
target_compile_options(${PROJECT_NAME}_LIB PUBLIC
                       $<$<BOOL:${UNIX}>:-Werror -Wall $<$<CONFIG:Debug>:-g>>)

add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_LIB)

对于测试,看起来您有 2 个或 3 个 main 函数 - 这将是一个问题:-) gtest_main 是一个小助手,它提供了main 函数调用所需的 gtest 函数来调用测试。我猜您在“test/test_main.cpp”中也有 main ,并且由于您当前包含所有“src/”文件,我想您也有一个 main 在“src/main.cpp”中。

通过将 mars_rover 目标拆分为 lib 和 exe,您可以仅链接到该 lib,并避免从测试中显式排除“src/main.cpp”。我无法判断您是否想使用自己的“test_main.cpp”或使用 gtest 的助手 - 我假设是后者:

include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
文件(GLOB_RECURSE TEST_SOURCES ...)
add_executable(${PROJECT_NAME}_TEST ${TEST_SOURCES})
target_link_libraries(${PROJECT_NAME}_TEST gtest gtest_main)

add_executable(${PROJECT_NAME}_TEST test/test_mars_rover.cpp)

# Only bring gtest's include path into scope - its src dir is not designed to
# be public 
target_include_directories(${PROJECT_NAME}_TEST PRIVATE
                           ${gtest_SOURCE_DIR}/include)

target_link_libraries(${PROJECT_NAME}_TEST ${PROJECT_NAME}_LIB gtest gtest_main)

最后,如果使用以下语法,则无需指定测试 exe 的完整路径:

add_test(NAME CardinalDirectionTests
         COMMAND ${PROJECT_NAME}_TEST
             --gtest_filter=MarsRoverTest.CardinalDirectionTests)
add_test(NAME RelativeDirectionTests
         COMMAND ${PROJECT_NAME}_TEST
             --gtest_filter=MarsRoverTest.RelativeDirectionTests)

关于c++ - 为什么谷歌测试可以编译但看不到我的项目源代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25252723/

相关文章:

c++ - 如何通过依赖注入(inject)使用 GMock?

c++ - 抑制谷歌测试断言的输出

c++ - 如何检测捕获设备的设备名称?

c++ - 到底是什么问题。 else if 逻辑错误?在 else 之前预期的主要表达式

c++ - cmake、conan 和 qt hello world 项目构建错误

visual-studio-2010 - Cmake 生成不正确的配置

c++ - 没有虚拟方法的模拟类

c++ - 是否实现定义了哪些算法可以接受可变的 lambda?

c++ - 找到一些宏被#define-ed的地方

cmake - 如何防止 Cmake 在 EXECUTABLE_OUTPUT_PATH 下创建 Debug/Release 文件夹?