Makefile'da bir değişken nasıl yazdırılır


247

Dosyamda, bir değişken 'NDK_PROJECT_PATH' var, sorum şu: Derlendiğinde nasıl yazdırabilirim?

"$ PATH" dizesini gösteren dosya yankı yap okudum ve denedim:

@echo $(NDK_PROJECT_PATH)
@echo $(value NDK_PROJECT_PATH)

Her ikisi de bana veriyor

"build-local.mk:102: *** missing separator.  Stop."

Biri neden benim için çalışmadığını biliyor mu?

Yanıtlar:


223

Bu yöntemi kullanarak ("var" adında bir değişkenle) makefile okundukça değişkenleri yazdırabilirsiniz (bu soruyu uygun şekilde etiketlediğiniz gibi GNU make varsayalım):

$(info $$var is [${var}])

Kabuğa hangi markanın geçeceğini görmek için bu yapıyı herhangi bir tarife ekleyebilirsiniz:

.PHONY: all
all: ; $(info $$var is [${var}])echo Hello world

Şimdi, burada olan şey, tüm tarifin ( $(info $$var is [${var}])echo Hello world) tek bir özyinelemeli olarak genişletilmiş değişken olarak depolanmasıdır . Tarifi çalıştırmaya karar verdiğinizde (örneğin yapmasını söylediğinizde all), değişkeni genişletir ve sonuçta ortaya çıkan her satırı ayrı ayrı kabuğa iletir.

Yani, acı verici detaylarda:

  • Genişler $(info $$var is [${var}])echo Hello world
  • Bunu yapmak için önce genişler $(info $$var is [${var}])
    • $$ gerçek olur $
    • ${var}olur :-)(söyle)
    • Yan etki, $var is [:-)]standart çıkışta görünür
    • Gerçeğin genişlemesi $(info...)boş
  • Make ile kaldı echo Hello world
    • echo Hello worldKabuktan ne yapmasını isteyeceğini size bildirmek için önce stdout'ta baskılar yapın
  • Kabuk Hello worldstdout üzerine yazdırır.

2
PHONY yerine (dot) .PHONY olmalı mı?
hammadian

172

Gereğince GNU manuel olun ve ayrıca cevap aşağıda 'bobbogo' tarafından işaret kullanabilirsiniz bilgileri / uyarı / hata ekranı metne.

$(error   text…)
$(warning text…)
$(info    text…)

Değişkenleri yazdırmak için,

$(error   VAR is $(VAR))
$(warning VAR is $(VAR))
$(info    VAR is $(VAR))

'error' , hata dizesini gösterdikten sonra make işlemini durdurur


Vay, bunu bilmiyordum. Günlüklerdeki komutu çoğaltan ekodan çok daha iyi.
deepelement


44

Sadece bir çıktı istiyorsanız, $(info)tek başına kullanmak istersiniz . Bunu bir Makefile'de herhangi bir yerde yapabilirsiniz ve bu satırın ne zaman değerlendirildiğini gösterecektir:

$(info VAR="$(VAR)")

VAR="<value of VAR>"Bu satırdaki işlemleri yaparken çıktı alır . Bu davranış çok konuma bağlıdır, bu nedenle $(info)genişlemenin, değiştirilebilecek her şey gerçekleştikten SONRA gerçekleştiğinden emin olmalısınız $(VAR)!

Daha genel bir seçenek, bir değişkenin değerini yazdırmak için özel bir kural oluşturmaktır. Genel olarak, kurallar değişkenler atandıktan sonra yürütülür, bu size gerçekte kullanılan değeri gösterecektir. (Yine de, bir kuralın bir değişkeni değiştirmesi mümkündür .) İyi biçimlendirme, bir değişkenin neye ayarlandığını netleştirmeye yardımcı olur ve $(flavor)işlev size bir şeyin ne tür bir değişken olduğunu söyler. Yani bu kuralda:

print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true
  • $*% desenin kuralda eşleştiği gövdeye genişler .
  • $($*)adı tarafından verilen değişkenin değerine genişler $*.
  • [Ve ]açıkça değişken genişleme tasvir. Ayrıca "ve "benzeri kullanabilirsiniz .
  • $(flavor $*)ne tür bir değişken olduğunu söyler. NOT: $(flavor) değişken adını alır , genişlemesini değil. Yani diyorsan make print-LDFLAGS,$(flavor LDFLAGS) , istediğin budur.
  • $(info text)çıktı sağlar. Genişlemenin bir yan etkisi olarak stdout'una baskı yapıntext . Yine de genişlemesi $(info)boş. Bunu şöyle düşünebilirsiniz @echo, ama önemlisi kabuğu kullanmaz, bu yüzden kabuk alıntı kuralları hakkında endişelenmenize gerek yoktur.
  • @truesadece kural için bir komut sağlamak içindir. Bu olmadan, make de çıktı print-blah is up to date. İşlem @trueyapmamanın daha açık olduğunu hissediyorum .

Koşmak, sen almak

$ make print-LDFLAGS
LDFLAGS is a recursive variable set to [-L/Users/...]

Bu soruya bir cevap sağlamaz. Bir yazardan eleştiri veya açıklama istemek için gönderilerinin altına bir yorum bırakın - her zaman kendi yayınlarınıza yorum yapabilirsiniz ve yeterli bir üne sahip olduğunuzda herhangi bir yazı hakkında yorum yapabilirsiniz . - Yorumdan
Dragon Energy

İnceleme için teşekkürler. Yeterli saygınlığım olduğunda yorum yapabileceğimi anlıyorum, ancak bu arada ne yapmalıyım? Cevabımın katma değer sağladığına inanıyorum, bu yüzden eklememeliyim?
Jim Nasby

1
Bunu, bu cevaba yersiz bir yorum olarak ifade etmek yerine, yorum yaptığınız kişiyle rekabet eden bağımsız bir yanıt olarak yeniden yazmanızı öneririm.
Charles Duffy

@JimNasby Evet, Charles'ın önerdiği. Aslında bir tür kırmızı bayrak gibi, "yorum için yeterli özür değil" parçasını kaldırmak için bir başlangıç ​​olarak yardımcı olabilir. Eğer cevabı tam bir cevaba dönüştürürseniz (istediğiniz her şeyi düzenleyebilirsiniz), gayet güzel yapmalıdır. Şerefe.
Dragon Energy

Mükemmel - bu şimdi çok daha iyi bir cevap. :)
Charles Duffy

6

@echo $ (NDK_PROJECT_PATH) bunu yapmanın iyi bir yoludur. Hatanın oradan geldiğini sanmıyorum. Genellikle bu hata, girintiyi yanlış yazdığınızda ortaya çıkar: Bence bir sekme olması gereken boşluklar var.


2
'@Echo $ (NDK_PROJECT_PATH)' denedim, hala "build-local.mk:102: *** ayırıcı eksik. Dur." Hatası alıyorum. 'Echo' dan sonra sadece 1 alanım var, '@echo' dan önce boşluk veya sekme yok.
michael

Hatanın bu satırdan geldiğinden emin misiniz? Bu çizgi bir kuralda mı? Muhtemelen girintili olmalıdır ...

6

Tüm sürümleri, makekomut satırlarının satırdaki ilk karakter olarak bir SEKME (boşluk değil) ile girintilenmesini gerektirir. Bize sadece söz konusu iki satır yerine tüm kuralı gösterdiyseniz, daha net bir cevap verebiliriz, ancak şöyle bir şey olmalı:

myTarget: myDependencies
        @echo hi

burada ikinci satırdaki ilk karakter SEKME olmalıdır.


4

Çalıştırmak make -n ; değişkenin değerini gösterir ..

Makefile ...

all:
        @echo $(NDK_PROJECT_PATH)

Komut:

export NDK_PROJECT_PATH=/opt/ndk/project
make -n 

Çıktı:

echo /opt/ndk/project

Bu oldukça yararlı ve yürütme yerine--just-print aynı kullanıyorum
Fredrick Gauss

3

Bu makefile, 'eksik ayırıcı' hata iletisini oluşturur:

all
    @echo NDK_PROJECT_PATH=$(NDK_PROJECT_PATH)

done:
        @echo "All done"

@echo "All done"( done:Kural ve eylem büyük ölçüde gereksiz olsa da) önünde bir sekme var , ama önce değil @echo PATH=$(PATH).

Sorun, satır başlangıcının bir hedef çizgi veya bir makro çizgi olduğunu ve her ikisinin de olmadığını belirtmek alliçin iki nokta üst üste :veya eşittir =olması gerektiğinden ayırıcı eksiktir.

Bir değişkenin değerini yansıtan eylem bir hedefle, muhtemelen bir kukla veya PHONEY hedefiyle ilişkilendirilmelidir. Ve bu hedef çizginin üzerinde iki nokta üst üste olmalı. Eğer bir eklerseniz :sonra allörnekte makefileve bir sekme ile sonraki satırda lider boşlukları yerine, bu sanely çalışacaktır.

Muhtemelen orijinalde 102. satırın yakınında benzer bir sorununuz var makefile. Başarısız olan eko işlemlerinden önce 5 boş olmayan, yorum yapmayan satır gösterdiyseniz, muhtemelen tanıyı bitirmek mümkün olabilir. Ancak, soru Mayıs 2013'te sorulduğundan, kırıkların makefileşimdi (Ağustos 2014) hala mevcut olması olası değildir , bu nedenle bu cevap resmi olarak doğrulanamaz. Sadece sorunun meydana geldiği makul bir yolu göstermek için kullanılabilir.


3

Makefile üzerinde değişiklik yapmaya gerek yok.

$ cat printvars.mak
print-%:
        @echo '$*=$($*)'

$ cd /to/Makefile/dir
$ make -f ~/printvars.mak -f Makefile print-VARIABLE

2

Sorun yankı sadece bir yürütme bloğu altında çalışıyor olmasıdır. "xx:" ifadesinden sonraki herhangi bir şey

Dolayısıyla, ilk yürütme bloğunun üzerindeki herhangi bir şey yalnızca başlatmadır, böylece yürütme komutu kullanılamaz.

Yani bir yürütme bloku oluşturun


1

Bu genel bir şekilde yapılabilir ve karmaşık bir dosyada hata ayıklama yaparken çok faydalı olabilir. Başka bir cevapta açıklananla aynı tekniği izleyerek, herhangi bir marka dosyasına aşağıdakini ekleyebilirsiniz:

# if the first command line argument is "print"
ifeq ($(firstword $(MAKECMDGOALS)),print)

  # take the rest of the arguments as variable names
  VAR_NAMES := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))

  # turn them into do-nothing targets
  $(eval $(VAR_NAMES):;@:))

  # then print them
  .PHONY: print
  print:
          @$(foreach var,$(VAR_NAMES),\
            echo '$(var) = $($(var))';)
endif

Sonra herhangi bir değişkenin değerini dökümü için "baskı yap" yapabilirsiniz:

$ make print CXXFLAGS
CXXFLAGS = -g -Wall


0

Makefile'in kendisini değiştirmek istemiyorsanız, --evalyeni bir hedef eklemek için kullanabilir ve ardından yeni hedefi yürütebilirsiniz;

make --eval='print-tests: @echo TESTS $(TESTS) ' print-tests

Gerekli TAB karakterini komut satırına aşağıdakileri kullanarak ekleyebilirsiniz: CTRL-V, TAB

yukarıdan Makefile örneği:

all: do-something

TESTS=
TESTS+='a'
TESTS+='b'
TESTS+='c'

do-something:
        @echo "doing something"
        @echo "running tests $(TESTS)"
        @exit 1

Senaryonuzu çalıştırmaya çalışıyorum ama hata alıyorummake: *** missing separator. Stop.
Rinaldi Segecin

Ah, üzgünüm, düzeltildi. "Baskı testleri" hedefinin sonunda eksik iki nokta üst üste.
Wade

Aslında yeni satırlara ve sekmelere ihtiyacınız yok, noktalı virgül yeterli olacaktır:make --eval='print-tests: ; @echo TESTS $(TESTS)' print-tests
bobbogo

0

android yapmak kullanırsanız (mka) @echo $(NDK_PROJECT_PATH)işe yaramaz ve hata verir android yapmak değişkenleri yazdırmaya çalışıyorsanız bu cevabı*** missing separator. Stop." kullanın

NDK_PROJECT_PATH := some_value
$(warning $(NDK_PROJECT_PATH))

benim için çalıştı


0

Değişken değerini görmek istersem genellikle bir hatayla yankılanırım. (Yalnızca değeri görmek istiyorsanız. Yürütmeyi durdurur.)

@echo $ (hata NDK_PROJECT_PATH = $ (NDK_PROJECT_PATH))

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.