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

xyz*_*xyz 107 whitespace tabs makefile spaces

target: dependencies
    command1
    command2
Run Code Online (Sandbox Code Playgroud)

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

在创建或编辑Makefile时,这是一个烦恼,因为我的编辑器设置为全时空间.

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

Alo*_*hal 111

这是一个语法奇怪/要求make,它与Mac OS X无关.不幸的是,如果你要使用它,你无能为力make.

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

你不是第一个不喜欢这个方面的人make.引用Unix Haters的手册:

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

"那又怎样?"你问道,"那有什么不对?"

它本身没有任何问题.只是当你考虑其他编程工具如何在Unix中运行时,使用制表符作为语法的一部分就像是绿色贝雷帽中的一个蹦极陷阱:来自堪萨斯州的可怜孩子就在John Wayne前面的步行点并没有看到行程电线.毕竟,在堪萨斯玉米田里没有值得注意的绊网.开个唱!

  • 制表符的问题是任何人使用make学习的第一件事 - 我从来没有发现它是一个真正的问题. (4认同)
  • 我刚刚找到https://www.gnu.org/software/make/manual/html_node/Special-Variables.html(参见`.RECIPEPREFIX`).下面的答案之一也提到了,应该标记为"正确"而不是我的.http://stackoverflow.com/a/21920142 (3认同)
  • @Neil,我也不是:我从未说过我同意UHH,我只是说有些人不喜欢它.:-) (2认同)
  • 似乎是使用cmake的好插件。并不是make语法中唯一令人沮丧的奇怪之处。 (2认同)
  • 这不是一个大问题,但它很烦人.每一次.这是令人讨厌的,它在线性时间内很烦人. (2认同)
  • 在本文章的第一点中,关于make和tab的有趣的评论(https://kukuruku.co/post/the-collapse-of-the-unix-philosophy/):)“他是这样做的,因为他没想到除了少数人之外,任何人都不会使用“ make”,后来又想到“ make”是一件好事,将其包含在其中会很好标准的UNIX软件包。_为了不破坏已经写的makefile(由这十个人写的意思),他决定不做任何更改。_嗯,事情就是这样……我们所有人都因为那十个人而受苦。 (2认同)

Bri*_*ell 54

在最初询问此问题以来,已发布GNU Make版本,允许您使用除Tab前缀字符之外的其他内容.从邮件列表公告:

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

此功能是在2010年7月发布的GNU Make 3.82中添加的(此问题的原始提问日期后六个月).由于它已经过了三年而且从那以后发生了变化,其他的Make口味很可能跟随GNU Make.


小智 50

有一种复杂的方法是拥有一个没有标签的有效makefile.

如果您将makefile更改为:

target: dependencies; command1; command2
Run Code Online (Sandbox Code Playgroud)

如果会奏效.如果你想要它在多行上,那么你可以这样做:

target: dependencies; \
command1; \
command2
Run Code Online (Sandbox Code Playgroud)

凌乱,但它的确有效.


小智 31

如果您的配置文件中有vimrc,则可以添加此行以防止vim更改为空格:

autocmd FileType make setlocal noexpandtab
Run Code Online (Sandbox Code Playgroud)

我也在努力解决这个问题,这个问题已经解决了.传播好话!


小智 19

如果您想使用空格,这对我来说就是这样

.RECIPEPREFIX +=
Run Code Online (Sandbox Code Playgroud)

  • GNU Make 4.1专为x86_64-pc-linux-gnu而构建我很抱歉,但确实有效 (2认同)
  • 这个答案不再有效。请参阅[我的答案](/sf/answers/4225418501/)了解最新的解决方案。 (2认同)

Pat*_*nan 11

在vim的插入模式下,Ctrl-v <TAB>即使已将tab键设置为插入空格,也可以使用插入文字选项卡.当然,这不能回答您的问题,但可能是可用于避免需要文字选项卡的方法的替代方法.


ive*_*r56 7

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

[Makefile]
indent_style = tab
Run Code Online (Sandbox Code Playgroud)


ynn*_*ynn 7

直到 GNU Make 4.2

史蒂文佩尼的回答有效。

.RECIPEPREFIX +=
Run Code Online (Sandbox Code Playgroud)

我的评论中描述了这样做的原因。


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

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

您可以改为使用

.RECIPEPREFIX := $(.RECIPEPREFIX)<space>
Run Code Online (Sandbox Code Playgroud)

,其中<space>是单个空格。虽然$(.RECIPEPREFIX)被扩展为一个空值,但这不是让 GNU Make 忽略的必要条件<space>。请注意,此代码甚至适用于 4.3 版之前的 GNU Make。

  • 尾随空白是不好的。最短的解决方案是“.RECIPEPREFIX := $() #”。[github](https://github.com/search?q=RECIPEPREFIX+filename%3Amakefile) 上最流行的解决方案是 `.RECIPEPREFIX := $(.RECIPEPREFIX) $(.RECIPEPREFIX)` (4认同)