una rutas ruta relativos relativas relativa qué ejemplos absolutos absolutas absoluta c++ boost cmake boost-test ctest

c++ - rutas - CMake: ¿cómo agregar casos de Boost.Test con directorios relativos?



rutas relativas php (2)

Tengo un proyecto en funcionamiento con CMake y Boost.Test con una estructura de directorios como esta (perdón por el 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

Actualmente compilo todos los archivos fuente en un gran ejecutable que puedo ejecutar con CTest. Mi CMakeLists.txt se ve así:

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)

Me gustaría compilar cada archivo .cpp en un archivo ejecutable independiente, y agregarlo por separado como una prueba para que pueda usar la maquinaria de expresión regular CTest (especialmente la exclusión de prueba que Boost.Test no parece tener) para ejecutar selectivamente ciertas pruebas Sin embargo, aparece un conflicto de nombre cuando CMake genera objetivos de compilación para foo / bar desde dir1 / dir2.

Mi pregunta es : ¿cómo puedo reflejar todo el árbol de directorios bajo test en un árbol similar bajo build para que no haya más conflictos de nombres entre los diversos ejecutables y para que CTest pueda ejecutarlos todos?

Nota : Renombrarlos en el árbol fuente no es una opción. Me gustaría hacer un foreach() sobre la variable ${test_cases} (como se explica en esta respuesta ), pero estoy teniendo problemas para extraer el directorio relativo y el nombre del archivo, y llevarlos a la build/ directorio en un archivo por archivo.

ACTUALIZACIÓN : al final, reconstruí este guión:

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


Una posible solución para FOREACH() nombres en una estructura de directorios como la que tiene utilizando un FOREACH() sobre ${test_cases} puede ser:

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

Como puede ver, este CMakeLists.txt crea 4 parejas distintas de prueba / ejecutable.


Es posible especificar un indicador RELATIVE y un directorio para un comando de file( GLOB ... ) . Aunque no se menciona directamente en la documentación del archivo (GLOB) , esto también funciona para el file( GLOB_RECURSE ... ) . Tenga en cuenta que probé esto en mi configuración de Windows. No sé sobre * nix.

  1. Junto con algunas llamadas get_filename_component con NAME_WE y / o banderas PATH , ahora es posible reconstruir el nombre y la ruta relativa del archivo cpp con respecto al directorio globbing.
  2. La extracción de un camino y un nombre (sin extensión) es en su mayoría similar a la respuesta de Massimiliano . Además, he usado su sugerencia para generar un nombre de prueba único con una string( REGEX REPLACE ... ) ; reemplazando barras diagonales por guiones bajos.
  3. Con un nombre de prueba único, el ejecutable se puede generar y luego su directorio de salida se puede modificar con set_target_properties .

Verifique esto y esta pregunta para obtener más información sobre cómo modificar el directorio de salida.

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} )