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

如何基于目标为Makefile配置不同后缀规则实现编译切换?

问题

我现在在Makefile里通过注释切换两组编译标志,来实现程序的优化编译或调试信息输出。想改成基于调用的目标(比如program-optimized或program-debug)自动使用对应的编译规则,让源码文件也用对应标志编译,不用手动注释切换。以下是现有代码和我的尝试方案,想问这个方案是否可行,以及正确的实现方式:

现有代码

FC = gfortran
# 我通过注释其中一行来切换编译标志
# FFLAGS = -Og -Wall -Wextra -fcheck=all -fbacktrace -fbounds-check
FFLAGS = -O3
MOD='Modules/'

SRC  = Modules/pyplot_module.f90
SRC += Modules/logs.f90
SRC += program.f90
OBJ  = ${SRC:.f90=.o}

%.o: %.f90
    $(FC) -c -J${MOD} $< $(FFLAGS) -o $@

program: $(OBJ)
    $(FC) -J${MOD} $(FFLAGS) -o $@ $(OBJ)

remake: remove program

clean:
    rm -f **/*.o **/*.mod

remove: clean
    rm -f program

尝试方案

FC = gfortran
# 这里做了修改
DEBUGFFLAGS = -Og -Wall -Wextra -fcheck=all -fbacktrace -fbounds-check
FFLAGS = -O3
MOD='Modules/'

SRC  = Modules/pyplot_module.f90
SRC += Modules/logs.f90
SRC += program.f90
OBJ  = ${SRC:.f90=.o}

%.o: %.f90
    $(FC) -c -J${MOD} $< $(FFLAGS) -o $@

%.o: %.f90 # 我希望这个后缀规则只在构建program-debug目标时生效
    $(FC) -c -J${MOD} $< $(DEBUGFFLAGS) -o $@

program-optimized: $(OBJ)
    $(FC) -J${MOD} $(FFLAGS) -o $@ $(OBJ)

program-debug: $(OBJ)
    # 但我也希望源码文件用这些标志编译
    $(FC) -J${MOD} $(DEBUGFFLAGS) -o $@ $(OBJ)

remake: remove program

clean:
    rm -f **/*.o **/*.mod

remove: clean
    rm -f program
解决方案

你的尝试方案不可行,因为Makefile中如果有多个相同的模式规则(比如两个%.o: %.f90),只会执行最后定义的那一个。也就是说不管你构建program-optimized还是program-debug,所有.o文件都会用DEBUGFFLAGS编译,完全达不到分目标切换的效果。

下面是两种正确的实现方式:

方式一:使用目标特定变量

利用Makefile的目标特定变量功能,给不同的目标指定对应的编译标志,同时让.o文件的编译规则自动继承当前目标的标志:

FC = gfortran
DEBUGFFLAGS = -Og -Wall -Wextra -fcheck=all -fbacktrace -fbounds-check
OPTFFLAGS = -O3
MOD='Modules/'

SRC  = Modules/pyplot_module.f90
SRC += Modules/logs.f90
SRC += program.f90
OBJ  = ${SRC:.f90=.o}

# 默认目标设为优化版
.DEFAULT_GOAL := program-optimized

# 通用编译规则
%.o: %.f90
    $(FC) -c -J${MOD} $< $(FFLAGS) -o $@

# 优化版目标:指定FFLAGS为优化标志
program-optimized: FFLAGS = $(OPTFFLAGS)
program-optimized: $(OBJ)
    $(FC) -J${MOD} $(FFLAGS) -o $@ $(OBJ)

# 调试版目标:指定FFLAGS为调试标志
program-debug: FFLAGS = $(DEBUGFFLAGS)
program-debug: $(OBJ)
    $(FC) -J${MOD} $(FFLAGS) -o $@ $(OBJ)

# 切换目标时强制清理旧文件,确保重新编译
program-debug: clean
program-optimized: clean

remake: remove program-optimized

clean:
    rm -f **/*.o **/*.mod

remove: clean
    rm -f program-optimized program-debug

这种写法简洁,通过给不同目标绑定专属的FFLAGS,让编译规则自动适配。添加clean依赖是为了避免切换目标时,Makefile认为旧的.o文件已经最新而跳过编译。

方式二:分离不同模式的目标文件目录

把调试版和优化版的.o文件分别放到不同的目录(比如build/debug和build/optimized),彻底避免文件冲突,还能同时保留两种版本的可执行文件:

FC = gfortran
DEBUGFFLAGS = -Og -Wall -Wextra -fcheck=all -fbacktrace -fbounds-check
OPTFFLAGS = -O3
MOD='Modules/'

SRC  = Modules/pyplot_module.f90
SRC += Modules/logs.f90
SRC += program.f90

# 定义不同模式的目标文件路径
DEBUG_OBJ = $(addprefix build/debug/,$(SRC:.f90=.o))
OPT_OBJ = $(addprefix build/optimized/,$(SRC:.f90=.o))

.DEFAULT_GOAL := program-optimized

# 调试版目标文件编译规则
build/debug/%.o: %.f90
    @mkdir -p $(dir $@)
    $(FC) -c -J${MOD} $< $(DEBUGFFLAGS) -o $@

# 优化版目标文件编译规则
build/optimized/%.o: %.f90
    @mkdir -p $(dir $@)
    $(FC) -c -J${MOD} $< $(OPTFFLAGS) -o $@

program-optimized: $(OPT_OBJ)
    $(FC) -J${MOD} $(OPTFFLAGS) -o $@ $(OPT_OBJ)

program-debug: $(DEBUG_OBJ)
    $(FC) -J${MOD} $(DEBUGFFLAGS) -o $@ $(DEBUG_OBJ)

remake: remove program-optimized

clean:
    rm -rf build/
    rm -f **/*.mod

remove: clean
    rm -f program-optimized program-debug

这种方式的优势是可以同时保留调试版和优化版的可执行文件,切换目标时不需要手动清理,Makefile会自动处理不同目录下的目标文件,适合需要同时维护两个版本的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 23:01:37