You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写Makefile pattern rule实现多子目录源文件生成单一目标

Makefile模式规则实现多源文件合并生成单个目标文件

需求

需要编写Makefile模式规则,将多个源文件合并生成单个目标文件。与常规单源文件场景不同,源文件存放在与目标同名的文件夹中(如目标lib1.so对应lib1/文件夹),源文件路径为src/[可变目录]/[库名]/形式,需忽略公共前缀src/及中间的可变目录,最终生成bin/[库名].so目标。

目录结构

需要生成的目标文件:

bin/lib1.so
bin/lib2.so
bin/lib3.so

源目录结构:

  • src/
    • foo/
      • lib1/
        • a.c
        • b.c
    • bar/
      • lib2/
        • d.c
        • e.c
      • lib3/
        • f.c
        • g.c

现有Makefile问题

当前通过make all构建,显式指定目标(实际使用shell find自动查找,此处简化):

all: bin/lib1.so bin/lib2.so bin/lib3.so

尝试编写的模式规则无法正常工作:

bin/%.so: $$(wildcard src/*/%/*.c)
   # 测试规则:
   echo $< > $@

问题核心:现有方案仅适配1:1文件映射场景,无法处理当前多源文件对应单个目标的n:1映射,且规则中的通配符展开时机错误,导致无法匹配到对应源文件。

期望结果

测试规则时,每个目标文件需记录对应所有源文件路径:

  • bin/lib1.so内容:
src/foo/lib1/a.c
src/foo/lib1/b.c
  • bin/lib2.so内容:
src/bar/lib2/d.c
src/bar/lib2/e.c
  • bin/lib3.so内容:
src/bar/lib3/f.c
src/bar/lib3/g.c

解决方案

方案1:使用二次展开模式规则

利用Make的.SECONDEXPANSION特性,让依赖中的通配符在匹配到具体目标后再展开,确保每个%能正确替换为库名:

# 启用二次展开,让规则依赖在模式匹配后再解析
.SECONDEXPANSION:

all: bin/lib1.so bin/lib2.so bin/lib3.so

# 模式规则:匹配bin/%.so,依赖为对应库目录下的所有.c文件
bin/%.so: $$(wildcard src/*/%/*.c)
	# 将所有依赖源文件列表写入目标,用tr替换空格为换行
	echo $^ | tr ' ' '\n' > $@

# 确保bin目录存在,作为所有目标的前置条件
$(all): | bin

bin:
	mkdir -p bin

方案2:自动收集目标+静态模式规则

适合需要自动发现所有库目标的场景,无需手动指定all中的目标:

# 自动查找src下所有以lib开头的目录
LIB_SRCDIRS := $(shell find src -type d -name "lib*")
# 将源目录路径转换为bin下的目标文件路径
LIB_TARGETS := $(patsubst src/%/lib%, bin/lib%.so, $(LIB_SRCDIRS))

all: $(LIB_TARGETS)

# 静态模式规则:为每个目标匹配对应的源文件
bin/lib%.so:
	# 查找当前库对应的所有.c文件
	$(eval SRCS := $(shell find src -path "*lib$*/*.c"))
	# 将源文件列表写入目标
	echo $(SRCS) | tr ' ' '\n' > $@

# 确保bin目录存在
$(LIB_TARGETS): | bin

bin:
	mkdir -p bin

说明

  • 方案1中,$^代表规则的所有依赖文件列表,通过tr ' ' '\n'将空格分隔的路径转换为每行一个,符合期望格式。
  • 方案2通过find自动发现所有库目录,适合库数量较多或目录结构动态变化的场景,无需手动维护all目标列表。

内容的提问来源于stack exchange,提问作者user66554

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 16:05:53