[英]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)
<?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
解決這個問題的方法很簡單:
string(REPLACE "\\n" ";" ...)
將我們的字符串值轉換為列表\\n
空格字符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.