TL; DR bunu yapmaya çalışma
$ make run arg
bunun yerine komut dosyası oluşturun:
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
ve bunu yapın:
$ ./buildandrunprog.sh arg
belirtilen soruya cevap:
tarifte bir değişken kullanabilirsiniz
run: prog
./prog $(var)
sonra değişken atamayı bağımsız değişken olarak
$ make run var=arg
bu yürütülür ./prog arg
.
ama tuzaklardan sakının. bu yöntemin tuzaklarını ve diğer yöntemleri daha ayrıntılı olarak açıklayacağım.
sorunun arkasındaki varsayılan niyetin cevabı:
varsayım: prog
bazı argümanlarla çalıştırmak istiyorsunuz, ancak gerekirse çalıştırmadan önce yeniden yapılandırılmasını istiyorsunuz.
cevap: gerekirse yeniden inşa eden bir komut dosyası oluşturun
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
bu senaryo niyeti çok açık hale getiriyor. iyi yapmak için make'i kullanır: bina. toplu işlem için iyi olanı yapmak için bir kabuk betiği kullanır.
ayrıca, bir kabuk dosyasının tüm esnekliği ve ifadesi ile bir makefile'in tüm uyarıları olmadan ihtiyacınız olan her şeyi yapabilirsiniz.
ayrıca çağıran sözdizimi artık pratik olarak aynıdır:
$ ./buildandrunprog.sh foo "bar baz"
karşılaştırmak:
$ ./prog foo "bar baz"
aksine
$ make run var="foo bar\ baz"
arka fon:
make argümanları bir hedefe aktarmak için tasarlanmamıştır. komut satırındaki tüm bağımsız değişkenler, hedef (hedef olarak da bilinir), seçenek olarak veya değişken ataması olarak yorumlanır.
yani bunu çalıştırırsanız:
$ make run foo --wat var=arg
Marka yorumlayacak run
ve foo
güncellemeye hedefleri (hedefler) olarak tariflere göre. --wat
yapmak için bir seçenek olarak. ve var=arg
değişken atama olarak.
daha fazla ayrıntı için bkz. https://www.gnu.org/software/make/manual/html_node/Goals.html#Goals
terminoloji için bakınız: https://www.gnu.org/software/make/manual/html_node/Rule-Introduction.html#Rule-Introduction
değişken atama yöntemi ve neden buna karşı öneriyorum
$ make run var=arg
ve tarifteki değişken
run: prog
./prog $(var)
bu, bir reçete argümanları iletmenin en "doğru" ve en kolay yoludur. ama yapabilirken bağımsız değişken içeren bir programı çalıştırmak için kullanılacak kesinlikle şekilde kullanılmak üzere tasarlanmamıştır. bkz. https://www.gnu.org/software/make/manual/html_node/Overriding.html#Overriding
bence bunun büyük bir dezavantajı var: yapmak istediğiniz şey prog
argümanla yürütülmek arg
. ama yazmak yerine:
$ ./prog arg
yazıyorsun:
$ make run var=arg
boşluk içeren birden çok argümanı veya argümanı iletmeye çalışırken bu daha da zorlaşır:
$ make run var="foo bar\ baz"
./prog foo bar\ baz
argcount: 2
arg: foo
arg: bar baz
karşılaştırmak:
$ ./prog foo "bar baz"
argcount: 2
arg: foo
arg: bar baz
kayıt için bu benim prog
gibi görünüyor:
#! /bin/sh
echo "argcount: $#"
for arg in "$@"; do
echo "arg: $arg"
done
Ayrıca $(var)
, makefile içinde tırnak işaretleri koymamalısınız:
run: prog
./prog "$(var)"
çünkü o prog
zaman her zaman sadece bir argüman elde edilir:
$ make run var="foo bar\ baz"
./prog "foo bar\ baz"
argcount: 1
arg: foo bar\ baz
tüm bu yüzden bu rotaya karşı öneriyorum.
tamlık için burada "çalıştırmak için argüman geçirmek" için başka yöntemler vardır.
Yöntem 1:
run: prog
./prog $(filter-out $@, $(MAKECMDGOALS))
%:
@true
süper kısa açıklama: mevcut hedefi hedefler listesinden filtreleyin. %
Diğer hedefleri sessizce göz ardı etmek için hiçbir şey yapmayan tüm hedefi yakala ( ) oluştur .
yöntem 2:
ifeq (run, $(firstword $(MAKECMDGOALS)))
runargs := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
$(eval $(runargs):;@true)
endif
run:
./prog $(runargs)
süper kısa açıklama: Eğer hedef daha run
sonra ilk hedefi kaldırmak ve oluşturmak için kalan hedefler için hiçbir şey yapmayın eval
.
her ikisi de böyle bir şey yazmanıza izin verecek
$ make run arg1 arg2
daha derin bir açıklama çalışması için make kılavuzu: https://www.gnu.org/software/make/manual/html_node/index.html
yöntem 1 sorunları:
kısa çizgi ile başlayan argümanlar marka haline getirilir ve hedef olarak iletilmez.
$ make run --foo --bar
geçici çözüm
$ make run -- --foo --bar
eşit işaretli argümanlar marka haline getirilir ve geçilmez.
$ make run foo=bar
geçici çözüm yok
boşluklu tartışmalar garip
$ make run foo "bar\ baz"
geçici çözüm yok
bir argüman run
(hedefe eşit) olursa, o da kaldırılır
$ make run foo bar run
./prog foo bar
yerine koşacak./prog foo bar run
yöntem 2 ile geçici çözüm mümkün
eğer bir argüman meşru bir hedefse, o da çalıştırılacaktır.
$ make run foo bar clean
./prog foo bar clean
aynı zamanda hedefin tarifini de çalıştıracaktır clean
(var olduğu varsayılarak).
yöntem 2 ile geçici çözüm mümkün
meşru bir hedefi yanlış yazdığınızda, tüm hedefi yakalama nedeniyle sessizce yok sayılır.
$ make celan
sessizce görmezden gelir celan
.
geçici çözüm her şeyi ayrıntılı yapmaktır. böylece ne olduğunu görüyorsunuz. ancak bu, meşru çıktı için çok fazla gürültü yaratır.
yöntem 2 sorunları:
bir argüman mevcut bir hedefle aynı ada sahipse, make üzerine yazıldığına dair bir uyarı yazdırır.
bildiğim bir çözüm yok
eşit işaretli argümanlar marka haline getirilip yorumlanmayacak
geçici çözüm yok
boşluklarla tartışmalar hala garip
geçici çözüm yok
boşluk aralarıyla argümanlar eval
kırmaya çalışan hiçbir şey yapmazlar.
geçici çözüm: yukarıdaki gibi hiçbir şey yapmadan tüm hedefi yakalamak. yukarıdaki sorunla, yanlış bir şekilde meşru hedefleri sessizce görmezden gelecektir.
eval
çalışma zamanında makefile değiştirmek için kullanır . okunabilirlik ve hata ayıklama ve en az şaşkınlık ilkesi açısından ne kadar kötüye gidebilirsiniz .
geçici çözüm: bunu yapmayın !! 1 yerine çalışan ve sonra çalışan bir kabuk komut dosyası yazın prog
.
Ben sadece gnu marka kullanarak test ettik. diğer markaların davranışları farklı olabilir.
TL; DR bunu yapmaya çalışma
$ make run arg
bunun yerine komut dosyası oluşturun:
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
ve bunu yapın:
$ ./buildandrunprog.sh arg