2010-11-06 4 views
3

** Question éditée **Makefile compilation plusieurs fois les mêmes sources

Voici un modèle Makefile typique:

TARGET = my_prog    # project name 

CC  = gcc -o 
CFLAGS = -Wall 
SOURCES := $(wildcard *.c) 
INCLUDES := $(wildcard *.h) 
OBJECTS := $(SOURCES:.c=*.o) 
rm  = rm -f 

$(TARGET): $(OBJECTS) 
    @$(CC) $(TARGET) $(CFLAGS) $(SOURCES) 
    @echo "Compilation complete!" 

clean: 
    @$(rm) $(TARGET) $(OBJECTS) 
    @echo "Cleanup complete!" 

Question: Pourquoi est- la ligne 11 (@S(CC) $(TARGET) ...) faisant écho encore quand appeler make?

Réponse: Parce que le problème est dans la règle par défaut et la ligne 11 est très bien.

** MISE A JOUR **

J'ai maintenant ce Makefile

# project name 
TARGET = my_prog 

CC  = gcc -c 
CFLAGS = -Wall -I. 
LINKER = gcc -o 
LFLAGS = -Wall 
SOURCES := $(wildcard *.c) 
INCLUDES := $(wildcard *.h) 
OBJECTS := $(SOURCES:.c=*.o) 
rm  = rm -f 

$(TARGET): $(OBJECTS) 
    $(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS) 

$(OBJECTS): $(SOURCES) $(INCLUDES) 
    $(CC) $(CFLAGS) $(SOURCES) 

clean: 
    $(rm) $(TARGET) $(OBJECTS) 

Question: Pourquoi$(CC) $(CFLAGS) $(SOURCES) en cours d'exécution n fois, où n est le nombre de sources des dossiers ?

** MISE À JOUR 2 **

Serait-ce une bonne façon de résoudre ce (semble fonctionner ...)?

$(TARGET): obj 
    $(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS) 

obj: $(SOURCES) $(INCLUDES) 
    $(CC) $(CFLAGS) $(SOURCES) 
+0

Quelle version de Make? – Beta

+0

@Beta, GNU. Je cours sous Linux –

Répondre

5

La commande $(CC) $(CFLAGS) $(SOURCES) est exécutée n fois, parce que la règle est exécutée n fois, parce qu'il ya des n objets à construire, parce que la règle a $(TARGET) que de nombreux objets comme des conditions préalables. Si vous souhaitez que la commande ne soit exécutée qu'une seule fois, remplacez tous ces prérequis par un seul pré-requis PHONY, dont la règle exécute la commande.

Mais il n'y a aucune raison de le faire de cette façon. Vous pouvez simplement rendre la commande plus sélective, de sorte qu'elle ne crée que l'objet qui était la cible réelle.De cette façon, Make ne perd pas de temps à reconstruire les mêmes objets à plusieurs reprises, et si un ou deux fichiers source ont été modifiés, reconstruira uniquement les objets pertinents, pas tous:

$(OBJECTS): %.o : %.c $(INCLUDES) 
    $(CC) $(CFLAGS) $< 

Cette règle est conservatif - il suppose que chaque objet dépend de chaque en-tête, donc il reconstruira parfois des choses inutilement. Vous pouvez le rendre meilleur, soit à la main si vous connaissez les vraies dépendances ou automatiquement avec une technique plus avancée.

EDIT:

Votre "mise à jour 2" est une solution décente, mais je vous suggère d'ajouter la ligne

.PHONY: obj 

à dire Faire qu'il n'y aura pas de fichier appelé « obj ". Sinon, Make exécutera la règle obj à chaque fois, en essayant de construire ce fichier.

Cela pose toujours le problème que si vous modifiez un fichier source, par ex. foo.c, Make va reconstruire tous les objets.

Le $< utilisé ci-dessus est un automatic variable. Cela signifie "le premier prérequis". Donc, lorsque Make essaie de construire foo.o, il va évaluer à foo.c.

EDIT:

Jack Kelly (le maudire!) A fait remarquer que je me trompe sur la façon dont les objectifs PHONY travail: la règle obj toujours courir, et il en sera la règle TARGET, si des fichiers source ont changé ou pas. La méthode "update 2" est donc efficace, mais brute.

+0

Oui, je peux voir le problème. (Voir ma "mise à jour 2"). BTW: quel est le '$ <' à la fin de la commande? –

+1

Vous êtes maintenant officiellement mon ennemi juré. Vous êtes toujours là en premier avec une réponse presque inattaquable :-). J'hésiterais à faire des choses dans le style "mise à jour 2", car une fois que vous avez fait 'obj' bidon, il reliera chaque fois que vous lancez' make'. 'make' est conçu pour être efficace dans le suivi des fichiers, alors laissez-le suivre les fichiers! –

1

Je pense que la sortie vient de générer les fichiers .o, non geverating My_Prog

On dirait que vous ne disposez pas d'une règle pour créer les fichiers .o, alors assurez utilise une par défaut .

Essayez de mettre ceci:

@echo "starting compilation" 

sur la ligne avant votre commande de construction ligne 11

Et vous pouvez voir que « la compilation de départ » est sortie après la ligne gcc.

ligne Peut-être 10 devrait lire:

$(TARGET): $(SOURCES) 

?

+0

+1 Je trouve amusant que vous puissiez obtenir autant de résultats différents avec un outil simple ... Ça marche maintenant! Mais il ne crée plus de fichiers .o. Pas que cela me dérange tellement ... –

+0

vous pouvez faire des fichiers objet si vous le souhaitez. C'est juste que si vous voulez les faire en silence, vous devrez faire une règle pour les construire – JasonWoof

Questions connexes