我有一个在CMake构建过程中生成的文件列表。我想使用 "add_library" 编译这些文件,但在它们生成之前我不知道哪些文件会被生成。有没有办法将此集成到CMake脚本中?
我有一个在CMake构建过程中生成的文件列表。我想使用 "add_library" 编译这些文件,但在它们生成之前我不知道哪些文件会被生成。有没有办法将此集成到CMake脚本中?
我认为这是可能的,所以我会分享一下我所做的。我的问题是,我必须编译几个CORBA idl文件以用作项目源代码的一部分,而我不想手动列出每个文件。我觉得找到这些文件会更好。因此,我是这样做的:
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}
)
在我的idl编译输出(*C.cpp,*C.h,*S.cpp和*S.h)中,如果某个文件未被创建,那么生成的属性很有用,这样构建命令就不会抱怨文件不存在。
使用CMake的 CMAKE_CONFIGURE_DEPENDS
目录属性可以实现这一点。如果任何指定的文件发生更改,这将强制CMake重新配置。
以下代码展示了用于单个模型文件的方法,该文件用作代码生成的输入:
set(MODEL_FILE your_model_file)
set_directory_properties(PROPERTIES CMAKE_CONFIGURE_DEPENDS ${MODEL_FILE})
set(GENERATED_SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/${MODEL_FILE})
file(REMOVE_RECURSE ${GENERATED_SOURCE_DIR})
file(MAKE_DIRECTORY ${GENERATED_SOURCE_DIR})
execute_process(COMMAND your_code_generation_tool -o ${GENERATED_SOURCE_DIR} ${MODEL_FILE})
file(GLOB LIBGENERATED_FILES ${GENERATED_SOURCE_DIR}/*)
add_library(libgenerated ${LIBGENERATED_FILES})
target_include_directories(libgenerated ${GENERATED_SOURCE_DIR})
使用以上方法,每当模型文件发生变化时,CMake将重新配置,导致模型重新生成。set(MODEL_FILE your_model_file)
set(GENERATOR_STAGING_DIR ${CMAKE_CURRENT_BINARY_DIR}/${MODEL_FILE}.staging)
set(GENERATOR_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${MODEL_FILE})
set_directory_properties(PROPERTIES CMAKE_CONFIGURE_DEPENDS ${MODEL_FILE})
# Create fresh staging/final output directory
file(REMOVE_RECURSE ${GENERATOR_STAGING_DIR})
file(MAKE_DIRECTORY ${GENERATOR_STAGING_DIR})
file(MAKE_DIRECTORY ${GENERATOR_OUTPUT_DIR})
# Run code generation
execute_process(COMMAND your_code_generation_tool -o ${GENERATOR_STAGING_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_FILE}")
# Remove stale files from final generator output directory
file(GLOB GENERATED_FILES RELATIVE "${GENERATOR_OUTPUT_DIR}/" "${GENERATOR_OUTPUT_DIR}/*")
foreach(FILE ${GENERATED_FILES})
if(NOT EXISTS "${GENERATOR_STAGING_DIR}/${FILE}")
file(REMOVE "${GENERATOR_OUTPUT_DIR}/${FILE}")
endif()
endforeach()
# Copy modified files from staging to final generator output directory
file(GLOB GENERATED_FILES RELATIVE "${GENERATOR_STAGING_DIR}/" "${GENERATOR_STAGING_DIR}/*")
foreach(FILE ${GENERATED_FILES})
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${GENERATOR_STAGING_DIR}/${FILE}" "${GENERATOR_OUTPUT_DIR}")
endforeach()
file(GLOB LIBGENERATED_FILES "${GENERATOR_OUTPUT_DIR}/*")
add_library(libgenerated ${LIBGENERATED_FILES})
target_include_directories(libgenerated PUBLIC ${GENERATOR_OUTPUT_DIR})
file(GLOB_RECURSE MY_SRC dest_folder/*.cpp)
add_library(libname SHARED ${MY_SRC})
现在我不确定什么会触发这些文件的生成。当您手动运行 CMake 时,“globbing” 将会发生:它无法自动检测到新文件的存在。把这个当作一个非答案的信息:
最近我需要处理一个问题,其中我有一个自动生成的 .cpp 文件,但我无法弄清楚如何让 CMake 构建 Visual Studio 项目文件,然后编译它。我不得不使用一些相当糟糕的方法:我必须从另一个位于 ${CMAKE_CURRENT_SOURCE}
目录下的文件中 #include <the_generated.cpp>
文件。在你的情况下,这并不能帮助你太多,因为我怀疑你有几个 .cpp 文件,所以这种方法并不可扩展。
此外,我发现添加到文件中的 GENERATED
源文件属性根本没有起到任何帮助。
我认为这种情况可能是 Visual Studio(在我的情况下是 VS2008 SP1)的一个 bug,或者是 CMake 生成 .vcproj 文件的方式的问题,或者两者都有。