2010-05-13 8 views

Répondre

476

Vous avez plusieurs options pour configurer des variables de l'extérieur de votre makefile:

  • De l'environnement - chaque variable d'environnement est transformé en une variable makefile avec le même nom et la valeur.

    Vous pouvez également définir l'option -e (alias --environments-override) sur, et vos variables d'environnement redéfinirez cessions effectuées dans makefile (à moins que ces affectations utilisent eux-mêmes le override directive. Cependant, on ne recommande pas, et il est beaucoup mieux et flexible utiliser ?= affectation (l'opérateur d'affectation variable conditionnelle, il a seulement un effet si la variable est pas encore définie):

    FOO?=default_value_if_not_set_in_environment 
    

    Notez que certaines variables ne sont pas héritées de l'environnement:

    • MAKE est obtenu à partir du nom du script
    • SHELL est soit fixée dans un makefile, ou par défaut /bin/sh (justification: les commandes sont spécifiées au sein du makefile, et ils sont spécifiques à la coquille).
  • ligne de commande-make peut accepter des affectations variables dans le cadre de sa ligne de commande, mêlée à des cibles:

    make target FOO=bar 
    

    Mais toutes les affectations à la variable FOO dans le makefile seront ignorés sauf si vous utilisez le override directive dans l'affectation. (L'effet est le même que pour l'option -e pour les variables d'environnement).

  • Exportation du parent Faire - si vous appelez faire à partir d'un Makefile, vous écrivez doit généralement pas explicitement les affectations de variables comme celui-ci:

    # Don't do this! 
    target: 
         $(MAKE) -C target CC=$(CC) CFLAGS=$(CFLAGS) 
    

    Au lieu de cela, une meilleure solution pourrait consister à exporter ces variables . L'exportation d'une variable le fait dans l'environnement de chaque invocation de shell, et les appels à partir de ces commandes choisissent ces variables d'environnement comme indiqué ci-dessus.

    # Do like this 
    CFLAGS=-g 
    export CFLAGS 
    target: 
         $(MAKE) -C target 
    

    Vous pouvez également exporter toutes les variables à l'aide export sans arguments.

+3

pour passer de la ligne de commande quelque chose avec des espaces faire '' faire A = '' comme df '' ' –

+2

On dirait que vous demandez des problèmes si vous vous souciez des variables d'environnement. D'une part, c'est un cauchemar de débogage si cela fonctionne à l'endroit A et non à l'endroit B, juste parce qu'ils ont des environnements différents. –

+0

Il est en fait orthographié --environment-overrides – user7610

115

La façon la plus simple est:

make foo=bar target 

Ensuite, dans votre makefile vous pouvez vous référer à $(foo). Notez que ceci ne se propagera pas automatiquement aux sous-marques.

Si vous utilisez des sous-marques, consultez cet article: Communicating Variables to a Sub-make

+2

par sous-fait vous voulez dire aux makefiles 'inclus' dans le makefile principal? – Pablo

+2

@Michael: Cela signifie appeler make depuis l'intérieur du makefile. J'ai mis à jour ma réponse puisque vous semblez être intéressé par ce détail. –

35

Supposons que vous avez un makefile comme ceci:

action: 
    echo argument is $(argument) 

Vous appelleriez alors make action argument=something

+2

afin que la cible et les arguments peuvent être échangés en termes de position? – Pablo

+3

@Michael: Oui (voir la réponse de Mark Byers) – nc3b

16

De l'manual:

Les variables de la marque peuvent provenir de l'environnement dans lequel make est exécuté. Chaque variable d'environnement qui rend visibles au démarrage est transformée en une variable make avec le même nom et la même valeur. Toutefois, une affectation explicite dans le fichier makefile ou avec un argument de commande remplace l'environnement.

Alors vous pouvez faire (de bash):

FOOBAR=1 make 

entraînant une variable FOOBAR dans votre Makefile.

+0

Je n'aime pas la manière de l'environnement, mais merci – Pablo

+1

L'autre moyen est en effet mieux dans presque tous les cas. Je vais laisser ceci ici pour l'exhaustivité. – Thomas

2

Si vous faites un fichier appelé Makefile et ajouter une variable comme cette $ (unittest) alors vous serez en mesure d'utiliser cette variable dans le Makefile même avec des jokers

exemple:

make unittest=* 

J'utilise BOOST_TEST et en donnant un caractère générique au paramètre --run_test = $ (unittest) alors, je vais pouvoir utiliser une expression régulière pour filtrer le test que je veux que mon Makefile courir

1

Il existe une autre option non citée ici qui est incluse dans le livre Make de GNU par Stallman et McGrath (voir http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_7.html). Il donne l'exemple:

archive.a: ... 
ifneq (,$(findstring t,$(MAKEFLAGS))) 
     +touch archive.a 
     +ranlib -t archive.a 
else 
     ranlib archive.a 
endif 

Il consiste à vérifier si un paramètre donné apparaît dans MAKEFLAGS. Par exemple ... supposons que vous étudiez des threads en C++ 11 et que vous ayez divisé votre étude en plusieurs fichiers (class01, ..., classNM) et que vous souhaitiez: compiler puis tout et exécuter individuellement ou compiler un à la fois et exécutez-le si un drapeau est spécifié (-r, par exemple).Ainsi, vous pourriez trouver la Makefile suivante:

CXX=clang++-3.5 
CXXFLAGS = -Wall -Werror -std=c++11 
LDLIBS = -lpthread 

SOURCES = class01 class02 class03 

%: %.cxx 
    $(CXX) $(CXXFLAGS) -o [email protected] $^ $(LDLIBS) 
ifneq (,$(findstring r, $(MAKEFLAGS))) 
    ./[email protected] 
endif 

all: $(SOURCES) 

.PHONY: clean 

clean: 
    find . -name "*.out" -delete 

Ayant cela, vous avez:

  • construire et exécuter un fichier w/make -r class02;
  • construire tout w/make ou make all;
  • construire et exécuter tous les w/make -r (supposons que tous contiennent une certaine sorte de assert choses et vous voulez juste les tester)
2
export ROOT_DIR=<path/value> 

utiliser la variable, $(ROOT_DIR) dans le Makefile .