Bisakah Anda membuat Makefile yang valid tanpa karakter tab?

114
target: dependencies
    command1
    command2

Pada sistem saya (Mac OS X), maketampaknya mengharuskan Makefiles memiliki karakter tab yang mendahului konten setiap commandbaris, atau memunculkan kesalahan sintaksis.

Ini adalah gangguan saat membuat atau mengedit Makefiles karena saya memiliki editor saya yang disetel menjadi semua spasi sepanjang waktu.

Bisakah Anda membuat Makefile yang valid tanpa karakter tab?

xyz
sumber
4
Saya juga telah mengonfigurasi editor saya untuk meniru tab dengan spasi. Tapi, editor saya juga memungkinkan saya untuk mengetik Ctrl-Tab dalam kesempatan langka ketika saya benar-benar harus memiliki tab, seperti di Makefiles. Mungkin editor Anda juga melakukannya.
perkakas

Jawaban:

118

Ini adalah keanehan / persyaratan sintaksis make, tidak ada hubungannya dengan Mac OS X. Sayangnya, tidak ada yang dapat Anda lakukan jika akan menggunakannya make.

Sunting : GNU Make sekarang mendukung awalan resep khusus. Lihat jawaban ini .

Anda bukan orang pertama yang tidak menyukai aspek ini make. Mengutip Buku Pegangan Pembenci Unix :

Masalah dengan Dennis's Makefile adalah ketika dia menambahkan baris komentar, dia secara tidak sengaja menyisipkan spasi sebelum karakter tab di awal baris 2. Karakter tab adalah bagian yang sangat penting dari sintaks Makefiles. Semua baris perintah (baris yang dimulai dengan cc dalam contoh kita) harus dimulai dengan tab. Setelah dia melakukan perubahannya, baris 2 tidak, maka kesalahannya.

"Terus?" Anda bertanya, "Apa yang salah dengan itu?"

Tidak ada yang salah dengan itu, dengan sendirinya. Hanya saja ketika Anda mempertimbangkan bagaimana alat pemrograman lain bekerja di Unix, menggunakan tab sebagai bagian dari sintaksis seperti salah satu jebakan pungee stick di The Green Barets: anak malang dari Kansas sedang berjalan di depan John Wayne dan tidak. t melihat kabel perjalanan. Lagi pula, tidak ada kabel perjalanan yang harus diperhatikan di ladang jagung Kansas. MEMUKUL!

Alok Singhal
sumber
5
Masalah dengan tab adalah salah satu hal pertama yang digunakan siapa pun yang menggunakan make learning - saya tidak pernah menganggapnya sebagai masalah nyata.
2
@Neil, Saya juga tidak: Saya tidak pernah mengatakan saya setuju dengan UHH, saya hanya mengatakan beberapa orang tidak menyukainya. :-)
Alok Singhal
2
Sepertinya steker yang bagus untuk menggunakan cmake. Bukan satu-satunya keanehan yang membuat frustasi dalam sintaksis.
orodbhen
3
Saya baru saja menemukan gnu.org/software/make/manual/html_node/Special-Variables.html (lihat .RECIPEPREFIX). Salah satu jawaban di bawah juga menyebutkan itu, dan harus ditandai sebagai "benar", bukan milik saya. stackoverflow.com/a/21920142
Alok Singhal
3
Ini bukan masalah besar, tapi mengganggu. Setiap saat. Ini benar-benar mengganggu, dan mengganggu dalam waktu linier \ omicron.
Parthian Shot
60

Sejak pertanyaan ini pertama kali diajukan, versi GNU Make telah dirilis yang memungkinkan Anda untuk menggunakan sesuatu selain Tabsebagai karakter awalan. Dari pengumuman milis :

Variabel khusus baru: .RECIPEPREFIX memungkinkan Anda menyetel ulang karakter pengantar resep dari default (TAB) ke yang lain. Karakter pertama dari nilai variabel ini adalah karakter pengantar resep baru. Jika variabel disetel ke string kosong, TAB digunakan lagi. Ini dapat diatur dan diatur ulang sesuka hati; resep akan menggunakan nilai aktif saat pertama kali diurai. Untuk mendeteksi fitur ini, periksa nilai $ (. RECIPEPREFIX).

Fitur ini ditambahkan di GNU Make 3.82, dirilis pada Juli 2010 (enam bulan setelah tanggal asli pertanyaan ini). Karena sudah tiga tahun dan berubah sejak itu, kemungkinan rasa Make lain telah mengikuti GNU Make.

Brighid McDonnell
sumber
51

Ada cara berbelit-belit untuk memiliki makefile yang valid tanpa tab.

Jika Anda mengubah makefile Anda menjadi:

target: dependencies; command1; command2

Jika akan berhasil. Jika Anda menginginkannya di lebih dari satu baris, maka Anda dapat melakukan:

target: dependencies; \
command1; \
command2

Berantakan, tetapi berhasil.

George
sumber
Mengupgrade ke versi Make yang mendukung .RECIPEPREFIXmungkin merupakan pendekatan terbaik. Namun, karena saya tidak ingin melakukan itu, saya akhirnya menggunakan solusi berdasarkan ini. Baris 1 target:\ :, Baris 2: [indentasi empat spasi] diikuti oleh;command
LS
33

Jika Anda memiliki vimrc di profil Anda, Anda dapat menambahkan baris ini untuk mencegah vim berubah ke spasi:

autocmd FileType make setlocal noexpandtab

Saya juga berjuang dengan ini, dan ini memperbaikinya untuk saya. Sebarkan kabar baik!

Pericolo
sumber
19

Ini melakukannya untuk saya jika Anda ingin menggunakan spasi

.RECIPEPREFIX +=

Contoh

Steven Penny
sumber
Versi make apa yang mendukung ini? Ini tidak berfungsi di GNU Make 4.1.
Cerin
2
GNU Make 4.1 Dibangun untuk x86_64-pc-linux-gnu maaf, tetapi berhasil
neok
mungkin, perlu disebutkan, bahwa variabel ini perlu dideklarasikan di dalam file make itu sendiri (awalan titik mudah tidak dikenali)
urusai_na
Setidaknya di versi 4.2, ini seharusnya berfungsi. Dokumentasi mengatakan dalam penjelasan .RECIPEPREFIXbahwa "Jika variabel kosong (seperti default ) karakter itu adalah karakter tab standar." Ini berarti variabel ditentukan secara default. Itu dikonfirmasi dengan menggunakan ifeq ($(origin .RECIPEPREFIX), undefined). Karena +=menambahkan satu spasi dan rhs ke lhs, var +=set varke satu spasi (ditambah string kosong) asalkan varsudah ditentukan. (Jika vartidak ditentukan, +=sama dengan =.)
ynn
1
Jawaban ini tidak lagi berfungsi. Lihat jawaban saya untuk solusi terbaru.
ynn
11

Dalam mode penyisipan vim, seseorang dapat menggunakan Ctrl-v <TAB>untuk menyisipkan tab literal, bahkan jika Anda telah mengatur tombol tab untuk menyisipkan spasi. Ini tidak menjawab pertanyaan Anda, tentu saja, tetapi mungkin menjadi alternatif dari metode yang tersedia untuk menghindari perlunya tab literal.

Patrick Sanan
sumber
10

Jika Anda menggunakan EditorConfig , Anda dapat menambahkan baris berikut ke .editorconfigfile Anda untuk memaksa IDE Anda menggunakan tab untuk indentasi alih-alih spasi di Makefile:

[Makefile]
indent_style = tab
iver56
sumber
4

Hingga GNU Make 4.2

Jawaban Steven Penny berhasil.

.RECIPEPREFIX +=

Alasan mengapa ini berhasil dijelaskan dalam komentar saya .


Sejak GNU Make 4.3 (dirilis pada 19 Jan 2020)

Perilaku +=operator telah diubah dengan cara yang tidak kompatibel dengan versi sebelumnya. Jika operan kiri memiliki nilai kosong, spasi tidak lagi ditambahkan.

Anda malah bisa menggunakan

.RECIPEPREFIX := $(.RECIPEPREFIX)<space>

, di mana <space>ada satu spasi. Meskipun $(.RECIPEPREFIX)diperluas sebagai nilai kosong, ini diperlukan agar GNU Make tidak mengabaikannya <space>. Perhatikan kode ini bekerja bahkan pada GNU Make lebih lama dari versi 4.3.

ynn
sumber
1

di ubuntu: vi Makefiles mengganti spasi dengan tab (atau apa pun yang Anda inginkan):

:%s/<space chars>/^I/g

Misalnya ganti 8 spasi dengan tab:

:%s/        /^I/g

Perhatikan: ^ Saya menyisipkan dengan tombol tab, bukan ^ dan karakter I : D

nobjta_9x_tq
sumber
-6

Tidak portabel. Rasa tertentu dari make benar-benar membutuhkan karakter tab. Namun alasan lain untuk lebih memilih tab daripada spasi :-)


sumber