如何在Makefile中从SRVS变量提取指定扩展名的无后缀文件名列表
解决Makefile中提取特定扩展名文件并生成无扩展名列表的问题
没问题,我来帮你搞定这个需求!你需要从逗号分隔的SRVS变量里筛选出指定扩展名的文件,再去掉扩展名生成foreach可用的列表,用Makefile内置函数就能轻松实现,不需要依赖shell命令(当然也可以用,但内置函数更高效)。
核心思路拆解
要达成目标,我们只需要三步:
- 把逗号分隔转成空格分隔:Makefile默认用空格作为列表分隔符,所以先把
SRVS里的,替换成空格,得到标准列表。 - 过滤特定扩展名的文件:用
filter函数筛选出符合目标扩展名的文件。 - 去掉扩展名:用
basename函数剥离每个文件名的扩展名,得到纯文件名。
完整代码示例
假设你的SRVS变量是Test1.java,test2.c,test3.c,test4.java,test5.c,我们可以这样处理:
SRVS=Test1.java,test2.c,test3.c,test4.java,test5.c # 提取所有.java文件,生成无扩展名的列表 JAVA_SRVS := $(basename $(filter %.java, $(subst ,, $(SRVS)))) # 提取所有.c文件,生成无扩展名的列表 C_SRVS := $(basename $(filter %.c, $(subst ,, $(SRVS)))) # 测试foreach循环 .PHONY: process-java process-c all all: process-java process-c process-java: @$(foreach srv, $(JAVA_SRVS), echo "Processing Java service: $(srv)";) process-c: @$(foreach srv, $(C_SRVS), echo "Processing C service: $(srv)";)
各部分解释
$(subst ,, $(SRVS)):将SRVS中的逗号替换为空格,把字符串Test1.java,test2.c...转换成Makefile可识别的列表Test1.java test2.c...。$(filter %.java, ...):只保留列表中以.java结尾的文件名,这里会得到Test1.java test4.java。$(basename ...):去掉每个文件名的扩展名,最终得到Test1 test4,正好是你需要的无扩展名列表。- 之后直接把
JAVA_SRVS或C_SRVS传入foreach循环即可,因为它们已经是标准的空格分隔列表了。
更通用的函数封装
如果需要频繁提取不同扩展名的文件,可以封装成一个可复用的函数,这样更灵活:
SRVS=Test1.java,test2.c,test3.c,test4.java,test5.c # 自定义函数:参数1=目标扩展名(比如.java),参数2=原始SRVS变量 extract_services = $(basename $(filter %$(1), $(subst ,, $(2)))) # 调用函数提取不同类型的文件 JAVA_SRVS := $(call extract_services,.java,$(SRVS)) C_SRVS := $(call extract_services,.c,$(SRVS))
这样不管你要提取.py还是.go的文件,只需要调用$(call extract_services,.py,$(SRVS))就能得到对应的无扩展名列表了。
内容的提问来源于stack exchange,提问作者Sven
相关产品推荐
相关产品推荐

