2010-05-13 8 views

risposta

476

Sono disponibili diverse opzioni per impostare le variabili dall'esterno makefile:

  • Da ambiente - ogni variabile d'ambiente si trasforma in una variabile makefile con lo stesso nome e valore.

    Si consiglia inoltre di impostare -e opzione (aka --environments-override), e le variabili d'ambiente si ignorare le assegnazioni fatte in makefile (a meno che queste assegnazioni si usano il override directive. Tuttavia, non è raccomandato, ed è molto meglio e flessibile per utilizzare ?= assegnazione (l'operatore di assegnazione variabile condizionale, ha effetto solo se la variabile non è ancora definita):

    FOO?=default_value_if_not_set_in_environment 
    

    noti che alcune variabili non vengono ereditate dall'ambiente:

    • MAKE è ottenuto dal nome dello script
    • SHELL si sia impostata all'interno di un makefile, o default /bin/sh (logica: i comandi sono specificati all'interno del makefile, e sono shell-specifico).
  • da linea di comando-make può richiedere assegnazioni di variabili come parte della sua linea di comando, si mescolava con gli obiettivi di:

    make target FOO=bar 
    

    Ma poi tutte le assegnazioni a FOO variabile all'interno del makefile saranno ignorati a meno che non si utilizzi lo override directive nell'assegnazione. (L'effetto è lo stesso dell'opzione -e per le variabili di ambiente).

  • Esportazione dal genitore Fai - se si chiama Fare da un Makefile, di solito non si dovrebbe scrivere in modo esplicito le assegnazioni delle variabili come questo:

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

    Invece, soluzione migliore potrebbe essere quella di esportare queste variabili . L'esportazione di una variabile lo rende nell'ambiente di ogni invocazione di shell, e Crea chiamate da questi comandi seleziona queste variabili d'ambiente come specificato sopra.

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

    È inoltre possibile esportare tutte le variabili utilizzando export senza argomenti.

+3

passare dalla riga di comando con gli spazi fai '' make A = '"come df"' '' –

+2

Sembra che tu stia chiedendo problemi se ti interessano le variabili di ambiente. Per prima cosa, è un incubo di debug se funziona nel posto A e non nel posto B, solo perché hanno ambienti diversi. –

+0

In realtà viene digitato - override dell'ambiente – user7610

115

Il modo più semplice è:

make foo=bar target 

Poi, nel tuo makefile si può fare riferimento a $(foo). Nota che questo non si propagherà automaticamente alle sub-marche.

Se si utilizza sotto-marche, leggi questo articolo: Communicating Variables to a Sub-make

+2

di sotto-ti intendi per i makefile 'inclusi' nel makefile principale? – Pablo

+2

@ Michael: Significa richiamare make dall'interno del makefile. Ho aggiornato la mia risposta poiché sembra che tu sia interessato a questo dettaglio. –

35

Diciamo che avete un makefile come questo:

action: 
    echo argument is $(argument) 

Si potrebbe quindi chiamare make action argument=something

+2

in modo che la destinazione e gli argomenti possano essere scambiati in termini di posizione? – Pablo

+3

@ Michael: Sì (vedere la risposta di Mark Byers) – nc3b

16

Dal manual:

Le variabili nella marca possono provenire da l'ambiente in cui viene eseguito make. Ogni variabile d'ambiente che make vede all'avvio viene trasformata in una variabile make con lo stesso nome e valore. Tuttavia, un'assegnazione esplicita nel makefile, o con un argomento di comando, sovrascrive l'ambiente.

così si può fare (da bash):

FOOBAR=1 make 

risultante in una variabile FOOBAR nel Makefile.

+0

Non mi piace il modo in cui l'ambiente, ma grazie – Pablo

+1

L'altro modo è davvero migliore in quasi tutti i casi. Lascerò questo qui per completezza. – Thomas

2

Se si commette un file chiamato Makefile e aggiungere una variabile come questo $ (unittest) allora si sarà in grado di utilizzare questa variabile all'interno del Makefile anche con caratteri jolly

esempio:

make unittest=* 

io uso BOOST_TEST e dando un jolly per il parametro --run_test = $ (unittest) allora sarò in grado di utilizzare espressioni regolari per filtrare il test voglio che il mio Makefile per eseguire

1

C'è un'altra opzione non citata qui che è inclusa nel libro GNU Make di Stallman e McGrath (vedere http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_7.html). Esso fornisce l'esempio:

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

essa comporta la verifica se un dato parametro appare in MAKEFLAGS. Ad esempio .. supponiamo che tu stia studiando i thread in C++ 11 e hai diviso il tuo studio su più file (class01, ..., classNM) e vuoi: compilare poi tutto ed eseguirlo individualmente o compilarne uno alla volta ed eseguirlo se viene specificato un flag (-r, ad esempio).Quindi, si potrebbe venire con il seguente Makefile:

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 

Avere che, devi:

  • costruire e gestire un file w/make -r class02;
  • build all w/make o make all;
  • costruire e gestire tutti w/make -r (supponiamo che tutti loro contengono qualche certo tipo di cose affermare e si desidera solo per testarli tutti)
2
export ROOT_DIR=<path/value> 

Quindi utilizzare la variabile, $(ROOT_DIR) nel Makefile .