CMake: como adicionar casos Boost.Test com diretórios relativos?

Eu tenho um projeto de trabalho com CMake e Boost.Test com uma estrutura de diretórios como esta (com o perdão da arte 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

No momento, compilo todos os arquivos de origem em um grande executável que posso executar com o CTest. Meu CMakeLists.txt é assim:

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)

Eu gostaria de compilar cada arquivo .cpp em um executável separado e adicioná-lo separadamente como um teste para que eu possa usar o mecanismo de expressão regular CTest (especialmente a exclusão de teste que Boost.Test não parece ter) para executar seletivamente certos testes. No entanto, recebo um conflito de nome quando o CMake está gerando alvos de compilação para foo / bar a partir de dir1 / dir2.

Minha pergunta é: como posso espelhar a árvore de diretórios inteira emtest para uma árvore semelhante sobbuild para que não haja mais conflitos de nome entre os vários executáveis ​​e para que o CTest possa executá-los todos?

Nota: Renomeá-los na árvore de origem não é uma opção. Eu gostaria de fazer umforeach() sobre a variável${test_cases} (como explicado emesta resposta), mas estou tendo problemas para extrair o diretório relativo eo nome do arquivo e portá-los para obuild/ diretório em uma base arquivo-a-arquivo.

ATUALIZAR: No final, eu juntei este 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()

questionAnswers(2)

yourAnswerToTheQuestion