girona español descargar bonn cmake

cmake - español - qgis girona



CMake compilando archivos generados (4)

Bueno, creo que es posible, así que compartiré lo que he hecho. Mi problema fue que tuve que compilar varios identificadores de CORBA para usar como parte de la fuente de un proyecto y no quería enumerar manualmente cada archivo. Pensé que sería mejor encontrar los archivos. Así lo hice así:

file(GLOB IDLS "idls/*.idl") set(ACE_ROOT ${CMAKE_FIND_ROOT_PATH}/ace/ACE-${ACE_VERSION}) foreach(GENERATE_IDL ${IDLS}) get_filename_component(IDLNAME ${GENERATE_IDL} NAME_WE) set(OUT_NAME ${CMAKE_CURRENT_SOURCE_DIR}/idls_out/${IDLNAME}) list(APPEND IDL_COMPILED_FILES ${OUT_NAME}C.h ${OUT_NAME}C.cpp ${OUT_NAME}S.h ${OUT_NAME}S.cpp) add_custom_command(OUTPUT ${OUT_NAME}C.h ${OUT_NAME}C.cpp ${OUT_NAME}S.h ${OUT_NAME}S.cpp COMMAND ${ACE_ROOT}/bin/tao_idl -g ${ACE_ROOT}/bin/ace_gperf -Sci -Ssi -Wb,export_macro=TAO_Export -Wb,export_include=${ACE_ROOT}/include/tao/TAO_Export.h -Wb,pre_include=${ACE_ROOT}/include/ace/pre.h -Wb,post_include=${ACE_ROOT}/include/ace/post.h -I${ACE_ROOT}/include/tao -I${CMAKE_CURRENT_SOURCE_DIR} ${GENERATE_IDL} -o ${CMAKE_CURRENT_SOURCE_DIR}/idls_out/ COMMENT "Compiling ${GENERATE_IDL}") endforeach(GENERATE_IDL) set_source_files_properties(${IDL_COMPILED_FILES} PROPERTIES GENERATED TRUE) set(TARGET_NAME ${PROJECT_NAME}${DEBUG_SUFFIX}) add_executable( ${TARGET_NAME} ${SOURCE} ${IDL_COMPILED_FILES} )

Las propiedades GENERADAS son útiles en caso de que no se cree una de mis salidas de compilación idl (* C.cpp, * Ch, * S.cpp y * Sh), por lo que el comando de compilación no se queja de que el archivo no existe .

Tengo una lista de archivos que se generan durante el proceso de construcción de CMake. Quiero compilar estos archivos usando "add_library" después, pero no sabré qué archivos se generan hasta después de que se generen. ¿Hay alguna forma de construir esto en un script CMake?


Bueno, es posible hacerlo con dos scripts CMake usando la función ExternalProject de CMake.

La solucion simple

En la secuencia de comandos principal de CMake, debe agregar un objetivo personalizado que genere los archivos de origen de la siguiente manera y una referencia al segundo proyecto CMake (externo):

# Main CMakeLists.txt add_custom_target( code_generation COMMAND your_code_generation_tool -o ${CMAKE_CURRENT_BINARY_DIR}/libgenerated/ ) include(ExternalProject) ExternalProject_Add( libgenerated DEPENDS code_generation SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/path/to/external/project/ BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/libgenerated-build CMAKE_ARGS -DGENERATED_SOURCE_DIR=${CMAKE_CURRENT_BINARY_DIR}/libgenerated BUILD_ALWAYS 1 INSTALL_CMD "" ) add_executable( ${PROJECT_NAME} ... ) target_link_libraries( ${PROJECT_NAME} ${CMAKE_CURRENT_BINARY_DIR}/libgenerated-build/libgenerated.a ) add_dependencies(${PROJECT_NAME} libgenerated)

Ahora puede realizar el agrupamiento de archivos en el segundo script CMake (externo) y vincular todos los archivos encontrados en una biblioteca estática:

# External project CMakeLists.txt project(libgenerated) file(GLOB_RECURSE SOURCES ${GENERATED_SOURCE_DIR}/*) add_library(${PROJECT_NAME} ${SOURCES})

En esta solución simple, sus archivos se generan y construyen cada vez que ejecuta el paso de compilación, incluso si nada cambia. Si desea evitar esto, puede agregar un archivo de sello a su destino personalizado como en la siguiente solución mejorada:

La solución de archivo de sello

# Main CMakeLists.txt add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libgenerated-stamp COMMAND your_code_generation_tool -o ${CMAKE_CURRENT_BINARY_DIR}/libgenerated/ COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/libgenerated-stamp DEPENDS the_input_file(s)_you_generate_your_code_from ) add_custom_target( code_generation DEPENDS ${CMAKE_CURRENT_BUILD_DIR}/libgenerated-stamp ) ...

Si un cambio en los archivos de entrada para su generador de código no resulta necesariamente en un cambio de todos los archivos generados, puede mejorar aún más la solución utilizando el comando copy_if_different de CMake en el proyecto externo, como en la siguiente solución avanzada:

La solucion avanzada

# External project CMakeLists.txt project(libgenerated) file(GLOB_RECURSE SOURCES ${GENERATED_SOURCE_DIR}/*) add_custom_target( make_directory COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/generated ) foreach(FILE ${SOURCES}) get_filename_component(BASENAME ${FILE} NAME) list(APPEND ACTUAL_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/generated/${BASENAME}") add_custom_target( copy_${BASENAME}_if_different COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FILE} ${CMAKE_CURRENT_BINARY_DIR}/generated ) add_dependencies(make_directory copy_${BASENAME}_if_different) endforeach() add_library(${PROJECT_NAME} ${ACTUAL_SOURCES}) add_dependencies(${PROJECT_NAME} make_directory)

En esta solución, todos los archivos generados se copian en otra ubicación ( ${CMAKE_CURRENT_BINARY_DIR}/generated ) si se han cambiado o se han agregado y se han creado desde allí. Este enfoque da como resultado una compilación de archivos modificados solamente (pero requiere una limpieza cuando se eliminan los archivos).


Si no sabe el nombre de los archivos que se generarán, puede "agrupar" las carpetas donde se encuentran.

file( GLOB_RECURSE MY_SRC dest_folder/*.cpp )
add_library( libname SHARED ${MY_SRC} )

Ahora no estoy seguro de lo que desencadena la generación de estos archivos. El "globbing" ocurrirá solo cuando ejecute manualmente cmake: no podrá detectar automáticamente que hay nuevos archivos presentes.


Trate esto como una no-respuesta, solo más información:

Hace poco tuve que hacer algo en un caso en el que tenía un archivo .cpp que se generó automáticamente, pero no pude averiguar cómo hacer que CMake construya el archivo de proyecto de Visual Studio que luego lo compilaría. Tuve que recurrir a algo bastante apestoso: tuve que #include <the_generated.cpp> de otro archivo que se encontraba en el directorio ${CMAKE_CURRENT_SOURCE} . Eso no te ayudará mucho en tu caso porque sospecho que tienes varios archivos .cpp, por lo que este enfoque no es escalable.

Además, encontré que la propiedad del archivo de origen GENERATED , cuando se agrega al archivo, no ayuda en absoluto.

Considero que esta condición es un error en Visual Studio (en mi caso fue VS2008 SP1), o en cómo CMake genera los archivos .vcproj, o ambos.