2009-12-30 4 views
6

Je suis nouveau sur Makefiles et g ++ et je suis frappé par un problème lors de la génération de dépendances des fichiers de projet en utilisant l'option -MM. Je poste le Makefile que j'utilise pour votre considération. S'il vous plaît, jetez un oeil.Problème de génération de dépendances dans Makefile en utilisant -MM

OUTPUT_ROOT := output/ 
SOURCE_ROOT := source/ 

TITLE_NAME := TestProj 

SOURCES := \ 
MyFile.cpp \ 
stdAfx.cpp \ 
Main.cpp \ 

OUT_DIR := $(OUTPUT_ROOT) 

OUT_O_DIR := $(OUT_DIR) 

OBJS = $(SOURCES:%.cpp=$(OUT_O_DIR)%.o) 
DEPS = $(OBJS:%.o=%.d) 
DIRS = $(subst /,/,$(sort $(dir $(OBJS)))) 
SOURCE_TARGET = $(SOURCES:%.cpp=$(SOURCE_ROOT)%.cpp) 
OUTPUT_TARGET = $(OUT_DIR)$(TITLE_NAME) 

#--------------------------------------------------------------------- 
# executables 
#--------------------------------------------------------------------- 
MD := mkdir -p 
RM := rm 
CC := g++ 

#--------------------------------------------------------------------- 
# rules 
#--------------------------------------------------------------------- 
.PHONY: clean directories objects title 

all: directories objects title 

directories: 
@$(MD) $(DIRS) 

clean: 
$(RM) -rf $(OUT_DIR) 

$(OBJS): $(SOURCE_TARGET) 
@$(CC) -c $< -o [email protected] 

$(DEPS): $(SOURCE_TARGET) 
@$(CC) -c -MM $< > $(DEPS) 

-include $(DEPS) 

objects:$(OBJS) $(DEPS) 

title: $(OBJS) 
@$(CC) $< -o [email protected] 

J'ai essayé plusieurs options et tellement de fois. J'ai cherché la solution mais je n'en ai pas trouvé.

L'option "-MM" est utilisée pour générer les dépendances. Si ce n'est pas le cas, veuillez me suggérer la bonne façon de générer les dépendances. Je voulais générer des dépendances automatiquement car mon projet aurait tellement de fichiers. Je pensais que c'est la meilleure option que d'écrire une dépendance evey manuellement.

Ce sont les erreurs que je reçois

g++: stdAfx.d: No such file or directory 
g++: Main.d: No such file or directory 
make: *** No rule to make target `stdAfx.d', needed by `objects'. Stop. 

Merci à l'avance.

+0

Que signifie "DEPS = $ (OBJS:% .o =% .d)"? Et pourquoi utilisez-vous parfois ': =' et parfois '='? –

+0

Il crée DEPS avec les noms des objets dans le répertoire de l'objet. Je suis juste en train de tester avec les options '=' et ': =', mais je ne connais pas la différence exacte entre eux – Jabez

Répondre

8

Il semble que vous essayez de générer un fichier de dépendance (appelé * .d, par vos règles de fichier makefile) pour chaque fichier .cpp. Ce n'est pas ma compréhension de la façon dont un fichier de dépendances est utilisé.

Utilisez l'option -M pour générer un seul fichier de dépendances pour votre projet, puis incluez le fichier de dépendances.

DEPS = $(OUR_DIR)/make.dep 

$(DEPS): $(SOURCE_TARGET) 
    @$(CC) -M $(SOURCE_TARGET) > $(DEPS) 

include $(DEPS) 

modifier Votre fichier de dépendance devrait aussi dépendre de vos têtes

$(DEPS): $(SOURCE_TARGET) $(HEADER_TARGET) 
    @$(CC) -M $(SOURCE_TARGET) > $(DEPS) 

où HEADER_TARGET est défini le même que SOURCE_TARGET. Ainsi, lorsqu'un fichier d'en-tête est modifié, le fichier de dépendance est reconstruit.

+1

Merci mcdave, c'est une très bonne astuce, je pense que générer un seul fichier vaut mieux que de générer beaucoup ... Merci encore – Jabez

+1

Je veux simplement vous faire remarquer que '-MM' exclut les en-têtes système (plus ou moins), ce qui rend la construction plus rapide puisqu'il y a moins de fichiers à 1) vérifier 2) traiter pour construire la liste des dépendances. Par exemple, créez foo.cpp avec un certain nombre de stl includes et lancez 'g ++ -M foo.cpp' pour le voir cracher une liste de près de 100 dépendances, dont aucune ne changera, et qui devra vérifier chaque build. –

+0

@Robert: Merci pour le conseil - Je ne le savais pas et je mettrais à jour mes makefiles pour les rendre plus efficaces! – mcdave

3

Pour un débutant, vous faites des choses exotiques. Vous devriez commencer simple et utiliser seulement du code dans votre Makefile que vous comprenez et que vous avez confiance à 100%. Même sur un grand projet avec des centaines de fichiers, vous ne passerez pas beaucoup de temps à maintenir le Makefile.

Les variables affectées de: = sont immédiatement étendues - toutes les valeurs $ (VAR) sont substituées dans la valeur de la variable lors de l'affectation. Les variables affectées avec = sont développées lorsqu'elles sont utilisées, elles peuvent donc faire des choses comme se référer à des variables qui ne sont pas encore définies.

L'indicateur -MM pour g ++ génère une ligne de dépendance Makefile, par ex. foo.o: foo.cc foo.hh, mais je ne l'ai jamais trouvé utile. J'ai eu une fausse "dépendance" cible qui a généré un seul fichier de dépendance. Votre idée de faire un tas de fichiers * .d avec ces dépendances d'une ligne peut fonctionner, mais vous finirez avec beaucoup de ces fichiers.

L'erreur que vous obtenez provient de g ++, pas de make. C'est parce que vous utilisez $ (DEPS) comme s'il s'agissait d'un seul fichier lorsqu'il s'agit de la liste complète des fichiers * .d. Ce qui se passe est cette ligne:

@$(CC) -c -MM $< > $(DEPS) 

obtient étendu à:

g++ -c -MM MyFile.cpp > MyFile.d stdAfx.d Main.cpp 

mcdave vient de publier le code que je l'ai utilisé pour générer un fichier de dépendance.Vous pouvez changer le style de fichier de dépendance unique, ou modifier votre commande -MM à ceci:

@$(CC) -MM $< > [email protected] 

Vous pouvez également fixer la déclaration -include parce que je ne pense pas qu'il prend en charge une liste de fichiers à comprendre.

+0

Merci Ken, j'utilise maintenant un seul fichier au lieu de tant de fichiers multiples. Merci de dire le diff b/w '=' et ': =', ça m'aide beaucoup. – Jabez

Questions connexes