CMake Компиляция сгенерированных файлов - PullRequest
20 голосов
/ 19 ноября 2010

У меня есть список файлов, которые генерируются в процессе сборки CMake. Я хочу скомпилировать эти файлы, используя add_library впоследствии, но я не буду знать, какие файлы были сгенерированы, пока они не будут сгенерированы Есть ли способ встроить его в скрипт CMake?

Ответы [ 4 ]

12 голосов
/ 05 января 2012

Ну, я думаю, что это возможно, поэтому я поделюсь тем, что я сделал.Моя проблема заключалась в том, что мне пришлось скомпилировать несколько идентификаторов CORBA для использования в качестве части исходного кода проекта, и я не хотел вручную перечислять каждый файл.Я думал, что было бы лучше найти файлы.Поэтому я сделал это так:

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

Свойства GENERATED полезны в случае, если один из моих выходных данных компиляции idl (* C.cpp, * Ch, * S.cpp и * Sh) не созданчтобы команда build не жаловалась на то, что файл не существует.

10 голосов
/ 01 сентября 2016

Ну, это можно сделать с помощью двух сценариев 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), если они были изменены или были добавлены и построены оттуда.Этот подход приводит к созданию только измененных файлов (но требует очистки после удаления файлов).

2 голосов
/ 24 ноября 2010

Если вы не знаете названия файлов, которые будут сгенерированы, вы можете «перетащить» папки, в которых они находятся.

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

Теперь я не уверен, что вызывает генерацию этих файлов. «Глобализация» произойдет, только если вы вручную запустите cmake: он не сможет автоматически определить наличие новых файлов.

1 голос
/ 11 декабря 2010

Рассматривайте это как отсутствие ответа, просто больше информации:

Недавно мне пришлось что-то сделать для одного случая, когда у меня был автоматически сгенерированный файл .cpp, но я не мог понять, какзаставить CMake создать файл проекта Visual Studio, который затем скомпилирует его.Мне пришлось прибегнуть к чему-то довольно вонючему: мне пришлось #include <the_generated.cpp> файл из другого файла, который находился в каталоге ${CMAKE_CURRENT_SOURCE}.Это не очень поможет в вашем случае, потому что я подозреваю, что у вас есть несколько файлов .cpp, поэтому этот подход не масштабируется.

Кроме того, я обнаружил, что свойство исходного файла GENERATED при добавлении вфайл, не помогло совсем.

Я считаю это условие либо ошибкой в ​​Visual Studio (в моем случае это был VS2008 SP1), либо тем, как CMake генерирует файлы .vcproj, или обоими.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...