Si vous utilisez GNU make, vous avez deux options (en plus de l'invocation make récursive, qui présente les problèmes décrits ci-dessus).
La première option consiste à utiliser des variables spécifiques à la cible. Vous les utilisez dans votre exemple original:
debug: CPPFLAGS=$(CPPFLAGS_DEBUG)
debug: CFLAGS=$(CFLAGS_DEBUG)
optimal: CPPFLAGS=$(CPPFLAGS_OPTIMAL)
optimal: CFLAGS=$(CFLAGS_OPTIMAL)
La chose vous manque est que les variables spécifiques à la cible sont héritées par leurs conditions. Vous devez donc déclarer les prérequis de "debug" et "optimal" (ils n'ont pas besoin d'avoir des recettes elles-mêmes, en fait, elles peuvent être déclarées .PHONY). Ainsi, par exemple:
debug: CPPFLAGS=$(CPPFLAGS_DEBUG)
debug: CFLAGS=$(CFLAGS_DEBUG)
debug: appfs appmount
optimal: CPPFLAGS=$(CPPFLAGS_OPTIMAL)
optimal: CFLAGS=$(CFLAGS_OPTIMAL)
optimal: appfs appmount
Maintenant, si vous exécutez « make debug » il va construire deux AppFS et appmount avec les paramètres de débogage pour CPPFLAGS et CFLAGS; Si vous exécutez "make optimal", il utilisera les paramètres optimaux.
Cependant, cela a le même inconvénient que l'invocation récursive de make; si vous lancez "make appfs" directement, aucun des paramètres ne sera utilisé; les variables spécifiques à la cible sont héritées du (des) parent (s) qui ont conduit à la construction de la cible dans cet appel de make. Si aucune de ces cibles n'est dans la liste des cibles parentes, leurs variables spécifiques à la cible ne seront pas utilisées.
La deuxième option, qui vous donne à peu près exactement l'interface que vous recherchez, consiste à utiliser la variable MAKECMDGOALS pour décider si l'utilisateur a demandé des versions optimales ou de débogage. Par exemple quelque chose comme ceci:
CPPFLAGS_debug = <debug CPPFLAGS>
CFLAGS_debug = <debug CFLAGS>
CPPFLAGS_optimal = <optimal CPPFLAGS>
CFLAGS_optimal = <optimal CFLAGS>
STYLE := $(firstword $(filter debug optimal,$(MAKECMDGOALS)))
$(if $(STYLE),,$(error No style "debug" or "optimal" set))
CPPFLAGS = $(CPPFLAGS_$(STYLE))
CFLAGS = $(CFLAGS_$(STYLE))
debug optimal:
.PHONY: debug optimal
Ou si vous préférez, vous pouvez choisir un comportement par défaut si l'on est pas donné, au lieu de jeter une erreur; ce choisit « debug » par défaut par exemple:
STYLE := $(firstword $(filter optimal,$(MAKECMDGOALS)) debug)
Cependant, il est important de noter que la raison pour laquelle cela semble difficile à faire est que ce que vous demandez est fondamentalement viciée. Suggérer qu'un seul fichier dérivé dans un répertoire doit être construit de l'une des deux façons différentes en fonction d'un paramètre de temps de construction pose des problèmes. Comment savez-vous quelle variante a été utilisée en dernier? Supposons que vous exécutiez make avec l'optimisation, que vous modifiiez certains fichiers, puis que vous exécutiez à nouveau cette fois avec le débogage ... maintenant certains de vos fichiers sont optimisés et d'autres sont débogués.
La meilleure façon de gérer différentes variantes de construction de code est de s'assurer que les fichiers dérivés sont uniques. Cela signifie que les cibles de débogage sont écrites dans un répertoire et que les cibles optimisées sont écrites dans un répertoire différent. Une fois que vous faites cette distinction, le reste tombe facilement: vous utilisez simplement les indicateurs de débogage lorsque vous écrivez les règles pour les cibles de débogage et les indicateurs optimaux lorsque vous écrivez les règles pour les cibles optimisées.
Il devait y avoir un meilleur moyen - et «hérité des prérequis» est le bit que je ne connaissais pas. –
Très bien, j'utilise cette solution maintenant (même si c'est plus spécifique à GNU make). J'ai également ajouté "$ (si $ (filtre 1, $ (mots $ (MAKECMDGOALS))), $ (erreur $ (ERROR_NOTARGET)),)" après la vérification de style pour s'assurer que l'utilisateur fournit une cible de construction (par exemple "). –