Jak utworzyć prosty plik makefile dla gcc w systemie Linux?

132

Mam trzy pliki: program.c, program.hi headers.h.

program.czawiera program.hi headers.h.

Muszę to skompilować w systemie Linux przy użyciu kompilatora gcc . Nie wiem, jak to zrobić. Netbeans stworzył jeden dla mnie, ale jest pusty.

user69514
źródło
1
Istnieje niezwykle eleganckie (i dobrze udokumentowane) rozwiązanie na spin.atomicobject.com/2016/08/26/makefile-c-projects .
Casey

Odpowiedzi:

196

Co ciekawe, nie wiedziałem, że make domyślnie użyje kompilatora C na podstawie reguł dotyczących plików źródłowych.

W każdym razie prostym rozwiązaniem, które demonstruje proste koncepcje Makefile, byłoby:

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

(pamiętaj, że make wymaga tabulatora zamiast wcięcia spacji, więc pamiętaj o poprawieniu tego podczas kopiowania)

Jednak aby obsługiwać więcej plików C, musiałbyś stworzyć nowe reguły dla każdego z nich. Tak więc, aby ulepszyć:

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

Starałem się to maksymalnie uprościć, pomijając zmienne, takie jak $ (CC) i $ (CFLAGS), które są zwykle widoczne w plikach makefile. Jeśli chcesz się tego dowiedzieć, mam nadzieję, że dałem ci dobry początek.

Oto plik Makefile, którego lubię używać dla źródeł C. Zapraszam do korzystania:

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)

Używa symboli wieloznacznych i funkcji patsubst narzędzia make do automatycznego dołączania plików .c i .h do bieżącego katalogu, co oznacza, że ​​kiedy dodasz nowe pliki kodu do swojego katalogu, nie będziesz musiał aktualizować pliku Makefile. Jeśli jednak chcesz zmienić nazwę wygenerowanego pliku wykonywalnego, bibliotek lub flag kompilatora, możesz po prostu zmodyfikować zmienne.

W obu przypadkach nie używaj autoconf. Błagam Cię! :)

Joey Adams
źródło
7
Aby być poprawnym technicznie, uważam, że powinieneś używać .PHONY: clean all defaulttych celów, które mają być używane z wiersza poleceń. Ponadto Autoconf / Automake nie jest taki zły. Jasne, czują się okropnie, a przyzwyczajenie się do nich jest tak samo zabawne, jak przebijanie głowy przez ceglaną ścianę, ale działają i są dobrze rozwinięte i obejmują większość twoich baz, jeśli chodzi o przenośność, i w końcu znacznie ułatwi ci życie, gdy przyzwyczaisz się do ich okropnego projektu.
Chris Lutz,
Myślę, że to działa, ale pomyślałem, że jeśli napiszę "make" na terminalu, program powinien się uruchomić. Oto co otrzymuję: gcc statsh.o -Wall -lm -o prog Czy można po prostu wpisać make i uruchomić program?
user69514
gdzie dodałbyś flagę openmp -fopenmp
MySchizoBuddy
1
Dlaczego nie używać autoconf joey-adams?
Michał Gonda
7
Jeśli ktoś się zastanawia, po co są kreski przed rm: stackoverflow.com/questions/2989465/rm-rf-versus-rm-rf
Tor Klingberg
25

Na przykład ten prosty plik Makefile powinien wystarczyć:

CC = gcc 
CFLAGS = -Wall

all: program
program: program.o
program.o: program.c program.h nagłówki.h

czysty:
    rm -f program program.o
Uruchom program
    ./program

Zauważ, że <tab>po wyczyszczeniu i uruchomieniu musi znajdować się w następnym wierszu, a nie spacje.

UPDATE Zastosowano poniższe komentarze

Viliam
źródło
@ user69514: makebez argumentów zwykle buduj tylko swoje oprogramowanie. Aby go uruchomić, użyj make run(dostępne w tej odpowiedzi, ale niekoniecznie we wszystkich Makefiles) lub uruchom bezpośrednio:./program
MestreLion
14
all: program
program.o: program.h headers.h

wystarczy. reszta jest domniemana

anonimowy
źródło
1
A jeśli cały program to pojedynczy .cplik, tylko program:jest potrzebny. Słodko :)
MestreLion
Chociaż jest to z pewnością proste, bez wątpienia, anonimowe i @MestreLion, jestem nowy w C i dopiero niedawno podzieliłem duży projekt na 2 pliki źródłowe i nagłówek, i nie używam plików makefile, ale raczej bardzo prostego programu w C, który w zasadzie tylko używa system()od stdlib.h... Żadnych wad tego podejścia, prawda?
AP Jo
@APJo: dzięki prostym projektom możesz uciec bez Makefilei po prostu bezpośrednio wywołać gcc *.c *.h -o program, prawdopodobnie dodając opcje takie jak -Wall -O2itp.
MestreLion
10

Najprostszym plikiem make może być

all : test

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

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

clean :
        rm test *.o
Indrakumar
źródło
możesz dodać więcej szczegółów, aby wyjaśnić, co robi twój plik Makefile
Federico
2
faktycznie możesz pójść o wiele prościej. zobacz @anonymous 1 liner
Mark Lakata
0

W zależności od liczby nagłówków i nawyków programistycznych możesz chcieć zbadać gccmakedep. Ten program sprawdza twój bieżący katalog i dodaje na końcu makefile zależności nagłówkowe dla każdego pliku .c / cpp. Jest to przesada, gdy masz 2 nagłówki i jeden plik programu. Jeśli jednak masz ponad 5 małych programów testowych i edytujesz jeden z 10 nagłówków, możesz zaufać firmie make, że odbuduje dokładnie te programy, które zostały zmienione przez Twoje modyfikacje.


źródło