2016-10-13 1 views
1

Je le schéma de dépendance suivanteCmake ne reconstruit pas dépendante après condition change

a.txt <- prereq <- stamp <- dest 

prereq et dest sont des cibles, et a.txt et stamp sont des fichiers. Je veux que le tampon soit mis à jour chaque fois que a.txt change.

Pour ce faire, je le fichier CMakeLists.txt suivant:

cmake_minimum_required(VERSION 3.6) 
project(sample) 

# variable holding location of stamp and a.txt file 
set(STAMP ${CMAKE_CURRENT_SOURCE_DIR}/stamp) 
set(ATXT ${CMAKE_CURRENT_SOURCE_DIR}/a.txt) 

add_custom_target(
     prereq 
     DEPENDS ${ATXT} 
) 


add_custom_command(
     OUTPUT ${STAMP} 
     COMMAND ${CMAKE_COMMAND} -E echo "Update stamp." 
     COMMAND ${CMAKE_COMMAND} -E touch ${STAMP} 
     DEPENDS prereq 
) 

add_custom_target(dest ALL DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/stamp) 

Dans un premier temps, je les fichiers suivants

$ ls 
a.txt 
CMakeLists.txt 

Après l'exécution de CMake et de faire pour la première fois que nous obtenons la comportement attendu,

$ cmake . 
$ make 
[ 0%] Built target prereq 
[100%] Generating stamp 
Update stamp. 
[100%] Built target dest 

Cependant, après avoir touché a.txt, je me attends à stamp pour être mis à jour, mais ce n'est pas le cas.

$ touch a.txt 
$ make 
[ 0%] Built target prereq 
[100%] Built target dest 

Est-ce un bug dans cmake ou est-ce le comportement attendu? Comment pouvons-nous forcer cmake à exécuter la commande tactile à chaque fois prereq changements?

Répondre

2

DEPENDS en add_custom_target() et add_custom_command() les appels se comportent différemment.

Il suffit de déplacer ATXT car la dépendance de votre appel add_custom_command(OUTPUT ${STAMP} ...) devrait résoudre le problème, car le nommage des fichiers non-sortie dans add_custom_target() ne fonctionnera pas.

Voir add_custom_command() documentation:

DEPENDS: spécifier les fichiers dont la commande dépend. Si une dépendance est une OUTPUT d'une autre commande personnalisée dans le même répertoire (fichier CMakeLists.txt) CMake introduit automatiquement l'autre commande personnalisée dans la cible dans laquelle cette commande est créée. Si DEPENDS n'est pas spécifié, la commande sera exécutée chaque fois que OUTPUT est manquant.

Voir add_custom_target() documentation:

DEPENDS: Les fichiers de référence et les sorties des commandes personnalisées créées avec add_custom_command() appels de commande dans le même répertoire (CMakeLists.txt fichier).

Le paramètre DEPENDS dans add_custom_target() est uniquement destinée à déterminer les dépendances d'appels cible/personnalisés.

Edit: Alternatives pour "Dépendance tardive Injection"

  1. Si vous êtes dans le même fichier CMakeLists.txt vous pouvez APPEND dépendances à une commande personnalisée précédente OUTPUT:

    add_custom_command(
        OUTPUT ${STAMP} 
        COMMAND ${CMAKE_COMMAND} -E echo "Update stamp." 
        COMMAND ${CMAKE_COMMAND} -E touch ${STAMP} 
    ) 
    
    add_custom_target(dest ALL DEPENDS ${STAMP}) 
    
    add_custom_command(
        OUTPUT ${STAMP} 
        DEPENDS ${ATXT} 
        APPEND 
    ) 
    
  2. Vous peut ajouter une sortie fictive pour avoir une commande personnalisée pour votre cible prereq, mais pour redéclencher la version dest vous avez besoin de toucher une partie des entrées ou supprimer la sortie de dest (add_dependencies() lui-même ne redéclencher pas une cible personnalisée, il est juste que l'on est appelé avant l'autre):

    add_custom_command(
        OUTPUT ATxtCheck 
        COMMAND ${CMAKE_COMMAND} -E remove ${STAMP} 
        COMMAND ${CMAKE_COMMAND} -E touch ATxtCheck 
        DEPENDS ${ATXT} 
    ) 
    
    add_custom_target(prereq DEPENDS ATxtCheck) 
    
    add_custom_command(
        OUTPUT ${STAMP} 
        COMMAND ${CMAKE_COMMAND} -E echo "Update stamp." 
        COMMAND ${CMAKE_COMMAND} -E touch ${STAMP} 
        DEPENDS prereq 
    ) 
    
    add_custom_target(dest ALL DEPENDS ${STAMP}) 
    

références

+0

Merci pour la suggestion. En fait, ce que vous suggérez fonctionne, mais la raison pour laquelle j'ai structuré le cmake de cette façon est que je voulais ajouter dynamiquement des dépendances en utilisant la commande 'add_dependencies', et cela ne fonctionne que sur' targets' et non sur 'output . Si j'utilise la commande 'DEPENDS' dans' add_custom_command', je ne pourrai pas utiliser cette commande et devra spécifier explicitement les dépendances. – dzhelil

+0

@dzhelil De rien. Vous pouvez toujours ajouter une cible personnalisée pour l'injection de regroupement ou de dépendance, il vous suffira de déplacer les dépendances du fichier source dans une commande personnalisée supplémentaire. Je vais mettre à jour ma réponse en conséquence demain. – Florian