如何在Makefile中为带占位符的地理坐标目标添加动态依赖
需求说明
我有一个模式目标%.hgtForCoordsAndNeighbours(示例:+64-016.hgtForCoordsAndNeighbours),每个目标对应一个地理坐标区块,需要依赖其中心区块+8个相邻1度区块的%.hgtForCoords目标。要求依赖的文件名必须符合带前导零的格式(对应printf的%+03d%+04d规则)。
当前用子$(MAKE)调用实现,但存在并发(-j参数)问题,且自调用属于不良风格,希望用纯Makefile语法实现,运行环境为GitHub Actions的Linux runner(GNU Make 4.3),坐标空间有限(360×180),所有依赖只需评估一次。
实现方案
1. 核心思路
利用GNU Make的自定义函数、字符串处理和Shell数值计算能力,直接在模式规则中动态生成所有依赖,无需子Make调用。
2. 完整Makefile实现
SHELL=/bin/bash # 从目标名中提取坐标前缀(去除.hgtForCoordsAndNeighbours后缀) extract_coords = $(basename $(1)) # 从坐标前缀中拆分出原始纬度、经度字符串(保留符号和前导零) raw_lat = $(word 1,$(subst -, ,$(extract_coords $(1)))) raw_lon = $(word 2,$(subst -, ,$(extract_coords $(1)))) # 将带符号的坐标字符串转为数值(自动去除前导零) lat_num = $(shell expr $(raw_lat)) lon_num = $(shell expr $(raw_lon)) # 生成单个区块的依赖文件名:参数为纬度偏移、经度偏移、目标名 make_dep = $(shell printf "%+03d%+04d" $$(($(lat_num $(3)) + $(1))) $$(($(lon_num $(3)) + $(2)))).hgtForCoords # 生成中心+8个相邻区块的所有依赖 all_neighbours = \ $(call make_dep,-1,-1,$@) \ $(call make_dep,0,-1,$@) \ $(call make_dep,1,-1,$@) \ $(call make_dep,-1,0,$@) \ $(call make_dep,0,0,$@) \ $(call make_dep,1,0,$@) \ $(call make_dep,-1,1,$@) \ $(call make_dep,0,1,$@) \ $(call make_dep,1,1,$@) # 模式规则:直接关联动态生成的依赖 %.hgtForCoordsAndNeighbours: $(all_neighbours) @echo "Prepare elevation data for $(extract_coords $@) and neighbours"
3. 关键细节说明
- 坐标解析:通过
$(basename)、$(subst)拆分目标名中的坐标部分,再用expr自动去除前导零并转换为数值。 - 依赖生成:
make_dep函数结合printf生成符合格式要求的依赖文件名,all_neighbours枚举所有相邻+中心的偏移组合。 - 并发友好:所有依赖在Make解析阶段直接生成,无需子进程触发,完全兼容
-j并行构建。
4. 效果验证
对于目标+64-016.hgtForCoordsAndNeighbours,会自动生成以下9个依赖:
+63-017.hgtForCoords +64-017.hgtForCoords +65-017.hgtForCoords +63-016.hgtForCoords +64-016.hgtForCoords +65-016.hgtForCoords +63-015.hgtForCoords +64-015.hgtForCoords +65-015.hgtForCoords
内容的提问来源于stack exchange,提问作者Jonas Eberle
相关产品推荐
相关产品推荐

