CMake 声明函数对 ExternalProject_Add 的依赖
CMake declare dependency of function on ExternalProject_Add
TLDR:
My problem is that CMake starts executing this function before
downloading the repository. I would like to declare a dependency for
that function on ExternalProject_Add so that CMake understands that it
should download, build and then run the function.
上下文:
我有一个 cmake 模块 SomeModule.cmake
,它应该从其存储库中添加 flatbuffers 作为外部项目并构建它。该构建将生成 flatbuffers 编译器可执行文件,我打算在 some/directory/CMakeLists.txt
文件中使用它从 flatbuffers 模式生成 c++ 头文件。因此,在我使用 ExternalProject_Add
的同一个 CMake 模块中,我声明了一个 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 functions are executed at configure stage, so you need to build the external project at configure stage too.
虽然我相信他提出的解决方案会奏效,但我还是有点不自在,一直认为必须有一个更优雅的解决方案。我咨询了一位同事并提出了一个更好的解决方案,它就像以下差异一样简单(删除 ${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 目标)之后,这将在 运行 之前有效地下载和构建外部项目项目。
TLDR:
My problem is that CMake starts executing this function before downloading the repository. I would like to declare a dependency for that function on ExternalProject_Add so that CMake understands that it should download, build and then run the function.
上下文:
我有一个 cmake 模块 SomeModule.cmake
,它应该从其存储库中添加 flatbuffers 作为外部项目并构建它。该构建将生成 flatbuffers 编译器可执行文件,我打算在 some/directory/CMakeLists.txt
文件中使用它从 flatbuffers 模式生成 c++ 头文件。因此,在我使用 ExternalProject_Add
的同一个 CMake 模块中,我声明了一个 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 functions are executed at configure stage, so you need to build the external project at configure stage too.
虽然我相信他提出的解决方案会奏效,但我还是有点不自在,一直认为必须有一个更优雅的解决方案。我咨询了一位同事并提出了一个更好的解决方案,它就像以下差异一样简单(删除 ${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 目标)之后,这将在 运行 之前有效地下载和构建外部项目项目。