Comme c'est pour Unix, les exécutables n'ont pas d'extensions.
Une chose à noter est qu'il root-config
s'agit d'un utilitaire qui fournit les bons indicateurs de compilation et de liaison; et les bonnes bibliothèques pour créer des applications contre root. Ce n'est qu'un détail lié à l'audience d'origine de ce document.
Fais-moi bébé
ou vous n'oublierez jamais la première fois que vous vous êtes fait
Une discussion introductive sur make et comment écrire un simple makefile
Qu'est-ce que Make? Et pourquoi devrais-je m'en soucier?
L'outil appelé Make est un gestionnaire de dépendances de génération. Autrement dit, il prend soin de savoir quelles commandes doivent être exécutées dans quel ordre pour prendre votre projet logiciel à partir d'une collection de fichiers source, de fichiers objets, de bibliothèques, d'en-têtes, etc., etc. - dont certains peuvent avoir changé récemment --- et les transformer en une version correcte et à jour du programme.
En fait, vous pouvez également utiliser Make pour d'autres choses, mais je ne vais pas en parler.
Un Makefile trivial
Supposons que vous ayez un répertoire contenant:, tool
tool.cc
tool.o
support.cc
support.hh
et support.o
qui dépendent root
et sont censés être compilés dans un programme appelé tool
, et supposez que vous avez piraté les fichiers source (ce qui signifie que l'existant tool
est désormais obsolète) et que vous souhaitez compiler le programme.
Pour le faire vous-même, vous pourriez
Vérifiez si support.cc
ou support.hh
est plus récent que support.o
, et si c'est le cas, exécutez une commande comme
g++ -g -c -pthread -I/sw/include/root support.cc
Vérifiez si l'un support.hh
ou l' autre tool.cc
est plus récent que tool.o
, et si c'est le cas, exécutez une commande comme
g++ -g -c -pthread -I/sw/include/root tool.cc
Vérifiez si tool.o
est plus récent que tool
, et si c'est le cas, exécutez une commande comme
g++ -g tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
-Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl
Phew! Quelle galère! Il y a beaucoup de choses à retenir et plusieurs chances de faire des erreurs. (BTW - les détails des lignes de commande présentées ici dépendent de notre environnement logiciel. Ceux-ci fonctionnent sur mon ordinateur.)
Bien sûr, vous pouvez simplement exécuter les trois commandes à chaque fois. Cela fonctionnerait, mais il ne s'adapte pas bien à un logiciel substantiel (comme DOGS qui prend plus de 15 minutes à compiler à partir de zéro sur mon MacBook).
Au lieu de cela, vous pouvez écrire un fichier appelé makefile
comme ceci:
tool: tool.o support.o
g++ -g -o tool tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
-Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl
tool.o: tool.cc support.hh
g++ -g -c -pthread -I/sw/include/root tool.cc
support.o: support.hh support.cc
g++ -g -c -pthread -I/sw/include/root support.cc
et tapez simplement make
sur la ligne de commande. Qui exécutera automatiquement les trois étapes ci-dessus.
Les lignes non indentées ici ont la forme "cible: dépendances" et indiquent à Make que les commandes associées (lignes indentées) doivent être exécutées si l'une des dépendances est plus récente que la cible. Autrement dit, les lignes de dépendance décrivent la logique de ce qui doit être reconstruit pour s'adapter aux modifications dans divers fichiers. Si cela support.cc
change, cela support.o
doit être reconstruit, mais tool.o
peut être laissé seul. Quand les support.o
modifications tool
doivent être reconstruites.
Les commandes associées à chaque ligne de dépendance sont déclenchées par un onglet (voir ci-dessous) qui devrait modifier la cible (ou au moins la toucher pour mettre à jour l'heure de modification).
Variables, règles intégrées et autres avantages
À ce stade, notre makefile se souvient simplement du travail qui doit être fait, mais nous avons encore dû comprendre et taper chaque commande nécessaire dans son intégralité. Il ne doit pas en être ainsi: Make est un langage puissant avec des variables, des fonctions de manipulation de texte et toute une série de règles intégrées qui peuvent nous faciliter la tâche.
Créer des variables
La syntaxe pour accéder à une variable make est $(VAR)
.
La syntaxe d'affectation à une variable Make est: VAR = A text value of some kind
(ou VAR := A different text value but ignore this for the moment
).
Vous pouvez utiliser des variables dans des règles comme cette version améliorée de notre makefile:
CPPFLAGS=-g -pthread -I/sw/include/root
LDFLAGS=-g
LDLIBS=-L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz \
-Wl,-framework,CoreServices -Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root \
-lm -ldl
tool: tool.o support.o
g++ $(LDFLAGS) -o tool tool.o support.o $(LDLIBS)
tool.o: tool.cc support.hh
g++ $(CPPFLAGS) -c tool.cc
support.o: support.hh support.cc
g++ $(CPPFLAGS) -c support.cc
ce qui est un peu plus lisible, mais nécessite encore beaucoup de frappe
Créer des fonctions
GNU make prend en charge une variété de fonctions pour accéder aux informations à partir du système de fichiers ou d'autres commandes du système. Dans ce cas, nous nous intéressons à $(shell ...)
ce qui se développe à la sortie des arguments, et $(subst opat,npat,text)
qui remplace toutes les instances de opat
with npat
dans le texte.
Profiter de cela nous donne:
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
tool: $(OBJS)
g++ $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
tool.o: tool.cc support.hh
g++ $(CPPFLAGS) -c tool.cc
support.o: support.hh support.cc
g++ $(CPPFLAGS) -c support.cc
qui est plus facile à taper et beaucoup plus lisible.
Remarquerez que
- Nous indiquons toujours explicitement les dépendances pour chaque fichier objet et l'exécutable final
- Nous avons dû taper explicitement la règle de compilation pour les deux fichiers source
Règles implicites et de modèle
Nous nous attendons généralement à ce que tous les fichiers source C ++ soient traités de la même manière, et Make fournit trois façons de le déclarer:
- règles de suffixe (considérées comme obsolètes dans la marque GNU, mais conservées pour des raisons de compatibilité descendante)
- règles implicites
- règles de modèle
Des règles implicites sont intégrées, et quelques-unes seront discutées ci-dessous. Les règles de modèle sont spécifiées sous une forme comme
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
ce qui signifie que les fichiers objets sont générés à partir des fichiers source C en exécutant la commande indiquée, où la variable "automatique" se $<
développe jusqu'au nom de la première dépendance.
Règles intégrées
Make a toute une série de règles intégrées qui signifient que très souvent, un projet peut être compilé par un makefile très simple, en effet.
La règle GNU make intégrée pour les fichiers source C est celle présentée ci-dessus. De même, nous créons des fichiers objets à partir de fichiers source C ++ avec une règle comme $(CXX) -c $(CPPFLAGS) $(CFLAGS)
.
Les fichiers d'objet unique sont liés à l'aide $(LD) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
, mais cela ne fonctionnera pas dans notre cas, car nous voulons lier plusieurs fichiers d'objet.
Variables utilisées par les règles intégrées
Les règles intégrées utilisent un ensemble de variables standard qui vous permettent de spécifier les informations d'environnement local (comme où trouver les fichiers d'inclusion ROOT) sans réécrire toutes les règles. Les plus susceptibles de nous intéresser sont:
CC
- le compilateur C à utiliser
CXX
- le compilateur C ++ à utiliser
LD
- l'éditeur de liens à utiliser
CFLAGS
- drapeau de compilation pour les fichiers source C
CXXFLAGS
- drapeaux de compilation pour les fichiers source C ++
CPPFLAGS
- drapeaux pour le préprocesseur c (incluent généralement les chemins de fichiers et les symboles définis sur la ligne de commande), utilisés par C et C ++
LDFLAGS
- drapeaux de l'éditeur de liens
LDLIBS
- bibliothèques à relier
Un Makefile de base
En tirant parti des règles intégrées, nous pouvons simplifier notre makefile pour:
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
all: tool
tool: $(OBJS)
$(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
tool.o: tool.cc support.hh
support.o: support.hh support.cc
clean:
$(RM) $(OBJS)
distclean: clean
$(RM) tool
Nous avons également ajouté plusieurs cibles standard qui effectuent des actions spéciales (comme le nettoyage du répertoire source).
Notez que lorsque make est invoqué sans argument, il utilise la première cible trouvée dans le fichier (dans ce cas tous), mais vous pouvez également nommer la cible à obtenir, ce qui explique la make clean
suppression des fichiers objet dans ce cas.
Nous avons toujours toutes les dépendances codées en dur.
Quelques améliorations mystérieuses
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
all: tool
tool: $(OBJS)
$(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
depend: .depend
.depend: $(SRCS)
$(RM) ./.depend
$(CXX) $(CPPFLAGS) -MM $^>>./.depend;
clean:
$(RM) $(OBJS)
distclean: clean
$(RM) *~ .depend
include .depend
Remarquerez que
- Il n'y a plus de ligne de dépendance pour les fichiers source!?!
- Il y a une magie étrange liée à .depend et dépend
- Si vous le faites
make
alors ls -A
vous voyez un fichier nommé .depend
qui contient des choses qui ressemblent à faire des lignes de dépendance
Autre lecture
Connaître les bugs et les notes historiques
La langue d'entrée pour Make est sensible aux espaces. En particulier, les lignes d'action suivant les dépendances doivent commencer par un onglet . Mais une série d'espaces peut se ressembler (et en effet, il existe des éditeurs qui convertissent silencieusement les tabulations en espaces ou vice versa), ce qui se traduit par un fichier Make qui semble correct et ne fonctionne toujours pas. Cela a été identifié comme un bug au début, mais ( l'histoire raconte ), il n'a pas été corrigé, car il y avait déjà 10 utilisateurs.
(Ceci a été copié à partir d'un article wiki que j'ai écrit pour des étudiants diplômés en physique.)