迭代 Makefile 中的列表?

发布于 2024-07-23 05:17:52 字数 471 浏览 5 评论 0原文

我发现我正在编写很多 Makefile,可以使用 n 元组列表来清理这些文件。 但我找不到任何方法来正确(且干净地)执行此操作。 到目前为止,我只能使用 $(shell ...)trsed 或其他非 - Makefile 标准。

例如,我想这样做:

XYZs = \
    dog.c  pull_tail bark  \
    duck.c chase     quack \
    cow.c  tip       moo

all:
    @- $(foreach X Y Z,$(XYZs), \
        $(CC) $X -o bully/$Y ; \
        ln bully/$Y sounds/$Z ; \
    )

Is有一个好的方法来迭代Makefiles中的n元组列表吗? 谢谢!

I find I'm writing a lot of Makefiles that could be cleaned up with the use of n-tuple lists. But I can't find any way to do this properly (and cleanly). So far I've only been able to come up with using $(shell ...) and tr, sed, or otherwise non-Makefile standards.

For example, I'd like to do this:

XYZs = \
    dog.c  pull_tail bark  \
    duck.c chase     quack \
    cow.c  tip       moo

all:
    @- $(foreach X Y Z,$(XYZs), \
        $(CC) $X -o bully/$Y ; \
        ln bully/$Y sounds/$Z ; \
    )

Is there a good way to iterate n-tuple lists in Makefiles? Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

陌伤浅笑 2024-07-30 05:17:52

我会查看 foreach 上的 GNU Make 手册。 这是我在不同项目中使用的一些随机片段...该示例不完整,但也许它会给您一些想法? 如果我有更多时间,我可能会稍后清理它......

REMAKE_PROGS:= dog duck cow

XYZs = \
    dog.c  pull_tail bark  \
    duck.c chase     quack \
    cow.c  tip       moo

$(foreach src, $(XYZs), $(eval $MAKE $(src))

$(REMAKE_PROGS):
        @echo "\n# === $@ linking\n"
        $(call compile,$@,$(OBJS_$@),$(CXX),$(MPICXX),$(LDFLAGS) $(LIBS) $(SYSLIBS) $(OTHER_LIB) $(EXTRA_LD_FLAGS))
        @echo "\n# --- $@ compiled\n"

define compile
  @mkdir -p $(dir $(1))
  $(if ${ANNOUNCE},@echo "\n# +++ ${MAKECMDGOALS} compiling\n" $(eval ANNOUNCE=))
  $(call compiler,$(1),NOMPI,$(3),$(4))
  $(eval MY_FLAGS=$(FLAGS_$(1)) $(5))
  $(if $(filter %xlf %xlf90,$(COMPILER_$(1))),$(eval MY_FLAGS:=$(MY_FLAGS:-D%=-WF,-D%)))
  $(strip $(COMPILER_$(1)) $(2) $(MY_FLAGS) -o $(1) )
endef

I'd check the GNU Make manual on foreach. here are some random snips that I've used in a different project... the example is incomplete, but maybe it will give you some ideas? I might clean this up later if I've got more time...

REMAKE_PROGS:= dog duck cow

XYZs = \
    dog.c  pull_tail bark  \
    duck.c chase     quack \
    cow.c  tip       moo

$(foreach src, $(XYZs), $(eval $MAKE $(src))

$(REMAKE_PROGS):
        @echo "\n# === $@ linking\n"
        $(call compile,$@,$(OBJS_$@),$(CXX),$(MPICXX),$(LDFLAGS) $(LIBS) $(SYSLIBS) $(OTHER_LIB) $(EXTRA_LD_FLAGS))
        @echo "\n# --- $@ compiled\n"

define compile
  @mkdir -p $(dir $(1))
  $(if ${ANNOUNCE},@echo "\n# +++ ${MAKECMDGOALS} compiling\n" $(eval ANNOUNCE=))
  $(call compiler,$(1),NOMPI,$(3),$(4))
  $(eval MY_FLAGS=$(FLAGS_$(1)) $(5))
  $(if $(filter %xlf %xlf90,$(COMPILER_$(1))),$(eval MY_FLAGS:=$(MY_FLAGS:-D%=-WF,-D%)))
  $(strip $(COMPILER_$(1)) $(2) $(MY_FLAGS) -o $(1) )
endef
暗恋未遂 2024-07-30 05:17:52

Makefile 本质上是声明性的,所以我认为 make 本身并不能提供您想要的东西。 但是,您似乎想要将一些字符串值与特定目标相关联,因此可能

还有一个特别之处
目标特定变量:当您
定义一个特定于目标的变量,
该变量值也有效
对于该目标的所有依赖项
(除非这些依赖项覆盖它
有自己特定的目标
变量值)。 因此,例如,一个
像这样的声明:

prog:CFLAGS = -g

prog : prog.o foo.o bar.o

将在命令中将CFLAGS设置为-g
prog 的脚本,但它也会
在命令中将 CFLAGS 设置为 -g
创建 prog.o, foo.o, 的脚本
和 bar.o,以及任何命令脚本
创建它们的依赖关系。

如果您还没有读过,GNU make 手册非常好。

编辑:要执行您在评论中询问的问题:

dog: ANIMAL=dog.c BULLY=pull_tail SOUND=bark

请使用:

dog: ANIMAL=dog.c 
dog: BULLY=pull_tail 
dog: SOUND=bark

Makefiles are essentially declarative in nature, so I don't think that make itself provides what you want. However, you seem to be wanting to associate some string values with specific targets, so maybe the Target specific variable values feature of GNU make will be of interest. This is an extract from the manual:

There is one more special feature of
target-specific variables: when you
define a target-specific variable,
that variable value is also in effect
for all dependencies of this target
(unless those dependencies override it
with their own target-specific
variable value). So, for example, a
statement like this:

prog : CFLAGS = -g

prog : prog.o foo.o bar.o

will set CFLAGS to -g in the command
script for prog, but it will also
set CFLAGS to -g in the command
scripts that create prog.o, foo.o,
and bar.o, and any command scripts
which create their dependencies.

If you haven't already read it, the GNU make manual is pretty damn good.

Edit: To do what you asked about in your comment:

dog: ANIMAL=dog.c BULLY=pull_tail SOUND=bark

use:

dog: ANIMAL=dog.c 
dog: BULLY=pull_tail 
dog: SOUND=bark
沫雨熙 2024-07-30 05:17:52

感谢您的提示——经过一番黑客攻击后,我认为这更符合我的期望:

XYZs = \
    dog.c:pull_tail:bark  \
    duck.c:chase:quack \
    cow.c:tip:moo

all:
    @- $(foreach XYZ,$(XYZs), \
        $(eval X = $(word 1,$(subst :, ,$(XYZ)))) \
        $(eval Y = $(word 2,$(subst :, ,$(XYZ)))) \
        $(eval Z = $(word 3,$(subst :, ,$(XYZ)))) \
        \
        $(CC) $X -o bully/$Y ; \
        ln bully/$Y sounds/$Z ; \
    )

有人能做得更好吗?

Thanks for the hints -- after some hacking I think this is more what I was hoping for:

XYZs = \
    dog.c:pull_tail:bark  \
    duck.c:chase:quack \
    cow.c:tip:moo

all:
    @- $(foreach XYZ,$(XYZs), \
        $(eval X = $(word 1,$(subst :, ,$(XYZ)))) \
        $(eval Y = $(word 2,$(subst :, ,$(XYZ)))) \
        $(eval Z = $(word 3,$(subst :, ,$(XYZ)))) \
        \
        $(CC) $X -o bully/$Y ; \
        ln bully/$Y sounds/$Z ; \
    )

Can anyone do better?

七禾 2024-07-30 05:17:52

据我所知,这是因为您试图强制 make 作为命令式语言工作,而事实并非如此。

在 GNU make 中,您可能想做类似的事情:

pull_tail : SOUND=bark
pull_tail : dog.c 
        $(CC) 
lt; -o $^
        ln $@ $(SOUND)

chase : SOUND=quack
chase : duck.c 
        $(CC) 
lt; -o $^
        ln $@ $(SOUND)

...

或者更好的是,重新定义 .c 文件的默认规则来为您处理链接,但是您的名称结构很奇怪(程序名称没有词法关系)源名称)使得这变得困难。

如果您希望能够快速重建而无需大量手动编辑,您可能需要编写一个脚本来从数据重新生成 makefile 片段并使用 GNU make 的 include 功能...

None that I know of, but that is because you're trying to force make to work ans an imperative language, when that is not what it is.

In GNU make you'd probably want to do something like:

pull_tail : SOUND=bark
pull_tail : dog.c 
        $(CC) 
lt; -o $^
        ln $@ $(SOUND)

chase : SOUND=quack
chase : duck.c 
        $(CC) 
lt; -o $^
        ln $@ $(SOUND)

...

Or better yet, redefine the default rule for .c files to handle the linking for you, but the strange structure of your names (the program names don't have a lexical relationship to the source names) makes that hard.

If what you want to be able to rebuild this quickly without an lot of hand editing, you probably want to write a script to regenerate the makefile framgment from data and use the include feature of GNU make...

椒妓 2024-07-30 05:17:52

你这是在倒退。

您试图将 make 视为脚本。 它不是,而是一组关于如何在给定 Y 的情况下创建 X 的规则。然后 make 引擎会计算出需要发生什么才能获得该结果。

对于给出的示例,您确实应该使用脚本来执行生成步骤。 也许可以从 make 调用它,但让 make 处理 CC 的东西。

You're doing it backwards.

You're trying to treat make like it's a script. It's not, instead its a set of rules on how to create X given Y. Then the make engine figures out what needs to happen to get that result.

For the example given, you really should be using a script for the generation steps. Perhaps calling that from make, but let make handle the CC stuff.

巡山小妖精 2024-07-30 05:17:52

您可以对具有相同扩展名的一组文件使用默认规则,将每个 c 文件编译为 o。 当然,您不限于任何特殊的文件扩展名。 要编译一组 .c 文件,您可以这样做:

OBJS = foo.o bar.o baz.o
OUT = myprog

all: $(OBJS)
        $(SILENT) echo "LD $@"
        $(SILENT) $(CPP) -o $(OUT) $^ $(LDFLAGS)

%.o: %.c
        $(SILENT) echo "CC 
lt;"
        $(SILENT) $(CC) $(CCOPTS) -o $@ -c 
lt;

You can use default rules for a set of files with the same extension as in for compiling each c file to an o. Of course you are not restricted to any special file extensions. For compiling a set of .c files you could do it like this:

OBJS = foo.o bar.o baz.o
OUT = myprog

all: $(OBJS)
        $(SILENT) echo "LD $@"
        $(SILENT) $(CPP) -o $(OUT) $^ $(LDFLAGS)

%.o: %.c
        $(SILENT) echo "CC 
lt;"
        $(SILENT) $(CC) $(CCOPTS) -o $@ -c 
lt;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文