【Linux】多文件标准工程目录的Makefile编写及通用模板
在这里我们介绍多文件Makefile的编写,多文件标准工程目录的Makefile的编写及通用模板。
以加、减、乘、除为基础建立一个小的计算器,源代码如下:
主函数cal.c
#include <stdio.h>
int main()
{
printf("a + b = %d\n", add(10, 5));
printf("a - b = %d\n", sub(10, 5));
printf("a * b = %d\n", mul(10, 5));
printf("a / b = %d\n", div(10, 5));
return 0;
}
加法 add.c
int add(int a, int b)
{
return a + b;
}
减法 sub.c
int sub(int a, int b)
{
return a - b;
}
乘法 mul.c
int mul(int a, int b)
{
return a * b;
}
除法 div.c
int div(int a, int b)
{
return a / b;
}
一、多文件Makefile的编写
打开Makefile编写页面:
vim Makefile
代码如下:
cal : cal.o add.o sub.o mul.o div.o
gcc cal.o add.o sub.o mul.o div.o -o cal
cal.o : cal.c
gcc -c cal.c
add.o : add.c
gcc -c add.c
sub.o : sub.c
gcc -c sub.c
mul.o : mul.c
gcc -c mul.c
div.o : div.c
gcc -c div.c
从下图看到,开始只有.c
文件,在编写完上图Makefile代码并执行了make
之后,此时生成了目标文件和可执行文件,运行可执行文件,可以得到相应的结果。
还可以用make clean
删除生成的目标文件和可执行文件,Makefile代码如下:
cal : cal.o add.o sub.o mul.o div.o
gcc cal.o add.o sub.o mul.o div.o -o cal
cal.o : cal.c
gcc -c cal.c
add.o : add.c
gcc -c add.c
sub.o : sub.c
gcc -c sub.c
mul.o : mul.c
gcc -c mul.c
div.o : div.c
gcc -c div.c
.PHONY : clean
clean :
rm -f *.o cal
结果如下,可以看到在执行了make clean
之后所有的目标文件和可执行文件都被删除了:
如果有多个源文件,再利用上述方法编写Makefile,容易遗漏或者是写错文件名,并且如果一个文件名被修改,会导致我们需要把代码中所有该文件名都修改掉,麻烦而且浪费时间。那么可以用变量代替文件名。将图1所示代码修改如下:
obj = cal.o add.o sub.o mul.o div.o
cal : $(obj)
gcc $(obj) -o cal
cal.o : cal.c
gcc -c cal.c
add.o : add.c
gcc -c add.c
sub.o : sub.c
gcc -c sub.c
mul.o : mul.c
gcc -c mul.c
div.o : div.c
gcc -c div.c
可以看到用变量和图1所示代码最后的结果是相同的,并且利用变量更加简洁方便:
二、多文件标准工程目录的Makefile编写
在上述多文件Makefile的编写中,我们将所有的源文件放在了一个目录里,如果有大量的源文件,将其放在一个目录里不利于管理,所以要按照不同的分类方法将其分别放在不同的目录里,而上述过程只能用于源文件在相同目录下,下面介绍源文件放在不同目录下的Makefile文件该如何编写。
首先创建一个目录cal
,并在目录里创建分别放加、减、乘、除和主函数的目录,同时创建一个scripts目录
。分别将源代码放在相应的目录的src目录
里:
在这里就要首先提一下Makefile的类型,一共分为三类:
- 总控Makefile:进入各个功能子目录里执行make命令,将所有的“.o”文件链接生成最终的可执行文件。
- 功能子目录Makefile:将src(放源代码的目录)目录下的“.c”文件编译成“.o”文件。
- scripts目录的Makefile:定义许多变量(相当于C语言的头文件),提高make的灵活性和维护性。
以下分别列出编写的三类Makefile的代码:
scripts目录的Makefile:
CC := gcc
CFLAGS := -Wall -O3
Libs = -lpthread
Target := cal
Source := $(wildcard src/*.c)
Objs := $(patsubst %.c,%.o,$(Source))
Modules += add sub mul div main
AllObjs := $(addsuffix /src/*.o,$(Modules))
总控Makefile:
include scripts/Makefile
modules_make = $(MAKE) -C $(1);
modules_clean = $(MAKE) clean -C $(1);
.PHONY: all mm mc clean
all: $(Target)
mm:
@ $(foreach n,$(Modules),$(call modules_make,$(n)))
mc:
@ $(foreach n,$(Modules),$(call modules_clean,$(n)))
$(Target): mm
$(CC) $(CFLAGS) -o $(Target) $(AllObjs) $(Libs)
@ echo $(Target) make done!
clean: mc
rm -rf $(Target)
@ echo clean done!
功能子目录Makefile(每个功能子目录的Makefile的代码是一样的):
include ../scripts/Makefile
all: $(Objs)
clean:
rm -rf $(Objs)
执行make
后目录如下:
运行可执行文件之后,得到正确的结果。
在这里,上述多文件标准工程目录的Makefile编写的三类Makefile可以作为一个模板,只需要在编写时修改部分内容即可。详情请关注下一篇文章《多文件标准工程目录的Makefile通用模板详解》。
更多推荐
所有评论(0)