Bagaimana cara mengirimkan argumen ke Makefile dari baris perintah?

109

Bagaimana cara mengirimkan argumen ke Makefile dari baris perintah?

Saya mengerti saya bisa melakukannya

$ make action VAR="value"
$ value

dengan Makefile

VAR = "default"
action:
    @echo $(VAR)

Bagaimana cara mendapatkan perilaku berikut?

$ make action value
value

?

Bagaimana tentang

$make action value1 value2
value1 value2
Meng Lu
sumber
3
Kemungkinan duplikat dari Argumen yang lewat ke "make run"
lesmana

Jawaban:

212

Anda mungkin sebaiknya tidak melakukan ini; Anda melanggar pola dasar cara kerja Make. Tapi ini dia:

action:
        @echo action $(filter-out $@,$(MAKECMDGOALS))

%:      # thanks to chakrit
    @:    # thanks to William Pursell

EDIT:
Untuk menjelaskan perintah pertama,

$(MAKECMDGOALS) adalah daftar "target" yang disebutkan pada baris perintah, misalnya "nilai tindakan1 nilai2".

$@adalah variabel otomatis untuk nama target aturan, dalam hal ini "tindakan".

filter-outadalah fungsi yang menghapus beberapa elemen dari daftar. Jadi $(filter-out bar, foo bar baz)pengembaliannya foo baz(bisa lebih halus, tapi kita tidak perlu kehalusan di sini).

Gabungkan keduanya dan $(filter-out $@,$(MAKECMDGOALS))kembalikan daftar target yang ditentukan pada baris perintah selain "tindakan", yang mungkin berupa "nilai1 nilai2".

Beta
sumber
1
$(shell echo $(MAKECMDGOALS) | sed 's!^.* $@ !!')untuk menghilangkan semua target sebelumnya dan anggap saja yang berikut ini sebagai argumen:make target1 target2 action value1 value2
Evgeniy Generalov
1
Maafkan ketidaktahuan saya. Saya sudah mencoba googling %:dan @:tidak dapat menemukan info tentang apa yang dilakukan "arahan" (atau apa pun namanya). Bisakah Anda menjelaskan?
Jon
15
@ Jon: Manualnya ada di sini . Bagian yang terdiri dari %:dan @:merupakan aturan . Nama target %berarti bahwa itu adalah aturan yang cocok dengan apapun ; artinya, jika Make tidak dapat menemukan cara lain untuk membuat hal yang Anda perintahkan untuk dibuat, Make akan menjalankan aturan itu. Ini @:adalah resepnya ; yang :berarti melakukan apa-apa, dan @cara melakukannya diam-diam.
Beta
Terima kasih. Saya telah membaca manual itu dan saya tidak mempertimbangkan pada awalnya, %:itu sebenarnya % :, nama target jenis wildcard. Saya tidak melihat apa pun di halaman manual itu mengenai @:... itu menyarankan bahwa aturan "tidak melakukan apa-apa" hanya akan memiliki ;setelah spesifikasi target, jadi, bukankah lebih akurat untuk menulis % : ;seperti "karakter pengganti -tidak ada aturan?
Jon
1
filter-outtidak berfungsi jika tindakannya adalah ketergantungan dari target yang ditentukan pada baris perintah, karena $@akan disetel ke nama ketergantungan, bukan argumen asli yang dipanggil pada baris perintah. Sebagai gantinya, saya menetapkan MAKECMDGOALSke array shell dan kemudian menghapus elemen pertama:@ args=($(MAKECMDGOALS)); args=("$${args[@]:1}")
Gingi
18

Berikut adalah solusi kerja umum berdasarkan @ Beta

Saya menggunakan GNU Make 4.1 dengan SHELL=/bin/bashdi atas Makefile saya, jadi YMMV!

Ini memungkinkan kita untuk menerima argumen tambahan (dengan tidak melakukan apa-apa saat kita mendapatkan pekerjaan yang tidak cocok, daripada membuat kesalahan).

%:
    @:

Dan ini adalah makro yang memberikan argumen untuk kami:

args = `arg="$(filter-out $@,$(MAKECMDGOALS))" && echo $${arg:-${1}}`

Inilah pekerjaan yang mungkin disebut ini:

test:
    @echo $(call args,defaultstring)

Hasilnya adalah:

$ make test
defaultstring
$ make test hi
hi

Catatan! Anda mungkin lebih baik menggunakan "Taskfile", yang merupakan pola bash yang cara kerjanya mirip, hanya saja tanpa nuansa Maketools. Lihat https://github.com/adriancooney/Taskfile

M3D
sumber
Berhasil !! KEPADA orang lain yang mencobanya, pastikan ada tabsebelumnya @echo, bukan space.
Abdullah Al Maruf - Tuhin
11

Pendekatan jauh lebih mudah. Pertimbangkan tugas:

provision:
        ansible-playbook -vvvv \
        -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory \
        --private-key=.vagrant/machines/default/virtualbox/private_key \
        --start-at-task="$(AT)" \
        -u vagrant playbook.yml

Sekarang ketika saya ingin menyebutnya, saya hanya menjalankan sesuatu seperti:

AT="build assets" make provision

atau hanya:

make provisiondalam hal ini ATadalah string kosong

kharandziuk
sumber
-2

jangan mencoba melakukan ini

$ make action value1 value2

alih-alih buat skrip:

#! /bin/sh
# rebuild if necessary
make
# do action with arguments
action "$@"

dan lakukan ini:

$ ./buildthenaction.sh value1 value2

untuk penjelasan lebih lanjut mengapa melakukan ini dan peringatan peretasan makefile, baca jawaban saya untuk pertanyaan lain yang sangat mirip tetapi tampaknya bukan duplikat: Meneruskan argumen untuk "lari"

lesmana
sumber