如何在Gnu Make文件中全局运行一些命令

3

我有一个GNU Makefile,通过环境变量收集版本信息。现在,我想在使用GNU Make语法构建任何目标之前全局做“某事”。伪代码如下:

  • 当一个指定的文件存在时,删除它
  • 遍历字符串数组,并将其值放入指定的文件中

我尝试了以下方法:

$(shell if exist $(subst /,\,$(products)filenames.h) del /F/Q $(subst /,\,$(products)filenames.h))
$(foreach Item, $(EnvFilenames), @echo $(Item) >> $(subst /,\,$(products)filenames.h))

这会给我一个错误:

C:\temp\Makefile.mak:72: *** missing separator.  Stop.

第72行是$(shell ...这一行。如果我将其放在define部分中:

define foobar
$(shell if exist $(subst /,\,$(products)filenames.h) del /F/Q $(subst /,\,$(products)filenames.h))
$(foreach Item, $(EnvFilenames), @echo $(Item) >> $(subst /,\,$(products)filenames.h))
endef

当为一个目标调用此函数时,它可以正常运行:

$(products)$test.o : test.c $(commons)
$(call foobar)
$(cc) $(cflags_m) test.c -o$@ 

它能够做它应该做的事情......但是一旦我想从另一个define内部调用它,它又会因为缺少分隔符而失败。

这意味着什么?我该如何修复它?

编译在Win32平台上进行,不需要多平台支持。

1个回答

7
如果每次执行“Make”只需要一次,您可以将其放在全局赋值中。
# Ignore the value, calling for side effects
IGNORE := $(shell commands with side effects)

我不建议使用这种黑客方法,但我可以想象一些它可能会派上用场的情况。

这对我来说不会被执行 - 只有当我删除 IGNORE: = 时才会执行。但是那时我会得到所描述的错误。顺便说一下,我使用的是Make 3.82。 - Coder02
这里是有效的,例如 IGNORE := $(shell rm foobar) 将删除 foobar,无论您调用哪个目标。您确定您没有在“:”和“=”之间放置空格吗? - Jens
请注意:您可以将您的命令写在一个批处理文件或者shell脚本中,并使用类似 IGNORE := $(shell foo.bat) 这样的方式进行调用,以尽可能减少不必要的麻烦。 - Jack Kelly
我们今天刚刚使用了这种技术,虽然感觉有些破解的味道,但它确实很有用。 - Clayton Stanley
“缺少分隔符”错误似乎来自于@echo-call,因此这一行与您的“hack”结合起来对我很有效:$(foreach Item, $(EnvFilenames), $(shell @echo $(Item) >> $(subst /,\,$(products)filenames.h))) - Coder02

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接