Comment créer un fichier makefile simple pour gcc sous Linux?

130

J'ai trois fichiers: program.c, program.het headers.h.

program.ccomprend program.het headers.h.

J'ai besoin de compiler ceci sur Linux en utilisant le compilateur gcc . Je ne sais pas comment faire ça. Netbeans en a créé un pour moi, mais il est vide.

user69514
la source
1
Il existe une solution extrêmement élégante (et bien documentée) sur spin.atomicobject.com/2016/08/26/makefile-c-projects .
Casey

Réponses:

193

Intéressant, je ne savais pas que make utiliserait par défaut le compilateur C étant donné les règles concernant les fichiers source.

Quoi qu'il en soit, une solution simple qui démontre des concepts simples de Makefile serait:

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

(gardez à l'esprit que make nécessite une tabulation au lieu d'une indentation d'espace, alors assurez-vous de corriger cela lors de la copie)

Cependant, pour prendre en charge plus de fichiers C, vous devrez créer de nouvelles règles pour chacun d'entre eux. Ainsi, pour améliorer:

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

J'ai essayé de rendre cela aussi simple que possible en omettant des variables comme $ (CC) et $ (CFLAGS) qui sont généralement vues dans les makefiles. Si cela vous intéresse, j'espère que je vous ai donné un bon départ.

Voici le Makefile que j'aime utiliser pour la source C. Sentez-vous libre de l'utiliser:

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)

Il utilise les fonctionnalités joker et patsubst de l'utilitaire make pour inclure automatiquement les fichiers .c et .h dans le répertoire actuel, ce qui signifie que lorsque vous ajoutez de nouveaux fichiers de code à votre répertoire, vous n'aurez pas à mettre à jour le Makefile. Cependant, si vous souhaitez modifier le nom de l'exécutable, des bibliothèques ou des indicateurs de compilateur générés, vous pouvez simplement modifier les variables.

Dans les deux cas, n'utilisez pas autoconf, s'il vous plaît. Je t'en supplie! :)

Joey Adams
la source
7
Pour être techniquement correct, je pense que vous devriez utiliser .PHONY: clean all defaultpour les cibles qui sont destinées à être utilisées à partir de la ligne de commande. De plus, Autoconf / Automake ne sont pas si mauvais. Bien sûr, ils se sentent horribles, et s'y habituer est à peu près aussi amusant que de se forcer la tête à travers un mur de briques, mais ils fonctionnent, et ils sont bien développés, et ils couvriront la plupart de vos bases en ce qui concerne la portabilité, et vous rendra la vie beaucoup plus facile à la fin une fois que vous vous serez habitué à leur conception horrible.
Chris Lutz
Je suppose que cela fonctionne, mais j'ai pensé que si je tapais "make" sur le terminal, le programme devrait fonctionner. Voici ce que j'obtiens: gcc statsh.o -Wall -lm -o prog Est-il possible de simplement taper make et exécuter le programme?
user69514
où ajouteriez-vous le drapeau openmp -fopenmp
MySchizoBuddy
1
Pourquoi ne pas utiliser autoconf joey-adams?
Michal Gonda
7
Si quelqu'un se demande pourquoi il y a des tirets devant rm: stackoverflow.com/questions/2989465/rm-rf-versus-rm-rf
Tor Klingberg
25

Par exemple, ce simple Makefile devrait suffire:

CC = gcc 
CFLAGS = -Mur

tout: programme
programme: programme.o
programme.o: programme.c programme.h en-têtes.h

nettoyer:
    rm -f programme programme.o
exécuter de programme
    ./programme

Notez qu'il doit y avoir <tab>sur la ligne suivante après nettoyage et exécution, pas d'espaces.

MISE À JOUR Les commentaires ci-dessous ont été appliqués

Viliam
la source
@ user69514: makesans argument, construisez uniquement votre logiciel. Pour l'exécuter, utilisez make run(disponible dans cette réponse, mais pas nécessairement dans tous les Makefiles), ou exécutez-le directement:./program
MestreLion
14
all: program
program.o: program.h headers.h

est assez. le reste est implicite

anonyme
la source
1
Et si votre programme entier est un seul .cfichier, seul program:est nécessaire. Sweet :)
MestreLion
10

Le fichier de création le plus simple peut être

all : test

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

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

clean :
        rm test *.o
Indrakumar
la source
vous pouvez ajouter plus de détails pour expliquer ce que fait votre Makefile
Federico
2
vous pouvez en fait faire beaucoup plus simple. voir @anonymous 1 liner
Mark Lakata
0

En fonction du nombre d'en-têtes et de vos habitudes de développement, vous voudrez peut-être étudier gccmakedep. Ce programme examine votre répertoire actuel et ajoute à la fin du makefile les dépendances d'en-tête pour chaque fichier .c / cpp. C'est exagéré lorsque vous avez 2 en-têtes et un fichier programme. Cependant, si vous avez plus de 5 petits programmes de test et que vous modifiez l'un des 10 en-têtes, vous pouvez alors faire confiance à make pour reconstruire exactement les programmes qui ont été modifiés par vos modifications.


la source