【问题标题】:Why would google tests compile but not be able to see my project sources?为什么 google 测试会编译但看不到我的项目源代码?
【发布时间】:2014-08-11 21:28:25
【问题描述】:

为什么 google 测试会编译但看不到我的项目源代码?

这是我得到的错误:

$ 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()

【问题讨论】:

    标签: c++ cmake googletest


    【解决方案1】:

    您的测试可执行文件找不到“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


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

    project(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")
    file(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 是一个小助手,它提供了一个调用所需 gtest 函数的 main 函数调用测试。我猜您在“test/test_main.cpp”中也有main,并且由于您当前包含所有“src/”文件,我想您在“src/”中也有main main.cpp”。

    通过将mars_rover 目标拆分为一个lib 和exe,您可以只链接到该lib 并避免从测试中明确排除“src/main.cpp”。我不知道你是想使用自己的“test_main.cpp”还是使用 gtest 的助手——我假设是后者:

    include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
    file(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)
    

    【讨论】:

    • 这是一个很棒的答案,它确实突出了我的问题。我今晚能够解决它们,现在效果很好。感谢您的回答!
    • 非常轻微的挑剔:您可能希望使用 PROJECT_SOURCE_DIR 而不是 CMAKE_SOURCE_DIR 来指定 inlcude 目录。即使您的 CMakeLists 被另一个项目通过add_subdirectory 拉入,前者仍将继续工作,而后者可能会在这种情况下中断。
    • 这应该是关于如何编写正确的CMake 文件的指南的一部分,这似乎是网络上缺乏的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多