Wie erstelle ich ein einfaches Makefile für gcc unter Linux?

130

Ich habe drei Dateien: program.c, program.hund headers.h.

program.cbeinhaltet program.hund headers.h.

Ich muss dies unter Linux mit dem gcc- Compiler kompilieren. Ich bin mir nicht sicher, wie ich das machen soll. Netbeans hat eine für mich erstellt, aber sie ist leer.

user69514
quelle
1
Unter spin.atomicobject.com/2016/08/26/makefile-c-projects gibt es eine äußerst elegante (und gut dokumentierte) Lösung .
Casey

Antworten:

192

Interessanterweise wusste ich nicht, dass make standardmäßig den C-Compiler verwenden würde, wenn Regeln für Quelldateien festgelegt wurden.

Eine einfache Lösung, die einfache Makefile-Konzepte demonstriert, wäre:

HEADERS = program.h headers.h

default: program

program.o: program.c $(HEADERS)
    gcc -c program.c -o program.o

program: program.o
    gcc program.o -o program

clean:
    -rm -f program.o
    -rm -f program

(Denken Sie daran, dass make eine Registerkarte anstelle einer Leerzeicheneinrückung erfordert. Korrigieren Sie dies daher beim Kopieren.)

Um jedoch mehr C-Dateien zu unterstützen, müssten Sie für jede neue Regeln erstellen. So verbessern:

HEADERS = program.h headers.h
OBJECTS = program.o

default: program

%.o: %.c $(HEADERS)
    gcc -c $< -o $@

program: $(OBJECTS)
    gcc $(OBJECTS) -o $@

clean:
    -rm -f $(OBJECTS)
    -rm -f program

Ich habe versucht, dies so einfach wie möglich zu gestalten, indem ich Variablen wie $ (CC) und $ (CFLAGS) weggelassen habe, die normalerweise in Makefiles angezeigt werden. Wenn Sie daran interessiert sind, das herauszufinden, hoffe ich, dass ich Ihnen einen guten Start gegeben habe.

Hier ist das Makefile, das ich gerne für die C-Quelle verwende. Fühlen Sie sich frei, es zu benutzen:

TARGET = prog
LIBS = -lm
CC = gcc
CFLAGS = -g -Wall

.PHONY: default all clean

default: $(TARGET)
all: default

OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
HEADERS = $(wildcard *.h)

%.o: %.c $(HEADERS)
    $(CC) $(CFLAGS) -c $< -o $@

.PRECIOUS: $(TARGET) $(OBJECTS)

$(TARGET): $(OBJECTS)
    $(CC) $(OBJECTS) -Wall $(LIBS) -o $@

clean:
    -rm -f *.o
    -rm -f $(TARGET)

Es verwendet die Platzhalter- und Patsubst-Funktionen des Dienstprogramms make, um automatisch .c- und .h-Dateien in das aktuelle Verzeichnis aufzunehmen. Wenn Sie also neue Codedateien zu Ihrem Verzeichnis hinzufügen, müssen Sie das Makefile nicht aktualisieren. Wenn Sie jedoch den Namen der generierten ausführbaren Datei, Bibliotheken oder Compiler-Flags ändern möchten, können Sie einfach die Variablen ändern.

Verwenden Sie in beiden Fällen bitte keine automatische Konfiguration. Ich flehe dich an! :) :)

Joey Adams
quelle
7
Um technisch korrekt zu sein, sollten Sie meiner Meinung .PHONY: clean all defaultnach Ziele verwenden, die über die Befehlszeile verwendet werden sollen. Auch Autoconf / Automake sind nicht so schlecht. Sicher, sie fühlen sich schrecklich an und es macht ungefähr so ​​viel Spaß, sich an sie zu gewöhnen, als würde man den Kopf durch eine Mauer zwingen, aber sie funktionieren, sind gut entwickelt und decken die meisten Ihrer Basen ab, was die Portabilität betrifft. und wird Ihr Leben am Ende viel einfacher machen, wenn Sie sich an ihr schreckliches Design gewöhnt haben.
Chris Lutz
Ich denke, das funktioniert, aber ich dachte, wenn ich auf dem Terminal "make" tippe, sollte das Programm ausgeführt werden. Folgendes bekomme ich: gcc statsh.o -Wall -lm -o prog Ist es möglich, einfach make einzugeben und das Programm auszuführen?
user69514
Wo würden Sie das OpenMP-Flag -fopenmp
MySchizoBuddy
1
Warum nicht autoconf joey-adams verwenden?
Michal Gonda
7
Wenn sich jemand wundert, warum es Bindestriche gibt vor rm: stackoverflow.com/questions/2989465/rm-rf-versus-rm-rf
Tor Klingberg
25

Zum Beispiel sollte dieses einfache Makefile ausreichen:

CC = gcc 
CFLAGS = -Wall

alle: Programm
Programm: program.o
program.o: program.c program.h headers.h

reinigen:
    rm -f program program.o
run: program
    ./Programm

Beachten Sie, dass <tab>nach dem Reinigen und Ausführen in der nächsten Zeile Leerzeichen stehen müssen.

UPDATE Kommentare unten angewendet

Viliam
quelle
@ user69514: makeOhne Argumente erstellen Sie normalerweise nur Ihre Software. Um es auszuführen, verwenden Sie entweder make run(in dieser Antwort verfügbar, aber nicht unbedingt in allen Makefiles) oder führen Sie es direkt aus:./program
MestreLion
14
all: program
program.o: program.h headers.h

reicht. der Rest ist implizit

anonym
quelle
1
Und wenn Ihr gesamtes Programm eine einzelne .cDatei ist, ist nur program:erforderlich. Süß :)
MestreLion
10

Die einfachste make-Datei kann sein

all : test

test : test.o
        gcc -o test test.o 

test.o : test.c
        gcc -c test.c

clean :
        rm test *.o
Indrakumar
quelle
Sie können weitere Details hinzufügen, um zu erklären, was Ihr Makefile tut
Federico
2
Sie können tatsächlich viel einfacher gehen. siehe @anonymous 1 Liner
Mark Lakata
0

Abhängig von der Anzahl der Header und Ihren Entwicklungsgewohnheiten möchten Sie möglicherweise gccmakedep untersuchen. Dieses Programm überprüft Ihr aktuelles Verzeichnis und fügt am Ende des Makefiles die Header-Abhängigkeiten für jede .c / cpp-Datei hinzu. Dies ist übertrieben, wenn Sie 2 Header und eine Programmdatei haben. Wenn Sie jedoch mehr als 5 kleine Testprogramme haben und einen von 10 Headern bearbeiten, können Sie make vertrauen, um genau die Programme neu zu erstellen, die durch Ihre Änderungen geändert wurden.


quelle