web-dev-qa-db-fra.com

GNU make: plusieurs cibles dans une seule règle

Duplicata possible:
règle GNU Makefile générant quelques cibles à partir d'un seul fichier source

Si j'ai une règle Makefile comme celle-ci:

a b c:
    echo "Creating a b c"
    touch a b c

output: a b c
    cat a b c > output

et je lance make -j9 output

make voit les 3 dépendances (a, b, c), cherche comment les produire: (la règle "a b c" ci-dessus), mais que se passe-t-il ensuite? Ne devrait-il pas réaliser que la règle "a b c" ne doit être exécutée qu'une seule fois pour créer les 3 cibles?

C'est ce que fait réellement:

[pavel@orianna test]$ make -j9 output -n
echo "Creating a b c"
touch a b c
echo "Creating a b c"
touch a b c
echo "Creating a b c"
touch a b c                                                                                                                                                                                                                                                                    
cat a b c > output                                                                                                                                                                                                                                                             
[pavel@orianna test]$

La même recette est exécutée 3 fois , une fois pour chaque dépendance pour gouverner la "sortie"!

Est-ce que quelqu'un sait pourquoi il se comporte de cette façon?

28
Pavel

Votre a b c: la règle indique à Make que voici comment construire tout de ces objectifs, pas comment construire tout d'eux. Make n'est pas assez intelligent pour analyser les commandes et en déduire que l'exécution de la règle une fois générera les trois. Faire savoir (à partir de la règle output) qu'il doit reconstruire a, b et c, c'est donc ce qu'il fait. Il exécute la première règle une fois pour a, une fois pour b et une fois pour c.

Si vous souhaitez les reconstruire individuellement, procédez comme suit:

a b c:
    echo "Creating $@"
    touch $@

Si vous souhaitez les reconstruire tous en même temps, faites quelque chose comme ceci:

.PHONY: things
things:
    echo "Creating a b c"
    touch a b c

output: things
    cat a b c > output

ou mieux encore:

THINGS = a b c
.PHONY: things
things:
    echo "Creating $(THINGS)"
    touch $(THINGS)

output: things
    cat $(THINGS) > output
30
Beta

a b c sont trois objectifs/cibles différents sans conditions préalables. i, e pour dire qu'il construira la cible chaque fois qu'on le lui demandera.

a b c:
    echo "Creating a b c"
    touch a b c

Vous demandez à make de construire une sortie nommée cible qui a un b c comme condition préalable. Ainsi, les cibles a b c sont construites séquentiellement et finalement la sortie est construite.

Maintenant, dans votre cas, toutes les cibles sont invariablement construites lorsque l'une des deux est appelée. Donc, pour éviter une construction redondante, vous devrez ajouter des conditions préalables aux cibles a, b, c. Construisez la cible "a" uniquement si "a" n'existe pas. De même pour "b" et "c"

a b c: $@
    echo "Creating a b c"
    touch a b c

Cependant, ce n'est pas conseillé. Idéalement, les cibles Makefile devraient être très spécifiques.

9
Kamath