Make : aide mémoire

Anne make développement

Tout d’abord, le lien vers la doc de gmake.

Anti-sèche pour les variables

  • $@ et $< : la cible et la (première) dépendance ;
  • $* : ce qui correspond au % dans la recette ;
  • $^ : toutes les dépendances, séparées par des espaces ;
  • $? : toutes les dépendances plus récentes que la cible, séparées par des espaces ;
  • D et F pour extraire le répertoire et le fichier, par exemple $(@D) et $(@F) pour avoir séparément le répertoire et le fichier de la cible.

Pour les autres, voir dans la doc.

Utiliser bash

Quand la variable SHELL n’est pas définie, le shell par défaut est /bin/sh qui est très minimal (mais portable…). Si on a besoin de bash, il faut ajouter au début du Makefile :

SHELL=/bin/bash

Tester la cible

On veut parfois faire des vérifications qui ne sont pas nécessaires pour certaines cibles. Pour faire ça, on peut tester la variable $(MAKECMDGOALS) :

ifneq ($(MAKECMDGOALS), clean)
  # vérification des outils
  ...
endif

Tester la présence d’un outil

TOOLNAME=toto
#TOOLNAME=gcc
TOOL=$(shell which $(TOOLNAME))

ifeq ($(TOOL),)

do_it:
	@echo "Don't have $(TOOLNAME)"

else

do_it:
	@echo "Have $(TOOLNAME)"

endif

Tester quelque chose d’indispensable

Ci-dessus, on a testé la présence d’un outil nécessaire à une certaine cible, mais on peut aussi vouloir tester quelque chose d’indispensable à l’utilisation du Makefile, comme par exemple, le chemin des fichiers à inclure. Voilà une solution à ce problème :

TOOLS_DIR=../../tools
TEST_TOOLS_DIR=$(shell if [ -d $(TOOLS_DIR) ] ; then echo "ok" ; fi)
ifneq ($(TEST_TOOLS_DIR),ok)
  $(warning No such directory: $(TOOLS_DIR))
  $(error Please adjust TOOLS_DIR definition in the Makefile)
endif

Fonction

define cmp_oracle
  LOG=$(1) \
  ORACLE=$(2) \
  OK=$(3) \
  if diff $$ORACLE $$LOG > /dev/null ; then \
    echo -e "Bravo... Test \e[32mOk\e[0m" ; \
    touch $$OK ; \
  else \
    echo -e "\e[1m\e[31mDIFFERENCES\e[0m : diff $$ORACLE $$LOG" ; \
    echo -e "To force a new run of the test:" ; \
    echo -e "  rm $$LOG ; make $$OK"; \
    echo -e "\e[31mTo accept the new results\e[0m: " ; \
    echo -e "  cp $$LOG $$ORACLE" ; \
    rm -f $$OK ; \
  fi
endef

et pour l’appeler:

$(call cmp_oracle, $*.log,  $*.oracle, $@)

Le mélange entre la syntaxe bash et la syntaxe make n’est pas toujours facile à ajuster. Par exemple :

define check_tool
  toolname=$(1) ; \
  if [ "$(shell which $(1))" == "" ] ; then \
    echo -e "$(TODO): sudo apt-get install $$toolname" ; \
  else \
    echo -e "$(OK): $$toolname installed" ; \
  fi
endef

Accès à la base de donnée interne

Lorsqu’on lance gmake, celui-ci commence par construire une base de donnée interne. On peut l’afficher grâce à l’option --print-data-base (ou -p).

Pour voir la base de donnée par défaut, on peut spécifier un Makefile bidon avec -f /dev/null.

Pour chercher par exemple la règle par défaut pour les fichiers .c, on peut faire :

$ make --print-data-base -f /dev/null 2>/dev/null | grep -A 6 '^\.c:' | grep -v '^#'

Supprimer les définitions par défaut

  • -r ou --no-builtin-rules permet de ne pas utiliser les règles implicites ;
  • -R ou --no-builtin-variables permet de ne pas définir les variables //built-in// ;

Voir aussi :