Si vous souhaitez exécuter ou mettre à jour une tâche lorsque certains fichiers sont mis à jour, le make
utilitaire peut venir dans maniable. La balise make
utilitaire nécessite un fichier, Makefile
(ou makefile
), qui définit un ensemble de tâches à exécuter. Vous avez peut-être utilisé make
pour compiler un programme à partir du code source. La plupart des projets open source utilisent make
pour compiler un binaire exécutable final, qui peut ensuite être installé en utilisant make install
.,
Dans cet article, nous allons explorer make
et Makefile
utilisation de base et des exemples avancés. Avant de commencer, assurez-vous que make
est installé dans votre système.
exemples
commençons par imprimer le classique « Hello World » sur le terminal. Créer un répertoire vide myproject
contenant un fichier Makefile
avec ce contenu:
say_hello:
echo "Hello World"
Maintenant, exécutez le fichier en tapant make
dans le répertoire myproject
., La sortie sera:
$ make
echo "Hello World"
Hello World
Dans l’exemple ci-dessus, say_hello
se comporte comme un nom de fonction, comme dans tout langage de programmation. Cela s’appelle de la cible. Les prérequis ou dépendances suivent la cible. Par souci de simplicité, nous n’avons défini aucune condition préalable dans cet exemple. La commande echo "Hello World"
s’appelle la recette. La recette utilise des conditions préalables pour faire une cible. La cible, les prérequis et les recettes forment ensemble une règle.,
Pour résumer, voici la syntaxe d’une règle générale:
target: prerequisites
<TAB> recipe
par exemple, une cible peut être un fichier binaire qui dépend de conditions préalables (fichiers sources). D’autre part, une condition peut également être une cible qui dépend d’autres dépendances:
Il n’est pas nécessaire pour que la cible soit un fichier; il pourrait être juste un nom pour la recette, comme dans notre exemple. Nous appelons ces « fausses cibles., »
pour revenir à l’exemple ci-dessus, lorsque make
a été exécuté, la commande entière echo "Hello World"
a été affichée, suivie de la sortie de la commande réelle. Souvent, nous n’en veux pas. Pour supprimer l’écho de la commande, nous avons besoin de commencer echo
par @
:
say_hello:
@echo "Hello World"
Maintenant, essayez d’exécuter make
nouveau., La sortie devrait afficher seulement ceci:
$ make
Hello World
nous allons ajouter un peu plus de fausses cibles: generate
et clean
à la balise Makefile
:
Si nous essayons d’exécuter make
après les changements, seule la cible say_hello
sera exécuté. En effet, seule la première cible du makefile est la cible par défaut. Souvent appelé objectif par défaut, c’est la raison pour laquelle vous verrez all
comme première cible dans la plupart des projets., Il est de la responsabilité de all
pour appeler d’autres cibles. Nous pouvons remplacer ce comportement en utilisant une cible bidon spéciale appelée .DEFAULT_GOAL
.
nous allons l’inclure au début de notre makefile:
.DEFAULT_GOAL := generate
Cela va exécuter la cible generate
comme valeur par défaut:
$ make
Creating empty text files...
touch file-{1..10}.txt
Comme son nom l’indique, le faux cible .DEFAULT_GOAL
pouvez exécuter qu’une seule cible à la fois. C’est pourquoi la plupart des makefiles incluent all
comme cible pouvant appeler autant de cibles que nécessaire.,
nous allons inclure le faux cible all
et supprimer .DEFAULT_GOAL
:
Avant d’exécuter make
, citons un autre faux cible, .PHONY
, où l’on définit toutes les cibles qui ne sont pas des fichiers. make
exécutera sa recette indépendamment du fait qu’un fichier avec ce nom existe ou de l’Heure de sa dernière modification., Voici le makefile complet:
Le make
devrait appeler say_hello
et generate
:
$ make
Hello World
Creating empty text files...
touch file-{1..10}.txt
C’est une bonne pratique de ne pas appeler clean
dans un all
ou le mettre comme première cible., clean
devrait être appelé manuellement lorsque le nettoyage est nécessaire dans un premier argument de make
:
$ make clean
Cleaning up...
rm *.txt
Maintenant que vous avez une idée de la façon dont un makefile de base fonctionne et comment écrire un makefile simple, regardons quelques exemples plus avancés.
exemples avancés
Variables
dans l’exemple ci-dessus, la plupart des valeurs cibles et prérequis sont codées en dur, mais dans les projets réels, elles sont remplacées par des variables et des modèles.,
la façon la plus simple de définir une variable dans un makefile est d’utiliser l’opérateur =
., Par exemple, pour assigner la commande gcc
pour une variable CC
:
CC = gcc
il est également appelé une récursif étendue variable, et il est utilisé dans une règle comme indiqué ci-dessous:
hello: hello.c
${CC} hello.c -o hello
Comme vous l’aurez deviné, la recette se développe comme ci-dessous lorsqu’il est transmis au terminal:
gcc hello.c -o hello
les Deux ${CC}
et $(CC)
sont valables références pour appeler gcc
. Mais si on essaie de réaffecter une variable à elle-même, cela provoquera une boucle infinie., Nous allons vérifier cela:
CC = gcc
CC = ${CC}
all:
@echo ${CC}
Exécution make
résultat sera:
$ make
Makefile:8: *** Recursive variable 'CC' references itself (eventually). Stop.
Pour éviter ce scénario, nous pouvons utiliser la balise :=
opérateur (ce qui est aussi appelé simplement l’étendue de la variable). Nous ne devrions avoir aucun problème à exécuter le makefile ci-dessous:
CC := gcc
CC := ${CC}
all:
@echo ${CC}
Patterns and functions
le makefile suivant peut compiler tous les programmes C en utilisant des variables, des patterns et des fonctions., Explorons-le ligne par ligne:
Voici la réécriture du makefile ci-dessus, en supposant qu’il soit placé dans le répertoire ayant un seul fichierfoo.c: