【发布时间】:2009-09-09 14:26:46
【问题描述】:
如何获取makefile中makefile的名称?
谢谢。
注意:
我需要它,因为我希望我的 makefile 调用自己,但 makefile 不称为 Makefile,所以我想写这样的东西:
target:
($MAKE) -f ($MAKEFILENAME) other_target
【问题讨论】:
标签: makefile
如何获取makefile中makefile的名称?
谢谢。
注意:
我需要它,因为我希望我的 makefile 调用自己,但 makefile 不称为 Makefile,所以我想写这样的东西:
target:
($MAKE) -f ($MAKEFILENAME) other_target
【问题讨论】:
标签: makefile
location = $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
WHERE_ART_THOU := $(location)
$(warning $(WHERE_ART_THOU))
我也相信这是 GNU make-specific,但我不太确定。
【讨论】:
WHERE_ART_THOU 用于一个 makefile,WHERE_ART_THOU_2 用于另一个等。我的目标是为所有 makefile 引入一个名称,该名称不仅在使用时有效在一个的顶部。
(如果您有任何疑问,请参阅惊人的写作GNU make manual。但请记住,就像 Makefile 一样,在将概念付诸实践之前应完整阅读本手册)。
我无法弄清楚它是如何轻松完成的。据我了解,您必须做一些体力活。
稍后我将描述它是如何完成的,并展示引入current_makefile 变量的脚本。但首先我想强调一个重要的概念。
你应该明白,如果我们有某种变量current_makefile,它会扩展为当前的makefile 名称,那么它在读取makefile 的过程中必须改变。这意味着它应该在“即时”扩展上下文中使用——即在在读取makefile期间执行的命令中。然而,大多数命令是在读取 makefile 之后执行的。因此,某些命令会顺利打印出正确的值,而在某些使用“deferred”扩展的地方,它总是会扩展为根 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 We're in makefile $(current_makefile))
这些函数使用“立即”展开并且会打印正确的值。
如何定义这样的$(current_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
如果您确定您的品牌足够新(版本 3.81+),请将 lastword 调用替换为内置函数:。
#inctead of $$(call lastword,$$(MAKEFILE_LIST))
$$(lastword $$(MAKEFILE_LIST))
有用吗?
完全没用。在这里可能有用的唯一用途是制作 100 个作为符号链接到一个 makefile 的 makefile,这些 makefile 中的规则取决于它们的名称。但它可以在手册中描述的一个 makefile 和 foreach-eval 技术中实现。所以我的帖子完全是浪费时间,虽然我玩得很开心:-)
【讨论】:
这将返回第一个调用的 Makefile 的名称,即调用堆栈底部的名称:
MAKEFILE_JUSTNAME := $(firstword $(MAKEFILE_LIST))
MAKEFILE_COMPLETE := $(CURDIR)/$(MAKEFILE_JUSTNAME)
在非交叉递归情况下使用时(例如用于 makedepend),它只是当前 makefile 的名称。
【讨论】:
当我使用 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`
【讨论】:
【讨论】:
生日,
如果您复制原始 makefile,请说 makefile_test,然后输入命令:
make -np -f makefile_test 2>&1 | tee output
这将评估 makefile 和您的 make 环境,但不会执行任何命令。查看输出文件中对 makefile_test 的引用将显示在 make 环境中设置的内容以及设置该值的位置。
注意这可以产生很多信息!并且不要添加 -d(调试)开关,它会生成大量关于 make 决策过程的额外输出,但会生成关于 make 环境的极少额外信息。
HTH
【讨论】:
这里的解决方案解决了 1) POSIX make with 2) Invoked, non included, makefile in 3) A Unix alike platform。
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 中包含的独特模式,使用前面的方法实现解决方案很简单。
当我觉得问题得到了适当的解决时,我从不回答。
【讨论】: