从makefile获取makefile的名称

从makefile获取makefile的名称,makefile,Makefile,如何在makefile中获取makefile的名称 谢谢 注意: 我需要它,因为我希望我的makefile调用它自己,但是makefile不是makefile,所以我想这样写: target: ($MAKE) -f ($MAKEFILENAME) other_target 快速游览一下这个地点,就可以知道答案了 location = $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) WHERE_ART_THOU :

如何在makefile中获取makefile的名称

谢谢

注意:

我需要它,因为我希望我的makefile调用它自己,但是makefile不是makefile,所以我想这样写:

target:
    ($MAKE) -f ($MAKEFILENAME) other_target
快速游览一下这个地点,就可以知道答案了

location = $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
WHERE_ART_THOU := $(location)
$(warning $(WHERE_ART_THOU))
我也相信这是GNU制定的,但我不太确定。

(如果您有任何问题,请参考令人惊讶的文字。但请记住,就像Makefile一样,在将概念付诸实践之前,应该完整阅读本手册)

我想不出这是怎么容易做到的。据我所知,你得做些手工活

稍后,我将描述如何实现它,并展示引入
current\u makefile
变量的脚本。但我首先要强调一个重要的概念

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

例如,如果希望在规则文本中使用此变量,则必须执行一些技巧,因为规则文本始终具有延迟扩展。那么,如果你有规则的话

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

或使用eval:

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

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

如果您只想使用当前Mag文件的名称作为调试用途,请考虑特殊的调试函数,如警告或信息:./P>

$(warning We're in 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技术中实现。因此,我的帖子完全是浪费时间,尽管我有一些乐趣:-)

当我使用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`
G'day

如果制作原始makefile的副本,请说makefile_test,然后输入以下命令:

make -np -f makefile_test 2>&1 | tee output
这将评估makefile和make环境,但不会执行任何命令。查看输出文件中对makefile_test的引用将显示在make环境中设置了什么以及在何处设置该值

注意,这会产生很多信息!并且不要添加-d(debug)开关,它将生成关于make决策过程的大量额外输出,但会生成关于make环境的最少额外信息


HTH

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

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

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

这里的解决方案解决了1)POSIX make,2)在类似Unix的平台中调用、非包含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
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
包含的makefiles的解决方案以及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

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

仅适用于GNU Make-一般来说,不适用于非GNU Make。如果在包含另一个makefile后检查makefile name,则此解决方案不起作用!这篇文章有一个很好的答案。由于编辑的内容太大,我无法确认是否保留了您的目标。最好是自己查看。如果在包含另一个makefile后检查makefile名称,则此解决方案不起作用!(复制粘贴的注释)“如果在包含另一个makefile后检查makefile名称,则此解决方案不起作用!”这不是一个大问题。我可以在Makefile的开头写下这段代码的前两行,它正确地设置了WHERE\u ART\u变量。然后我可以在Makefile中的任何位置使用该变量,它将正确包含我的Makefile的名称。但是对于包含的Makefile,您必须使用不同的名称:
WHERE\u you
对于一个Makefile,
WHERE_You_2
用于另一个等。我的目标是为所有makefiles引入一个名称,它不仅在一个文件的顶部使用时有效。你说得对,Pavel。现在我理解了你的解决方案:)这很有趣,但它如何回答实际问题呢?环境列表。变量包含