使用列表作为对add_custom_command的依赖项 [英] Use list as dependencies on add_custom_command
问题描述
我想使用列表,即 set(RESOURCES foo.txt bar.txt foo.bar bar.foo)
作为依赖项,而不是在 add_custom_command
上手动键入取决于部分.
I want to use list ie., set(RESOURCES foo.txt bar.txt foo.bar bar.foo)
as dependencies instead of typing out manually on add_custom_command
DEPENDS part.
实际的实际用例是 glib-compile-resources
实用工具,用户可以使用-generate-dependencies
参数.在我们的例子中,使用CMake的 execute_process()
将输出存储在变量中.这样,每次在xml文件中添加或删除新资源时,我都不必手动更新CMake脚本.
The actual real-life use case is for glib-compile-resources
utility tool where a user can let it generate all the dependencies from the xml file using --generate-dependencies
parameter. In our case, the output is stored on a variable using CMake's execute_process()
. That way I don't have to manually update CMake script every time a new resource is added or removed from the xml file.
cmake_minimum_required(VERSION 3.15)
project(dummy LANGUAGES C)
find_program(GLIB_COMPILE_RESOURCES NAMES glib-compile-resources REQUIRED)
set(GRESOURCE_C dummy.gresource.c)
set(GRESOURCE_XML dummy.gresource.xml)
set(GRESOURCE_XML_IN dummy.gresource.xml.in)
set(GRESOURCE_DEPENDENCIES)
set(OLD ${CMAKE_CURRENT_SOURCE_DIR}/${GRESOURCE_XML_IN})
set(NEW ${CMAKE_CURRENT_BINARY_DIR}/${GRESOURCE_XML})
if(NOT EXISTS ${OLD} OR (${OLD} IS_NEWER_THAN ${NEW}))
configure_file(${GRESOURCE_XML_IN} ${GRESOURCE_XML})
execute_process(
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${GLIB_COMPILE_RESOURCES} --generate-dependencies ${GRESOURCE_XML}
OUTPUT_VARIABLE GRESOURCE_DEPENDENCIES
)
endif()
add_custom_command(
OUTPUT ${GRESOURCE_C}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${GLIB_COMPILE_RESOURCES}
ARGS
--generate-source
--target=${CMAKE_CURRENT_BINARY_DIR}/${GRESOURCE_C}
{NEW}
VERBATIM
MAIN_DEPENDENCY ${GRESOURCE_XML}
DEPENDS ${GRESOURCE_DEPENDENCIES} # <-- Here lies the problem
)
add_custom_target(
dummy-resource
DEPENDS ${GRESOURCE_C}
)
add_executable(${PROJECT_NAME} dummy.c)
add_dependencies(${PROJECT_NAME} dummy-resource)
dummy.gresource.xml.in
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource>
<!-- touch foo.glade && touch bar.glade -->
<file>foo.glade</file>
<file>bar.glade</file>
</gresource>
</gresources>
假人现在可以成为世界了.
The dummy can just be hello world for now.
列表未在上述DEPENDS部分扩展.但是,如果我手动输入所有依赖项,它将起作用.有没有办法实现我想要的行为?
List isn't expanded on the above DEPENDS part. But if I manually type in all the dependencies it works. Is there a way to achieve the behavior I want?
推荐答案
原因在于我们从 execute_process()
尝试将其实际长度打印为列表.我们将获得1号尺寸!
Try printing out its actual length as a list. We'll get size 1!
但是使用 message($ {GRESOURCE_DEPENDENCIES})
打印的字符串是如此令人信服:
But the string printed using message(${GRESOURCE_DEPENDENCIES})
is so convincing:
foo.glade
bar.glade
但是输出错误!只有将 foreach()
循环与 message()
结合使用时,我们才能获得这种输出.没有循环,仅使用 message()
打印的列表,正确的输出如下所示:
But that output is wrong! We only get that kind of output if foreach()
loop is used in conjunction with message()
. Without loop, a list printed using only message()
, the correct output comes out like this:
foo.gladebar.glade
对此的补救方法很简单:
The remedy to this is simple:
- 使用
string(REPLACE"\ n"; ..."
将我们的字符串值转换为列表 - 弹出最后一项,因为它只是一个
\ n
空格字符 - 感谢上面的评论将
GRESOURCE_DEPENDENCIES
设置为持久变量
- Use
string(REPLACE "\n" ";" ...)
to convert our string value to a list - Pop out the last item because it's just a single
\n
whitespace character - Thanks to the comments above Set
GRESOURCE_DEPENDENCIES
as a persistent variable
更正的脚本
cmake_minimum_required(VERSION 3.15)
project(dummy LANGUAGES C)
find_program(GLIB_COMPILE_RESOURCES NAMES glib-compile-resources REQUIRED)
set(GRESOURCE_C dummy.gresource.c)
set(GRESOURCE_XML dummy.gresource.xml)
set(GRESOURCE_XML_IN dummy.gresource.xml.in)
set(GRESOURCE_DEPENDENCIES CACHE INTERNAL "GResource dependencies for dummy")
set(OLD ${CMAKE_CURRENT_SOURCE_DIR}/${GRESOURCE_XML_IN})
set(NEW ${CMAKE_CURRENT_BINARY_DIR}/${GRESOURCE_XML})
if(NOT EXISTS ${NEW} OR (${OLD} IS_NEWER_THAN ${NEW}))
configure_file(${GRESOURCE_XML_IN} ${GRESOURCE_XML})
execute_process(
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${GLIB_COMPILE_RESOURCES} --generate-dependencies ${GRESOURCE_XML}
OUTPUT_VARIABLE GRESOURCE_DEPENDENCIES
)
# OUTPUT_VARIABLE is not a list but a single string value with newlines
# Convert it to a list and pop out the last newline character
string(REPLACE "\n" ";" GRESOURCE_DEPENDENCIES ${GRESOURCE_DEPENDENCIES})
list(POP_BACK GRESOURCE_DEPENDENCIES)
endif()
add_custom_command(
OUTPUT ${GRESOURCE_C}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${GLIB_COMPILE_RESOURCES}
ARGS
--generate-source
--target=${CMAKE_CURRENT_BINARY_DIR}/${GRESOURCE_C}
${NEW}
VERBATIM
MAIN_DEPENDENCY ${GRESOURCE_XML}
DEPENDS ${GRESOURCE_DEPENDENCIES}
)
add_custom_target(
dummy-resource
DEPENDS ${GRESOURCE_C}
)
add_executable(${PROJECT_NAME} dummy.c)
add_dependencies(${PROJECT_NAME} dummy-resource)
这篇关于使用列表作为对add_custom_command的依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!