Comment puis-je faire Makefile pour recompiler uniquement les fichiers modifiés?
J'ai été un peu en difficulté pour obtenir make pour compiler uniquement les fichiers qui ont été modifiés. Cependant, je n'ai pas eu beaucoup de succès et tous les fichiers sont recompilés. Quelqu'un peut-il m'expliquer pourquoi?
Mes fichiers sont:
main.c
a_functions.c
où principal.c comprend principal.h
et a_functions.c comprend un.h
Voici mon makefile:
CC=gcc
CFLAGS=-Wall -I. -c
EXEC_FILE=program1
all: program
a_functions.o: a_functions.c
a_functions.c: a.h
main.o: main.c
main.c: main.h
objects: a_functions.c main.c
$(CC) a_functions.c main.c $(CFLAGS)
program: a_functions.o main.o
$(CC) a_functions.o main.o -o $(EXEC_FILE)
Modification du makefile que par des suggestions semble avoir le même problème::
all: program
a_functions.o: a_functions.c a.h
gcc a_functions.c -c
main.o: main.c main.h
gcc main.c -c
program: a_functions.o main.o
gcc a_functions.o main.o -o program1
-I.
me paraît étrange. Qu'est-ce qui?- juste des moyens de recherche pour inclure les fichiers dans le répertoire en cours ainsi que la mise en œuvre-définis. Si besoin est discutable, mais je ne pense pas qu'il serait la cause de tout mal.
- peut-être, mais je suppose que c'est un symptôme d'un autre problème. Si son programme ne fournit pas à l'échelle du système des en-têtes pour quelque chose et il se doit de fournir à ses propres versions, c'est une chose, mais je suppose que c'est une erreur qu'il est...
- Comment est que peut-être une erreur? Il y a certainement des fichiers d'en-tête qui doivent être inclus dans le répertoire courant dans pratiquement n'importe quel programme que vous avez envie de compiler.
- Je l'ai enlevé et il a toujours le même problème
- J'ai plus été pensée pour des choses comme
a.h
dans le répertoire courant. La valeur par défaut peut bien avoir (par exemple)/usr/include
pour le système d'en-têtes, mais pas.
pour les spectacles locaux. Je suis à peu près certain de tous gcc je n'ai jamais utilisé aussi regardé dans le répertoire courant par défaut (le comportement réel de la mise en œuvre est définie), mais il peut être une étrange variante ici. - Ce n'est pas une bonne idée de changer les questions d'une manière qui invalide les réponses. Hésitez pas à compléter les informations (voir mon edit) sinon devient beaucoup moins utile puisque les réponses ne correspondent pas aux questions.
- vous avez raison. Va garder à l'esprit pour les questions d'avenir 🙂
- dans ce cas, pourquoi ne pas utiliser
#include "a.h"
d'inclure le fichier plutôt que de#include <a.h>
? - Nous ne pouvons pas #include <un.h> le <> les symboles sont utilisés pour rechercher l'en-tête dans les répertoires système. Je n'ai, en effet, utiliser #include "un.h" comme prévu. Je ne suis pas sûr mais pourquoi ne pas avoir TOUT comprendre, mais en utilisant -I. au lieu de cela ne fonctionne pas.
Vous devez vous connecter pour publier un commentaire.
Le problème spécifique que vous êtes parle -- Faire reconstruit
program1
(en réassocier les objets), même si rien n'a changé, est dans cette règle:L'objectif de cette règle est
program
, et de Faire suppose que c'est un fichier. Mais depuis il n'y a pas de tel fichier, à chaque fois que vous exécutez Make, Make pense que ce fichier doit être reconstruit, et exécute la règle. Je suggère ceci:Ou mieux, c':
Ou mieux encore ceci:
(Et ne pas oublier de changer le
all
règle de correspondance.)Quelques autres points:
Comme @paxdiablo souligné,
Il n'est pas logique de faire le lien entre ces objets ensemble, à moins que quelque chose dans un (probablement
main.o
) appelle quelque chose dans l'autre (probablementa_functions.o
), donc je m'attends à voir une dépendance comme ceci:Donc je pense que vous avez quelques égarés déclarations.
Vous déclarez un
objects
règle, mais jamais de les consulter. Si vous n'avez jamais réellement l'utiliser; Faire utilise la règle par défaut pour%.o: %.c
. Je suggère ceci:(Dans ce cas, vous pouvez modifier
$(EXEC_FILE): a_functions.o main.o
à$(EXEC_FILE): $(OBJECTS)
.) Ou tout simplement ceci:program
ne devrait pas être un fichier (et doit être exécuté même si un tel fichier arrive à exister). Pratiquement, non, car Faire serait de toujours exécuter cette règle à chaque fois, même si rien n'avait changé.Ne sais pas si cela est la cause de votre problème spécifique, mais les deux lignes:
sont absolument faux, car il n'y a généralement pas de commande pour re-créer un fichier C basé sur un en-tête on comprend.
C fichiers ne dépendent pas de leurs fichiers d'en-tête, le objets créé par ces C fichiers faire.
Par exemple, un
main.c
de:serait dans le
makefile
que quelque chose comme:Changement:
à:
(en supposant que
a_functions.c
comprenda.h
etmain.c
comprendmain.h
) et essayez à nouveau.Si cette hypothèse ci-dessus est fausse, vous devez nous dire ce que C les fichiers à inclure ce que les en-têtes de sorte que nous pouvons vous dire le bon règlement.
Si votre thèse est que la
makefile
est encore à construire, même après ces modifications, vous devez regarder à deux choses.La première est la sortie de
ls -l
sur tous les fichiers importants de sorte que vous pouvez voir ce que les dates et les heures qu'ils ont.La deuxième est la sortie réelle de
make
. La sortie demake -d
sera particulièrement utile, car il montre quels sont les fichiers et les datesmake
est l'aide à comprendre ce qu'il faut faire.En termes d'enquête,
make
semble bien fonctionner que par la transcription suivante:Cette très tard le soir après le fait, et en fait c'est basé sur paxdiablo excellente réponse, mais tout en expérimentant j'ai trouvé que vous n'avez pas besoin de séparer les objectifs pour chacun .o fichier, sauf si vous êtes en train de faire quelque chose d'intelligent.
Donc pour mon makefile:
En faire 4.1 il compile le .o les fichiers automatiquement, vous n'avez pas à faire quoi que ce soit si votre .o fichiers ont le même nom que votre fichier source. Donc, ça va aller chasser pour a_functions.c, a_functions.h, main.h et principal.c automagiquement. Si vous n'avez pas les sources des noms de code, alors vous aurez une erreur du type:
J'ai également ajouté un "nettoyage" de la cible pour vous. "Propre" est utile si vous avez besoin de libérer votre logiciel sous forme de code source, ou vous souhaitez simplement supprimer tous les objets compilés fichiers et /ou binaires.
Et c'est tout ce que vous devez faire.
Enregistrer ce pour "Makefile" et exécutez la commande:
pour construire votre binaire. Et
pour nettoyer les objets compilés et les binaires dans votre code.