J'ai le makefile suivant que j'utilise pour construire un programme (un noyau, en fait) sur lequel je travaille. C'est à partir de zéro et j'apprends le processus, donc ce n'est pas parfait, mais je pense que c'est assez puissant à ce stade pour mon niveau d'expérience dans l'écriture de makefiles.
AS = nasm
CC = gcc
LD = ld
TARGET = core
BUILD = build
SOURCES = source
INCLUDE = include
ASM = assembly
VPATH = $(SOURCES)
CFLAGS = -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions \
-nostdinc -fno-builtin -I $(INCLUDE)
ASFLAGS = -f elf
#CFILES = core.c consoleio.c system.c
CFILES = $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
SFILES = assembly/start.asm
SOBJS = $(SFILES:.asm=.o)
COBJS = $(CFILES:.c=.o)
OBJS = $(SOBJS) $(COBJS)
build : $(TARGET).img
$(TARGET).img : $(TARGET).elf
c:/python26/python.exe concat.py stage1 stage2 pad.bin core.elf floppy.img
$(TARGET).elf : $(OBJS)
$(LD) -T link.ld -o $@ $^
$(SOBJS) : $(SFILES)
$(AS) $(ASFLAGS) $< -o $@
%.o: %.c
@echo Compiling $<...
$(CC) $(CFLAGS) -c -o $@ $<
#Clean Script - Should clear out all .o files everywhere and all that.
clean:
-del *.img
-del *.o
-del assembly\*.o
-del core.elf
Mon principal problème avec ce makefile est que lorsque je modifie un fichier d'en-tête qu'un ou plusieurs fichiers C incluent, les fichiers C ne sont pas reconstruits. Je peux résoudre ce problème assez facilement en faisant en sorte que tous mes fichiers d'en-tête soient des dépendances pour tous mes fichiers C, mais cela entraînerait effectivement une reconstruction complète du projet chaque fois que je modifierais / ajouterais un fichier d'en-tête, ce qui ne serait pas très gracieux.
Ce que je veux, c'est que seuls les fichiers C qui incluent le fichier d'en-tête que je modifie soient reconstruits et que l'ensemble du projet soit à nouveau lié. Je peux faire le lien en faisant en sorte que tous les fichiers d'en-tête soient des dépendances de la cible, mais je ne peux pas comprendre comment rendre les fichiers C invalides lorsque leurs fichiers d'en-tête inclus sont plus récents.
J'ai entendu dire que GCC a quelques commandes pour rendre cela possible (afin que le makefile puisse d'une manière ou d'une autre déterminer quels fichiers doivent être reconstruits) mais je ne peux pas pour la vie de moi trouver un exemple d'implémentation réel à regarder. Quelqu'un peut-il publier une solution qui permettra ce comportement dans un makefile?
EDIT: Je devrais clarifier, je suis familier avec le concept de mettre les cibles individuelles et d'avoir chaque target.o exiger les fichiers d'en-tête. Cela m'oblige à modifier le fichier makefile chaque fois que j'inclus un fichier d'en-tête quelque part, ce qui est un peu pénible. Je recherche une solution qui puisse dériver les dépendances du fichier d'en-tête par elle-même, ce que je suis assez certain d'avoir vu dans d'autres projets.
la source
Vous pouvez ajouter une commande 'make depend' comme d'autres l'ont indiqué, mais pourquoi ne pas demander à gcc de créer des dépendances et de compiler en même temps:
Le paramètre '-MF' spécifie un fichier dans lequel stocker les dépendances.
Le tiret au début de '-include' indique à Make de continuer lorsque le fichier .d n'existe pas (par exemple lors de la première compilation).
Notez qu'il semble y avoir un bogue dans gcc concernant l'option -o. Si vous définissez le nom de fichier de l'objet pour dire, le fichier
obj/_file__c.o
généré_file_.d
contiendra toujours_file_.o
, nonobj/_file_c.o
.la source
g++ -c -Wall -Werror -MM -MF main.d -o main.o main.cpp
j'ai obtenu le fichier main.d, mais main.o était de 0 octet. Cependant, l'indicateur -MMD semble faire exactement ce qui était requis. Donc, ma règle de travail makefile est devenue:$(CC) -c $(CFLAGS) -MMD -o $@ $<
Cela équivaut à la réponse de Chris Dodd , mais utilise une convention de dénomination différente (et par coïncidence n'exige pas la
sed
magie. Copié à partir d' un duplicata ultérieur .Si vous utilisez un compilateur GNU, le compilateur peut assembler une liste de dépendances pour vous. Fragment Makefile:
Il y a aussi l'outil
makedepend
, mais je ne l'ai jamais autant aimégcc -MM
la source
SRCS
etOBJS
. Je suis d'accord la plupart du temps, mais tout le monde devrait savoir de quoi il s'agit.Vous devrez créer des cibles individuelles pour chaque fichier C, puis répertorier le fichier d'en-tête en tant que dépendance. Vous pouvez toujours utiliser vos cibles génériques et placer simplement les
.h
dépendances par la suite, comme ceci:la source
Fondamentalement, vous devez créer dynamiquement les règles makefile pour reconstruire les fichiers objets lorsque les fichiers d'en-tête changent. Si vous utilisez gcc et gnumake, c'est assez simple; il suffit de mettre quelque chose comme:
dans votre makefile.
la source
Au-delà de ce que @mipadi a dit, vous pouvez également explorer l'utilisation du '
-M
option ' pour générer un enregistrement des dépendances. Vous pouvez même les générer dans un fichier séparé (peut-être 'depend.mk') que vous incluez ensuite dans le makefile. Ou vous pouvez trouver unemake depend
règle ' ' qui édite le fichier makefile avec les dépendances correctes (termes Google: "ne pas supprimer cette ligne" et dépendre).la source
Aucune des réponses n'a fonctionné pour moi. Par exemple, la réponse de Martin Fido suggère que gcc peut créer un fichier de dépendances, mais quand j'ai essayé de générer des fichiers objets vides (zéro octet) pour moi sans aucun avertissement ni erreur. Cela pourrait être un bogue gcc. Je suis sur
Voici donc mon Makefile complet qui fonctionne pour moi; c'est une combinaison de solutions + quelque chose qui n'a été mentionné par personne d'autre (par exemple "règle de remplacement de suffixe" spécifiée comme .cc.o :):
Remarquez que j'ai utilisé .cc .. Le Makefile ci-dessus est facile à ajuster pour les fichiers .c.
Notez également l'importance de ces deux lignes:
donc gcc est appelé une fois pour construire d'abord un fichier de dépendance, puis compile en fait un fichier .cc. Et ainsi de suite pour chaque fichier source.
la source
Solution plus simple: utilisez simplement le Makefile pour que la règle de compilation .c à .o dépende du ou des fichiers d'en-tête et de tout ce qui est pertinent dans votre projet en tant que dépendance.
Par exemple, dans le Makefile quelque part:
la source
Je crois que la
mkdep
commande est ce que vous voulez. Il scanne en fait les fichiers .c pour les#include
lignes et crée une arborescence de dépendances pour eux. Je pense que les projets Automake / Autoconf l'utilisent par défaut.la source