Utiliser la liste comme dépendances sur add_custom_command
Je veux utiliser list ie., set(RESOURCES foo.txt bar.txt foo.bar bar.foo)Comme dépendances au lieu de taper manuellement sur la add_custom_commandpartie DEPENDS.
Le cas d'utilisation réel est celui de l' glib-compile-resourcesoutil utilitaire où un utilisateur peut le laisser générer toutes les dépendances à partir du fichier xml à l'aide du --generate-dependenciesparamètre. Dans notre cas, la sortie est stockée sur une variable à l'aide de CMake execute_process(). De cette façon, je n'ai pas à mettre à jour manuellement le script CMake chaque fois qu'une nouvelle ressource est ajoutée ou supprimée du fichier 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>
Le mannequin peut juste être bonjour le monde pour le moment.
La liste n'est pas développée sur la partie DEPENDS ci-dessus. Mais si je tape manuellement toutes les dépendances, cela fonctionne. Existe-t-il un moyen d'obtenir le comportement que je souhaite?
Réponses
La source de la cause est la valeur de sortie que GRESOURCE_DEPENDENCIESnous avons obtenueexecute_process()
Essayez d'imprimer sa longueur réelle sous forme de liste. Nous aurons la taille 1!
Mais la chaîne imprimée à l'aide message(${GRESOURCE_DEPENDENCIES})est si convaincante:
foo.glade
bar.glade
Mais cette sortie est fausse! Nous n'obtenons ce type de sortie que si la foreach()boucle est utilisée conjointement avec message(). Sans boucle, une liste imprimée en utilisant uniquement message(), la sortie correcte sort comme ceci:
foo.gladebar.glade
Le remède à cela est simple:
- Utilisez
string(REPLACE "\n" ";" ...)pour convertir notre valeur de chaîne en liste - Soulevez le dernier élément car il ne s'agit que d'un seul
\ncaractère d'espace blanc - Merci aux commentaires ci-dessus Définir
GRESOURCE_DEPENDENCIEScomme une variable persistante
Script corrigé
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)