Yapmak için komut satırından ek değişkenler iletme


614

Değişkenleri bir GNU Makefile dosyasına komut satırı bağımsız değişkenleri olarak iletebilir miyim? Başka bir deyişle, sonunda Makefile'de değişken olacak bazı argümanları aktarmak istiyorum.

Yanıtlar:


753

Dosyanızın dışından değişkenleri ayarlamak için birkaç seçeneğiniz vardır:

  • Ortamdan - her ortam değişkeni aynı ad ve değere sahip bir makefile değişkenine dönüştürülür.

    Ayrıca -e(aka --environments-override) seçeneğini de ayarlamak isteyebilirsiniz ve ortam değişkenleriniz makefile'a yapılan atamaları geçersiz kılar (bu atamaların kendileri overrideyönerge kullanmadığı sürece . Ancak, önerilmez ve ?=atamayı (koşullu değişken) kullanmak çok daha iyi ve esnektir atama işleci, yalnızca değişken henüz tanımlanmadıysa bir etkisi vardır):

    FOO?=default_value_if_not_set_in_environment
    

    Bazı değişkenlerin ortamdan miras alınmadığını unutmayın:

    • MAKE senaryo adından alınmıştır
    • SHELLbir makefile içinde ayarlanır veya varsayılan olarak /bin/sh(rationale: komutlar makefile içinde belirtilir ve kabuklara özgüdür).
  • Komut satırından - komut satırının birmake parçası olarak değişken atamaları hedeflerle karışabilir:

    make target FOO=bar
    

    Ancak , atamada yönergeyi kullanmazsanız, makefile içindeki değişkene yapılan tüm atamalar FOOyok sayılır . (Etki, ortam değişkenleri seçeneğiyle aynıdır ).override-e

  • Üst markadan dışa aktarma - Bir Makefile'den Make'ı çağırırsanız, genellikle açıkça aşağıdaki gibi değişken atamaları yazmamalısınız:

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

    Bunun yerine, bu değişkenleri dışa aktarmak daha iyi bir çözüm olabilir. Bir değişkeni dışa aktarmak, onu her kabuk çağrısının ortamına dönüştürür ve bu komutlardan çağrı yap, bu ortam değişkenini yukarıda belirtildiği gibi seçer.

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

    Ayrıca bağımsız değişkenleri kullanarak tüm değişkenleri dışa aktarabilirsiniz export.


10
komut satırından boşluk ile bir şey yapmakmake A='"as df"'
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

4
Ortam değişkenlerine önem veriyorsanız sorun istediğiniz anlaşılıyor. Birincisi, sadece farklı ortamlara sahip oldukları için B yerine değil, A yerinde çalışıyorsa, bir hata ayıklama kabusu.
James Moore

12
Sadece deneyime dayanarak, CFLAGS gibi şeyleri dışa aktarmak büyük projeler için kabus için bir reçetedir. Büyük projeler genellikle yalnızca belirli bir bayrak kümesiyle derlenen (hiç kimsenin düzeltmeyi rahatsız etmediği) 3. parti kütüphaneleri vardır. CFLAGS'ı dışa aktarırsanız, projenizin CFLAGS'ları 3. taraf kitaplıklarını geçersiz kılar ve derleme hatalarını tetikler. Alternatif bir yol olarak tanımlamak export PROJECT_MAKE_ARGS = CC=$(CC) CFLAGS=$(CFLAGS)ve iletmek olabilir make -C folder $(PROJECT_MAKE_FLAGS). Eğer kütüphanenin yapıtını çevreyi görmezden gelmesini söylemenin bir yolu varsa, bu ideal olur (-e'nin tersi).
RD

24
UYARI: Yukarıdaki "Üst öğeden dışa aktarma" bölümünde, "Bunu yapma!" olduğu eleştirel yanıltıcı . Alt makefile komut satırında geçersiz kılar atamalar değişken geçirme ancak ihraç değişkenler do not alt makefile atamaları geçersiz kılar. Bir alt makefile değişkenler geçirilmesi için bu iki yöntem vardır değil eşdeğer ve karıştırılmamalıdır.
Jonathan Ben-Avraham

4
Herhangi bir fark ? make target FOO=bar make FOO=bar target?
gfan

213

En basit yol:

make foo=bar target

Daha sonra makyaj dosyanızda $(foo) . Bunun otomatik olarak alt markalara yayılmayacağını unutmayın.

Alt marka kullanıyorsanız, şu makaleye bakın: Değişkenleri Alt Marka ile İletişim


2
alt-make includedile ana makefile makefiles demek ?
Pablo

2
@Michael: Bu, makefile içinden make yapmak demek. Bu ayrıntıyla ilgileniyor gibi göründüğün için cevabımı güncelledim.
Mark Byers

2
"Bunun otomatik olarak alt markalara yayılmayacağını unutmayın." Gerçek dışı! "Varsayılan olarak, yalnızca ortamdan veya komut satırından gelen değişkenler özyinelemeli çağrılara geçirilir. Diğer değişkenleri iletmek için verme yönergesini kullanabilirsiniz." gnu.org/software/make/manual/html_node/…
ThomasMcLeod

82

Diyelim ki böyle bir makyajınız var:

action:
    echo argument is $(argument)

O zaman derdiniz make action argument=something


5
böylece hedef ve argümanlar konum bakımından değiştirilebilir mi?
Pablo

4
@Michael: Evet (Mark Byers'ın cevabına bakınız)
nc3b

25

Gönderen manuel :

Markadaki değişkenler, markanın çalıştığı ortamdan gelebilir. Başladığında gören her ortam değişkeni, aynı ada ve değere sahip bir marka oluşturma değişkenine dönüştürülür. Ancak, makefile veya komut bağımsız değişkeni içeren açık bir atama ortamı geçersiz kılar.

Böylece (bash'tan) şunları yapabilirsiniz:

FOOBAR=1 make

FOOBARMakefile'nizde bir değişkenle sonuçlanır .


2
Diğer yol ise neredeyse tüm durumlarda daha iyidir. Bunu bütünlük için burada bırakacağım.
Thomas

Aynı satırda make komutundan önce değişkenlerin atanmasını gösteren tek cevap budur - bunun bir sözdizimi hatası olmadığını bilmeye değer.
M_M

7

Burada belirtilmeyen, Stallman ve McGrath'in GNU Make kitabında yer alan başka bir seçenek var (bkz. Http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_7.html ). Örneği sağlar:

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

Belirli bir parametrenin görünüp görünmediğini doğrulamayı içerir MAKEFLAGS. Örneğin, diyelim ki c ++ 11'deki konuları inceliyorsunuz ve çalışmanızı birden fazla dosyaya ( class01, ..., classNM) bölüyorsunuz ve şunları yapmak istiyorsunuz: hepsini derleyin ve tek tek çalıştırın veya bir zamanını seçin ve bir bayrak belirtilmişse ( -rörneğin) çalıştırın. Yani, aşağıdakileri ortaya çıkarabilirsiniz Makefile:

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

SOURCES = class01 class02 class03

%: %.cxx
    $(CXX) $(CXXFLAGS) -o $@.out $^ $(LDLIBS)
ifneq (,$(findstring r,  $(MAKEFLAGS)))
    ./$@.out
endif

all: $(SOURCES)

.PHONY: clean

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

Buna sahip olsaydınız:

  • bir dosya oluşturmak ve çalıştırmak w / make -r class02;
  • tüm w / makeveya make all;
  • yapı ve çalışan tüm w / make -r(hepsi assert bazı şeyler belli bir tür içerir ve sadece hepsini test etmek istediğinizi varsayalım)

6

anlaşılan

komut argümanları üzerine yazma ortam değişkeni

Makefile

send:
    echo $(MESSAGE1) $(MESSAGE2)

Örneği çalıştır

$ MESSAGE1=YES MESSAGE2=NG  make send MESSAGE2=OK
echo YES OK
YES OK

5

Makefile adlı bir dosya yaparsanız ve bu $ (unittest) gibi bir değişken eklerseniz, bu değişkeni Makefile içinde joker karakterlerle bile kullanabilirsiniz.

misal :

make unittest=*

BOOST_TEST kullanın ve --run_test = $ (unittest) parametresine bir joker karakter vererek daha sonra Makefile çalıştırmak istiyorum testi filtrelemek için düzenli ifade kullanabilecektir


4
export ROOT_DIR=<path/value>

Sonra $(ROOT_DIR)Makefile değişkenini kullanın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.