115 votes

Makefile, dépendances des en-têtes

Disons que j'ai un makefile avec la règle suivante

%.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'établir une liste de dépendances, chaque fois qu'un fichier d'en-tête dans le fichier /include change, alors tous les objets du répertoire doivent être reconstruits.

Je ne vois pas comment modifier la règle pour tenir compte de cette situation, mais je suis ouvert à toute suggestion. Des points bonus si la liste des en-têtes ne doit pas être codée en dur.

0 votes

Après avoir écrit ma réponse ci-dessous, j'ai regardé dans la liste connexe et j'ai trouvé : stackoverflow.com/questions/297514/ qui semble être un duplicata. La réponse de Chris Dodd est équivalente à la mienne, bien qu'elle utilise une convention de dénomination différente.

3voto

g24l Points 1355

Cela fera l'affaire, même si des sous-répertoires sont spécifiés :

    $(CC) $(CFLAGS) -MD -o $@ $<

testé avec gcc 4.8.3

3voto

tbodt Points 6671

Voici une double phrase :

CPPFLAGS = -MMD
-include $(OBJS:.c=.d)

Cela fonctionne avec la recette make par défaut, tant que vous avez une liste de tous vos fichiers objets dans OBJS .

2voto

MaximumFPS Points 81

Une version légèrement modifiée de celle de Sophie réponse 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) :

$(OBJDIR)/%.o: %.cpp
# Generate dependency file
    mkdir -p $(@D:$(OBJDIR)%=$(DEPDIR)%)
    $(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM -MT $@ $< -MF $(@:$(OBJDIR)/%.o=$(DEPDIR)/%.d)
# Generate object file
    mkdir -p $(@D)
    $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@

Notez que le paramètre

-MT $@

est utilisé pour s'assurer que les cibles (c'est-à-dire les noms des fichiers d'objets) dans les fichiers *.d générés contiennent le chemin complet vers les fichiers *.o et pas seulement le nom du fichier.

Je ne sais pas pourquoi ce paramètre n'est PAS nécessaire lorsqu'on utilise -MMD en combinaison avec -c (comme dans le cas de Sophie version ). Dans cette combinaison, il semble écrire le chemin complet des fichiers *.o dans les fichiers *.d. Sans cette combinaison, -MMD n'écrit que 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 pas trouvé d'indication dans la page de manuel de g++.

1voto

Marcel Keller Points 1

Ce qui suit fonctionne pour moi :

DEPS := $(OBJS:.o=.d)

-include $(DEPS)

%.o: %.cpp
    $(CXX) $(CFLAGS) -MMD -c -o $@ $<

1voto

Nicholas Hamilton Points 630

Je préfère cette solution à la réponse acceptée par Michael Williamson, elle permet de prendre en compte les modifications apportées aux sources + fichiers en ligne, puis aux sources + en-têtes, et enfin aux sources uniquement. L'avantage de cette solution est que la bibliothèque entière n'est pas recompilée si seulement quelques changements sont effectués. Ce n'est pas une grande considération pour un projet avec quelques fichiers, mais si vous avez 10 ou 100 sources, vous remarquerez la différence.

COMMAND= gcc -Wall -Iinclude ...

%.o: %.cpp %.inl
    $(COMMAND)

%.o: %.cpp %.hpp
    $(COMMAND)

%.o: %.cpp
    $(COMMAND)

2 votes

Cela ne fonctionne que si vous n'avez rien dans vos fichiers d'en-tête qui nécessiterait la recompilation de tout fichier cpp autre que le fichier d'implémentation correspondant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X