如何通过Makefile将编译生成文件保存至独立目录?
把Fortran编译产物全塞进Build目录的Makefile修改方案
原Makefile改了OBJDIR却没生效?问题出在这几个地方:
- 用了未定义的
SOURCES变量,导致目标文件路径转换完全失效 .mod模块文件默认丢主目录,没指定输出到Build.d依赖文件也留在主目录,没统一管理- 可执行文件还是生成在根目录,没移到Build
- 没自动创建Build目录,编译时可能因为目录不存在报错
修改后的完整Makefile
# Compiler settings - 可自定义 CC = gfortran CPP = gfortran -cpp # 加-J$(OBJDIR)让.mod文件输出到Build目录 CXXFLAGS = -g -O0 -Wall -Wextra -Wshadow -pedantic -J$(OBJDIR) LDFLAGS = # Makefile settings - 可自定义 APPNAME = myapp EXT = .f90 SRCDIR = src # 把Build放主目录和src平级,更清晰(想放src里就改回src/Build) OBJDIR = Build ############## 核心修改部分 ############# # 获取src下所有Fortran源文件 SRC = $(wildcard $(SRCDIR)/*$(EXT)) # 把源文件路径转成Build下的.o文件路径 OBJ = $(patsubst $(SRCDIR)/%$(EXT), $(OBJDIR)/%.o, $(SRC)) # 依赖文件也放Build里 DEP = $(OBJ:$(OBJDIR)/%.o=$(OBJDIR)/%.d) # Unix系统设置 RM = rm -rf DELOBJ = $(OBJ) $(DEP) $(OBJDIR)/*.mod # 可执行文件直接放Build APP_PATH = $(OBJDIR)/$(APPNAME) # Windows系统设置 DEL = del /Q /F EXE = .exe WDELOBJ = $(patsubst $(SRCDIR)/%$(EXT), $(OBJDIR)\\%.o, $(SRC)) WAPP_PATH = $(OBJDIR)\\$(APPNAME)$(EXE) ######################################################################## ####################### 编译目标开始 ######################### ######################################################################## all: $(APP_PATH) # 编译前先确保Build目录存在 $(OBJDIR): mkdir -p $(OBJDIR) # 生成可执行文件,依赖Build目录和所有.o文件 $(APP_PATH): $(OBJDIR) $(OBJ) $(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) # 生成依赖文件,输出到Build目录 $(OBJDIR)/%.d: $(SRCDIR)/%$(EXT) $(OBJDIR) @$(CPP) $(CXXFLAGS) $< -MM -MT $(@:$(OBJDIR)/%.d=$(OBJDIR)/%.o) >$@ # 引入所有依赖文件 -include $(DEP) # 编译生成.o文件,依赖Build目录 $(OBJDIR)/%.o: $(SRCDIR)/%$(EXT) $(OBJDIR) $(CC) $(CXXFLAGS) -o $@ -c $< ################### Unix系统清理规则 ################### # 清理所有编译产物 .PHONY: clean clean: $(RM) $(DELOBJ) $(APP_PATH) # 只清理依赖文件 .PHONY: cleandep cleandep: $(RM) $(DEP) #################### Windows系统清理规则 ##################### # 清理所有编译产物 .PHONY: cleanw cleanw: $(DEL) $(WDELOBJ) $(OBJDIR)\*.mod $(DEP) $(WAPP_PATH) if exist $(OBJDIR) rmdir /S /Q $(OBJDIR) # 只清理依赖文件 .PHONY: cleandepw cleandepw: $(DEL) $(DEP)
关键修改点说明
- 管住.mod文件:在
CXXFLAGS里加-J$(OBJDIR),gfortran会自动把编译生成的模块文件扔到Build目录,不会乱跑到主目录 - 修复路径转换:把原Makefile里的
$(SOURCES)换成实际定义的$(SRC),这样目标文件的路径转换才会生效 - 统一依赖文件:把
.d依赖文件也放到Build目录,主目录再也不会出现一堆零散的依赖文件 - 自动建目录:新增
$(OBJDIR)目标,编译前自动创建Build目录,不用手动建 - 可执行文件搬家:把可执行文件的输出路径改成
$(OBJDIR)/$(APPNAME),编译完直接在Build里找就行 - 清理更彻底:清理规则加上了
.mod文件的删除,执行make clean就能把Build目录的产物全清干净
内容的提问来源于stack exchange,提问作者mho
相关产品推荐
相关产品推荐

