[英]CMake: how to add Boost.Test cases with relative directories?
I have a working project with CMake and Boost.Test with a directory structure like this (pardon the ASCII art): 我有一个使用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
I currently compile all source files into one big executable that I can run with CTest. 我目前将所有源文件编译成一个可以与CTest一起运行的大型可执行文件。 My CMakeLists.txt looks like this:
我的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)
I would like to compile each .cpp file into a separate executable, and add it separately as a test so that I can use the CTest regular expression machinery (especially the test exclusion which Boost.Test doesn't seem to have) to selectively run certain tests. 我想将每个.cpp文件编译成一个单独的可执行文件,并将其作为测试单独添加,以便我可以使用CTest正则表达式机制(特别是Boost.Test似乎没有的测试排除)来选择性地运行某些测试。 However, I get a name conflict when CMake is generating build targets for foo/bar from dir1/dir2.
但是,当CMake从dir1 / dir2生成foo / bar的构建目标时,我得到名称冲突。
My question is : how can I mirror the entire directory tree under test
to a similar tree under build
so that there are no more name conflicts between the various executables and so that CTest can run them all? 我的问题是 :如何将
test
的整个目录树镜像到build
下的类似树,以便各种可执行文件之间不再存在名称冲突,以便CTest可以全部运行它们?
Note : Renaming them in the source tree is not an option. 注意 :不能在源树中重命名它们。 I'd like to do a
foreach()
over the variable ${test_cases}
(as explained in this answer ), but I am having trouble to extract the relative directory and the file name, and port those to the build/
directory on a file-by-file basis. 我想对变量
${test_cases}
做一个foreach()
(如本回答所述 ),但是我无法提取相关目录和文件名,并将它们移植到build/
目录上逐个文件。
UPDATE : In the end, I pieced together this script: 更新 :最后,我拼凑了这个脚本:
# 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()
A possible solution to disambiguate names in a directory structure like the one you have using a FOREACH()
over ${test_cases}
may be: 消除目录结构中名称的可能解决方案,例如使用
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()
As you can see this CMakeLists.txt
creates 4 distinct test/executable couples. 正如您所看到的,此
CMakeLists.txt
创建了4个不同的测试/可执行对。
It is possible to specify a RELATIVE
flag and a directory to a file( GLOB ... )
command. 可以指定
RELATIVE
标志和file( GLOB ... )
目录file( GLOB ... )
命令。 Although not mentioned directly in the documentation of file( GLOB ) , this works for file( GLOB_RECURSE ... )
too. 虽然文档(GLOB)文档中没有直接提及,但这也适用于
file( GLOB_RECURSE ... )
。 Note, I tested this on my windows setup. 注意,我在Windows设置上测试了这个。 I don't known about *nix.
我不知道* nix。
NAME_WE
and/or PATH
flags, it is now possible to reconstruct the name and the relative path of the cpp-file with respect to the globbing dir. NAME_WE
和/或PATH
标志的get_filename_component调用一起,现在可以重建cpp文件的名称和相对于globbing dir的相对路径。 string( REGEX REPLACE ... )
; string( REGEX REPLACE ... )
的唯一testname string( REGEX REPLACE ... )
; replacing forward slashes by underscores. Check this and this question for more info on modifying the output directory. 有关修改输出目录的更多信息,请查看此 问题和此问题 。
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} )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.