Bạn có thể tạo các Makefiles hợp lệ mà không có ký tự tab không?


114
target: dependencies
    command1
    command2

Trên hệ thống của tôi (Mac OS X), makedường như yêu cầu rằng các tệp Makefiles phải có một ký tự tab đứng trước nội dung của mỗi commanddòng, nếu không nó sẽ gây ra lỗi cú pháp.

Đây là một điều khó chịu khi tạo hoặc chỉnh sửa Makefiles vì ​​tôi đã thiết lập trình chỉnh sửa của mình thành mọi không gian-mọi lúc.

Bạn có thể tạo các Makefiles hợp lệ mà không có ký tự tab không?


4
Tôi cũng đã định cấu hình trình chỉnh sửa của mình để mô phỏng các tab có dấu cách. Nhưng, trình soạn thảo của tôi cũng cho phép tôi gõ Ctrl-Tab trong những trường hợp hiếm hoi khi tôi thực sự phải có một tab, như trong Makefiles. Có lẽ biên tập viên của bạn cũng vậy.
toolic

Câu trả lời:


118

Đây là một yêu cầu / kỳ quặc về cú pháp make, nó không liên quan gì đến Mac OS X. Thật không may, bạn không thể làm gì nếu định sử dụng make.

Chỉnh sửa : GNU Make hiện hỗ trợ tiền tố công thức tùy chỉnh. Xem câu trả lời này .

Bạn không phải là người đầu tiên không thích khía cạnh này của make. Để trích dẫn Cẩm nang của Unix Haters :

Vấn đề với Makefile của Dennis là khi anh ấy thêm dòng chú thích, anh ấy đã vô tình chèn một khoảng trắng trước ký tự tab ở đầu dòng 2. Ký tự tab là một phần rất quan trọng trong cú pháp của Makefiles. Tất cả các dòng lệnh (các dòng bắt đầu bằng cc trong ví dụ của chúng tôi) phải bắt đầu bằng các tab. Sau khi anh ấy thực hiện thay đổi của mình, dòng 2 không có, do đó lỗi.

"Vậy thì sao?" bạn hỏi, "Có gì sai với điều đó?"

Không có gì sai với nó, tự nó. Chỉ là khi bạn xem xét cách các công cụ lập trình khác hoạt động trong Unix, việc sử dụng các tab như một phần của cú pháp giống như một trong những cái bẫy dính pungee trong The Green Berets: đứa trẻ tội nghiệp từ Kansas đang đi bộ trước mặt John Wayne và không ' t xem dây chuyến đi. Rốt cuộc, không có dây chuyến đi nào để đề phòng ở các cánh đồng ngô ở Kansas. TẠI SAO!


5
Vấn đề với các tab là một trong những điều đầu tiên mà bất kỳ ai sử dụng make đều tìm hiểu - tôi chưa bao giờ thấy đó là một vấn đề thực sự.

2
@Neil, Tôi cũng vậy: Tôi chưa bao giờ nói rằng tôi đồng ý với UHH, tôi chỉ nói rằng một số người không thích nó. :-)
Alok Singhal

2
Có vẻ như một phích cắm tốt để sử dụng cmake. Không phải là sự kỳ quặc gây khó chịu duy nhất trong cú pháp.
orodbhen

3
Tôi vừa tìm thấy gnu.org/software/make/manual/html_node/Special-Variables.html (xem .RECIPEPREFIX). Một trong những câu trả lời bên dưới cũng đề cập đến điều đó và nên được đánh dấu là "đúng" thay vì của tôi. stackoverflow.com/a/21920142
Alok Singhal

3
Nó không phải là một vấn đề lớn, nhưng nó là khó chịu. Mỗi và mọi lúc. Điều đó thật khó chịu và thật khó chịu trong thời gian tuyến tính \ omicron.
Parthian Shot

60

Trong thời gian kể từ khi câu hỏi này được hỏi ban đầu, một phiên bản của GNU Make đã được phát hành cho phép bạn sử dụng thứ gì đó khác ngoài Tablàm ký tự tiền tố. Từ thông báo danh sách gửi thư :

Biến đặc biệt mới: .RECIPEPREFIX cho phép bạn đặt lại ký tự giới thiệu công thức từ mặc định (TAB) sang một thứ khác. Ký tự đầu tiên của giá trị biến này là ký tự giới thiệu công thức mới. Nếu biến được đặt thành chuỗi trống, TAB sẽ được sử dụng lại. Nó có thể được thiết lập và đặt lại theo ý muốn; các công thức nấu ăn sẽ sử dụng giá trị đang hoạt động khi chúng được phân tích cú pháp lần đầu. Để phát hiện tính năng này, hãy kiểm tra giá trị của $ (. RECIPEPREFIX).

Tính năng này đã được thêm vào GNU Make 3.82, phát hành vào tháng 7 năm 2010 (sáu tháng sau ngày hỏi ban đầu của câu hỏi này). Vì nó đã lần lượt được ba năm và thay đổi kể từ đó, có khả năng là các hương vị Make khác đã theo sau GNU Make.


51

Có một cách phức tạp để có một tệp trang điểm hợp lệ mà không có tab.

Nếu bạn thay đổi makefile của mình để đọc:

target: dependencies; command1; command2

Nếu sẽ làm việc. Nếu bạn muốn nó trên nhiều dòng, thì bạn có thể làm:

target: dependencies; \
command1; \
command2

Lộn xộn, nhưng nó hoạt động.


Nâng cấp lên phiên bản Make hỗ trợ .RECIPEPREFIXcó lẽ là cách tốt nhất. Tuy nhiên, vì tôi không thích làm điều đó, nên tôi đã sử dụng một giải pháp dựa trên giải pháp này. Dòng 1 target:\ :, Dòng 2: [thụt lề bốn dấu cách] theo sau;command
LS

33

Nếu bạn có vimrc trong hồ sơ của mình, bạn có thể thêm dòng này để ngăn vim thay đổi thành dấu cách:

autocmd FileType make setlocal noexpandtab

Tôi cũng đã đấu tranh với điều này, và điều này đã khắc phục nó cho tôi. Truyền bá những lời tốt đẹp!


19

Điều này sẽ giúp tôi nếu bạn muốn sử dụng dấu cách

.RECIPEPREFIX +=

Thí dụ


Phiên bản make nào hỗ trợ điều này? Điều này không hoạt động trong GNU Make 4.1.
Cerin

2
GNU Make 4.1 xây dựng cho x86_64-pc-linux-gnu tôi xin lỗi nhưng nó làm việc
neok

có lẽ, nó cần phải được đề cập, rằng biến này cần phải được khai báo bên trong làm cho tập tin riêng của mình (tiền tố dot dễ dàng không để phát hiện)
urusai_na

Ít nhất trong phiên bản 4.2, điều này sẽ hoạt động. Tài liệu giải thích .RECIPEPREFIXrằng "Nếu biến trống ( theo mặc định ) thì ký tự đó là ký tự tab chuẩn." Điều này có nghĩa là biến được xác định theo mặc định. Nó được xác nhận bằng cách sử dụng ifeq ($(origin .RECIPEPREFIX), undefined). Bởi vì +=nối một khoảng trắng duy nhất và rhs vào lhs, var +=đặt varthành một không gian duy nhất (cộng với một chuỗi rỗng) miễn là varđã được xác định. (Nếu varkhông được xác định, +=giống như =.)
ynn

1
Câu trả lời này không còn hoạt động. Xem câu trả lời của tôi để biết giải pháp mới nhất.
ynn

11

Trong chế độ chèn của vim, người ta có thể sử dụng Ctrl-v <TAB>để chèn một tab chữ, ngay cả khi bạn đã đặt phím tab để chèn khoảng trắng. Tất nhiên, điều này không trả lời câu hỏi của bạn, nhưng có thể là một giải pháp thay thế cho các phương pháp có sẵn để tránh cần các tab nghĩa đen.


10

Nếu bạn đang sử dụng EditorConfig , bạn có thể thêm các dòng sau vào .editorconfigtệp của mình để buộc IDE của bạn sử dụng tab để thụt lề thay vì khoảng trắng trong Makefile:

[Makefile]
indent_style = tab

4

Cho đến khi GNU Make 4.2

Câu trả lời của Steven Penny hoạt động.

.RECIPEPREFIX +=

Lý do tại sao công trình này được mô tả trong nhận xét của tôi .


Kể từ GNU Make 4.3 (phát hành vào ngày 19 tháng 1 năm 2020)

Hành vi của +=nhà điều hành đã được thay đổi theo hướng ngược lại không tương thích. Nếu toán hạng bên trái có giá trị trống, một khoảng trắng không còn được thêm vào.

Thay vào đó bạn có thể sử dụng

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

, đâu <space>là một không gian. Mặc dù $(.RECIPEPREFIX)được mở rộng như một giá trị trống, điều này là cần thiết để GNU Make bỏ qua <space>. Lưu ý rằng mã này hoạt động ngay cả trên GNU Make cũ hơn phiên bản 4.3.


1

trong ubuntu: vi Makefiles thay thế không gian bằng tab (hoặc bất kỳ thứ gì khác bạn muốn):

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

Đối với ví dụ thay thế 8 dấu cách bằng tab:

:%s/        /^I/g

Hãy chú ý: ^ Tôi chèn bằng phím tab, không phải ký tự ^I : D


-6

Không đáng kể. Một số hương vị của thực hiện hoàn toàn yêu cầu các ký tự tab. Tuy nhiên, một lý do khác để thích tab hơn khoảng trắng :-)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.