Ну, это можно сделать с помощью двух сценариев CMake, используя функцию CMake ExternalProject.
Простое решение
В основной сценарий CMake необходимо добавить настраиваемую цель, которая генерируетследующие исходные файлы и ссылка на 2-й (внешний) проект CMake:
# 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)
Теперь вы можете выполнить глобализацию файлов во 2-м (внешнем) сценарии CMake и связать все файлы, найденные в статической библиотеке:
# External project CMakeLists.txt
project(libgenerated)
file(GLOB_RECURSE SOURCES ${GENERATED_SOURCE_DIR}/*)
add_library(${PROJECT_NAME} ${SOURCES})
В этом простом решении ваши файлы генерируются и собираются каждый раз, когда вы запускаете этап сборки, даже если ничего не изменилось.Если вы хотите избежать этого, вы можете добавить файл штампа к вашей пользовательской цели, как показано в следующем улучшенном решении:
Решение файла штампа
# 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
)
...
Если изменение во входных файлах дляваш генератор кода не обязательно приводит к изменению всех сгенерированных файлов, вы можете улучшить решение, используя команду CMake copy_if_different
во внешнем проекте, как в следующем расширенном решении:
Расширенное решение
# 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)
В этом решении все сгенерированные файлы копируются в другое место (${CMAKE_CURRENT_BINARY_DIR}/generated
), если они были изменены или были добавлены и построены оттуда.Этот подход приводит к созданию только измененных файлов (но требует очистки после удаления файлов).