Use a lista como dependências em add_custom_command
Eu quero usar list ie., set(RESOURCES foo.txt bar.txt foo.bar bar.foo)Como dependências em vez de digitar manualmente na add_custom_commandparte DEPENDS.
O caso de uso da vida real real é para glib-compile-resourcesferramenta de utilitário onde um usuário pode deixá-lo gerar todas as dependências do arquivo xml usando o --generate-dependenciesparâmetro. Em nosso caso, a saída é armazenada em uma variável usando o CMake execute_process(). Dessa forma, não preciso atualizar manualmente o script CMake cada vez que um novo recurso é adicionado ou removido do arquivo xml.
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>
O manequim pode ser apenas oi, mundo por enquanto.
A lista não está expandida na parte DEPENDS acima. Mas se eu digitar manualmente todas as dependências, funciona. Existe uma maneira de alcançar o comportamento que desejo?
Respostas
A fonte da causa é o valor de saída que GRESOURCE_DEPENDENCIESobtemos deexecute_process()
Tente imprimir seu comprimento real como uma lista. Vamos pegar o tamanho 1!
Mas a string impressa usando message(${GRESOURCE_DEPENDENCIES})é tão convincente:
foo.glade
bar.glade
Mas essa saída está errada! Só obteremos esse tipo de saída se o foreach()loop for usado em conjunto com message(). Sem loop, uma lista impressa usando apenas message(), a saída correta sai assim:
foo.gladebar.glade
O remédio para isso é simples:
- Use
string(REPLACE "\n" ";" ...)para converter nosso valor de string em uma lista - Destaque o último item porque é apenas um único
\ncaractere de espaço em branco - Graças aos comentários acima Definir
GRESOURCE_DEPENDENCIEScomo uma variável persistente
Script corrigido
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)