Comment faire un makefile qui compile tous les .cpp

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjours à tous,

je suis en ce moment en train de coder une lib de math pour appliquer mes connaissances sur le langage c++ mais j'ai un problème avec make, j'ai choisi de coder mes fonctions dans des fichiers séparés mais de toutes les indexer dans le fichier math.h, voici à quoi ressemble un ls dans mon dossier

1
2
3
# ludovic at Tardis in ~workspace/C++/math on git:master x [19:29:54]
$ ls
abs.cpp  main.cpp  main.o  Makefile  #Makefile#  math.h  pow.cpp  sqrt.cpp

je compile depuis peu avec make donc je ne sais pas comment faire pour que ma règle all demande à ce que tous les .cpp soit compilés en .o, voici malgré tous mon Makefile actuel

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
.PHONY: clean, mrproper
.SUFFIXES:

CXX = g++
CXXFLAGS = -std=c++14 -W -Wall -Wextra
EXEC = executable
DEBUG = no

ifeq ($(DEBUG),yes)
    CXXFLAGS += -g
endif

all: main.o 
    $(CXX) $(CXXFLAGS) $^ -o $(EXEC)

main.cpp: math.h

%.o: %.cpp
    $(CXX) $(CXXFLAGS) -c $< -o $@

clean:
    rm *.o

mrproper: clean
    rm $(EXEC)

je pense qu'il y a un jocker mais % et * ne marche pas, sinon je suppose qu'il faut écrire un script qui récupère tous les .cpp présents mais j'espère qu'il y a une solution plus simple :)

j'espère que vous pourrez répondre à ma question et vous remercie d'avance de vos réponces

« La Nature est un livre écrit en langage mathématique », Galilée

+0 -0

Il ne faut pas seulement que all dépende de main.o, mais aussi de tous les autres fichiers relogeables (et de préférence les fichiers d'en-tête).

Puis si tu pars sur la compilation d'une bibliothèque, il faudra que ton programme de test dépende de la lib, et que la lib dépende des .o.

Davidbrcz, je suis pas d'accord avec toi. Ce que tu dis est vrai dans le cadre d'un projet d'une certaine taille, mais franchement pour un petit projet aucune raison de ne pas faire un Makefile. Il ne faudrait pas faire dans l'overkill. Pour un gros projet je sortirais CMake mais pour un petit projet c'est vraiment overkill, un petit Makefile et hop fini.

OP, en plus de main.o il faut ajouter tous les autres .o comme dépendances de la règle all comme dit entwanne.

Je crois aussi que tu peux utiliser l'option -MMD de gcc pour gérer les dépendances mais je peux pas t'aider vu que j'ai jamais fait ça.

Voilà une piste.

Édité par anonyme

+3 -2

Davidbrcz, je suis pas d'accord avec toi. Ce que tu dis est vrai dans le cadre d'un projet d'une certaine taille, mais franchement pour un petit projet aucune raison de ne pas faire un Makefile. Il ne faudrait pas faire dans l'overkill. Pour un gros projet je sortirais CMake mais pour un petit projet c'est vraiment overkill, un petit Makefile et hop fini.

OP, en plus de main.o il faut ajouter tous les autres .o comme dépendances de la règle all comme dit entwanne.

Je crois aussi que tu peux utiliser l'option -MMD de gcc pour gérer les dépendances mais je peux pas t'aider vu que j'ai jamais fait ça.

Voilà une piste.

Grimur

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ ls                                           [21:33:51]
a.cpp  b.cpp  SConstruct
$ cat SConstruct
Program('program', Glob('*.cpp'))
$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o a.o -c a.cpp
g++ -o b.o -c b.cpp
g++ -o program a.o b.o
scons: done building targets.

Tu veux plus d'arguments ?

+3 -1

Oui, c'est vrai que c'est concis, bien plus que le Makefile dans ce cas. Cet argument ne me suffit pas, il faudrait que je regarde la configuration de SCons.

Quand je fais du C typiquement je reprends le dernier Makefile que j'ai écrit, il y a souvent très peu de choses à modifier sur mes projets. J'apprécie aussi le fait que make soit déjà installé, ça ne fait pas une dépendance d'exécution.

Je peux complètement comprendre que tu n'aies pas envie d'utiliser make, c'est parfaitement ton droit et c'est ton choix. Pour un microprojet je ne sortirai jamais l'artillerie lourde, c'est aussi mon droit.

(Sinon si vous moinssez mon message plus haut expliquez-moi au moins pourquoi, sinon ça ne fait pas avancer le schmilblick)

+2 -3
Staff

Salut,

De manière générale, pour ma part, je te conseil de rester simple si tu souhaites utiliser des Makefile et de te cantonner aux fonctionnalités décrites par la norme POSIX. Cela t'évitera de mauvaise surprises si tu changes de version (notamment GNU vers *BSD ou vice-versa) et de te prendre la tête avec des fonctions et/ou variables obscures.

Du coup, oui, il te faut écrire tes noms de fichiers objets, qui plus est deux fois, si tu souhaites un fichier Makefile fonctionnel.

1
2
all: abs.o pow.o sqrt.o main.o
    $(CC) $(LDFLAGS) abs.o pow.o sqrt.o main.o -o x

Maintenant, si tu souhaites quelques chose de plus automatique, il y a des programmes qui font très bien cela comme l'a précisé Davidbrcz, mais tu peux aussi faire de même à l'aide d'un préprocesseur comme m4 ou avec un petit script. ;)

+0 -0

La configuration est simple, c'est du python derrière (pour Sconcs). Cmake est plus verbeux mais toujours moins cryptique que Make + autotools… Cmake (et dans une moindre mesure Scons) sont des standards quasi de facto pour le C++ donc c'est rarement une dépendance supplémentaire. Et puis bon, apt/dnf install et c'est réglé. Alors, qualifier ça d'artillerie lourde, ca me fait doucement rire.

Tu parles de réutiliser des makefiles. Déjà on en a pas tous sous la main et faire un truc basique n'est pas simple (la preuve par ce topic même). Les outils sont faits pour t'aider, si tu bloques sur un truc basique, c'est qu'il est temps de changer d'outil.

Les outils que je propose sont plus expressifs, plus versatils et concis que make. Pourquoi se faire chier à faire les Makefile à la main ? Dans le même genre, pourquoi écrire des fonctions, des boucles et des if au lieu et place de goto ? Vu qu'en dessous c'est la même chose

mais tu peux aussi faire de même à l'aide d'un préprocesseur comme m4 ou avec un petit script.

Non, non et non. C'est tout le but des outils que je cite. Pourquoi refaire des choses à la main alors qu'il existe des outils faits pour ca ?

Édité par Davidbrcz

+3 -0

Make est un outil super versatile. J'ai des Makefiles pour automatiser pas mal de choses: génération de PDF avec LaTeX, root de mon téléphone, sauvegarde et restauration de ma liste de paquets installés pour pouvoir réinstaller mon environnement super rapidement entre autres. Je l'ai appris une fois et réutilisé plein de fois.

J'ai choisi d'utiliser Make parce que je peux l'utiliser dans plusieurs cas. De plus, il se trouve que pour de petits projets ça me suffit parfaitement, je code mes dépendances en dur dans le Makefile. Je trouve ça minimaliste au sens où je n'ai pas de dépendances externes à SCons pour pouvoir compiler et au sens où je te fais un Makefile en 1 minute top chrono pour un petit projet. Compare la taille installée de CMake à celle du projet une fois compilé. C'est énorme la différence.

Si tu n'as pas envie d'utiliser Make, c'est ton droit comme je te l'ai déjà dit.

Tu ne peux pas dire que plus personne n'utilise Make parce que c'est tout simplement faux. Make n'est pas un outil du passé, c'est un outil qui a sa place et qui se prête bien à certains usages. Si Taurre, l'OP ou moi et plein d'autres utilisons Make, c'est clairement que Make n'est pas mort. Pour être franc, je connais moins de projets qui utilisent des gros systèmes de build que de projets qui ont un Makefile.

Ensuite, quand je réponds à l'OP et que je dis que je trouve SCons overkill pour ça, tu me réponds en me balançant l'exemple d'utilisation de SCons, certes attrayant, mais tu passes à côté de l'argument principal. Vu comme tu le présentes, SCons c'est royal, c'est suprt simple. Sauf que c'est un paquet de plus à installer et je ne suis pas sûr de comprendre pourquoi utiliser des systèmes de build super puissants et démesurés par rapport à un petit projet d'apprentissage est justifié. Mais soit.

Sauf que le problème c'est qu'en tant que programmeur tu dois savoir compiler. Pour un projet d'apprentissage, je trouve donc plus pertinent d'apprendre au moins une fois à utiliser Make car celui-ci ne te cache pas comment se déroule la compilation, tu es obligé de savoir comment ça marche. Après ça, si tu veux utiliser tel système tu le fais; pédagogiquement ça me paraît juste mieux au moins au début de faire les choses un peu à la main.

Pour finir, je vois que tu aimes SCons, c'est vrai que cet outil a l'air bien. Je te trouve juste agressif pour rien. Quand tu me sors l'exemple, ça fait "ben et ça alors, ça compte pour du beurre ?". C'est pas une bonne manière de présenter les choses. Je te trouve bien trop catégorique sur ton refus de Make. Personnellement tu peux très bien ne pas t'en approcher à moins de 25 km, mais OP a demandé du Make alors je lui donne du Make. Je suis pas là pour dénigrer les autres systèmes de build, et je n'ai pas envie de rentrer dans une flamewar.

Sur ce je me désabonne du topic parce que j'ai pas envie de rentrer dans de la flamewar/prêche pour sa paroisse. Je voulais juste répondre à la question.

+3 -1

je vais juste répondre là dessus (je suis en désacord sur le reste, mais vu que ma réponse ne sera pas lue…)

mais OP a demandé du Make alors je lui donne du Make.

Non, c'est là que tu trompes.

L'OP veut faire du un lib de math en C++, pas apprendre make. Make n'est qu'un problème collatéral qu'il rencontre, surement car il ne connait que Make. Je propose des solutions plus adaptées à son utilisation. Le problème est une variante du problème XY où tu réponds à Y et moi à X.

Édité par Davidbrcz

+0 -0

J'ai pas envie de troller, mais pour une fois, vive Windows !

1
2
3
4
@echo off
if not exist obj md obj
for %%i in (*.cpp) do g++ -c -O3 -s -std=gnu++11 %%i -o obj\%%~ni.o
g++ -s -O3 -w -o a.exe obj\*.o

Ligne 2: Création du dossier obj s'il n'existe pas
Ligne 3: On exécute la commande sur tous les .cpp, un par un, dans le dossier courant et tous les sous-dossiers. C'est pratique, ça permet même d'organiser son code en dossiers et sous-dossiers quand on commence à avoir trop de .cpp pour tous les mettre dans le même dossier.
Ligne 4: On compile le .exe à partir de tous les .o

J'utilise à peu de chose près ce batch pour tous mes projets perso.

ET pour le mode debug, j'ai celui-ci :

1
2
3
4
@echo off
if not exist obj md obj
for %%i in (*.cpp) do isnewer %%i obj\%%~ni.o && g++ -c -g -std=gnu++11 %%i -o obj\%%~ni.o
g++ -g -o a.exe obj\*.o

La différence avec l'autre c'est qu'il ne compile que les .cpp qui sont plus récents que les .o correspondants. Avec la commande isnewer qui n'existe pas par défaut mais qui est très très simple à faire, c'est le petit programme suivant (En C, pas en C++) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<windows.h>
#include<stdio.h>

unsigned long long getFileTime (const char* fn) {
unsigned long long l = 0;
FILETIME ft;
HANDLE h = CreateFile(fn, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
if (h==INVALID_HANDLE_VALUE) return 0;
if (GetFileTime(h, NULL, NULL, &ft)) l = (((unsigned long long)ft.dwHighDateTime)<<32) | ft.dwLowDateTime;
CloseHandle(h);
return l;
}

int main (int argc, char** argv) {
if (argc!=3) {
printf("Usage: isnewer <file1> <file2>\r\n");
printf("This utility returns error code 0 if file1 is newer than file2, 1 otherwise.\r\n");
}
unsigned long long 
time1 = getFileTime(argv[1]),
time2 = getFileTime(argv[2]);
return time1 < time2;
}

Édité par QuentinC

Ma plateforme avec 23 jeux de société classiques en 6 langues et 13000 joueurs: http://qcsalon.net/ | Apprenez à faire des sites web accessibles http://www.openweb.eu.org/

+0 -2

Make n'est pas un outil du passé, c'est sa génération manuelle qui est du passé. Accessoirement, à moins d'avoir un éditeur de texte configuré pour avoir la même productivité qu'un IDE (emacs ou vim sous stéroïdes) et donc de ne pas avoir besoin de se taper le Makefile à la main, utiliser un IDE, ça peut être une bonne solution.

Après, apprendre à utiliser des outils de générations automatiques pendant qu'on travaille sur des petits projets c'est peut être plus malin que de le faire sur des gros projets plus tard quand on n'aura pas que ça à foutre. Sinon, c'est un coup à continuer à faire du Makefile manuel sur du gros projets et pleurer pour la maintenance plus tard.

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+1 -0

Ksass`Peuk, je ne tape pas mes Makefiles à la main pour mes petits projets. Mes petits projets, c'est un fichier, et gnumake sait les traiter sans avoir à écrire le moindre Makefile (sauf sous cette bouse mal configurée de mingw). Il suffit juste de connaitre les variables qui vont bien: $CXX, $CXXFLAGS, $LDFLAGS, etc.

Ou alors pour 2-3 fichiers, je me contente juste de déclarer les dépendances et la ligne de link – je ne vise que gnumake. Et s'il faut faire portable, je ne veux plus entendre parler de Makefile.

Ce qui me fait penser que j'ai vu plus d'un projet mal gaulé où les gens se redéfinissent des variables qui ne sont pas des standards de facto ou qui vont confondre $CPPFLAGS avec $CXXFLAGS. C'est con, mais cela fini vite par mettre la grouille.

Je rajouterai aussi que les Makefile, c'est vite tordu pour gérer automagiquement et correctement les dépendances (surtout quand on vise la compilation hors répertoire des sources), et notamment celles qui permettent de générer automatiquement des répertoires.

Toujours est-il, je suis on ne peut plus convaincu par l'intérêt de passer à CMake et à la compilation à l'extérieur du répertoire des sources (cela permet d'avoir plusieurs cibles de compil, genre Release, Debug, ReleaseWithDebugInfo, Sanatized …). Et je ne veux plus entendre parler des autotools – pas assez portables à mon goût.

Édité par lmghs

+3 -0

J'ai pas envie de troller, mais pour une fois, vive Windows !

QuentinC

Un script shell, t'en fais autant sous GNU/Linux, je ne vois pas le rapport avec l'OS. Sauf que ça ne répond pas à la question, tu n'as pas de gestion de dépendances, tu refais l'édition de lien à chaque exécution du script, etc.

Ksass`Peuk, je ne tape pas mes Makefiles à la main pour mes petits projets.

lmghs

J'ai dû mal formuler, c'est ce que je sous entendais, nos environnements nous permettent de ne pas en avoir besoin.

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+0 -0

Make n'est pas un outil du passé, c'est sa génération manuelle qui est du passé.

Ksass`Peuk

C'est effectivement un outil du passe au sens ou s'infliger une telle torture que d'ecrire trois lignes de Make a la main n'a aucun sens et personne ne le fait a part des gens qui ont du temps a perdre.

Pour repondre a Grimur.

L'argument du 'mes makefiles sont prets j'ai plus rien a faire' c'est pas un argument. J'ai un CMake des familles tout pret avec lequel j'ai juste a demander de me generer un makefile, qui sera plus complet, mieux ecrit et avec moins d'erreurs que celui de Grimur.

L'argument du 'c'est simple et leger' c'est aussi pas un argument. Arretez d'utiliser un IDE et utilisez echo et pipe pour editer des fichiers au lieu d'avoir un paquet supplementaire super lourd. C'est simple et ca fonctionne, pourquoi s'emmerder avec le progres ?

Le seul argument recevable pour savoir ecrire un makefile c'est:

  1. Etre compatible avec les dinosaures (mais generalement comme ils font du C, on s'en fout).
  2. Savoir un peu mieux comment fonctionne la chaine de compilation la plus basique qui soit. Autrement dit, quand on debute.

Et par ailleurs, pour ce dernier point, je suis seduit par la reponse de lmghs sur le fait qu'a ce tarif, autant utiliser directement gcc et l'environnement.

Au passage, comparer make a CMake c'est un peu comparer pdflatex a pandoc.

Édité par KFC

+1 -0

Et par ailleurs, pour ce dernier point, je suis seduit par la reponse de lmghs sur le fait qu'a ce tarif, autant utiliser directement gcc et l'environnement.

Je réagit sur cette partie. L'avantage de passé par make plutôt que gcc est de ne compiler que les sources qui ont changés. Perso, pareil que lmghs, quelques lignes dans un Makefile, voir pas de Makefile du tout (l=(*.cpp) ; make ${l//.cpp/.o} && g++ *o). Le reste à travers les variables et règles implicites.

+1 -0

Et par ailleurs, pour ce dernier point, je suis seduit par la reponse de lmghs sur le fait qu'a ce tarif, autant utiliser directement gcc et l'environnement.

KFC

Attention, je n'ai pas dit ça. J'ai voulu dire que quand j'ai un seul fichier, je n'écris pas de Makefile. Pas que j'appelle directement gcc, car en vrai, j'appelle toujours make en passant en argument le nom de mon source privé de son extension. Et ça marche! (sauf avec la configuration salopée de gnumake sous mingw). Et ça, je le fais sans quitter vim. Si je veux compiler en C++14, je tape un petit :let $CXXFLAGS='-std=c++14', avant mon :Make/<F7>, et c'est réglé – et je me dis qu'il va falloir que je songe à enrichir mon plugin dédié à la compilation pour générer automatiquement le Makefile qui s'occupera des dépendances.

Pour quatre fichiers, je vais juste avoir des toto.o:toto.h titi.h et la ligne du link. Et là, c'est la solution de jo_link_noir qui me séduit.

+0 -0
Auteur du sujet

Bon, du coup pour l'instant j'ai marqué tous les noms de mes fichiers dans les dépendances de ma rule all, sinon je pense apprendre CMake ou scons puisque je considère que je ne peux me positionner sans avoir essayer toutes les possibilités et puis je perds rien a le faire. Merci pour vos réponses :)

« La Nature est un livre écrit en langage mathématique », Galilée

+0 -0
Staff

Non, non et non. C'est tout le but des outils que je cite. Pourquoi refaire des choses à la main alors qu'il existe des outils faits pour ca ?

Davidbrcz

Si, si et si ? Et pourquoi ne pas refaire les choses à la main ? On a plus le droit de s'amuser et d'essayer par soi-même ?

C'est effectivement un outil du passe au sens ou s'infliger une telle torture que d'ecrire trois lignes de Make a la main n'a aucun sens et personne ne le fait a part des gens qui ont du temps a perdre.

KFC

Mon Dieu… Et tu tiens le coup avec la ligne que tu dois écrire avec CMake ou tu trouves cela encore trop long ? :-°

L'argument du 'c'est simple et leger' c'est aussi pas un argument. Arretez d'utiliser un IDE et utilisez echo et pipe pour editer des fichiers au lieu d'avoir un paquet supplementaire super lourd. C'est simple et ca fonctionne, pourquoi s'emmerder avec le progres ?

KFC

Alors, de un les vrais programmeurs utilisent la commande cat(1) ou tee(1) pour écrire leur code et non la commande echo et les redirections qui manquent franchement de classe. À la rigueur ed(1), mais c'est déjà limite un mini IDE. De deux, et plus sérieusement, j'ignorais qu'il n'existait aucune solution entre les IDEs et les redirections de flux…

  1. Etre compatible avec les dinosaures (mais generalement comme ils font du C, on s'en fout).

KFC

Juste pour dire :

CMake

Édité par Taurre

+1 -2
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte