TL; DR jangan mencoba melakukan ini
$ make run arg
alih-alih membuat skrip:
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
dan lakukan ini:
$ ./buildandrunprog.sh arg
menjawab pertanyaan yang disebutkan:
Anda dapat menggunakan variabel dalam resep
run: prog
./prog $(var)
kemudian lulus tugas variabel sebagai argumen untuk dibuat
$ make run var=arg
ini akan mengeksekusi ./prog arg
.
tapi waspadalah terhadap jebakan. Saya akan menguraikan tentang perangkap metode ini dan metode lain lebih jauh ke bawah.
jawaban atas anggapan niat di balik pertanyaan:
asumsi: Anda ingin menjalankan prog
dengan beberapa argumen tetapi minta dibangun kembali sebelum dijalankan jika perlu.
jawabannya: buat skrip yang membangun kembali jika perlu kemudian jalankan prog dengan args
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
naskah ini memperjelas niatnya. ia menggunakan make untuk melakukan apa yang baik untuk: membangun. menggunakan skrip shell untuk melakukan apa yang baik untuk: pemrosesan batch.
ditambah Anda dapat melakukan apa pun yang mungkin Anda butuhkan dengan fleksibilitas penuh dan ekspresif dari skrip shell tanpa semua peringatan dari makefile.
juga sintaks panggilan sekarang praktis identik:
$ ./buildandrunprog.sh foo "bar baz"
dibandingkan dengan:
$ ./prog foo "bar baz"
berbeda dengan
$ make run var="foo bar\ baz"
Latar Belakang:
make tidak dirancang untuk meneruskan argumen ke target. semua argumen pada baris perintah ditafsirkan sebagai tujuan (alias target), sebagai opsi, atau sebagai penugasan variabel.
jadi jika Anda menjalankan ini:
$ make run foo --wat var=arg
membuat akan menafsirkan run
dan foo
sebagai tujuan (target) untuk memperbarui sesuai dengan resep mereka. --wat
sebagai opsi untuk make. dan var=arg
sebagai tugas variabel.
untuk lebih jelasnya lihat: https://www.gnu.org/software/make/manual/html_node/Goals.html#Goals
untuk terminologi lihat: https://www.gnu.org/software/make/manual/html_node/Rule-Introduction.html#Rule-Introduction
tentang metode penugasan variabel dan mengapa saya merekomendasikannya
$ make run var=arg
dan variabel dalam resep
run: prog
./prog $(var)
ini adalah cara yang paling "benar" dan langsung untuk menyampaikan argumen ke resep. tetapi sementara itu dapat digunakan untuk menjalankan program dengan argumen itu tentu tidak dirancang untuk digunakan seperti itu. lihat https://www.gnu.org/software/make/manual/html_node/Overriding.html#Overriding
menurut saya ini memiliki satu kelemahan besar: apa yang ingin Anda lakukan adalah menjalankan prog
argumen arg
. tetapi bukannya menulis:
$ ./prog arg
kamu sedang menulis:
$ make run var=arg
ini semakin canggung ketika mencoba mengoper beberapa argumen atau argumen yang mengandung spasi:
$ make run var="foo bar\ baz"
./prog foo bar\ baz
argcount: 2
arg: foo
arg: bar baz
dibandingkan dengan:
$ ./prog foo "bar baz"
argcount: 2
arg: foo
arg: bar baz
Sebagai catatan, seperti inilah prog
penampilan saya :
#! /bin/sh
echo "argcount: $#"
for arg in "$@"; do
echo "arg: $arg"
done
juga perhatikan bahwa Anda tidak harus memberi $(var)
tanda kutip di makefile:
run: prog
./prog "$(var)"
karena dengan begitu prog
akan selalu mendapatkan hanya satu argumen:
$ make run var="foo bar\ baz"
./prog "foo bar\ baz"
argcount: 1
arg: foo bar\ baz
semua ini adalah mengapa saya merekomendasikan rute ini.
untuk kelengkapan berikut adalah beberapa metode lain untuk "meneruskan argumen untuk menjalankan".
metode 1:
run: prog
./prog $(filter-out $@, $(MAKECMDGOALS))
%:
@true
Penjelasan super singkat: menyaring tujuan saat ini dari daftar tujuan. buat catch all target ( %
) yang tidak melakukan apa pun untuk mengabaikan tujuan lain secara diam-diam.
metode 2:
ifeq (run, $(firstword $(MAKECMDGOALS)))
runargs := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
$(eval $(runargs):;@true)
endif
run:
./prog $(runargs)
Penjelasan super singkat: jika target tersebut run
kemudian menghapus tujuan pertama dan membuat lakukan target apa-apa untuk tujuan yang tersisa menggunakan eval
.
keduanya akan memungkinkan Anda untuk menulis sesuatu seperti ini
$ make run arg1 arg2
untuk penjelasan lebih lanjut, pelajari manual make: https://www.gnu.org/software/make/manual/html_node/index.html
masalah metode 1:
argumen yang dimulai dengan tanda hubung akan ditafsirkan dengan membuat dan tidak diteruskan sebagai tujuan.
$ make run --foo --bar
solusi
$ make run -- --foo --bar
argumen dengan tanda sama akan ditafsirkan dengan membuat dan tidak lulus
$ make run foo=bar
tidak ada solusi
argumen dengan spasi canggung
$ make run foo "bar\ baz"
tidak ada solusi
jika sebuah argumen kebetulan run
(sama dengan target) itu juga akan dihapus
$ make run foo bar run
akan berjalan ./prog foo bar
sebagai gantinya./prog foo bar run
solusi mungkin dengan metode 2
jika sebuah argumen adalah target yang sah, maka itu juga akan dijalankan.
$ make run foo bar clean
akan berjalan ./prog foo bar clean
tetapi juga resep untuk target clean
(dengan asumsi itu ada).
solusi mungkin dengan metode 2
ketika Anda salah mengetik target yang sah itu akan diam-diam diabaikan karena menangkap semua target.
$ make celan
hanya akan diam-diam mengabaikan celan
.
solusi adalah untuk membuat semuanya bertele-tele. jadi Anda lihat apa yang terjadi. tapi itu menciptakan banyak suara untuk keluaran yang sah.
masalah metode 2:
jika suatu argumen memiliki nama yang sama dengan target yang ada maka make akan mencetak peringatan bahwa itu sedang ditimpa.
tidak ada solusi yang saya tahu
argumen dengan tanda sama dengan masih akan ditafsirkan dengan membuat dan tidak lulus
tidak ada solusi
argumen dengan spasi masih canggung
tidak ada solusi
argumen dengan ruang istirahat eval
mencoba membuat target melakukan apa-apa.
solusi: membuat tangkapan global semua target tidak melakukan apa pun seperti di atas. dengan masalah seperti di atas bahwa ia akan lagi diam-diam mengabaikan target yang sah salah ketik.
ini digunakan eval
untuk memodifikasi makefile saat runtime. seberapa buruk Anda dalam hal keterbacaan dan debugabilitas dan Prinsip yang paling mengejutkan .
solusi: jangan lakukan ini !! 1 sebagai gantinya tulis skrip shell yang menjalankan make lalu jalankan prog
.
saya hanya diuji menggunakan gnu make. merek lain mungkin memiliki perilaku yang berbeda.
TL; DR jangan mencoba melakukan ini
$ make run arg
alih-alih membuat skrip:
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
dan lakukan ini:
$ ./buildandrunprog.sh arg