Ich habe das folgende Makefile, mit dem ich ein Programm (eigentlich einen Kernel) erstelle, an dem ich arbeite. Es ist von Grund auf neu und ich lerne etwas über den Prozess, daher ist es nicht perfekt, aber ich denke, es ist zu diesem Zeitpunkt mächtig genug für meine Erfahrung beim Schreiben von 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
Mein Hauptproblem bei diesem Makefile ist, dass beim Ändern einer Header-Datei, die eine oder mehrere C-Dateien enthält, die C-Dateien nicht neu erstellt werden. Ich kann dies ganz einfach beheben, indem alle meine Header-Dateien Abhängigkeiten für alle meine C-Dateien darstellen. Dies würde jedoch jedes Mal, wenn ich eine Header-Datei ändere / hinzufüge, zu einer vollständigen Neuerstellung des Projekts führen, was nicht sehr elegant wäre.
Ich möchte, dass nur die C-Dateien, die die von mir geänderte Header-Datei enthalten, neu erstellt und das gesamte Projekt erneut verknüpft werden. Ich kann die Verknüpfung durchführen, indem alle Header-Dateien Abhängigkeiten vom Ziel darstellen, aber ich kann nicht herausfinden, wie die C-Dateien ungültig werden, wenn ihre enthaltenen Header-Dateien neuer sind.
Ich habe gehört, dass GCC einige Befehle hat, um dies zu ermöglichen (damit das Makefile irgendwie herausfinden kann, welche Dateien neu erstellt werden müssen), aber ich kann für mein ganzes Leben kein tatsächliches Implementierungsbeispiel finden, das ich mir ansehen kann. Kann jemand eine Lösung veröffentlichen, die dieses Verhalten in einem Makefile ermöglicht?
EDIT: Ich sollte klarstellen, ich bin mit dem Konzept vertraut, die einzelnen Ziele einzufügen und jedes Ziel zu haben. Um die Header-Dateien zu benötigen. Das erfordert, dass ich das Makefile jedes Mal bearbeite, wenn ich irgendwo eine Header-Datei einbinde, was ein bisschen mühsam ist. Ich suche nach einer Lösung, die die Abhängigkeiten der Header-Dateien selbst ableiten kann. Ich bin mir ziemlich sicher, dass ich sie in anderen Projekten gesehen habe.
quelle
Sie können einen 'make abhängigen' Befehl hinzufügen, wie andere angegeben haben, aber warum nicht gcc dazu bringen, Abhängigkeiten zu erstellen und gleichzeitig zu kompilieren:
Der Parameter '-MF' gibt eine Datei an, in der die Abhängigkeiten gespeichert werden sollen.
Der Bindestrich am Anfang von '-include' weist Make an, fortzufahren, wenn die .d-Datei nicht vorhanden ist (z. B. bei der ersten Kompilierung).
Beachten Sie, dass es in gcc einen Fehler bezüglich der Option -o zu geben scheint. Wenn Sie den Objektdateinamen auf "setzen" setzen, enthält
obj/_file__c.o
der generierte_file_.d
weiterhin "_file_.o
Nicht"obj/_file_c.o
.quelle
g++ -c -Wall -Werror -MM -MF main.d -o main.o main.cpp
hat Folgendes generiert und ausgeführt: Ich habe die Datei main.d erhalten, aber main.o war 0 Byte. Das -MMD-Flag scheint jedoch genau das zu tun, was erforderlich war. So wurde meine Arbeits-Makefile-Regel:$(CC) -c $(CFLAGS) -MMD -o $@ $<
Dies entspricht der Antwort von Chris Dodd , verwendet jedoch eine andere Namenskonvention (und erfordert zufällig keine
sed
Magie. Von einem späteren Duplikat kopiert .Wenn Sie einen GNU-Compiler verwenden, kann der Compiler eine Liste von Abhängigkeiten für Sie zusammenstellen. Makefile-Fragment:
Es gibt auch das Tool
makedepend
, aber es hat mir nie so gut gefallen wiegcc -MM
quelle
SRCS
undOBJS
. Ich würde die meiste Zeit zustimmen, aber jeder sollte wissen, was das sind.Sie müssen für jede C-Datei individuelle Ziele festlegen und dann die Header-Datei als Abhängigkeit auflisten. Sie können weiterhin Ihre generischen Ziele verwenden und anschließend die
.h
Abhängigkeiten wie folgt platzieren:quelle
Grundsätzlich müssen Sie die Makefile-Regeln dynamisch erstellen, um die Objektdateien neu zu erstellen, wenn sich die Header-Dateien ändern. Wenn Sie gcc und gnumake verwenden, ist dies ziemlich einfach. Setzen Sie einfach so etwas wie:
in deinem Makefile.
quelle
Über das hinaus, was @mipadi gesagt hat, können Sie auch die Verwendung der
-M
Option ' ' untersuchen, um einen Datensatz der Abhängigkeiten zu generieren. Sie können diese sogar in einer separaten Datei (möglicherweise 'abhängige.mk') generieren, die Sie dann in das Makefile aufnehmen. Oder Sie finden eine 'make depend
' Regel, die das Makefile mit den richtigen Abhängigkeiten bearbeitet (Google-Begriffe: "Diese Zeile nicht entfernen" und abhängig).quelle
Keine der Antworten hat bei mir funktioniert. Zum Beispiel schlägt die Antwort von Martin Fido vor, dass gcc eine Abhängigkeitsdatei erstellen kann, aber als ich versuchte, leere Objektdateien (null Bytes) für mich ohne Warnungen oder Fehler zu generieren. Es könnte ein gcc-Fehler sein. ich bin on
Hier ist mein komplettes Makefile, das für mich funktioniert. Es ist eine Kombination aus Lösungen + etwas, das von niemand anderem erwähnt wurde (z. B. "Suffix-Ersetzungsregel", angegeben als .cc.o :):
Beachten Sie, dass ich .cc verwendet habe. Das obige Makefile kann einfach für .c-Dateien angepasst werden.
Es ist auch wichtig, die Bedeutung dieser beiden Zeilen zu beachten:
Daher wird gcc einmal aufgerufen, um zuerst eine Abhängigkeitsdatei zu erstellen und dann tatsächlich eine .cc-Datei zu kompilieren. Und so weiter für jede Quelldatei.
quelle
Einfachere Lösung: Verwenden Sie einfach das Makefile, damit die Kompilierungsregel .c to .o von den Header-Dateien und allen anderen in Ihrem Projekt relevanten Abhängigkeiten abhängig ist.
ZB irgendwo im Makefile:
quelle
Ich glaube, der
mkdep
Befehl ist das, was Sie wollen. Es durchsucht tatsächlich .c-Dateien nach#include
Zeilen und erstellt einen Abhängigkeitsbaum für diese. Ich glaube, dass Automake / Autoconf-Projekte dies standardmäßig verwenden.quelle