TLDR:
Моя проблема в том, что CMake начинает выполнять эту функцию раньше
загрузка хранилища. Я хотел бы объявить зависимость для
эта функция на ExternalProject_Add, так что CMake понимает, что это
должен скачать, собрать и затем запустить функцию.
контекст:
У меня есть модуль cmake SomeModule.cmake
который должен добавить flatbuffers как внешний проект из своего репозитория и построить его. Сборка создаст исполняемый файл компилятора flatbuffers, который я собираюсь использовать в some/directory/CMakeLists.txt
файл для генерации заголовочных файлов c ++ из схемы flatbuffers. Так что в том же модуле CMake, который я использую ExternalProject_Add
Я объявил функцию CMake, которая генерирует заголовочные файлы из заданного набора файлов схемы и где-то в some/directory/CMakeLists.txt
Я называю эту функцию.
Моя проблема в том, что CMake начинает выполнять эту функцию перед загрузкой репозитория. Я хотел бы объявить зависимость для этой функции от ExternalProject_Add, чтобы CMake понимал, что он должен загрузить, построить и затем запустить функцию.
Хватит говорить. Вот соответствующие части кода:
SomeModule.cmake
:
include(ExternalProject)
set(flatbuffers_CMAKE_ARGS
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}""-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}""-DFLATBUFFERS_BUILD_TESTS=OFF""-DFLATBUFFERS_BUILD_FLATC=ON""-DFLATBUFFERS_BUILD_FLATHASH=OFF""-DCMAKE_INSTALL_PREFIX=${OTS_DEPENDENCIES}")
ExternalProject_Add(
flatbuffers
GIT_REPOSITORY "https://github.com/google/flatbuffers.git"GIT_TAG "v1.9.0"SOURCE_DIR "${OTS_DEPDENDENCIES_DIR}/flatbuffers"BINARY_DIR "${OTS_DEPDENDENCIES_DIR}/flatbuffers"CMAKE_ARGS "${flatbuffers_CMAKE_ARGS}"INSTALL_COMMAND "")
ExternalProject_Get_Property(flatbuffers SOURCE_DIR)
ExternalProject_Get_Property(flatbuffers BINARY_DIR)
set(flatbuffers_SOURCE_DIR ${SOURCE_DIR})
set(flatbuffers_BINARY_DIR ${BINARY_DIR})
set(flatbuffers_INCLUDE_DIR ${flatbuffers_SOURCE_DIR}/include)
set(flatbuffers_FLATC_EXECUTABLE ${flatbuffers_BINARY_DIR}/flatc)
# please assume that the variables above are all set to appropriate values
function(FlatbuffersGenerateCpp SCHEMA_FILES GENERATED_DIR GENERATED_CXX)
foreach(SCHEMA_FILE ${SCHEMA_FILES})
get_filename_component(NAME ${SCHEMA_FILE} NAME_WE)
set(GENERATED_HEADER_FILE_PATH ${GENERATED_DIR}/${NAME}_generated.h)
message(STATUS "attempting to generate: ${GENERATED_HEADER_FILE_PATH}")
add_custom_command(
DEPENDS ${flatbuffers_FLATC_EXECUTABLE}
OUTPUT ${GENERATED_HEADER_FILE_PATH}
COMMAND ${flatbuffers_FLATC_EXECUTABLE} -o ${GENERATED_DIR} -c ${SCHEMA_FILE}
COMMENT "generating flatbuffers c++ header file: ${GENERATED_HEADER_FILE_PATH}")
list(APPEND GENERATED_FILES ${GENERATED_HEADER_FILE_PATH})
endforeach()
message(STATUS "generated c++ header files: ${GENERATED_FILES}")
set(${GENERATED_CXX} ${GENERATED_FILES} PARENT_SCOPE)
endfunction()
А также some/directory/CMakeLists.txt
:
# cmake module path is properly set so the following works:
include(SomeModule)
set(flatbuffers_GENERATED_INCLUDES_DIR
${CMAKE_BINARY_DIR}/generated/config/flatbuffers
)
FlatbuffersGenerateCpp(
"${flatbuffers_SCHEMAS}""${flatbuffers_GENERATED_INCLUDES_DIR}"flatbuffers_GENERATED_CXX
)
add_library(
my_framework
SHARED
${THE_PUBLIC_HEADER_FILES}
${THE_IMPL_SOURCE_FILES}
${THE_IMPL_HEADER_FILES}
${flatbuffers_GENERATED_CXX}
)
add_dependencies(my_framework flatbuffers ${flatbuffers_GENERATED_CXX})
target_include_directories(my_framework PRIVATE ${flatbuffers_INCLUDE_DIR})
target_include_directories(my_framework PRIVATE ${CMAKE_SOURCE_DIR})
target_include_directories(my_framework PRIVATE ${CMAKE_BINARY_DIR}/generated)
set_source_files_properties(${flatbuffers_GENERATED_CXX} PROPERTIES GENERATED TRUE)
Я начал изменять свой код на основе комментариев, опубликованных Цыварев:
Функции CMake выполняются на этапе настройки, поэтому вам также необходимо собрать внешний проект на этапе настройки.
Хотя я верил, что предложенное им решение будет работать, мне было немного не по себе и я думал, что должно быть более элегантное решение. Я проконсультировался с коллегой и нашел лучшее решение, которое так же просто, как следующий diff (который удаляет ${flatbuffers_GENERATED_CXX}
).
- add_dependencies(my_framework flatbuffers ${flatbuffers_GENERATED_CXX})
+ add_dependencies(my_framework flatbuffers)
мы рассмотрели, что проблема с данным кодом заключается в том, что, как есть, CMake читает add_dependencies(my_framework flatbuffers ${flatbuffers_GENERATED_CXX})
и понимает, что ему нужно ${flatbuffers_GENERATED_CXX}
как цель для строительства my_framework
так что продолжается с запуском функции. Но у него нет возможности понять, что функция зависит от внешнего проекта. Теперь, если мы удалим явное объявление зависимости ${flatbuffers_GENERATED_CXX}
CMake откладывает запуск функции после разрешения других зависимостей (целевой объект flatbuffers), которые эффективно загрузят и соберут внешний проект до запуска проекта.
Других решений пока нет …