您可以制作没有制表符的有效Makefile吗?


114
target: dependencies
    command1
    command2

在我的系统(Mac OS X)上,make似乎要求Makefile在每command行内容的前面带有一个制表符,否则会引发语法错误。

创建或编辑Makefile时这很烦人,因为我将编辑器设置为全时空。

您可以制作没有制表符的有效Makefile吗?


4
我还配置了编辑器以模拟带有空格的选项卡。但是,我的编辑器还允许我在绝对肯定要具有制表符的罕见情况下(例如Makefiles)键入Ctrl-Tab。也许您的编辑器也一样。
toolic 2010年

Answers:


118

这是语法的怪异/要求make,与Mac OS X无关。不幸的是,如果要使用,您将无能为力make

编辑:GNU Make现在支持自定义配方前缀。看到这个答案

您不是第一个不喜欢此方面的人make。引用《Unix Haters手册》

Dennis的Makefile的问题在于,当他添加注释行时,他无意间在第2行的开头的制表符前面插入了一个空格。制表符是Makefiles语法中非常重要的一部分。所有命令行(在我们的示例中以cc开头的行)必须以制表符开头。他进行更改后,第2行没有更改,因此出现了错误。

“所以呢?” 你问:“那是怎么了?”

本身没有任何问题。只是当您考虑其他编程工具如何在Unix中工作时,使用制表符作为语法的一部分就像是《绿色贝雷帽》中的那些橡皮筋陷阱之一:来自堪萨斯州的可怜孩子正站在约翰·韦恩的面前,而看不到跳闸线。毕竟,在堪萨斯州的玉米田里没有绊脚石。HAM!


5
标签问题是任何使用make的人都要学习的第一件事-我从未发现这是一个真正的问题。

2
@Neil,我都没有:我从未说过我同意UHH,我只是说有些人不喜欢它。:-)
Alok Singhal 2010年

2
似乎是使用cmake的好插件。并不是make语法中唯一令人沮丧的奇怪之处。
orodbhen

3
我刚刚找到gnu.org/software/make/manual/html_node/Special-Variables.html(请参阅参考资料.RECIPEPREFIX)。以下答案之一也提到了这一点,应将其标记为“正确”而不是我的。 stackoverflow.com/a/21920142
Alok Singhal

3
这不是一个大问题,但是很烦人。每次。它确实令人讨厌,并且在\ micron线性时间内令人讨厌。
Parthian Shot

60

自最初提出此问题以来,已经发布了GNU Make版本,该版本允许您使用除Tab前缀字符以外的其他内容。从邮件列表公告中

新的特殊变量:.RECIPEPREFIX允许您将配方介绍字符从默认(TAB)重置为其他内容。该变量值的第一个字符是新配方介绍字符。如果变量设置为空字符串,则再次使用TAB。可以随意设置和重置;配方在首次解析时将使用活动值。要检测此功能,请检查$(。RECIPEPREFIX)的值。

此功能已添加到2010年7月发布的GNU Make 3.82中(该问题的原始要求日期之后六个月)。既然已经过去了三年,并且自那以后发生了变化,那么其他Make口味很可能也跟随了GNU Make。


51

有一个复杂的方法,使有效的makefile没有制表符。

如果将makefile更改为:

target: dependencies; command1; command2

如果可以的话。如果要在多条线上进行操作,则可以执行以下操作:

target: dependencies; \
command1; \
command2

凌乱,但有效。


升级到支持的Make版本.RECIPEPREFIX可能是最好的方法。但是,由于我不想这样做,所以最终使用了基于该解决方案的解决方案。第1行target:\ ,第2行:[四空间缩进],然后是;command
LS

33

如果您的个人资料中有vimrc,则可以添加以下行以防止vim更改为空格:

autocmd FileType make setlocal noexpandtab

我也为此而苦苦挣扎,这为我解决了这一问题。传播好词!


19

如果您想使用空格,这对我有用

.RECIPEPREFIX +=


哪个版本的make支持此功能?这在GNU Make 4.1中不起作用。
Cerin

2
很抱歉,GNU Make 4.1是为x86_64-pc-linux-gnu构建的,但是确实可以工作
neok

需要指出的是,此变量需要在make文件本身内部声明(前缀点不易发现)
urusai_na

至少在4.2版中,这应该有效。文档在解释中.RECIPEPREFIX说:“如果变量为空(默认情况下为),则该字符为标准制表符。” 这意味着该变量是默认定义的。通过使用确认ifeq ($(origin .RECIPEPREFIX), undefined)。因为在lhs后面加上了一个空格,并将rhs +=附加到了空格,所以只要已经定义,就将其设置为一个空格(加上一个空字符串)。(如果未定义,则与相同。)var +=varvarvar+==
ynn

1
此答案不再有效。请参阅我的答案以获取最新解决方案。
ynn

11

在vim的插入模式下,Ctrl-v <TAB>即使您已将Tab键设置为插入空格,也可以用来插入文字标签。当然,这不能回答您的问题,但是可以替代为避免使用文字标签而可用的方法。


10

如果您使用的是EditorConfig,则可以在.editorconfig文件中添加以下几行,以强制您的IDE使用制表符进行缩进,而不是空格Makefile

[Makefile]
indent_style = tab

4

直到GNU Make 4.2

史蒂文·彭尼(Steven Penny)的答案有效。

.RECIPEPREFIX +=

我的评论中描述了这种方法起作用的原因。


自GNU Make 4.3(于2020年1月19日发布)以来

+=操作员的行为已以向后不兼容的方式更改。如果左操作数的值为空,则不再添加空格。

您可以改用

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

,哪里<space>是一个空格。尽管$(.RECIPEPREFIX)将其扩展为空值,但不要使GNU Make忽略<space>。请注意,即使在版本低于4.3的GNU Make上,此代码也可以使用。


1

在ubuntu中:vi Makefile用tab(或您想要的任何其他东西)替换空间:

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

例如,用制表符替换8个空格:

:%s/        /^I/g

请注意:^我用Tab键插入,而不是^I字符:D


-6

不便携。make的某些口味绝对需要使用制表符。选择制表符而不是空格的另一个原因是:-)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.