Disons que j'ai un makefile avec la règle
%.o: %.c
gcc -Wall -Iinclude ...
Je veux que * .o soit reconstruit chaque fois qu'un fichier d'en-tête change. Plutôt que d'élaborer une liste de dépendances, à chaque fois qu'un fichier d'en-tête /include
change, tous les objets du répertoire doivent être reconstruits.
Je ne peux pas penser à une bonne façon de changer la règle pour s'adapter à cela, je suis ouvert aux suggestions. Des points bonus si la liste des en-têtes ne doit pas être codée en dur
Réponses:
Si vous utilisez un compilateur GNU, le compilateur peut assembler une liste de dépendances pour vous. Fragment Makefile:
ou
où
SRCS
est une variable pointant vers toute votre liste de fichiers source.Il y a aussi l'outil
makedepend
, mais je ne l'ai jamais autant aimégcc -MM
la source
depend
exécuter uniquement lorsque les fichiers sources ont changé? Il semble fonctionner à chaque fois, peu importe ...build/file.o
?La plupart des réponses sont étonnamment compliquées ou erronées. Cependant, des exemples simples et robustes ont été publiés ailleurs [ codereview ]. Certes, les options fournies par le préprocesseur gnu sont un peu déroutantes. Cependant, la suppression de tous les répertoires de la cible de construction avec
-MM
est documentée et non un bogue [ gpp ]:L'
-MMD
option (un peu plus récente) est probablement ce que vous voulez. Pour être complet, un exemple de makefile qui prend en charge plusieurs répertoires src et des répertoires de construction avec quelques commentaires. Pour une version simple sans répertoire de compilation, voir [ codereview ].Cette méthode fonctionne car s'il existe plusieurs lignes de dépendance pour une seule cible, les dépendances sont simplement jointes, par exemple:
est équivalent à:
comme mentionné à: Makefile plusieurs lignes de dépendance pour une seule cible?
la source
CPP
devrait lireCPPS
a.cpp
,b.cpp
)./src/
, cette substitution ne serait-elle pas effectuée$(OBJ)=./build/src/a.o ./build/src/b.o
?Comme je l'ai posté ici, gcc peut créer des dépendances et compiler en même temps:
Le paramètre '-MF' spécifie un fichier dans lequel stocker les dépendances.
Le tiret au début de '-include' indique à Make de continuer lorsque le fichier .d n'existe pas (par exemple lors de la première compilation).
Notez qu'il semble y avoir un bogue dans gcc concernant l'option -o. Si vous définissez le nom de fichier de l'objet sur obj / _file__c.o, le fichier généré .d contiendra toujours le fichier .o, pas obj / _file__c.o.
la source
man gcc
dit-MM
implique-E
, qui "s'arrête après le prétraitement". Vous avez besoin à la-MMD
place de: stackoverflow.com/a/30142139/895245Que diriez-vous de quelque chose comme:
Vous pouvez également utiliser les caractères génériques directement, mais j'ai tendance à trouver que j'en ai besoin à plus d'un endroit.
Notez que cela ne fonctionne bien que sur les petits projets, car cela suppose que chaque fichier objet dépend de chaque fichier d'en-tête.
la source
make clean all
chaque fois.gcc
ligne n'est pas exécutée du tout, mais la règle intégrée (%o: %.c
règle) est exécutée à la place.La solution de Martin ci-dessus fonctionne très bien, mais ne gère pas les fichiers .o qui résident dans des sous-répertoires. Godric souligne que l'indicateur -MT résout ce problème, mais il empêche simultanément le fichier .o d'être écrit correctement. Ce qui suit prendra en charge ces deux problèmes:
la source
Cela fera très bien le travail, et même gérer les sous-répertoires spécifiés:
testé avec gcc 4.8.3
la source
Voici un deux lignes:
Cela fonctionne avec la recette de création par défaut, tant que vous avez une liste de tous vos fichiers objets dans
OBJS
.la source
Je préfère cette solution, à la réponse acceptée par Michael Williamson, elle détecte les modifications apportées aux sources + fichiers en ligne, puis aux sources + en-têtes, et enfin aux sources uniquement. L'avantage ici est que toute la bibliothèque n'est pas recompilée si seulement quelques modifications sont apportées. Ce n'est pas une considération énorme pour un projet avec quelques fichiers, mais si vous avez 10 ou 100 sources, vous remarquerez la différence.
la source
Ce qui suit fonctionne pour moi:
la source
Une version légèrement modifiée de la réponse de Sophie qui permet de sortir les fichiers * .d dans un dossier différent (je ne collerai que la partie intéressante qui génère les fichiers de dépendance):
Notez que le paramètre
est utilisé pour garantir que les cibles (c'est-à-dire les noms de fichier objet) dans les fichiers * .d générés contiennent le chemin complet des fichiers * .o et pas seulement le nom du fichier.
Je ne sais pas pourquoi ce paramètre n'est PAS nécessaire lors de l'utilisation de -MMD en combinaison avec -c (comme dans la version de Sophie ). Dans cette combinaison, il semble écrire le chemin complet des fichiers * .o dans les fichiers * .d. Sans cette combinaison, -MMD écrit également uniquement les noms de fichiers purs sans aucun composant de répertoire dans les fichiers * .d. Peut-être que quelqu'un sait pourquoi -MMD écrit le chemin complet lorsqu'il est combiné avec -c. Je n'ai trouvé aucun indice dans la page de manuel g ++.
la source