IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Systèmes de compilation Discussion :

Un Makefile générique


Sujet :

Systèmes de compilation

  1. #1
    Membre averti Avatar de Ekinoks
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2003
    Messages
    687
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2003
    Messages : 687
    Points : 358
    Points
    358
    Par défaut Un Makefile générique
    Salut,

    J'écris souvent des petits programmes C/C++ contenant plusieurs fichiers sources.

    J'ai cherché sur Internet un Makefile générique mais je n'ai pas trouvé exactement celui que je voulais. (et les Makefile génériques se font plutôt rare )

    J'en est donc créé un que je colle ici, car je suis sur qu'il pourras intéresser d'autre personnes.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    26
    27
    28
    29
    30
     
    # Makefile Generique
     
    EXT = c
    CXX = gcc
    EXEC = exe
     
    CXXFLAGS = -Wall -W -pedantic 
    LDFLAGS = 
     
     
    OBJDIR = obj
    SRC = $(wildcard *.$(EXT))
    OBJ = $(SRC:.$(EXT)=.o)
    OBJ := $(addprefix $(OBJDIR)/, $(OBJ))
     
    all: $(EXEC)
     
    $(EXEC): $(OBJ)
    	@$(CXX) -o $@ $^ $(LDFLAGS)
     
    $(OBJDIR)/%.o: %.$(EXT)
    	@$(CXX) -o $@ -c $< $(CXXFLAGS)
     
    clean:
    	@rm -rf $(OBJDIR)/*.o
    	@rm -f $(EXEC)
     
    install: $(EXEC)
    	@cp $(EXEC) /usr/bin/
    L'utilisation est simple. On met le Makefile avec les sources.
    Si c'est un projet C on utilise le Makefile tel quel.
    Si c'est un projet C++ on met CXX = g++ et EXT a cpp ou cc suivant l'extension qu'on utilise.

    Pour compiler :
    Pour nettoyer les *.o et l'exécutable :
    Pour installer (avec droit admin sous Linux) :
    Ne pas oublier de créer un dossier "obj" dans le répertoire du Makefile (pour éviter d'avoir des *.o mélangé au code source ^^)

    PS : Si vous voyez des améliorations possible, surtout n'hésitez pas !

  2. #2
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour,

    D'abord, ce Makefile est bien foutu.

    Une suggestion : créer automatiquement le répertoire obj :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $(EXEC): $(OBJ)
    	mkdir -p $(OBJDIR)
    	@$(CXX) -o $@ $^ $(LDFLAGS)

    Une question : que fait cette ligne ? ou plutôt, où trouver de la doc sur les mots clefs addprefix, wildcard... ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    OBJ := $(addprefix $(OBJDIR)/, $(OBJ))

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 7
    Points : 9
    Points
    9
    Par défaut Re: Makefile Générique
    Je me joins à Mabu pour dire que ce Makefile est bienfoutu.

    Cependant, je ne suis pas tout à fait d'accord avec sa suggestion: la création des fichiers .o ayant lieux avant la création du fichier exécutable, cela risque de faire échouer tout de même la compilation .c(c) => .o

    J'ai fait fonctionner la version suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    $(OBJDIR)/%.o: %.$(EXT)
    	- mkdir $(OBJDIR)
    	@$(CXX) -o $@ -c $< $(CXXFLAGS)
    Le '-' est important car la commande sera tenté à chaque fichier .o, donc échouera à la 2 ième tentative, avec le '-' l'echec sera ignoré et la construction poursuivra.

    Je tenterai de poster une variante de Makefile générique (largement) inspirée des puissants outils du monde Java (façon Ant ou Maven ...)

    Citation Envoyé par mabu Voir le message
    Bonjour,

    D'abord, ce Makefile est bien foutu.

    Une suggestion : créer automatiquement le répertoire obj :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $(EXEC): $(OBJ)
    	mkdir -p $(OBJDIR)
    	@$(CXX) -o $@ $^ $(LDFLAGS)

    Une question : que fait cette ligne ? ou plutôt, où trouver de la doc sur les mots clefs addprefix, wildcard... ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    OBJ := $(addprefix $(OBJDIR)/, $(OBJ))
    Pour répondre à la question, cette documentation te founira toutes les réponses sur Make :
    http://www.gnu.org/software/autoconf/manual/make/

    Cdlt,
    Guillaume Wallet

  4. #4
    Nouveau Candidat au Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2014
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2014
    Messages : 1
    Points : 1
    Points
    1
    Par défaut Ma version perso, si ça peut aider
    Salut,

    Voici un Makefile générique que j'ai réalisé lors d'un projet d'études.

    J'y ai ajouté quelques commentaires afin d'expliquer les principaux éléments.

    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
     
    EXT = c
    CC = gcc
    DEBUG = yes
    CFLAGS = -W -Wall -ansi -pedantic
     
    # Ici, on active le standard C99 si le projet est en C
    ifeq ($(CC),gcc)
    	CFLAGS := $(CFLAGS) -std=c99
    endif
     
    # La constant DEBUG peut être utilisée dans votre projet.
    # Ex. pour faire des printf conditionnels.
    ifeq ($(DEBUG),yes)
    	CFLAGS := -g $(CFLAGS) -DDEBUG
    endif
     
    LDFLAGS=
     
    # Le nom de l'exécutable final
    EXEC=dicosyn
     
    # Les fichiers sont séparés dans des répertoires distincts.
    SRCDIR=src
    OBJDIR=obj
    BINDIR=bin
     
    # Ici, vous pouvez exclure une liste de fichiers des sources.
    # Ex. une acienne implémentation que vous ne voulez pas supprimer.
    EXCLUDE=$(SRCDIR)/dico-old.c
     
    # Ici, la liste de fichiers est construite
    SRC  = $(wildcard $(SRCDIR)/*.$(EXT))
    SRC := $(filter-out $(EXCLUDE),$(SRC))
    OBJ  = $(SRC:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
     
    # La cible par défaut est all
    default: all
     
    # La cible all construit l'exécutable
    all: $(EXEC)
     
    # Ici, on indique les cibles qui ne génèrent pas de fichier
    # et qui, par conséquent, doivent toujours être exécutées
    .PHONY: help clean mrproper
     
    # Affichage de l'aide
    help:
    	@ echo 'Makefile for ISIN project `dicosyn`'
    	@ echo ''
    	@ echo 'Usage :'
    	@ echo 'make           Build project executable'
    	@ echo 'make all       Build project executable'
    	@ echo 'make clean     Clean objects directory'
    	@ echo 'make mrproper  Remove objects and binaries directory'
    	@ echo 'make help      Show this help message'
    	@ echo ''
     
    # Cible de construction de l'exécutable
    $(EXEC): $(OBJ)
    	@ [ -d $(BINDIR) ] || mkdir $(BINDIR)
    	@ $(CC) -o $(BINDIR)/$@ $^ $(LDFLAGS)
    	@ [ -h $@ ] || ln -s $(BINDIR)/$@ $@
     
    # Déclaration des dépendances supplémentaires spécifiques
    # Les dépendances listées ici s'ajoutent à la règle générique
    $(OBJDIR)/mot.o: $(SRCDIR)/liste.h
    # En cas de liste trop longue liste, on peut le faire en deux étapes
    DICODEPS=arbre.h mot.h
    $(OBJDIR)/dico.o: $(DICODEPS:%=$(SRCDIR)/%)
    INDEX2DEPS=table.h mot.h
    $(OBJDIR)/index2.o: $(INDEX2DEPS:%=$(SRCDIR)/%)
     
    # Déclaration de a règle générique
    # Si tous vos fichiers c/cpp n'ont pas de .h correspondant,
    # vous pouvez enlever $(SRCDIR)/%.h des dépendances.
    $(OBJDIR)/%.o: $(SRCDIR)/%.c $(SRCDIR)/%.h
    	@ [ -d $(OBJDIR) ] || mkdir $(OBJDIR)
    	@ $(CC) -o $@ -c $< $(CFLAGS)
     
    # Nettoyage du répertoire des objets
    clean:
    	@ rm -f $(OBJDIR)/*.o
     
    # Suppression des répertoires des objets et des binaires
    mrproper: clean
    	@ rm -rf $(EXEC) $(OBJDIR) $(BINDIR)

    Exemple de code pour utiliser la constante DEBUG (nécessite C99):

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    #include <stdio.h>
    #if defined(DEBUG)
    #define TRACE(x, ...) fprintf(stderr, x, ##__VA_ARGS__)
    #else
    #define TRACE(x, ...)
    #endif
     
    int main(void) {
        TRACE("Hello %s !!\n", "World");
        return 0;
    }

    Voilà, en espérant que ça pourra servir à quelqu'un.

  5. #5
    Membre averti
    Homme Profil pro
    Dev
    Inscrit en
    Novembre 2006
    Messages
    112
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Novembre 2006
    Messages : 112
    Points : 350
    Points
    350
    Par défaut
    bonjour

    dans mon makefile , j'utilise un gestion automatique des dépendances

    voici mon Makefile type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    
    
    CC   = g++
    
    
    BIN  = ...
    INC = ....
    
    
    CXXFLAGS= $(CXXINCS) -Wall   -Wno-deprecated -s    -O3 -MMD  
    CFLAGS= $(INCS) -Wall  -Wno-deprecated  -s    -O3 -MMD  
    
    # liste des source
    SRCS=$(wildcard  src/*.cpp)
    SRCS+=$(wildcard src/subrep1/*.cpp)
    ....
    SRCS+=$(wildcard src/subrepN/*.cpp)
    
    # liste des points *.o en fonction de *.c
    OBJS=$(SRCS:src/%.cpp=objet/%.o)
    
    
    # liste des fichier *.d
    DEPS = $(wildcard obj/*.d)
    DEPS += $(wildcard obj/subrep1/*.d)
    ...
    DEPS += $(wildcard obj/subrepN/*.d)
    
    
    
    
    
    .SILENT:
    LIBS = ....
    
    all:$(BIN)
    
    $(BIN):     $(OBJS)  
    	echo linker
    	echo $(BIN)
    	$(CC)     $(OBJS)   $(LIBS) -o $(BIN) -s
    
    
    clean:
    	rm -f $(OBJS) $(BIN)
    
    # regle général
    obj/%.o : src/%.cpp
    	echo $@
    	$(CPP) -c $< -o $@ $(CXXFLAGS)  -I $(INC)
    
    
    
    
    
    #dépendance spécifique
    
    ifneq ($(DEPS),)
    include $(DEPS)
    endif
    
    
    
    cleand:
    	rm -f $(DEPS)
    explication:

    avec Make , il est possible d'avoir une règle générique de construction :
    et d'avoir à la suite les dépendances
    comme par ex:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    obj/toto.o: src/toto.c src/titi.h src/toto.h
    obj/titi.o: src/titi.c src/titi.h src/toto.h
    il est aussi possible d'inclure des fichiers dans make
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    include montrucainclure1, montrucainclure2
    de plus gcc /g++ offre une option au niveau du preprocessor qui permet de lister les dépendances
    -M : créer un fichier avec toute les dépendances ( tout les .h , meme ceux appelé par d'autre .h ) et arrêté la compilation
    -MM : créer un fichier avec toute les dépendances sans les dépendances systèmes ( /usr/include/ ) arrêté la compilation
    -MD: créer un fichier avec toute les dépendances et continue la compilation
    -MMD : ( MM + MD ) créer un fichier avec toute les dépendances sans les dépendances systèmes ( /usr/include/ )et continue la compilation.
    on obtiens un fichier *.d dans le même dossier que le .o
    ex
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    obj/level.o: src/level.cpp src/level.h src/graph/initdx9.h \
      src/graph/..\liste\liste.h src/graph/..\liste\/listenewton.h \
      src/graph/..\liste\/listeg.h src/graph/..\liste\/listenewton.h \
      src/graph/..\liste\/listeg.h src/graph/..\directrelease.h \
      src/graph/vertex.h src/graph/initdx9.h src/graph/basevertex.h \
      src/graph/vertex/objet3D.h src/graph/vertex/..\basevertex.h \
      src/graph/vertex/texel.h src/graph/vertex/variable.h
    il suffit de liste tous les .d et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DEPS = $(wildcard obj/*.d)
    et de les inclures dans le make ( après avoir vérifier que la liste n'est pas vide )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ifneq ($(DEPS),)
    include $(DEPS)
    endif
    et voici un makefile avec un gestion auto des dépendances

  6. #6
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    $CC -> cc/gcc/clang
    $CXX -> c++/g++/clang++
    $LD -> ld (IIRC)
    $CPP -> le précompilateur : cpp

    N'allez pas mettre g++ dans $CC. Il y a plein de conventions dans les makefiles qui nous permettent de profiter de règles implicites déjà écrites. Souvent il suffit de spécifier les dépendances entre fichiers, quelques flags, et c'est fini. Même pas besoin de redonner les règles de compilation.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

Discussions similaires

  1. Makefile générique
    Par kwariz dans le forum Télécharger
    Réponses: 3
    Dernier message: 28/04/2013, 16h22
  2. Makefile complet et générique
    Par Damoun dans le forum Débuter
    Réponses: 4
    Dernier message: 15/12/2009, 12h03
  3. Makefile générique pour compilation projet C
    Par AuraHxC dans le forum Systèmes de compilation
    Réponses: 1
    Dernier message: 13/12/2007, 21h29
  4. Réponses: 3
    Dernier message: 07/03/2006, 22h29
  5. Compilation avec un Makefile
    Par Mau dans le forum GTK+ avec C & C++
    Réponses: 3
    Dernier message: 28/02/2003, 11h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo