Ya, Anda dapat menggunakan kata kunci define untuk mendeklarasikan variabel multi-baris, seperti ini:
define ANNOUNCE_BODY
Version $(VERSION) of $(PACKAGE_NAME) has been released.
It can be downloaded from $(DOWNLOAD_URL).
etc, etc.
endef
Bagian yang sulit adalah mengembalikan variabel multi-garis Anda dari makefile. Jika Anda hanya melakukan hal yang jelas dengan menggunakan "echo $ (ANNOUNCE_BODY)", Anda akan melihat hasil yang diposting orang lain di sini - shell mencoba menangani baris kedua dan berikutnya dari variabel sebagai perintah itu sendiri.
Namun, Anda dapat mengekspor nilai variabel apa adanya ke shell sebagai variabel lingkungan, lalu mereferensikannya dari shell sebagai variabel lingkungan (BUKAN variabel make). Sebagai contoh:
export ANNOUNCE_BODY
all:
@echo "$$ANNOUNCE_BODY"
Perhatikan penggunaan $$ANNOUNCE_BODY
, yang menunjukkan referensi variabel lingkungan shell, bukan $(ANNOUNCE_BODY)
, yang akan menjadi referensi variabel make reguler. Pastikan juga untuk menggunakan tanda kutip di sekitar referensi variabel Anda, untuk memastikan bahwa baris baru tidak diinterpretasikan oleh shell itu sendiri.
Tentu saja, trik khusus ini mungkin peka terhadap platform dan shell. Saya mengujinya di Ubuntu Linux dengan GNU bash 3.2.13; YMMV.
export ANNOUNCE_BODY
hanya menetapkan variabel di dalam aturan - ini tidak mengizinkan referensi $$ ANNOUNCE_BODY untuk menentukan variabel lain.ANNOUNCE_BODY
dalam definisi variabel lain, cukup referensikan seperti variabel make lainnya. MisalnyaOTHER=The variable ANNOUNCE_BODY is $(ANNOUNCE_BODY)
,. Tentu saja Anda masih memerlukanexport
trik jika Anda inginOTHER
keluar sesuai perintah.Pendekatan lain untuk 'mendapatkan variabel multi-baris Anda kembali dari makefile' (dicatat oleh Eric Melski sebagai 'bagian yang sulit'), adalah merencanakan untuk menggunakan
subst
fungsi untuk mengganti baris baru yang diperkenalkan dengandefine
dalam string multi-baris Anda dengan\n
. Kemudian gunakan -e denganecho
untuk menafsirkannya. Anda mungkin perlu menyetel .SHELL = bash untuk mendapatkan gema yang melakukan ini.Keuntungan dari pendekatan ini adalah Anda juga memasukkan karakter pelarian lain ke dalam teks Anda dan membuatnya dihormati.
Semacam ini mensintesis semua pendekatan yang disebutkan sejauh ini ...
Anda berakhir dengan:
Perhatikan bahwa tanda kutip tunggal pada gema terakhir sangat penting.
sumber
=
setelahnyadefine ANNOUNCE_BODY
untuk menjalankannya.Dengan asumsi Anda hanya ingin mencetak konten variabel Anda pada keluaran standar, ada solusi lain:
sumber
make: 'do-echo' is up to date.
. Dengan menggunakan perintah "no op" dan saya bisa membungkamnya:@: $(info $(YOUR_MULTILINE_VAR))
.PHONY
untuk memberi tahu Makefile Anda bahwa tidak ada yang perlu diperiksa untuk aturan itu. Makefiles pada awalnya untuk kompiler, jika saya tidak salah, begitumake
juga melakukan sihir yang saya tidak mengerti untuk mengantisipasi bahwa aturan tidak akan mengubah apa pun, dan dengan demikian menganggapnya 'selesai'. Menambahkan.PHONY do-echo
file Anda akan memberitahumake
untuk mengabaikan ini dan tetap menjalankan kodenya.$(info ...)
luar aturan make. Ini masih akan menghasilkan keluaran.Iya. Anda keluar dari baris baru dengan
\
:memperbarui
Ah, Anda ingin baris baru? Kalau begitu tidak, saya rasa tidak ada cara lain di Vanilla Make. Namun, Anda selalu dapat menggunakan dokumen di sini di bagian perintah
[Ini tidak berfungsi, lihat komentar dari MadScientist]
sumber
Hanya sebuah postscript untuk jawaban Eric Melski: Anda dapat menyertakan output dari perintah dalam teks, tetapi Anda harus menggunakan sintaks Makefile "$ (shell foo)" daripada sintaks shell "$ (foo)". Sebagai contoh:
sumber
Ini tidak memberikan dokumen di sini, tetapi ini menampilkan pesan multi-baris dengan cara yang sesuai untuk pipa.
=====
=====
Anda juga dapat menggunakan makro yang dapat dipanggil Gnu:
=====
=====
Berikut hasilnya:
=====
=====
sumber
Mengapa Anda tidak menggunakan karakter \ n dalam string Anda untuk menentukan akhir baris? Tambahkan juga garis miring terbalik ekstra untuk menambahkannya di beberapa baris.
sumber
$(subst \n ,\n,$(TEXT))
meskipun saya berharap ada cara yang lebih baik!GNU `make 'manual, 6.8: Mendefinisikan Variabel Multi-Baris
sumber
echo
.Anda harus menggunakan "define / endef" Buat konstruksi:
Maka Anda harus meneruskan nilai variabel ini ke perintah shell. Tetapi, jika Anda melakukan ini menggunakan Make variable substitution, itu akan menyebabkan perintah terpecah menjadi beberapa:
Qouting juga tidak akan membantu.
Cara terbaik untuk meneruskan nilai adalah dengan meneruskannya melalui variabel lingkungan:
Memperhatikan:
sumber
Dalam semangat .ONESHELL, Anda dapat mendekati lingkungan yang menantang .ONESHELL:
Contoh penggunaannya akan seperti ini:
Itu menunjukkan output (dengan asumsi pid 27801):
Pendekatan ini memungkinkan beberapa fungsi tambahan:
Opsi shell ini akan:
Kemungkinan menarik lainnya kemungkinan besar akan muncul dengan sendirinya.
sumber
Saya paling suka jawaban alhadis. Tetapi untuk mempertahankan format kolom, tambahkan satu hal lagi.
Keluaran:
sumber
make
, mereka biasanya melakukannya dengan harapan untuk memulai proses pembangunan.Tidak sepenuhnya terkait dengan OP, tapi semoga ini akan membantu seseorang di masa depan. (karena pertanyaan ini adalah yang paling sering muncul di pencarian google).
Di Makefile saya, saya ingin meneruskan konten file, ke perintah build buruh pelabuhan, setelah banyak kekhawatiran, saya memutuskan untuk:
lihat contoh di bawah ini.
nb: Dalam kasus khusus saya, saya ingin meneruskan kunci ssh, selama pembuatan gambar, menggunakan contoh dari https://vsupalov.com/build-docker-image-clone-private-repo-ssh-key/ (menggunakan build buruh pelabuhan multi-tahap untuk mengkloning repo git, lalu jatuhkan kunci ssh dari gambar terakhir di tahap ke-2 pembuatan)
Makefile
Dockerfile
sumber
Dengan GNU Make 3.82 dan yang lebih baru,
.ONESHELL
opsinya adalah teman Anda dalam hal cuplikan kerangka multiline. Mengumpulkan petunjuk dari jawaban lain, saya mendapatkan:Pastikan, saat menyalin dan menempel contoh di atas ke dalam editor Anda, bahwa setiap
<tab>
karakter dipertahankan, jika tidak,version
target akan rusak!Perhatikan itu
.ONESHELL
akan menyebabkan semua target di Makefile menggunakan satu shell untuk semua perintah mereka.sumber
make version printf "Version 1.2.3 of foo-bar has been released. /bin/sh: 1: Syntax error: Unterminated quoted string make: *** [version] Error 2
(GNU make 3,81)@printf ...
pernyataan - sepertinya TAB selalu dirender sebagai 4 spasi ....ONESHELL
baru di make 3.82.*** missing separator. Stop.
.Bukan jawaban yang benar-benar membantu, tetapi hanya untuk menunjukkan bahwa 'definisikan' tidak berfungsi seperti yang dijawab oleh Ax (tidak sesuai dengan komentar):
Ini memberikan kesalahan bahwa perintah 'Itu' tidak dapat ditemukan, jadi ia mencoba untuk menafsirkan baris kedua dari ANNOUNCE BODY sebagai perintah.
sumber
Ini berhasil untuk saya:
sumber
GNU Makefile dapat melakukan hal-hal seperti berikut ini. Ini jelek, dan saya tidak akan mengatakan Anda harus melakukannya, tetapi saya melakukannya dalam situasi tertentu.
make .profile
membuat file .profile jika tidak ada.Solusi ini digunakan di mana aplikasi hanya akan menggunakan GNU Makefile di lingkungan shell POSIX. Proyek ini bukanlah proyek sumber terbuka yang masalah kompatibilitas platformnya.
Tujuannya adalah untuk membuat Makefile yang memfasilitasi penyiapan dan penggunaan jenis ruang kerja tertentu. Makefile membawa serta berbagai sumber daya sederhana tanpa memerlukan hal-hal seperti arsip khusus lainnya, dll. Ini, dalam arti tertentu, arsip shell. Sebuah prosedur kemudian dapat mengatakan hal-hal seperti meletakkan Makefile ini di folder untuk bekerja masuk Siapkan ruang kerja Anda masuk
make workspace
, lalu lakukan bla, masukmake blah
, dll.Apa yang bisa menjadi rumit adalah mencari tahu apa yang harus dikutip oleh shell. Di atas melakukan pekerjaan dan dekat dengan gagasan untuk menentukan dokumen di sini di Makefile. Apakah itu ide yang baik untuk penggunaan umum adalah masalah lain.
sumber
Saya yakin jawaban teraman untuk penggunaan lintas platform adalah menggunakan satu gema per baris:
Ini untuk menghindari asumsi tentang versi gema tersedia.
sumber
Gunakan substitusi string :
Lalu di resep Anda, masukkan
Ini berfungsi karena Make menggantikan semua kemunculan
|
(perhatikan spasi) dan menukar dengan karakter baris baru ($$'\n'
). Anda dapat menganggap pemanggilan skrip-shell yang setara sebagai sesuatu seperti ini:Sebelum:
Setelah:
Saya tidak yakin apakah
$'\n'
tersedia pada sistem non-POSIX, tetapi jika Anda dapat memperoleh akses ke satu karakter baris baru (bahkan dengan membaca string dari file eksternal), prinsip dasarnya sama.Jika Anda memiliki banyak pesan seperti ini, Anda bisa mengurangi kebisingan dengan menggunakan makro :
Di mana Anda akan memintanya seperti ini:
Semoga ini bisa membantu seseorang. =)
sumber
Sebagai alternatif, Anda dapat menggunakan perintah printf. Ini berguna di OSX atau platform lain dengan fitur yang lebih sedikit.
Untuk hanya mengeluarkan pesan multiline:
Jika Anda mencoba meneruskan string sebagai arg ke program lain, Anda dapat melakukannya seperti ini:
sumber