使用列表作为对add_custom_command的依赖项 [英] Use list as dependencies on add_custom_command

查看:79
本文介绍了使用列表作为对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:

  1. 使用 string(REPLACE"\ n"; ..." 将我们的字符串值转换为列表
  2. 弹出最后一项,因为它只是一个 \ n 空格字符
  3. 感谢上面的评论 GRESOURCE_DEPENDENCIES 设置为持久变量
  1. Use string(REPLACE "\n" ";" ...) to convert our string value to a list
  2. Pop out the last item because it's just a single \n whitespace character
  3. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆