Question

J'ai un fichier makefile qui se construit puis appelle un autre fichier 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

Remarque: noms supprimés pour protéger l'innocent

.

Édition: Version définitive corrigé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
Était-ce utile?

La solution

Vous pouvez déclarer une ou plusieurs de vos cibles. bidon .

  

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

     

...

     

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

Autres conseils

Le commutateur -B à créer, dont la forme longue est - always-make , indique à make de ne pas tenir compte des horodatages et de définir le paramètre spécifié. cibles. Cela peut aller à l’encontre de l’utilisation de make, mais peut être ce dont vous avez besoin.

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

Etant donné que .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é.

Cela vaut également la peine de se demander pourquoi make considère que la publication est à jour. Cela peut être dû au fait que vous avez une commande touch release 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 pas de dépendances et est donc à jour. Ensuite, il y a la raison réelle ...

Quelqu'un a suggéré .PHONY, qui est tout à fait 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. Comme vous n’avez aucune cible de la forme sortie: entrée , vous devez utiliser .PHONY pour TOUTES!!

Cela étant 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 à la fois des sections d'entrée et de sortie afin que vous puissiez utiliser les avantages de make, à savoir: Ne compilez réellement que les choses nécessaires à la copmile!

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

.PHONY: clean    
clean:
    $(clean)

Si je me souviens bien, 'make' utilise des horodatages (heure de modification du fichier) pour déterminer si une cible est à jour ou non. Un moyen courant 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 l'un de ces sous-makefiles), ce qui pourrait forcer Make à exécuter cette commande.

Cette technique simple permet 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 fichier Make . 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 . Ainsi, la cible par défaut sera définie chaque fois que vous tapez make force .

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

force:
       touch yourProgram.cpp
       make

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

ajouter ces lignes à Makefile

clean:
    rm *.o output

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

enregistrer et appeler maintenant

make new 

et tout sera recompilé à nouveau

Que s'est-il passé?

1) les «nouveaux» appels sont nettoyés. 'clean' do 'rm' qui supprime tous les fichiers objet portant l'extension '.o'.

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

Bonne chance

Selon les méthodes récursives considérées comme nuisibles de Miller, vous devez éviter d'appeler $ (MAKE) ! Dans le cas que vous montrez, c'est inoffensif, car ce n'est pas vraiment un makefile, mais un script de 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.

Évidemment, avec GNU, il est difficile à é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. Seulement si vous faites des choses redondantes ou, pire, contradictoires, entre vos envois, vous devez demander - traditional-récursive-make (ce qui casse bien sûr cet avantage de makepp). Je ne connais pas vos autres fichiers makefile, mais s’ils sont bien écrits, avec makepp, les reconstructions nécessaires devraient se faire automatiquement, sans qu’il soit nécessaire de procéder à des piratages suggérés par d’autres.

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

nmake /A 

reconstruit tout

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 modèle FORCE décrit dans les réponses ici.

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

Si vous touchez tous les fichiers source à compiler, la commande touch modifie l'horodatage d'un fichier en heure système, puis touchez . commande a été exécutée.

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

Par exemple: si le projet était un projet c ++, alors touchez * .cpp , puis exécutez à nouveau make et make devrait recompiler le projet entier.

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

Sur mon système Linux (Centos 6.2), il existe une différence importante entre la déclaration de la cible .PHONY et la création d'une fausse dépendance sur FORCE, lorsque la règle crée effectivement un fichier correspondant à la cible. Lorsque le fichier doit être régénéré à chaque fois, il faut à la fois la fausse dépendance FORCE sur le fichier et .PHONY pour la fausse dépendance.

faux

date > $@

droite:

FORCE
    date > $@
FORCE:
    .PHONY: FORCE
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top