如何实现任意路径下共享库的Makefile依赖自动获取?
解决方案
纯Makefile方案(推荐)
核心问题是规则依赖的展开时机错误:默认情况下Make读取规则时就会解析依赖,此时$@是模式${DIR_OUT}/%.so,而非实际目标路径。使用二次展开(.SECONDEXPANSION:)可以让依赖在规则执行前才展开,此时$@会替换为实际的共享库完整路径。
方法1:使用Make内置wildcard函数(更高效)
在Rules.make中添加:
.SECONDEXPANSION: ${DIR_OUT}/%.so: $$(wildcard $$(dir $$@)*.o) $(CC) $(CFLAGS) -o $@ $(CLIBS) -shared $^
$$是转义符,二次展开时会解析为单个$,此时$$(dir $$@)会获取实际共享库所在的子目录,wildcard会查找该目录下所有.o文件。- 无需调用外部命令,性能更优。
方法2:使用shell find(兼容复杂目录结构)
如果需要递归查找嵌套子目录下的.o文件,可改用find:
.SECONDEXPANSION: ${DIR_OUT}/%.so: $$(shell find $$(dir $$@) -name '*.o') $(CC) $(CFLAGS) -o $@ $(CLIBS) -shared $^
- 给
*.o加单引号,避免Shell提前展开通配符。
可选:精确指定依赖(适合多库同目录场景)
如果同一子目录下存在多个共享库,自动查找所有.o会导致依赖混淆,可在子目录的极简Makefile中补充少量配置:
# 子目录Makefile include $(DIR_TOP)/Rules.make # 指定libfoo.so对应的目标文件 LIBFOO_OBJS := foo_core.o foo_utils.o $(DIR_OUT)/path/to/libfoo.so: $(addprefix $(DIR_OUT)/path/to/,$(LIBFOO_OBJS))
主Rules.make中保留通用链接规则即可:
${DIR_OUT}/%.so: $(CC) $(CFLAGS) -o $@ $(CLIBS) -shared $^
Bash脚本辅助方案
若上述Makefile方案无法满足需求,可编写脚本动态获取依赖,同时确保Make能感知依赖变化:
- 编写
get_lib_objs.sh脚本:
#!/bin/bash SO_PATH="$1" find "$(dirname "$SO_PATH")" -name '*.o'
- 在
Rules.make中通过二次展开调用脚本:
.SECONDEXPANSION: ${DIR_OUT}/%.so: $$(shell ./get_lib_objs.sh $$@) $(CC) $(CFLAGS) -o $@ $(CLIBS) -shared $^
- 需给脚本添加执行权限:
chmod +x get_lib_objs.sh。
内容的提问来源于stack exchange,提问作者user17113867
相关产品推荐
相关产品推荐

