web-dev-qa-db-fra.com

Remplacer la cible dans le makefile pour ajouter plus de commandes?

Au travail, nous utilisons un makefile commun que d'autres makefiles incluent (via l'instruction include) et il a une cible générique "propre" qui tue certains fichiers communs. Je veux ajouter à cette cible dans mon nouveau makefile afin de pouvoir supprimer certains fichiers spécifiques, mais si j'ajoute une cible propre dans mon makefile, elle remplace simplement l'ancienne.

Je sais que je peux simplement créer une nouvelle cible avec un nouveau nom et le faire appeler clean, puis faire d'autres choses, mais pour des raisons de cohérence, j'aimerais pouvoir simplement appeler make clean et lui faire tout faire.

Est-ce possible?

43
Paul D.

Vous pouvez écrire votre propre nettoyage et en faire un pré-requis du nettoyage commun.

 clean: myclean 
 
 myclean: 
 rm quel que soit 

Le vôtre courra en premier. Si, pour une raison quelconque, vous souhaitez que le nettoyage commun s'exécute en premier, la solution sera plus compliquée.

MODIFIER:

Voici la meilleure solution que je puisse voir qui exécute la règle commune avant la règle locale:

include Makefile.common

clean:
    $(MAKE) -f Makefile.common $@
    rm whatever additional things

La directive include est nécessaire car le makefile local s'appuie sur le commun pour d'autres choses que clean. La règle locale clean remplace la règle commune clean, mais invoque la règle commune clean avant d'effectuer le travail supplémentaire. (Ce dépassement entraînera certains avertissements, ce qui est une nuisance; je ne connais pas un bon moyen de les faire taire.)

34
Beta

J'ai vu cela dans plusieurs magasins. L'approche la plus courante consiste à utiliser des règles à deux points, en supposant que vous utilisez quelque chose comme GNU make. Dans votre makefile commun, vous auriez quelque chose comme ceci:

clean::
        # standard cleanup, like remove all .o's:
        rm -f *.o

Notez qu'il y a deux deux-points après clean, pas un seul!

Dans votre autre makefile, vous déclarez simplement clean à nouveau, en tant que règle à deux points:

clean::
        # custom cleanup, like remove my special generated files:
        rm -f *.h.gen

Lorsque vous invoquez make clean, GNU make exécutera automatiquement ces deux "branches" de la règle propre:

% make clean
rm -f *.o
rm -f *.h.gen

C'est simple à mettre en place et ça compose assez bien je pense. Notez que spécifiquement parce qu'il s'agit d'une règle à deux points, vous n'obtenez pas les erreurs "commandes prioritaires" que vous obtenez normalement lorsque vous définissez deux règles pour la même cible. C'est en quelque sorte l'intérêt des règles du double-colon.

68
Eric Melski

Il semble que la règle commune du makefile devrait être appelée quelque chose comme common-clean. Ensuite, chaque makefile principal déclarerait sa règle propre comme

clean: common-clean

et vous êtes prêt.

Si ce n'est pas une option, vous pouvez jeter un œil à règles du double-point , mais celles-ci introduisent un tout autre ensemble de problèmes à considérer.

5
jamessan

Utilisez des règles implicites:

existing-target: my-extention

my-extention:
    echo running command 1
    echo running command 2

Tutoriel très simple pour monter en puissance.

Lorsque vous utilisez :: , vous pouvez rencontrer des problèmes car make se plaint lorsque vous mélangez des deux-points : et les deux points :: règles:

a:
    echo a

a::
    echo aa

aura pour résultat:

. . .
*** target file `a' has both : and :: entries.  Stop.
4
Bohdan

Ajout d'une autre solution possible que j'ai vue pour la postérité ... Je sais que l'OP se méfiait de changer le makefile commun, mais quelque chose comme ça fonctionne et implique des changements minimes.

makefile local 1:

CLEAN=MyExe1 MyExe2
....
include /my/common/makefile

makefile local 2:

CLEAN=MyExe3 MyExe4
....
include /my/common/makefile

makefile commun:

clean:
     rm -f *.dep *.o *.a $(CLEAN)

Fondamentalement, l'idée est de définir une variable (dans ce cas CLEAN) dans chaque makefile local avec tous les éléments spécifiques que vous souhaitez supprimer. Ensuite, le makefile commun s'exécute rm -f sur tous les types de fichiers communs à supprimer, plus tout ce qui a été spécifiquement marqué pour suppression dans chaque makefile local via la variable CLEAN. S'il n'y a rien de spécifique à supprimer, omettez simplement la déclaration de variable ou laissez-la vide (CLEAN=)

Alors maintenant, si nous exécutons make clean pour le makefile local 1, il s'exécute

rm -f *.dep *.o *.a MyExe1 MyExe2

Et si nous courons make clean pour le makefile local 2, il s'exécute

rm -f *.dep *.o *.a MyExe3 MyExe4
3
yano

Pour la nôtre, nous définissons une variable, EXTRAFILESTOCLEAN, puis lorsque la règle de nettoyage s'exécute, elle a une étape pour supprimer tout ce qui est spécifié dans la variable EXTRAFILESTOCLEAN

clean:
    rm -f *.o
ifdef $(EXTRAFILESTOCLEAN)
    rm -f $(EXTRAFILESTOCLEAN)
endif

Cela peut provoquer des problèmes inattendus si vous définissez cette variable sur des valeurs étranges, mais vous pouvez vous prémunir contre celles-ci en ajoutant des préfixes ou d'autres tests.

1
davenpcj