C++ 将cmake代码段转换为函数-不工作
我有一个带有可执行文件和几个插件的项目,每个插件都有QML和其他文件(例如图像、svg)。为此创建CMake构建需要在适当的位置安装运行时所需的插件及其相关文件。文件的类型和相对位置使得每个模块都需要重复,因此我将重复的CMake代码移动到一个.CMake文件中,该文件包含在每个插件的CMakeLists.txt中。当它只是.cmake文件中的基本代码时,它工作得非常好。我最近想把它转换成一个函数,但一直没能让它工作。我想我遗漏了一些关于在生成过程中调用函数的基本信息。转换为函数后,文件的复制不起作用,从函数调用返回后${copiedFiles}为空C++ 将cmake代码段转换为函数-不工作,c++,cmake,C++,Cmake,我有一个带有可执行文件和几个插件的项目,每个插件都有QML和其他文件(例如图像、svg)。为此创建CMake构建需要在适当的位置安装运行时所需的插件及其相关文件。文件的类型和相对位置使得每个模块都需要重复,因此我将重复的CMake代码移动到一个.CMake文件中,该文件包含在每个插件的CMakeLists.txt中。当它只是.cmake文件中的基本代码时,它工作得非常好。我最近想把它转换成一个函数,但一直没能让它工作。我想我遗漏了一些关于在生成过程中调用函数的基本信息。转换为函数后,文件的复制不
find_package(Qt5 COMPONENTS Core REQUIRED)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC OFF) # Set this to ON if you want resources compiled in
set(OUTPUT_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AEPPApps/ImportFiles)
set(RESOURCE_FOLDERS
.
images
)
include(copy_common_files) # only this when not using 'function'
copy_common_files(${RESOURCE_FOLDERS} ${OUTPUT_DIR} copiedFiles)
# Adding ${copiedFiles} as a dependency below forces the conditional copy
# to get considered:
# https://stackoverflow.com/questions/33938239/cmake-does-not-copy-file-in-custom-command
add_library(ImportFiles SHARED ${copiedFiles})
target_compile_definitions(ImportFiles
PRIVATE
IMPORTFILESPLUGIN_LIBRARY
NOMINMAX
)
target_include_directories(ImportFiles
PRIVATE
.
)
# Enable below when you want to compile resources for apps, then remove the copying above
#
#qt5_add_resources(ImportFiles_RESOURCES
# ImportFiles.qrc
# )
target_sources(ImportFiles
PRIVATE
Redacted.cpp
)
target_link_libraries(ImportFiles
PUBLIC
REDACTED-lib
PRIVATE
Qt5::Core
)
set_target_properties(ImportFiles PROPERTIES RUNTIME_OUTPUT_DIRECTORY
${OUTPUT_DIR}
)
下面是.cmake文件,在底部注释了代码。该代码的函数实现位于顶部
# This convenience snippet expects ${RESOURCE_FOLDERS} and ${OUTPUT_DIR} to
# set.
#
function(copy_common_files RESOURCE_FOLDERS OUTPUT_DIR copiedFiles)
foreach(folder ${RESOURCE_FOLDERS})
file(GLOB QML_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${folder}/*.qml)
file(GLOB SVG_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${folder}/*.svg)
file(GLOB QMLDIR_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${folder}/qmldir)
file(GLOB APPCFG_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${folder}/appconfig.json)
file(GLOB TRANSLATION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${folder}/*.ts)
file(GLOB QRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${folder}/*.qrc)
set(FILES_TO_COPY
${QML_FILES} ${SVG_FILES} ${QM_FILES} ${QMLDIR_FILE} ${QRC_FILES}
${APPCFG_FILE} ${TRANSLATION_FILES}
)
foreach(file ${FILES_TO_COPY})
get_filename_component(nam ${file} NAME)
add_custom_command(OUTPUT ${OUTPUT_DIR}/${folder}/${nam}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${file} ${OUTPUT_DIR}/${folder}
DEPENDS ${file}
COMMENT "Copying ${file}"
VERBATIM
)
list(APPEND outputList ${OUTPUT_DIR}/${folder}/${nam})
set(${copiedFiles} ${outputList} PARENT_SCOPE)
endforeach()
endforeach()
endfunction()
#foreach(folder ${RESOURCE_FOLDERS})
# file(GLOB QML_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${folder}/*.qml)
# file(GLOB SVG_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${folder}/*.svg)
# file(GLOB QMLDIR_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${folder}/qmldir)
# file(GLOB APPCFG_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${folder}/appconfig.json)
# file(GLOB TRANSLATION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${folder}/*.ts)
# file(GLOB QRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${folder}/*.qrc)
# set(FILES_TO_COPY
# ${QML_FILES} ${SVG_FILES} ${QM_FILES} ${QMLDIR_FILE} ${QRC_FILES}
# ${APPCFG_FILE} ${TRANSLATION_FILES}
# )
# foreach(file ${FILES_TO_COPY})
# get_filename_component(nam ${file} NAME)
# add_custom_command(OUTPUT ${OUTPUT_DIR}/${folder}/${nam}
# COMMAND ${CMAKE_COMMAND} -E copy_if_different ${file} ${OUTPUT_DIR}/${folder}
# DEPENDS ${file}
# COMMENT "Copying ${file}"
# VERBATIM
# )
# list(APPEND copiedFiles ${OUTPUT_DIR}/${folder}/${nam})
# endforeach()
#endforeach()
这里是调用该函数的插件CMakeLists.txt的一个示例,其工作方式只是include语句,而不包括函数调用
find_package(Qt5 COMPONENTS Core REQUIRED)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC OFF) # Set this to ON if you want resources compiled in
set(OUTPUT_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AEPPApps/ImportFiles)
set(RESOURCE_FOLDERS
.
images
)
include(copy_common_files) # only this when not using 'function'
copy_common_files(${RESOURCE_FOLDERS} ${OUTPUT_DIR} copiedFiles)
# Adding ${copiedFiles} as a dependency below forces the conditional copy
# to get considered:
# https://stackoverflow.com/questions/33938239/cmake-does-not-copy-file-in-custom-command
add_library(ImportFiles SHARED ${copiedFiles})
target_compile_definitions(ImportFiles
PRIVATE
IMPORTFILESPLUGIN_LIBRARY
NOMINMAX
)
target_include_directories(ImportFiles
PRIVATE
.
)
# Enable below when you want to compile resources for apps, then remove the copying above
#
#qt5_add_resources(ImportFiles_RESOURCES
# ImportFiles.qrc
# )
target_sources(ImportFiles
PRIVATE
Redacted.cpp
)
target_link_libraries(ImportFiles
PUBLIC
REDACTED-lib
PRIVATE
Qt5::Core
)
set_target_properties(ImportFiles PROPERTIES RUNTIME_OUTPUT_DIRECTORY
${OUTPUT_DIR}
)
您的
RESOURCE\u文件夹
变量包含两个值
将它们传递给函数时,它们被解释为函数的两个参数(RESOURCE\u FOLDERS
和OUTPUT\u DIR
)
方式1。您可以传递“多值”变量引号:
copy_common_files("${RESOURCE_FOLDERS}" ${OUTPUT_DIR} copiedFiles)
请注意,引用仅适用于命名参数
否则,这种方法是完全有效的,例如在执行命令时使用
方式2。将多值参数排列到函数签名中的结尾,在命名参数之后:
function(copy_common_files OUTPUT_DIR copiedFiles)
该函数可以称为
copy_common_files(${OUTPUT_DIR} copiedFiles ${RESOURCE_FOLDERS})
在函数内部,您可以将rest参数列表称为${ARGN}
:
foreach(folder ${ARGN})
这种方法在许多非内部CMake命令中使用。函数
copy_common_files
创建许多add_custom_命令
,每个生成的源文件一个,并设置输出参数copiedFiles
以包含该源文件的列表。功能的哪一部分没有工作?您可以使用通常的message()
call检查输出参数的值。是的,问得好。最终文件没有被复制,我现在可以看到${copiedFiles}在从函数调用返回后是空的。我只是注意到我的输入变量是一个列表,它在函数中的第一个值之后被截断。出于好奇,在这种情况下宏是更好的选择吗?不,宏无法解决多值参数的问题。此外,宏在解释ARGN
方面有一些特定的功能,因此我发现无论何时只要两者都适用,函数都比宏更好。但是,当需要不惜任何代价避免嵌套范围时,宏是一个不错的选择。