You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何优化Makefile以实现便捷添加PGM程序?

优化Makefile实现PGM程序便捷添加

问题背景

我正尝试优化Makefile以实现PGM程序的便捷添加,当前使用的待优化Makefile内容如下:

SOURCES = main.cpp logic.cpp
OBJECTS = $(SOURCES:.cpp=.o)
CC = CC
MODEL001 = FLAGA FLAGB
MODEL002 = FLAGC
CFLAGS001 = -c $(MODEL001:%=-D%)
CFLAGS002 = -c $(MODEL002:%=-D%)
PGMNUM = 001 002
all: PGM001 PGM002
PGM001:$(SOURCES)
	$(CC) $(CFLAGS001) $(SOURCES)
	$(CC) -o $PGM001 $(OBJECTS)
PGM002:$(SOURCES)
	$(CC) $(CFLAGS002) $(SOURCES)
	$(CC) -o $PGM002 $(OBJECTS)

目前添加PGM003时,需要执行以下操作:新增MODEL003、CFLAGS003、PGM003的编译规则,同时修改PGMNUM变量和all目标。我希望仅通过新增MODEL配置和更新PGMNUM变量即可完成PGM程序的添加,为此编写了如下伪代码但无法正常工作:

SOURCES = main.cpp logic.cpp
OBJECTS = $(SOURCES:.cpp=.o)
CC = CC
MODEL001 = FLAGA FLAGB
MODEL002 = FLAGC
MODEL003 = FLAGD FLAGE
PGMNUM = 001 002 003
CFLAGS$(PGMNUM) = -c $(MODEL$(PGMNUM):%=-D%)
all: $(PGMNUM:%=PGM%)
PGM$(PGMNUM):$(SOURCES)
	$(CC) $(CFLAGS$(PGMNUM)) $(SOURCES)
	$(CC) -o $PGM$(PGMNUM) $(OBJECTS)

请问如何实现这一需求?

解决方案

你的思路方向是对的,但Makefile不支持CFLAGS$(PGMNUM)这种直接批量赋值变量的写法,我们可以借助**foreach+eval组合动态生成变量,再配合静态模式规则**处理每个PGM的编译逻辑,就能实现只新增MODEL配置和更新PGMNUM的需求。

优化后的Makefile(基础版)

SOURCES = main.cpp logic.cpp
OBJECTS = $(SOURCES:.cpp=.o)
CC = CC

# 新增PGM只需在这里添加对应的MODEL配置
MODEL001 = FLAGA FLAGB
MODEL002 = FLAGC
MODEL003 = FLAGD FLAGE

# 只需更新这个列表,就能自动生成对应PGM的编译规则
PGMNUM = 001 002 003

# 用foreach遍历PGMNUM,动态生成每个PGM对应的CFLAGS变量
$(foreach num,$(PGMNUM),$(eval CFLAGS$(num) = -c $(MODEL$(num):%=-D%)))

# 生成默认目标all,包含所有PGM程序
all: $(PGMNUM:%=PGM%)

# 静态模式规则:匹配所有PGM开头的目标,自动绑定对应编号的编译参数
.PHONY: all $(PGMNUM:%=PGM%)

PGM%:
	$(CC) $(CFLAGS$*) $(SOURCES)
	$(CC) -o $@ $(OBJECTS)

进阶优化:避免重复编译源文件

上面的写法每次编译不同PGM都会重新编译所有源文件,我们可以拆分编译和链接步骤,先编译通用的目标文件,再针对不同模型做链接,提升效率:

SOURCES = main.cpp logic.cpp
OBJECTS = $(SOURCES:.cpp=.o)
CC = CC

MODEL001 = FLAGA FLAGB
MODEL002 = FLAGC
MODEL003 = FLAGD FLAGE
PGMNUM = 001 002 003

# 动态生成每个PGM的宏定义参数(去掉-c,移到链接阶段或编译阶段根据需求调整)
$(foreach num,$(PGMNUM),$(eval CFLAGS$(num) = $(MODEL$(num):%=-D%)))

all: $(PGMNUM:%=PGM%)

# 先编译通用目标文件(仅执行一次)
$(OBJECTS): %.o: %.cpp
	$(CC) -c $< -o $@

# 针对每个PGM做链接,添加对应模型的宏定义
PGM%: $(OBJECTS)
	$(CC) $(CFLAGS$*) -o $@ $^

.PHONY: all $(PGMNUM:%=PGM%)

关键逻辑说明

  1. foreach+eval组合:这是Makefile动态生成代码的核心,foreach遍历PGMNUM里的每个编号,eval把生成的变量赋值语句当作Makefile代码执行,自动创建CFLAGS001CFLAGS002这类变量。
  2. 静态模式规则与$*变量PGM%会匹配所有以PGM开头的目标,$*会提取目标里的编号部分(比如PGM001$*就是001),从而动态引用对应的CFLAGS$*参数。
  3. .PHONY伪目标:标记all和所有PGM目标为伪目标,避免和同名文件冲突,确保每次执行make都会触发编译。

现在你添加新PGM时,只需要做两件事:

  • 新增一行MODELXXX = 宏定义列表
  • PGMNUM里添加XXX编号

完全不需要修改其他编译规则,就能自动生成新PGM的编译逻辑。

内容的提问来源于stack exchange,提问作者김진원

火山引擎 最新活动