Makefile 项目管理(升级版)
本帖最后由 Jackdaw 于 2020-9-2 20:12 编辑上次写了一篇《Makefile 项目管理》,感觉意犹未尽,现在重新写了一个新的
此次更新内容包括:
1. 文件分类存放
2. 自动生成依赖关系
依赖:
makedepf90
Makefile:
#!/bin/bash
# 设置文件路径
SRCDIR = src
OBJDIR = obj
MODDIR = mod
BINDIR = bin
# 文件
SRC = floatPrecision.f90 GE_MPC.f90
SRC := $(SRC) main.f90
OBJ = $(SRC:.f90=.o)
# 增加前缀
SRCS= $(addprefix $(SRCDIR)/, $(SRC))
OBJS= $(addprefix $(OBJDIR)/, $(OBJ))
# 编译器相关设置
FC = gfortran
FF = -cpp -O0 -g -fbacktrace
DF = -DDOUBLE_PRECISION
EXE = myPro
# 所有目标
all: $(OBJDIR)/depend $(OBJS) binary
# 依赖关系
include $(OBJDIR)/depend
# 链接
binary: $(OBJS)
$(FC) $(FF) $(DF) -J$(MODDIR) $(OBJS) -o $(BINDIR)/$(EXE)
# 编译
$(OBJS):
$(FC) $(FF) $(DF) -J$(MODDIR) -c $< -o $@
# 检查路径,并生成依赖关系
.PONHY: $(OBJDIR)/depend
$(OBJDIR)/depend:
@if test -d $(SRCDIR); then echo "# directory "$(SRCDIR) "exists"; else mkdir $(SRCDIR); fi
@if test -d $(OBJDIR); then echo "# directory "$(OBJDIR) "exists"; else mkdir $(OBJDIR); fi
@if test -d $(MODDIR); then echo "# directory "$(MODDIR) "exists"; else mkdir $(MODDIR); fi
@if test -d $(BINDIR); then echo "# directory "$(BINDIR) "exists"; else mkdir $(BINDIR); fi
makedepf90 -b $(OBJDIR) $(SRCS) > $(OBJDIR)/depend
# 清理工程
.PONHY: clean
clean :
rm -rf $(OBJDIR)/depend $(MODDIR)/*.mod $(OBJS) $(BINDIR)/$(EXE)
下面看看执行结果(测试代码见附件):
赞!
要是有个cmake的简易教程就完美了 pasuka 发表于 2019-1-29 09:19
赞!
要是有个cmake的简易教程就完美了
也有,以前写的,很简单的一个帖子
使用cmake管理Fortran项目(demo) Jackdaw 发表于 2019-1-29 13:59
也有,以前写的,很简单的一个帖子
使用cmake管理Fortran项目(demo)
这个模板非常好,我正在好好学习。有个问题不明白,想请教楼主,第9行为何=号前面有:号呢?这表示什么呢?我在makefile的书写规则里查不到这个,希望楼主指点一下,非常感谢! 静待花开 发表于 2023-8-4 20:56
这个模板非常好,我正在好好学习。有个问题不明白,想请教楼主,第9行为何=号前面有:号呢?这表示什么 ...
首先你需要理解,makefile文件并不是像编程语言一样按行执行的,make会一次性的把makefile读取完,并根据生成规则去执行(而不是按照文件顺序一行一行执行)。
所以,
a = text
a = next
这样写的话。a 的值会是整个makefile中最后一次的赋值(也就是next)。
而如果写成
a := text
a := next
的话,则 a 的值会是按照当前行的顺序而获得的值。
一般情况下,如果要重复对一个量赋值,第一次写 =,第二次及以后都写 := 本帖最后由 静待花开 于 2023-8-5 11:13 编辑
kyra 发表于 2023-8-4 21:22
首先你需要理解,makefile文件并不是像编程语言一样按行执行的,make会一次性的把makefile读取完,并根据 ...
非常感谢版主回得这么快、这么详细。经过您的讲解,我理解了楼主这样处理 似乎就是为了 编译含有module这样的程序。这种处理 module的巧妙,令人佩服。因为我按照常规方法准备Makefile,make后总是提示找不到.mod文件,所以才找到了这个经典的贴子。
把楼主的文件down下来操作一遍,总是有问题,不能make成功。才发现makedepf90也是一个需要预先安装的程序,sudo apt install makedepf90。然后顺利编译成功。谢谢楼主提供这么好的一个Makefile模板。
打算在这个基础上再修改一下,不需要自己输入第8行、第9行的文件名,不知道可不可行。
kyra 发表于 2023-8-4 21:22
首先你需要理解,makefile文件并不是像编程语言一样按行执行的,make会一次性的把makefile读取完,并根据 ...
查了好多,没有见到解释 25行/28行 中的 -J 是表示什么,可否请版主指点下?非常感谢 静待花开 发表于 2023-8-6 10:35
查了好多,没有见到解释 25行/28行 中的 -J 是表示什么,可否请版主指点下?非常感谢 ...
-J 不是 make 的语法哟,是 gfortran 的命令行参数。
表示指定 .mod 文件所在的路径。
可以在这里查看gfortran的帮助
https://gcc.gnu.org/onlinedocs/gfortran/
-J属于目录指定参数(类别)
https://gcc.gnu.org/onlinedocs/gfortran/Directory-Options.html kyra 发表于 2023-8-6 10:55
-J 不是 make 的语法哟,是 gfortran 的命令行参数。
表示指定 .mod 文件所在的路径。
嗯嗯,明白了,:-handshake:-handshake非常非常感谢,我还得继续学习gfortran,也是刚接触 。 本帖最后由 静待花开 于 2023-8-8 15:56 编辑
kyra 发表于 2023-8-6 10:55
-J 不是 make 的语法哟,是 gfortran 的命令行参数。
表示指定 .mod 文件所在的路径。
这是我在楼主基础上修改后的。就是想做得更通用一点,不需要用户在makefile里面输入源代码文件名(如原makefile第8、第9行)。思路是:把module文件的后缀都改为.module,一个module写在一个.module文件中,并且文件名与module名称完全一样。但make之后,生成的*.mod文件除了输出到mod文件夹内,还输出在了makefile所在的目录(即与makefile放在一起),能编译成功,但多了这些.mod文件,还需要在删除。试了好多办法,实在想不到更好办法,想请版主看看是什么问题。楼主看到的话,也请指点一下。
下面是我改后makefile文件。
#!/bin/bash
# 设置文件路径
SRCDIR= src
OBJDIR= obj
MODDIR= mod
BINDIR= bin
# 文件
SRC = $(wildcard $(SRCDIR)/*.f90)
OBJ = $(addprefix $(OBJDIR)/, $(patsubst %.f90,%.o,$(notdir $(SRC))))
MODSRC = $(wildcard $(SRCDIR)/*.module)
MODOBJ = $(addprefix $(OBJDIR)/, $(patsubst %.module,%.o,$(notdir $(MODSRC))))
MOD = $(addprefix $(MODDIR)/, $(patsubst %.module,%.mod,$(notdir $(MODSRC))))
# 编译器相关设置
FC = gfortran
FF = -cpp -O0 -g -fbacktrace
DF = -DDOUBLE_PRECISION
EXE = myPro
# 所有目标
all: $(OBJDIR)/depend binary
# 依赖关系
include $(OBJDIR)/depend
# 链接
binary: $(OBJ) $(MODOBJ)
$(FC) $(FF) $(DF) -J$(MODDIR) $(OBJ) $(MODOBJ) -o $(BINDIR)/$(EXE)
# 编译
$(OBJ): $(SRC) $(MOD)
$(FC) $(FF) $(DF) -J$(MODDIR) -c $< -o $@
$(OBJDIR)/%.o: $(SRCDIR)/%.module
$(FC) -c -cpp -x f95 $< -o $@
$(MODDIR)/%.mod: $(SRCDIR)/%.module
$(FC) -c -cpp -x f95 $< -o $@
# 检查路径,并生成依赖关系
.PONHY: $(OBJDIR)/depend
$(OBJDIR)/depend:
@if test -d $(SRCDIR); then echo "# directory "$(SRCDIR) "exists"; else mkdir $(SRCDIR); fi
@if test -d $(OBJDIR); then echo "# directory "$(OBJDIR) "exists"; else mkdir $(OBJDIR); fi
@if test -d $(MODDIR); then echo "# directory "$(MODDIR) "exists"; else mkdir $(MODDIR); fi
@if test -d $(BINDIR); then echo "# directory "$(BINDIR) "exists"; else mkdir $(BINDIR); fi
makedepf90 -b $(OBJDIR) $(SRCS) > $(OBJDIR)/depend
clean-all:
rm -rf $(OBJDIR)/depend *.o *.mod $(MOD) $(MODOBJ) $(OBJ) $(BINDIR)/$(EXE)
页:
[1]