簡體   English   中英

使用列表作為 add_custom_command 的依賴項

[英]Use list as dependencies on add_custom_command

我想使用列表即set(RESOURCES foo.txt bar.txt foo.bar bar.foo)作為依賴項,而不是在add_custom_command DEPENDS 部分手動輸入。

實際的實際用例是glib-compile-resources實用工具,用戶可以使用--generate-dependencies參數--generate-dependencies從 xml 文件生成所有--generate-dependencies 在我們的例子中,輸出使用 CMake 的execute_process()存儲在一個變量中。 這樣我就不必每次在 xml 文件中添加或刪除新資源時都手動更新 CMake 腳本。

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>

虛擬人現在可以只是 hello world。

列表未在上述 DEPENDS 部分展開。 但是如果我手動輸入所有依賴項,它就可以工作。 有沒有辦法實現我想要的行為?

原因的根源是我們從execute_process()得到的輸出值GRESOURCE_DEPENDENCIES

嘗試將其實際長度打印為列表。 我們會得到 1 號!

但是使用message(${GRESOURCE_DEPENDENCIES})打印的字符串非常有說服力:

foo.glade
bar.glade

但是那個輸出是錯誤的! 如果foreach()循環與message()結合使用,我們只會得到那種輸出。 沒有循環,只使用message()打印的列表,正確的輸出是這樣的:

foo.gladebar.glade

解決這個問題的方法很簡單:

  1. 使用string(REPLACE "\\n" ";" ...)將我們的字符串值轉換為列表
  2. 彈出最后一項,因為它只是一個\\n空格字符
  3. 感謝上面的評論GRESOURCE_DEPENDENCIES設置為持久變量

更正的腳本

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM