Use la lista como dependencias en add_custom_command

Aug 30 2020

Quiero usar la lista, es decir, set(RESOURCES foo.txt bar.txt foo.bar bar.foo)como dependencias en lugar de escribir manualmente en la add_custom_commandparte DEPENDS.

El caso de uso de la vida real es para una glib-compile-resourcesherramienta de utilidad donde un usuario puede permitirle generar todas las dependencias del archivo xml usando el --generate-dependenciesparámetro. En nuestro caso, la salida se almacena en una variable usando CMake execute_process(). De esa manera, no tengo que actualizar manualmente el script CMake cada vez que se agrega o elimina un nuevo recurso del archivo 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>

El muñeco puede ser hola mundo por ahora.

La lista no está expandida en la parte anterior DEPENDE. Pero si escribo manualmente todas las dependencias, funciona. ¿Hay alguna forma de lograr el comportamiento que quiero?

Respuestas

1 KeyikedalubeNdang Sep 01 2020 at 04:40

La fuente de la causa es el valor de salida GRESOURCE_DEPENDENCIESque obtuvimos deexecute_process()

Intente imprimir su longitud real como una lista. ¡Conseguiremos talla 1!

Pero la cadena impresa usando message(${GRESOURCE_DEPENDENCIES})es tan convincente:

foo.glade
bar.glade

¡Pero esa salida es incorrecta! Solo obtenemos ese tipo de salida si foreach()se usa loop junto con message(). Sin bucle, una lista impresa usando solo message(), la salida correcta sale así:

foo.gladebar.glade

El remedio para esto es simple:

  1. Úselo string(REPLACE "\n" ";" ...)para convertir nuestro valor de cadena en una lista
  2. Saque el último elemento porque es solo un \ncarácter de espacio en blanco
  3. Gracias a los comentarios anteriores Establecer GRESOURCE_DEPENDENCIEScomo variable persistente

Guión corregido

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)