CMake:如何使用相对目录添加Boost.Test案例?

Tem*_*Rex 6 c++ boost cmake ctest boost-test

我有一个使用CMake和Boost.Test的工作项目,其目录结构如下(请原谅ASCII艺术):

+-proj
|---CMakeLists.txt
|---build
|---test
|\----dir1
|   \----foo.cpp // contains one BOOST_AUTO_TEST_SUITE and several BOOST_AUTO_TEST_CASE
|    |---bar.cpp // contains one BOOST_AUTO_TEST_SUITE and several BOOST_AUTO_TEST_CASE
 \----dir2
    \----foo.cpp // contains one BOOST_AUTO_TEST_SUITE and several BOOST_AUTO_TEST_CASE
     |---bar.cpp // contains one BOOST_AUTO_TEST_SUITE and several BOOST_AUTO_TEST_CASE
Run Code Online (Sandbox Code Playgroud)

我目前将所有源文件编译成一个可以与CTest一起运行的大型可执行文件.我的CMakeLists.txt看起来像这样:

file(GLOB_RECURSE test_cases FOLLOW_SYMLINKS "test/*.[h,c]pp")
add_executable(test_suite ${test_cases})
include_directories(${PROJECT_SOURCE_DIR} ${Boost_INCLUDE_DIRS})
target_link_libraries(test_suite ${Boost_LIBRARIES})
include(CTest)
add_test(test_runner test_suite)
Run Code Online (Sandbox Code Playgroud)

我想将每个.cpp文件编译成一个单独的可执行文件,并将其作为测试单独添加,以便我可以使用CTest正则表达式机制(特别是Boost.Test似乎没有的测试排除)来选择性地运行某些测试.但是,当CMake从dir1/dir2生成foo/bar的构建目标时,我得到名称冲突.

我的问题是:如何将整个目录树镜像test到一个类似的树下,build以便各种可执行文件之间不再存在名称冲突,以便CTest可以全部运行它们?

注意:不能在源树中重命名它们.我想foreach()对变量做一个${test_cases}(如本答案中所解释的),但我无法提取相关目录和文件名,并build/逐个文件地将它们移植到目录中.

更新:最后,我拼凑了这个脚本:

# get the test sources
file(GLOB_RECURSE test_sources RELATIVE ${PROJECT_SOURCE_DIR} *.cpp)

# except any CMake generated sources under build/
string(REGEX REPLACE "build/[^;]+;?" "" test_sources "${test_sources}")

# get the test headers
file(GLOB_RECURSE test_headers RELATIVE ${PROJECT_SOURCE_DIR} *.hpp)

# except any CMake generated headers under build/
string(REGEX REPLACE "build/[^;]+;?" "" test_headers "${test_headers}")

# compile against the test headers, the parent project, and the Boost libraries
include_directories(${PROJECT_SOURCE_DIR} ${ParentProject_include_dirs} ${Boost_INCLUDE_DIRS})

# calls enable_testing()
include(CTest)

foreach(t ${test_sources} )
  # get the relative path in the source tree
  get_filename_component(test_path ${t} PATH)

  # get the source name without extension
  get_filename_component(test_name ${t} NAME_WE)

  # concatenate the relative path and name in an underscore separated identifier
  string(REPLACE "/" "_" test_concat "${test_path}/${test_name}")

  # strip the leading "test_" part from the test ID
  string(REGEX REPLACE "^test_" "" test_id ${test_concat})

  # depend on the current source file, all the test headers, and the parent project headers
  add_executable(${test_id} ${t} ${test_headers} ${ParentProject_headers})

  # link against the Boost libraries
  target_link_libraries(${test_id} ${Boost_LIBRARIES})

  # match the relative path in the build tree with the corresponding one in the source tree 
  set_target_properties(${test_id} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${test_path})

  # add a test with executable in the relative path of the build tree
  add_test(${test_id} ${test_path}/${test_id})
endforeach()
Run Code Online (Sandbox Code Playgroud)

Mas*_*ano 5

一个可能的解决方案来消除歧义的名字像你已经使用了一个目录结构FOREACH()${test_cases}可能是:

# Set Cmake version and policy
CMAKE_MINIMUM_REQUIRED( VERSION 2.8.7 )
CMAKE_POLICY( VERSION 2.8.7 )

PROJECT( DUMMY CXX )

FILE( GLOB_RECURSE test_cases FOLLOW_SYMLINKS "test/*.[h,c]pp" )

FOREACH( case ${test_cases} )
  ## Get filename without extension
  GET_FILENAME_COMPONENT(case_name_we ${case} NAME_WE)
  ## Get innermost directory name
  GET_FILENAME_COMPONENT(case_directory ${case} PATH)
  GET_FILENAME_COMPONENT(case_innermost ${case_directory} NAME_WE)
  ## Construct executable name
  SET( exe_name "${case_innermost}_${case_name_we}")
  ## Construct test name
  SET( test_name "${exe_name}_test")
  ## Add executable and test
  ADD_EXECUTABLE( ${exe_name} ${case} )
  ADD_TEST( ${test_name} ${exe_name} )
ENDFOREACH()
Run Code Online (Sandbox Code Playgroud)

如您所见,这将CMakeLists.txt创建4个不同的测试/可执行对。


And*_*dré 4

可以RELATIVE为命令指定标志和目录file( GLOB ... )尽管在file( GLOB ) 的文档中没有直接提及,但这也适用file( GLOB_RECURSE ... )。请注意,我在 Windows 设置上对此进行了测试。我不知道*nix。

  1. 与一些带有 和/或标志的get_filename_component调用一起,现在可以重建 cpp 文件相对于通配目录的名称和相对路径。NAME_WEPATH
  2. 提取路径和名称(不带扩展名)与Massimiliano 的答案非常相似。此外,我还使用了他的建议来生成一个唯一的测试名称string( REGEX REPLACE ... );用下划线替换正斜杠。
  3. 使用唯一的测试名称,可以生成可执行文件,然后可以使用set_target_properties修改其输出目录。

检查这个这个问题以获取有关修改输出目录的更多信息。

file( GLOB_RECURSE TEST_CPP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp )

foreach( test_case ${TEST_CPP_SOURCES} )
    # Get the name without extension
    get_filename_component( test_name ${test_case} NAME_WE )
    # Get the path to the test-case, relative to the ${CMAKE_CURRENT_SOURCE_DIR} 
    # thanks to the RELATIVE flag in file( GLOB_RECURSE ... )
    get_filename_component( test_path ${test_case} PATH )

    message( STATUS "  name = " ${test_name} )
    message( STATUS "  path = " ${test_path} )
    # I would suggests constructing a 'unique' test-name
    string( REPLACE "/" "_" full_testcase "${test_name}/${test_path}" )

    # Add an executable using the 'unique' test-name
    message( STATUS "  added " ${full_testcase} " in " ${test_path} )
    add_executable( ${full_testcase} ${test_case} )
    # and modify its output paths. 
    set_target_properties( ${full_testcase} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${test_path} )
endforeach( test_case ${TEST_CPP_SOURCES} )
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

2243 次

最近记录:

12 年,8 月 前