346 votes

Comment créer un Makefile C++ SIMPLE

Nous sommes tenus d'utiliser un Makefile pour rassembler tous les éléments de notre projet, mais notre professeur ne nous a jamais montré comment faire.

Je n'ai que un fichier, a3driver.cpp . Le conducteur importe une classe à partir d'un emplacement, "/user/cse232/Examples/example32.sequence.cpp" .

C'est tout. Tout le reste est contenu dans le .cpp .

Comment faire pour créer un Makefile simple qui crée un exécutable appelé a3a.exe ?

14 votes

.EXE, il s'agit donc bien de Windows. En y réfléchissant bien, le chemin d'accès est de type Unix. Il utilise probablement Mingw-32.

3 votes

Soupir. Je suppose qu'il faut apprendre les bases de chaque métier, même si on ne les utilisera jamais. Il faut juste comprendre comment les choses fonctionnent. Il y a de bonnes chances que vous développiez toujours dans un IDE, comme Eclipse. Vous obtiendrez une réponse ici pour votre cas simple d'une ligne et il y a beaucoup de tutoriels sur le web, mais si vous voulez des connaissances approfondies, vous ne pouvez pas battre le livre d'O'reilly (même chose pour la plupart des sujets s/w). amazon.com/Managing-Projects-Make-Nutshell-Handbooks/dp/ Choisissez un exemplaire d'occasion sur amazon, half.com, betterworldbooks eBay

3 votes

Le lien posté par @Dennis est maintenant mort, mais le même matériel peut être trouvé dans ceci archive.org page .

8voto

John Knoeller Points 20754

Votre fichier Make aura une ou deux règles de dépendance selon que vous compilez et liez avec une seule commande, ou avec une commande pour la compilation et une autre pour la liaison.

Les dépendances sont un arbre de règles qui ressemble à ceci (notez que l'indentation doit soit un TAB) :

main_target : source1 source2 etc
    command to build main_target from sources

source1 : dependents for source1
    command to build source1

Il y a doit une ligne vierge après les commandes d'une cible, et il doit y avoir une ligne vierge après les commandes d'une cible. no une ligne vierge avant les commandes. La première cible du fichier makefile est l'objectif global, et les autres cibles ne sont construites que si la première cible en dépend.

Ainsi, votre fichier makefile ressemblera à quelque chose comme ceci.

a3a.exe : a3driver.obj 
    link /out:a3a.exe a3driver.obj

a3driver.obj : a3driver.cpp
    cc a3driver.cpp

8voto

Jezz Points 92

Je propose (notez que l'indentation est un TAB) :

tool: tool.o file1.o file2.o
    $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@

ou

LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH)
tool: tool.o file1.o file2.o

Cette dernière suggestion est légèrement meilleure puisqu'elle réutilise les règles implicites de GNU Make. Cependant, pour fonctionner, un fichier source doit avoir le même nom que l'exécutable final (c'est-à-dire : tool.c y tool ).

Attention, il n'est pas nécessaire de déclarer les sources. Les fichiers d'objets intermédiaires sont générés en utilisant la règle implicite. Par conséquent, cette Makefile fonctionnent pour C et C++ (et aussi pour Fortran, etc...).

Notez également que, par défaut, Makefile utilise $(CC) en tant qu'éditeur de liens. $(CC) ne fonctionne pas pour lier des fichiers objets C++. Nous modifions LINK.o uniquement pour cette raison. Si vous voulez compiler du code C, vous n'avez pas besoin de forcer le programme LINK.o valeur.

Bien sûr, vous pouvez aussi ajouter vos drapeaux de compilation avec la variable CFLAGS et ajoutez vos bibliothèques dans LDLIBS . Par exemple :

CFLAGS = -Wall
LDLIBS = -lm

Une remarque : si vous devez utiliser des bibliothèques externes, je vous suggère de utiliser pkg-config afin de définir correctement CFLAGS y LDLIBS :

CFLAGS += $(shell pkg-config --cflags libssl)
LDLIBS += $(shell pkg-config --libs libssl)

Le lecteur attentif remarquera que cette Makefile ne se reconstruit pas correctement si un en-tête est modifié. Ajoutez ces lignes pour résoudre le problème :

override CPPFLAGS += -MMD
include $(wildcard *.d)

-MMD permet de construire des fichiers .d qui contiennent des fragments de Makefile sur les dépendances des en-têtes. La deuxième ligne les utilise simplement.

Il est certain qu'un Makefile bien écrit devrait également inclure clean y distclean règles :

clean:
    $(RM) *.o *.d

distclean: clean
    $(RM) tool

Avis, $(RM) est l'équivalent de rm -f mais il est préférable de ne pas appeler rm directement.

En all est également appréciée. Pour fonctionner, elle doit être la première règle de votre fichier :

all: tool

Vous pouvez également ajouter un install règle :

PREFIX = /usr/local
install:
    install -m 755 tool $(DESTDIR)$(PREFIX)/bin

DESTDIR est vide par défaut. L'utilisateur peut la définir pour installer son programme sur un autre système (obligatoire pour le processus de compilation croisée). Les responsables de paquets pour des distributions multiples peuvent également modifier PREFIX afin d'installer votre paquet dans /usr .

Un dernier mot : Ne placez pas les fichiers sources dans des sous-répertoires. Si vous voulez vraiment le faire, gardez ceci Makefile dans le répertoire racine et utilisez les chemins complets pour identifier vos fichiers (c'est-à-dire subdir/file.o ).

En résumé, votre Makefile complet devrait ressembler à ceci :

LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH)
PREFIX = /usr/local
override CPPFLAGS += -MMD
include $(wildcard *.d)

all: tool
tool: tool.o file1.o file2.o
clean:
    $(RM) *.o *.d
distclean: clean
    $(RM) tool
install:
    install -m 755 tool $(DESTDIR)$(PREFIX)/bin

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X