web-dev-qa-db-fra.com

Comment forcer un fichier Make à reconstruire une cible

J'ai un makefile qui construit et appelle ensuite un autre makefile. Comme ce makefile appelle plus de makefiles qui font le travail, cela ne change pas vraiment. Ainsi, il continue à penser que le projet est construit et à jour.

dnetdev11 ~ # make
make: `release' is up to date.

Comment forcer le makefile à reconstruire la cible?

clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean


build = svn up ~/xxx                                                       \
        $(clean)                                                                \
        ~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace        \
        $(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1)                    \


release:
        $(build )

debug:
        $(build DEBUG=1)

clean:
        $(clean)

install:
        cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
        cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib

Note: Noms enlevés pour protéger l'innocent

Edit: Version définitive fixée:

clean = $(MAKE) -f xxx_compile.workspace.mak clean;


build = svn up;                                         \
        $(clean)                                        \
        ./cbp2mak/cbp2mak -C . xxx_compile.workspace;   \
        $(MAKE) -f xxx_compile.workspace.mak    $(1);   \


.PHONY: release debug clean install

release:
        $(call build,)

debug:
        $(call build,DEBUG=1)

clean:
        $(clean)

install:
        cp ./source/xxx_utillity/release/xxx_util /usr/bin
        cp ./dlls/Release/xxxcore.so /usr/lib
152
Lodle

Vous pouvez déclarer une ou plusieurs de vos cibles comme étant faux .

Une cible bidon est une cible qui n'est pas vraiment le nom d'un fichier. c'est plutôt un nom pour une recette à exécuter lorsque vous faites une demande explicite. L'utilisation d'une cible factice a deux raisons: éviter un conflit avec un fichier du même nom et améliorer les performances.

...

Une cible factice ne devrait pas être une condition préalable à un fichier cible réel; si c'est le cas, sa recette sera exécutée à chaque fois que make va mettre à jour ce fichier. Tant qu'une cible factice n'est jamais une condition préalable à une cible réelle, la recette de cible factice ne sera exécutée que si la cible factice est un objectif spécifié

26
Dave

Le -B _ switch to make, dont la forme longue est --always-make, dit à make de ne pas tenir compte des horodatages et de créer les cibles spécifiées. Cela peut aller à l'encontre de l'utilisation de make, mais c'est peut-être ce dont vous avez besoin.

641
sykora

Une astuce qui était documentée dans un manuel Sun pour make consiste à utiliser une cible (non existante) '.FORCE'. Vous pouvez le faire en créant un fichier, force.mk, qui contient:

.FORCE:
$(FORCE_DEPS): .FORCE

Ensuite, en supposant que votre makefile existant s'appelle makefile, vous pouvez exécuter:

make FORCE_DEPS=release -f force.mk -f makefile release

Puisque .FORCE n'existe pas, tout ce qui en dépend sera périmé et reconstruit.

Tout cela fonctionnera avec n’importe quelle version de make; sous Linux, vous avez GNU Make et pouvez donc utiliser la cible .PHONY comme indiqué.

Il est également intéressant de considérer pourquoi make considère que la publication est à jour. Cela pourrait être parce que vous avez un touch release commande parmi les commandes exécutées; cela pourrait être dû au fait qu'il existe un fichier ou un répertoire appelé 'release' qui n'existe pas, il n'a donc aucune dépendance et est donc à jour. Ensuite, il y a la raison réelle ...

15

Quelqu'un a suggéré .PHONY qui est certainement correct. .PHONY doit être utilisé pour toute règle pour laquelle une comparaison de date entre l'entrée et la sortie n'est pas valide. Puisque tu n'as aucune cible de la forme output: input vous devriez utiliser .PHONY pour TOUS!

Cela dit, vous devriez probablement définir des variables en haut de votre makefile pour les différents noms de fichiers, et définir de véritables règles de création comportant des sections d'entrée et de sortie afin de pouvoir utiliser les avantages de make, à savoir que vous ne compilerez réellement choses qui sont nécessaires pour copmile!

Edit: exemple ajouté. Non testé, mais c'est comme ça que vous faites .PHONY

.PHONY: clean    
clean:
    $(clean)
13
easel

Cette technique simple permettra au makefile de fonctionner normalement lorsque le forçage n'est pas souhaité. Créez une nouvelle cible appelée force à la fin de votre makefile. La cible force touchera un fichier dont dépend votre cible par défaut. Dans l'exemple ci-dessous, j'ai ajouté touch myprogram.cpp. J'ai également ajouté un appel récursif à make. Cela fera que la cible par défaut sera créée chaque fois que vous tapez make force.

yourProgram: yourProgram.cpp
       g++ -o yourProgram yourProgram.cpp 

force:
       touch yourProgram.cpp
       make
4
groko

Si je me souviens bien, "make" utilise des horodatages (heure de modification de fichier) pour déterminer si une cible est à jour ou non. Une façon courante de forcer une reconstruction est de mettre à jour cet horodatage à l'aide de la commande 'touch'. Vous pouvez essayer d'appeler 'touch' dans votre makefile pour mettre à jour l'horodatage de l'une des cibles (peut-être un de ces sous-makefiles), ce qui pourrait forcer Make à exécuter cette commande.

4
poundifdef

J'ai essayé cela et cela a fonctionné pour moi

ajoute ces lignes à Makefile

clean:
    rm *.o output

new: clean
    $(MAKE)     #use variable $(MAKE) instead of make to get recursive make calls

enregistrer et maintenant appeler

make new 

et il va tout recompiler à nouveau

Qu'est-il arrivé?

1) "nouveaux" appels propres. 'clean' do 'rm' qui supprime tous les fichiers objets portant l'extension '.o'.

2) "nouveaux" appels "faire". 'make' voit qu'il n'y a pas de fichiers '.o', donc il crée à nouveau tout le '.o'. alors l'éditeur de liens lie tout le fichier .o int à une sortie exécutable

Bonne chance

3
hamaney

Si vous n'avez pas besoin de conserver les sorties que vous avez déjà compilées avec succès

nmake /A 

reconstruit tout

1
CZahrobsky

Selon Miller Récursif Make Considéré Nocif vous devriez éviter d'appeler $(MAKE)! Dans le cas que vous montrez, c'est inoffensif, car il ne s'agit pas vraiment d'un fichier Make, mais d'un script wrapper, qui aurait tout aussi bien pu être écrit dans Shell. Mais vous dites que vous continuez ainsi à des niveaux de récursion plus profonds, vous avez donc probablement rencontré les problèmes présentés dans cet essai révélateur.

Bien sûr, avec GNU, il est fastidieux d’éviter. Et même s’ils sont conscients de ce problème, c’est leur façon documentée de faire les choses.

OTOH, makepp a été créé pour résoudre ce problème. Vous pouvez écrire vos makefiles au niveau d'un répertoire, mais ils sont tous rassemblés dans une vue complète de votre projet.

Mais les makefiles existants sont écrits de manière récursive. Il existe donc une solution de contournement dans laquelle $(MAKE) ne fait que rediriger les sous-demandes vers le processus de création principal. Si vous faites des choses superflues ou, pire, contradictoires, vous devez demander --traditional-recursive-make (qui casse bien sûr cet avantage du maquillage). Je ne connais pas vos autres fichiers Make, mais s’ils sont bien écrits, avec makepp, les reconstructions nécessaires devraient se faire automatiquement, sans qu’aucun piratage ne soit suggéré ici par d’autres.

1
Daniel

make clean supprime tous les fichiers objets déjà compilés.

0
Hanan Shteingart
0
abernier

Cela a déjà été mentionné, mais je pensais pouvoir ajouter quelque chose à l'utilisation de touch

Si vous touch tous les fichiers source à compiler, la commande touch modifie l'horodatage d'un fichier en fonction de l'heure à laquelle la commande touch a été exécutée.

Le timstamp du fichier source est ce que make utilise pour "savoir" qu'un fichier a changé et doit être recompilé

Par exemple: Si le projet était un projet c ++, alors faites touch *.cpp, puis exécutez à nouveau make et effectuez la recompilation de tout le projet.

0
mrflash818

Cela dépend en fait de la cible. S'il s'agit d'une cible factice (c'est-à-dire que la cible n'est PAS liée à un fichier), vous devez la déclarer comme .PHONY.

Si, toutefois, la cible n'est pas une cible factice mais que vous souhaitez simplement la reconstruire pour une raison quelconque (par exemple, lorsque vous utilisez la macro de prétraitement __TIME__), vous devez utiliser le schéma FORCE décrit dans les réponses fournies ici.

0
Kostas