http://lpnheweb3.in2p3.fr/spip.php?article1210
makefile et recherche de dépendances
- Le LPNHE - Pages du personnel permanent - Chercheurs - Beau Tristan - Divers - Vielleries -
Date de mise en ligne : jeudi 18 mai 2017
Copyright © LPNHE - UMR 7585 - Tous droits réservés
Je vous propose ci-dessous un
makefiletrès générique qui recherche automatiquement les dépendances des différents fichiers sources entre eux, afin d'éviter une écriture fastidieuse voire erronnée du
makefile.
Les répertoires de travail pour les fichiers
includeou sources sont définis en tête du fichier
makefiledans
$(SRCDIR)et
$(INCDIR). Les binaires objets et exécutables se placeront dans
$(OBJDIR),
$(OBMDIR)(pour les
.oavec un
main) et
$(BINDIR). Si ces répertoires n'existent pas, ils seront créés. Les extensions attendus pour chaque type de fichier sont définies aussi dans le fichier
makefile.
La compilation est ici machine dépendante, assurant la transmission de flags aux sources pour tester la machine sur laquelle la compilation est effectuée (option -D). Usuellement, la variable d'environnement $(SYSTEM) est déjà prédéfinie ; si ce n'est pas le cas, on l'ajoutera au variables d'environnement, soit par exemple :
export SYSTEM=Linux
Le principal intérêt de ce
makefileest la détermination automatique des dépendances des sources aux fichiers headers. Celà passe par l'utilisation de l'option
-MMdonnée au compilateur qui n'exécute que le préprocesseur et lui demande de trouver les dépendances utilisateurs.
Enfin, si les sources sont attendus dans
$(SRCDIR), le
mainest attendu dans le répertoire en cours (c'est a priori le seul fichier utilisateur dans la racine du répertoire de travail). Si plusieurs fichiers source dans cette racine ont un
main
, il y aura dans
$(BINDIR)autant de fichiers exécutables.
Nota : Le
makefileci-dessous suppose l'utilisation du GNU Make. Sur une machine Sun par exemple, le
makestandard ne fonctionnera pas.
Dernier point. Lorsque vous faites une erreur de nom lors de l'inclusion d'un fichier (commande
#include), une erreur est créée dans les fichiers de dependances. Il faut alors les effacer avec
gmake clean_dep
voire éventuellement pour effacer tous les fichiers objets et les dépendances :
gmake clean_all
Voici donc la source de ce
makefile. Notez qu'on suppose l'utilisation du logiciel
rootdans ce
makefile; si vous ne l'utilisez pas, supprimer les lignes qui y font référence.
Si vous faites du copier - coller à la souris du fichier ci-dessous, faites attention à ce que les tabulations soient bien
prises en compte...
##############################################################
# Makefile generique pour les plateformes RS, HP, Sun, Linux #
##############################################################
# Tristan Beau, le 02/11/2000
CURDIR = .
SRCDIR = $(CURDIR)/src IMPDIR = $(CURDIR)/imp INCDIR = $(CURDIR)/include BINDIR = $(CURDIR)/bin OBJDIR = $(CURDIR)/obj OBMDIR = $(CURDIR)/objmain
ObjSuf = .o SrcSuf = .cpp ExeSuf = DllSuf = .so IncSuf = .hpp ImpSuf = .ipp DepSuf = .d OutPutOpt = -o
#ROOTCFLAGS = $(shell root-config --cflags)
#ROOTLIBS = $(shell root-config --libs)
#ROOTGLIBS = $(shell root-config --glibs)
ifndef ($(SYSTEM))
SYSTEM = $(OSTYPE) endif
ifeq ($(SYSTEM),AIX)
# IBM AIX
CXX = xlC
CXXFLAGS = -O -g -I$(INCDIR) -I$(IMPDIR) -DIBM_SYSTEM LD = xlC
LDFLAGS = -g SOFLAGS = else
ifeq ($(SYSTEM),HP-UX)
# HP-UX 10.x with aCC CXX = aCC
CXXFLAGS = -O +Z -I$(INCDIR) -I$(IMPDIR) -DHP_SYSTEM LD = aCC
LDFLAGS = -g -z SOFLAGS = -b else
ifeq ($(SYSTEM),Linux)
# Linux with egcs CXX = g++
CXXFLAGS = -O -Wall -fPIC -I$(INCDIR) -I$(IMPDIR) -DLINUX_SYSTEM
LD = g++
LDFLAGS = -O SOFLAGS = -shared else
ifeq ($(SYSTEM),SunOS)
# Solaris
CXX = CC
CXXFLAGS = -O -KPIC -I$(INCDIR) -I$(IMPDIR) -DSUN_SYSTEM LD = CC
LDFLAGS = -g SOFLAGS = -G endif
endif endif endif
#CXXFLAGS += $(ROOTCFLAGS)
#LIBS = $(ROOTLIBS)
#GLIBS = $(ROOTGLIBS)
#---
MAIN = $(wildcard $(CURDIR)/*$(SrcSuf))
PROG = $(patsubst $(CURDIR)/%$(SrcSuf),$(BINDIR)/%$(ExeSuf),$(MAIN)) DEMA = $(patsubst $(CURDIR)/%$(SrcSuf),$(OBMDIR)/%$(DepSuf),$(MAIN)) SRCS = $(wildcard $(SRCDIR)/*$(SrcSuf))
OBJF = $(patsubst $(SRCDIR)/%$(SrcSuf),$(OBJDIR)/%$(ObjSuf),$(SRCS)) OBJM = $(patsubst $(CURDIR)/%$(SrcSuf),$(OBJDIR)/%$(ObjSuf),$(MAIN)) DEPS = $(patsubst $(SRCDIR)/%$(SrcSuf),$(OBJDIR)/%$(DepSuf),$(SRCS)) INCS = $(wildcard $(INCDIR)/*$(IncSuf))
IMPS = $(wildcard $(IMPDIR)/*$(ImpSuf)) OBJS = $(OBJF) $(OBJM)
all: $(PROG)
.PHONY: clean print clean_all clean_dep
.DELETE_ON_ERROR: $(OBJS) $(PROG) $(DEPS) $(DEMA)
print:
@echo "$(MAIN)"
@echo "$(PROG)"
@echo "$(DEMA)"
@echo "$(SRCS)"
@echo "$(OBJS)"
@echo "$(DEPS)"
clean:
@rm -f $(OBJS) $(BINDIR)/core $(DIR)/core $(DEPS) $(DEMA) @echo "Clean done"
clean_all:
@rm -R -f $(OBJDIR) $(OBMDIR) $(BINDIR) @echo "Clean all done"
clean_dep:
@rm -R -f $(DEPS) $(DEMA) @echo "Dependencies cleaned"
ifneq ($(MAKECMDGOALS),clean) ifneq ($(MAKECMDGOALS),clean_dep) ifneq ($(MAKECMDGOALS),clean_all) -include $(DEPS)
-include $(DEMA) endif
endif endif
$(OBJDIR)/%$(DepSuf): $(SRCDIR)/%$(SrcSuf) $(INCS) $(IMPS) @echo 'Making $< dependencies...'
@if [ ! -d $(OBJDIR) ] ; then mkdir $(OBJDIR) ;fi ;
@$(CXX) $(CXXFLAGS) -MM $< | sed 's/\($*\)\.o[ :]*/$(@D)\/\1.o : /' > $@ ; @echo ' @echo "Compiling $<..."' >> $@;
@echo ' @$(CXX) $(CXXFLAGS) -c $< -o $(patsubst %$(DepSuf),%$(ObjSuf),$@)' >> $@;
$(OBMDIR)/%$(DepSuf): $(CURDIR)/%$(SrcSuf) $(INCS) $(IMPS) @echo 'Making $< dependencies...'
@if [ ! -d $(OBJDIR) ] ; then mkdir $(OBJDIR) ;fi @if [ ! -d $(OBMDIR) ] ; then mkdir $(OBMDIR) ;fi
@$(CXX) $(CXXFLAGS) -MM $< | sed 's/\($*\)\.o[ :]*/$(@D)\/\1.o : /' > $@ ; @echo ' @echo "Compiling $<..."' >> $@;
@echo ' @$(CXX) $(CXXFLAGS) -c $< -o $(patsubst %$(DepSuf),%$(ObjSuf),$@)' >> $@;
$(BINDIR)/%$(BinSuf): $(OBMDIR)/%$(ObjSuf) $(OBJF) @echo "Linking $@..."
@if [ ! -d $(BINDIR) ] ; then mkdir $(BINDIR) ;fi @$(LD) $(LDFLAGS) $^ $(OutPutOpt) $@ $(LIBS) @echo "$@ done"