Make:根据要构建的目标设置变量 [英] Make: Set variable depending on which target is to be build

查看:170
本文介绍了Make:根据要构建的目标设置变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在(GNU)make中,我希望在特定目标的构建链开始时为变量分配一个值.对于分别取决于b.o的目标a.sob.so,我可以像这样手动进行操作:

In (GNU) make, I want a variable to be assigned a value when the build chain of specific targets are starting. For targets a.so and b.so, each depending on b.o, I can do this manually like this:

# Rules
all: a.so b.so
a.so: b.o
    @echo Current .so is $(current)
    touch $@
b.so: b.o
    @echo Current .so is $(current)
    touch $@
b.o:
    @echo Current .so is $(current)
    touch $@

# Set the "current" variable based on which .so is being build
a.so: current = a.so
b.so: current = b.so

在这里,当同时执行a.sob.o的规则时,current的值是a.so,而仅当执行b.so的规则时,current的值是b.so.这就是我要的.我的思维模式是,一旦make发现应该构建a.so(即在运行a.sob.so的规则之前),就会触发行a.so: current = a.so.如果我错了,请纠正我.

Here, current has the value a.so when executing the rules for both a.so and b.o, while current has the value b.so only when executing the rule for b.so. This is what I want. The mental model I have of this is that the line a.so: current = a.so gets triggered as soon as make finds out that a.so should be build (that is, before the rules of either a.so or b.so are run). Please correct me if I'm wrong.

在我的实际情况下,我还有更多的.so文件,因此我想用这样的东西替换最后两行;

In my actual case, I have many more .so files, and so I want to replace the two last lines with something like this;

%.so: current = $@

或者这个;

sofiles = a b
$(addsuffix .so, $(sofiles)): current = $@

但是,这两种方法都会导致相同的错误行为,即使要构建b.o目标,也要重新设置current变量.为什么b.o目标会触发这些行?如何实现与为每个.so手动编写a.so: current = a.so时却没有为每个.so实际接线时相同的行为?

However, both of these result in the same, wrong behavior, where the current variable gets set anew even when the b.o target is about to be build. Why does the b.o target trigger these lines? How can I achieve the same behavior as when manually writing a.so: current = a.so for every .so, but without actually wiring this for every single .so?

注意:我知道示例代码中显示的用例很奇怪,并且不需要这个笨拙的current变量就可以实现所追求的效果.但是,我对不使用此变量即可解决问题的任何解决方案都不感兴趣.

Note: I know that the use case shown in the example code is weird and that the sought after effect can be achieved without this awkward current variable. I am however not interested in any solution which solves the problem without using this variable.

推荐答案

这里有很多事情要讨论.首先,您关于目标特定变量的工作原理的心智模型不太准确(行a.so:current = a.so会在make发现应构建a.so之后立即触发").真正发生的是,每个目标的相遇都会创建一个新的作用域",该作用域在创建该目标及其所有先决条件时处于活动状态,并且该目标的特定于目标的变量在该范围内有效.一旦该作用域退出(目标已完成),那么这些变量设置就消失了.

There are many things to discuss here. First, your mental model of how target-specific variables works is not quite accurate ("the line a.so: current = a.so gets triggered as soon as make finds out that a.so should be build"). What really happens is that each target make encounters creates a new "scope" which is active while that target and all its prerequisites are being created, and the target-specific variables for that target are in effect inside that scope. Once that scope exits (the target is finished) then those variable settings are gone.

在上面的示例中,当创建b.o作为a.so的先决条件时,current在仅b.o 的配方内将具有值a.so.如果创建b.o作为b.so的先决条件,则current将是b.so.因为您的makefile首先列出了a.so,所以它将首先被构建,并且由于b.o只会被构建一次(每次调用make),因此它似乎总是使用a.so作为current的值,但是不太准确.考虑一下:

In your example above, current will have the value a.so inside the recipe for b.o only when b.o is being created as a prerequisite of a.so. If b.o was being created as a prerequisite of b.so, then current would be b.so. Because your makefile lists a.so first it will be built first, and because b.o will only be built once (per invocation of make), it may appear that it's always using a.so as the value of current but that's not precisely accurate. Consider this:

$ make all
Current .so is a.so
touch b.o
Current .so is a.so
touch a.so
Current .so is b.so
touch b.so

但这也是

$ rm -f b.o
$ make b.so
Current .so is b.so
touch b.o
Current .so is b.so
touch b.so

了解如果构建了b.o,则如何将current设置为b.so,因为它是b.so而不是a.so的先决条件.

See how current is set to b.so if b.o is built because it's a prerequisite of b.so not a.so.

还有这个:

$ rm -f b.o
$ make b.o
Current .so is
touch b.o

在这里,因为b.o不是任何.so的先决条件,所以根本没有设置current

Here because b.o isn't a prerequisite of any .so, then current is not set at all!

接下来要考虑的是这一行:

The next thing to think about is this line:

%.so : current = $@

对于b.o,此行被触发"是不正确的.但是,这会将特定于模式的变量current设置为值$@(请注意, NOT 表示$@变量的扩展!).这意味着,每次使用$(current)进行扩展时,它都会扩展为$@,即 current 目标名称,无论使用哪种配方.因此,不会扩展为a.sob.so,除非当前目标名称实际上是a.sob.so.如果目标名称为b.o,则$@会扩展为b.o.

It's not true that this line is "triggered" for b.o. However, this sets the pattern-specific variable current to the value $@ (note, NOT to the expansion of the $@ variable!). This means that each time $(current) is expanded it will expand to $@, which is the current target name, for whatever recipe it's used in. So this won't expand to a.so or b.so unless the current target name is actually a.so or b.so. If the target name is b.o then $@ expands to b.o.

如果要执行此操作,则不能使用像$@这样的变量,而必须使用实际值.您可以使用eval进行此操作,例如:

If you want to do this you can't use a variable like $@, you have to use the real value. You can do this with eval, for example:

sofiles = a b
$(foreach SO,$(sofiles),$(eval $(SO).so: current = $(SO).so))

但是,根据上面的第一句话,我不确定这是否足以满足您的需求.

However, based on the first comments above I'm not sure that's sufficient for your needs.

这篇关于Make:根据要构建的目标设置变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆