从makefile中获取makefile的名称

发布于 2024-08-05 02:17:46 字数 222 浏览 3 评论 0原文

如何获取makefile中makefile的名称?

谢谢。

注意:

我需要它,因为我希望我的 makefile 能够调用自身,但 makefile 不被称为 Makefile,所以我想写这样的内容:

target:
    $(MAKE) -f $(MAKEFILENAME) other_target

How to get the name of the makefile in the makefile?

Thanks.

Note:

I would need that because I would like my makefile to call itself, but the makefile is not called Makefile, so I'd like to write something like this:

target:
    $(MAKE) -f $(MAKEFILENAME) other_target

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

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

发布评论

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

评论(6

莫言歌 2024-08-12 02:17:46
location = $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
WHERE_ART_THOU := $(location)
$(warning $(WHERE_ART_THOU))

我也相信这是 GNU make 特定的,但我不太确定。

location = $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
WHERE_ART_THOU := $(location)
$(warning $(WHERE_ART_THOU))

I also believe this is GNU make-specific, but I'm not too sure.

梦明 2024-08-12 02:17:46

(如果您有任何疑问,请参阅编写得令人惊叹的 GNU make 手册。但请记住,就像 Makefile 一样,在将概念付诸实践之前应该完整阅读本手册)。

我不明白它是如何轻松完成的。据我了解,你必须做一些手动工作。

稍后我将描述如何完成它并显示引入 current_makefile 变量的脚本。但我想首先强调一个重要的概念。

你应该明白,如果我们有某种变量current_makefile,它扩展到当前的makefile名称,那么它在读取makefile的过程中必须改变。这意味着它应该在“立即”扩展上下文中使用——即在读取 makefile 期间执行的命令中。然而,大多数命令是在读取 makefile 后执行的。因此,某些命令会顺利打印出正确的值,而在某些使用“延迟”扩展的地方,它将始终扩展为根 makefile 名称。

例如,如果您想在规则文本中使用此变量,则必须采取一些技巧,因为规则文本始终具有延迟扩展。因此,如果您有规则,

rule:
        echo In makefile $(current_makefile):
        echo Making target $@

它将始终打印根 makefile 的名称。相反,要强制立即扩展,您必须创建另一个具有 makefile 特定名称的变量(即每个 makefile 中此类变量的名称应该不同):

this_makefile_unique_name := $(current_makefile)
rule:
        echo In makefile $(current_makefile):
        echo Making target $@

或使用 eval:。

define make_rule
rule:
        echo In makefile $(1):
        echo Making target $@

$(eval $(call make_rule,$(current_makefile)))

如果您只想将当前 makefile 的名称用于调试目的,请考虑特殊的调试功能,例如 warning 或 info:。

$(warning We're in makefile $(current_makefile))

这些函数使用“立即”扩展并将打印正确的值。


如何定义这样的 $(current_makefile)?

您必须手动维护 makefile 包含的堆栈。当你包含一个 makefile 时,它​​的名字被放置在堆栈的顶部;当您从包含的 makefile 返回到外部 makefile 时,最上面的名称将从堆栈中弹出。这是通过在 makefile 的开头和结尾插入特殊调用来实现的:

# Beginning of makefile
$(eval $(makefile_names_push))
#... makefile text
$(warning $(current_makefile))
#...
$(eval $(makefile_names_pop))
#End of file

现在在根 makefile 的开头定义函数。

lastword=$(word $(words $(1)),$(1))

define makefile_names_push
current_makefile := $(CURDIR)/$(call lastword,$(MAKEFILE_LIST))
makefile_stack :=$(makefile_stack) $(current_makefile)
endef

define makefile_names_pop
makefile_stack := $(filter-out $(current_makefile),$(makefile_stack))
current_makefile := $(call lastword,$(makefile_stack))
endef

如果您确定您的 make 足够新(版本 3.81+),请将 lastword 调用替换为内置函数:。

#inctead of $(call lastword,$(MAKEFILE_LIST))
$(lastword $(MAKEFILE_LIST))

有用吗?

完全没用。此处可能有用的唯一用途是制作 100 个 makefile,它们是一个 makefile 的符号链接,这些 makefile 中的规则取决于它们的名称。但它可以通过手册中描述的一个 makefile 和 foreach-eval 技术来实现。所以我的帖子完全是浪费时间,尽管我玩得很开心:-)

(Should you have any questions, refer to amazingly written GNU make manual. But remember, that, just like Makefile, this manual should be read completely before putting the concepts into practice).

I couldn't figure out how it is done easily. As far as I understand, you'll have to do some manual job.

Later I will describe how it could be done and show scripts that introduce current_makefile variable. But I would like to stress an important concept at the first place.

You should understand that if we had some kind of variable current_makefile, that expands to the current makefile name, then it will have to change during the process of reading makefiles. That means that it should be used withinin "immediate" expansion context -- i.e. within commands that are executed during reading the makefile. Most commands, however, are executed after makefiles are read. Therefore, some commands will print the correct value smoothly, while in certain places, where "deferred" expansion is used, it will always expand to the root makefile name.

If you would want to use this variable within rule text, for example, you'll have to do tricks, because rule text always has deferred expansion. So, if your have the rule

rule:
        echo In makefile $(current_makefile):
        echo Making target $@

it will always print the name of the root makefile. Instead, to force immediate expansion, you will have to create another variable with makefile-specific name (i.e. names of such variables should be different in each makefile):

this_makefile_unique_name := $(current_makefile)
rule:
        echo In makefile $(current_makefile):
        echo Making target $@

or use eval:.

define make_rule
rule:
        echo In makefile $(1):
        echo Making target $@

$(eval $(call make_rule,$(current_makefile)))

If you want to use the name of current makefile for debug purpose only, consider special debugging functions, like warning or info:.

$(warning We're in makefile $(current_makefile))

These functions use "immediate" expansion and will print the correct value.


How to define such a $(current_makefile)?

You have to manually maintain stack of makefile inclusions. When you include a makefile, its name is placed to the top of the stack; when you return from included makefile to the outer one, the topmost name is popped out of stack. This is achieved by inserting special calls to the beginning and the end of makefile:

# Beginning of makefile
$(eval $(makefile_names_push))
#... makefile text
$(warning $(current_makefile))
#...
$(eval $(makefile_names_pop))
#End of file

Now define the functions at the beginning of your root makefile.

lastword=$(word $(words $(1)),$(1))

define makefile_names_push
current_makefile := $(CURDIR)/$(call lastword,$(MAKEFILE_LIST))
makefile_stack :=$(makefile_stack) $(current_makefile)
endef

define makefile_names_pop
makefile_stack := $(filter-out $(current_makefile),$(makefile_stack))
current_makefile := $(call lastword,$(makefile_stack))
endef

If you're sure your make is new enough (version 3.81+), replace lastword call with builtin function:.

#inctead of $(call lastword,$(MAKEFILE_LIST))
$(lastword $(MAKEFILE_LIST))

Is it useful?

Totally useless. An only use that might be useful here is to make 100 makefiles that are symlinks to one makefile, the rules in these makefiles depending on their names. But it can be achieved within one makefile and foreach-eval technique described in the manual. So my post was a complete waste of time, though I had some fun :-)

终陌 2024-08-12 02:17:46

这将返回第一个调用的 Makefile 的名称,即位于调用堆栈底部的 Makefile:

MAKEFILE_JUSTNAME := $(firstword $(MAKEFILE_LIST))
MAKEFILE_COMPLETE := $(CURDIR)/$(MAKEFILE_JUSTNAME)

当在非交叉递归情况下使用时(例如,对于 makedepend),它只是当前 makefile 的名称。

This returns the name of the first Makefile called, i.e. the one at the bottom of the call stack:

MAKEFILE_JUSTNAME := $(firstword $(MAKEFILE_LIST))
MAKEFILE_COMPLETE := $(CURDIR)/$(MAKEFILE_JUSTNAME)

When used in non-cross-recursive situations (e.g. for makedepend), it is just the name of the current makefile.

比忠 2024-08-12 02:17:46

当我使用 Make 管理简单的重复任务时,我想做一些类似的事情(用于回显 Makefile 的内容)。我偶然发现了这个页面,发现它正是我所追求的,并且对于我对 make 的有限理解非常有用。

阅读此页后我的结果:

    # Makefile - 'make' and 'make help' now echo the makefile.
    help:
        cat $(lastword $(MAKEFILE_LIST))
    start:
        sudo -u www /path/to/webapp/myhttpd restart
    stop:
        sudo kill `cat /path/to/webapp/data/httpd.pid`

I wanted to do something similar (for echoing the contents of the Makefile) for when I use Make for managing simple repetitive tasks. I came across this page and found it was exactly what I was after and really useful for my limited understanding of make.

My result after reading this page:

    # Makefile - 'make' and 'make help' now echo the makefile.
    help:
        cat $(lastword $(MAKEFILE_LIST))
    start:
        sudo -u www /path/to/webapp/myhttpd restart
    stop:
        sudo kill `cat /path/to/webapp/data/httpd.pid`
魂牵梦绕锁你心扉 2024-08-12 02:17:46

这里的解决方案解决了 1) POSIX make with 2) 调用的、不包含的 makefile 3) 类似 Unix 的平台。

OP 要求的内容:

target:
    @pid=$$; \
    while test `ps -ocomm= $pid` != make; do \
        pid=`ps -oppid= $pid`; \
    done; \
    MAKEFILENAME=`ps -oargs= $pid|sed 's/^.* -f *\([^ ]*\).*$/\1/'`; \
    test -z "$MAKEFILENAME" -a -f Makefile && MAKEFILENAME=Makefile; \
    test -z "$MAKEFILENAME" -a -f makefile && MAKEFILENAME=makefile; \
    export MAKEFILENAME; \
    $(MAKE) -e -f $MAKEFILENAME other_target

目标取决于 makefile,有点臃肿:

TARGET1_MAKEFILENAME = target1_preamble

all: target1 target2...

target1: $(TARGET1_MAKEFILENAME) other_dependencies...
    @test $(TARGET1_MAKEFILENAME) == target1_preamble && exit 0; \
    built_instructions_for_target1;

target1_preamble:
    @pid=$$; \
    while test `ps -ocomm= $pid` != make; do \
        pid=`ps -oppid= $pid`; \
    done; \
    MAKEFILENAME=`ps -oargs= $pid|sed 's/^.* -f *\([^ ]*\).*$/\1/'`; \
    test -z "$MAKEFILENAME" -a -f Makefile && MAKEFILENAME=Makefile; \
    test -z "$MAKEFILENAME" -a -f makefile && MAKEFILENAME=makefile; \
    export MAKEFILENAME; \
    $(MAKE) -e -f $MAKEFILENAME target1;

如果仅针对所有目标调用 make,则可以稍微简化。

MAKEFILENAME = invoked_makefile_placeholder

all: target1 target2...

target1: $(MAKEFILENAME) other_dependencies...
    @test $(MAKEFILENAME) == invoked_makefile_placeholder && exit 0; \
    built_instructions_for_target1;

invoked_makefile_placeholder:
    @pid=$$; \
    while test `ps -ocomm= $pid` != make; do \
        pid=`ps -oppid= $pid`; \
    done; \
    MAKEFILENAME=`ps -oargs= $pid|sed 's/^.* -f *\([^ ]*\).*$/\1/'`; \
    test -z "$MAKEFILENAME" -a -f Makefile && MAKEFILENAME=Makefile; \
    test -z "$MAKEFILENAME" -a -f makefile && MAKEFILENAME=makefile; \
    export MAKEFILENAME; \
    $(MAKE) -e -f $MAKEFILENAME

使用前面的方法,可以轻松实现基于 grep包含的 makefile 解决方案以及 makefile 中包含的独特模式。

当我觉得问题得到了正确的解决时,我从不回答。

The solutions here addresses 1) POSIX make with 2) Invoked, non included, makefile in 3) A Unix alike platform.

What the OP asked for:

target:
    @pid=$$; \
    while test `ps -ocomm= $pid` != make; do \
        pid=`ps -oppid= $pid`; \
    done; \
    MAKEFILENAME=`ps -oargs= $pid|sed 's/^.* -f *\([^ ]*\).*$/\1/'`; \
    test -z "$MAKEFILENAME" -a -f Makefile && MAKEFILENAME=Makefile; \
    test -z "$MAKEFILENAME" -a -f makefile && MAKEFILENAME=makefile; \
    export MAKEFILENAME; \
    $(MAKE) -e -f $MAKEFILENAME other_target

The targets depends on the makefile, kind of bloated:

TARGET1_MAKEFILENAME = target1_preamble

all: target1 target2...

target1: $(TARGET1_MAKEFILENAME) other_dependencies...
    @test $(TARGET1_MAKEFILENAME) == target1_preamble && exit 0; \
    built_instructions_for_target1;

target1_preamble:
    @pid=$$; \
    while test `ps -ocomm= $pid` != make; do \
        pid=`ps -oppid= $pid`; \
    done; \
    MAKEFILENAME=`ps -oargs= $pid|sed 's/^.* -f *\([^ ]*\).*$/\1/'`; \
    test -z "$MAKEFILENAME" -a -f Makefile && MAKEFILENAME=Makefile; \
    test -z "$MAKEFILENAME" -a -f makefile && MAKEFILENAME=makefile; \
    export MAKEFILENAME; \
    $(MAKE) -e -f $MAKEFILENAME target1;

Can be a bit simplified if make is invoked only for all targets.

MAKEFILENAME = invoked_makefile_placeholder

all: target1 target2...

target1: $(MAKEFILENAME) other_dependencies...
    @test $(MAKEFILENAME) == invoked_makefile_placeholder && exit 0; \
    built_instructions_for_target1;

invoked_makefile_placeholder:
    @pid=$$; \
    while test `ps -ocomm= $pid` != make; do \
        pid=`ps -oppid= $pid`; \
    done; \
    MAKEFILENAME=`ps -oargs= $pid|sed 's/^.* -f *\([^ ]*\).*$/\1/'`; \
    test -z "$MAKEFILENAME" -a -f Makefile && MAKEFILENAME=Makefile; \
    test -z "$MAKEFILENAME" -a -f makefile && MAKEFILENAME=makefile; \
    export MAKEFILENAME; \
    $(MAKE) -e -f $MAKEFILENAME

With the previous approach is trivial to implement a solution for included makefiles based in grep and a unique pattern contained in the makefile.

I never answer when I feel the question got a proper solution.

揪着可爱 2024-08-12 02:17:46

天哪,

如果您复制原始 makefile,例如 makefile_test,然后输入命令:

make -np -f makefile_test 2>&1 | tee output

这将评估 makefile 和您的 make 环境,但不执行任何命令。查看输出文件中对 makefile_test 的引用将显示 make 环境中设置的内容以及设置该值的位置。

注意这可以生成很多信息!并且不要添加 -d (调试)开关,这将生成大量有关 make 决策过程的附加输出,但有关 make 环境的附加信息很少。

华泰

G'day,

If you make a copy of your original makefile, say makefile_test, and then enter the command:

make -np -f makefile_test 2>&1 | tee output

That will evaluate the makefile and your make environment but not execute any of the commands. Looking through the output file for references to makefile_test will show you what is set in make's environment and where that value is being set.

N.B. This can generate a lot of info! And don't add the -d (debug) switch which will generate tons of additional output about make's decision process but minimal additional info about make's env.

HTH

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文