使用sed在Makefile中使用大写文件名

使用sed在Makefile中使用大写文件名,sed,makefile,Sed,Makefile,我尝试在Makefile中将文件名(如foo/bar/baz.proto转换为类似foo/bar/baz.java)的文件名。为此,我想我可以使用sed。但是,该命令似乎没有按预期工作: uppercase_file = $(shell echo "$(1)" | sed 's/\(.*\/\)\(.*\)/\1\u\2/') # generated Java sources PROTO_JAVA_TARGETS := ${PROTO_SPECS:$(SRCDIR)/%.proto=$(JAVA

我尝试在Makefile中将文件名(如
foo/bar/baz.proto
转换为类似
foo/bar/baz.java
)的文件名。为此,我想我可以使用
sed
。但是,该命令似乎没有按预期工作:

uppercase_file = $(shell echo "$(1)" | sed 's/\(.*\/\)\(.*\)/\1\u\2/')
# generated Java sources
PROTO_JAVA_TARGETS := ${PROTO_SPECS:$(SRCDIR)/%.proto=$(JAVAGEN)/$(call uppercase_file,%).java}
当我尝试在命令行上运行sed命令时,它似乎可以工作:

~$ echo "foo/bar/baz" | sed 's/\(.*\/\)\(.*\)/\1\u\2/'
foo/bar/Baz
你知道为什么这在Makefile中不起作用吗

更新:

生成的java文件具有以下目标:
$(JAVAGEN)/%.java:$(SRCDIR)/%.proto


如何将替换也应用于目标?

GNU Make不会替换a的替换部分中的
%
字符,如果它是变量引用的一部分,则它基本上是一个语法糖。我没有发现文档中描述的这种行为,但是您可以在源代码中查看它的实现(我相信相关的函数是)

我建议将调用移出替换引用,因为
uppercase\u file
显然可以在任何文件路径上正常工作:

PROTO_JAVA_TARGETS := $(call uppercase_file,${PROTO_SPECS:$(SRCDIR)/%.proto=$(JAVAGEN)/%.java})
如果
$(PROTO_SPECS)
不是解析为单个元素,而是解析为元素列表,则可以使用对已处理列表的每个元素调用函数:

PROTO_JAVA_TARGETS := $(foreach JAVA,${PROTO_SPECS:$(SRCDIR)/%.proto=$(JAVAGEN)/%.java},$(call uppercase_file,$(JAVA)))
java文件是使用以下目标生成的:
$(JAVAGEN)/%.java:$(SRCDIR)/%.proto

我如何将替代也应用于目标

由于Make首先匹配目标,并且无法向后运行
sed
,因此这里需要定义一个反函数,或者生成多个显式规则。我将展示后一种方法

define java_from_proto
$(call uppercase_file,$(1:$(SRCDIR)/%.proto=$(JAVAGEN)/%.java)): $1
    # Whatever recipe you use.
    # Use `$$@`, `$$<` and so on instead of `$@` or `$<`.
endef

$(foreach PROTO,$(PROTO_SPECS),$(eval $(call java_from_proto,$(PROTO))))
from_proto定义java_
$(调用大写字母_文件,$(1:$(SRCDIR)/%.proto=$(JAVAGEN)/%.java)):$1
#不管你用什么食谱。

#使用`$$@`,`$$这在Makefile中对我有什么帮助?应该是什么?(我认为您显示的行在makefile的全局范围内,而不是在配方或函数定义中)。您需要发布更多的makefile以使其更清晰。请确保shell和sed路径在makefile内与在makefile外相同。GNU make也有可以使用的uc/lc功能。好主意!但是,
PROTO_SPECS
是一个使用通配符创建的列表:
PROTO_SPECS:=$(通配符$(PROTODIR)/*.PROTO)
现在我需要一种方法在list@AlexanderR奥斯勒:是的,谢谢!现在,我还需要对目标应用替换(请参见我的更新)。你有没有办法解决这个问题?