2010-06-21 13 views
9

Disons que j'ai des fichiers:Comment définir des règles dans le Makefile pour compiler uniquement que les fichiers * .cpp qui a été modifié (et leurs dépendances), et non pas tous les fichiers * .cpp

Libs:

  • one.cpp, one.h
  • two.cpp, two.h
  • three.cpp, three.h

Programme:

  • program.cpp

Y at-il moyen, pour créer Makefile qui compilera seulement * .cpp qui ont été modifiés depuis la dernière compilation?

Actuellement, j'ai quelque chose comme ça:

SRCS = one.cpp two.cpp three.cpp 
OBJS = $(SRCS:.cpp=.o) 

all: $(OBJS) program 

.cpp.o: 
    g++ -Wall -c $< 

program: 
    g++ -Wall $(OBJS) program.cpp -o program 

clean: 
    rm -f $(OBJS) program 

je fonctionne très bien, mais quand je compile mon programme, puis changer two.cpp ou two.h je dois exécuter « make clean » Tout d'abord, parce que quand Je lance d'autre part « make » je reçois:

Nothing to be done for 'all'. 

Je voudrais changer mon Makefile de cette façon, il reconnaîtrait mes changements et recompiler ce fichier et ses dépendances (si one.cpp utilise le code de two.cpp qui a été modifié, les deux fichiers doivent être recompilés).

Donc, si je modifie two.cpp, faire devrait faire:

g++ -Wall -c two.cpp 
g++ -Wall $(OBJS) program.cpp -o program 

Mais si one.cpp utilise le code de two.cpp qui a été modifié, faire Shold faire:

g++ -Wall -c one.cpp 
g++ -Wall -c two.cpp 
g++ -Wall $(OBJS) program.cpp -o program 
+0

(Je pense que vous voulez dire 'one.cpp', pas' first.cpp'.) – Beta

+0

Oui, ça devrait être one.cpp. – user360872

Répondre

12

Tout d'abord, nous faisons les fichiers objet conditions préalables de l'exécutable. Une fois cela fait, make reconstruira program chaque fois l'un des changements de SRCS, donc on n'a pas besoin OBJS comme une cible explicite:

all: program 

program: $(OBJS) 
    g++ -Wall $(OBJS) program.cpp -o program 

Ensuite, nous faisons les conditions préalables fichiers d'en-tête des objets, de sorte que si nous changer three.h, make reconstruira three.o:

$(OBJS): %.o : %.h 

enfin depuis one.cpp utilise le code de two.cpp au moyen de two.h (je l'espère), nous faisons two.ha condition sine qua non d'un .o:

one.o: two.h 

Et pour rendre les choses plus propres et plus faciles à entretenir que nous utilisons les variables automatiques:

program: $(OBJS) 
    g++ -Wall $^ program.cpp -o [email protected] 

Mettez tous ensemble et nous obtenons:

SRCS = one.cpp two.cpp three.cpp 
OBJS = $(SRCS:.cpp=.o) 

all: program 

$(OBJS): %.o : %.h 

one.o: two.h 

.cpp.o: 
    g++ -Wall -c $< 

program: $(OBJS) 
    g++ -Wall $^ program.cpp -o [email protected] 

clean: 
    rm -f $(OBJS) program 

Il y a quelques autres choses que nous pourrions faire (comme ajouter program.o à OBJS), mais cela suffit pour aujourd'hui.

1

Ajouter les fichiers dont une commande dépend pour s'exécuter à la droite du nom de la cible.

Exemple:

default: hello.c 
    gcc -o hello.bin hello.c 

install: hello.bin 
    cp hello.bin ../ 
+0

N'est-ce pas ce que '$ (OBJS)' est pour? – JAB

+0

Vous me dites, c'est votre code. Je n'ai jamais utilisé de variables dans les champs de dépendance, mais il n'y a rien de logique qui empêche cela de fonctionner. – mcandre

+0

Mais ce n'est pas mon code. – JAB

0

Tout ce que vous devez faire est de dire make que le fichier .o dépend du fichier .cpp:

%.cpp.o: %.cpp 
    g++ -Wall -c -o [email protected] $< 
+0

Cela ne résoudra pas les problèmes de dépendances sur les fichiers d'en-tête ou les fichiers objets. – Beta