Makefile的使用和编写

一:了解Makefile

无论是C、C++、还是pas,首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File,这个动作叫做编译(compile)。然后再把大量的Object File合成执行文件,这个动作叫作链接(link)

  • 在一个较大项目里,通常都有很多源代码需要编译和链接.完全手工用gcc命令进行编译工作量太大.
  • 在一项目里, 代码通常都引用关系.因此需要指定谁先编译,谁后编译.甚至是更复杂的功能操作
  • Makefile 就为解决上述一系统问题而创造的.可以把Makefile 理解成是一种由make 程序进行解释的一种特殊脚本.
  • 它跟Shell 脚本有一定相似性.如变量定义和使用,条件判断,又有自己一定的独特性.如规则的定义.
  • makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率
  • IDE环境里通常由图形界面来完成Makefile的修改.如果VC++.但通常也支持命令行的Make,如VC++的nmake,Linux 下主要是命令行界面make,通常需要开发者手工编写Makefile
  • Linux 几乎所有项目都是通过Makefile 方式编译的,如MySQL,Apache和操作系统本身,因此Linux 下开发必须掌握Makefile的编写和使用

二:Makefile的规则

目标: 依赖
	命令
  • 目标是该规则的结果
  • 依赖是生成目标所需要的依赖文件
  • 命令绝大多数情况下就是一条或者多条编译指令
  • 命令可以是任何shell命令,但要求每行命令 第一个字符必须是tab字符. 否则Make 运行会报错.这个是要特别注意的.
  • 如果 命令太长,可以用\来换行
  • Makefile 用#打头的行来表示注释
  • 综合来说:一条规则实际上就是按照命令所指定的方式,通过所有的指定的依赖文件生成最终的目标
  • 目标必须顶格写,目标和依赖文件之间使用":",多个依赖文件之间使用空格分隔,命令必须以TAB键开始

Gnu make 解释Makefile 的命令行工具
一但完成Makefile,在命令行输入make,它会自动在当前目录下查找Makefile 或makefile 进行解释

三、用例说明

比如工程student_manager中包含stu.h,stu.c,myhead.h,main.c这样几个文件,
比如将stu.c,stu.h生成stu.o就可以组成一个规则

stu.o: stu.h, stu.c
	gcc -c stu.c -o stu.o

一般在一个Makefile文件中,第一个目标为最终目标,也就是该工程编译以后的最终输出

student_manager: stu.o  main.o
	gcc stu.o main.o -o student_manager
stu.o: stu.c  stu.h
	gcc -c stu.c -o stu.o
main.o: main.c
	gcc -c main.c -o main.o

make工具在执行Makefile文件的时候,会根据目标文件和依赖文件之间的时间戳来确定目标是否需要重新生成–也就是说make工具可以根据文件之间的时间关系来确定Makefile文件中哪些指令需要执行
在student_manager工程目录下编写如下Makefile文件:

student_manager:stu.o main.o
	gcc stu.o main.o -o student_manager
stu.o:stu.c stu.h
	gcc -c stu.c -o stu.o
main.o:main.c
	gcc -c main.c -o main.o

在shell提示符下输入:

[root@localhost student_manager]# make
gcc -c stu.c -o stu.o
gcc -c main.c -o main.o
gcc stu.o main.o -o student_manager

执行完成以后,在该目录下就可以看到生成的目标文件:stu.o, main.o和student_manager

[root@localhost student_manager]# ls
head1.h  main.c  Makefile   stu.c            stu.h      stu.o
main     main.o    student_manager  
[root@localhost student_manager]# ./student_manager 
101, Jack,   88.50

如果在工程中修改了main.c,再次执行make的时候,就只会编译main.o

[root@localhost student_manager]# make
gcc -c main.c -o main.o
gcc stu.o main.o -o student_manager
  • make自动执行Makefile文件,在GNU下,Makefile文件可以是三种文件名:Makefile,gnumakefile,makefile;但通常情况下就以Makefile为文件名;make阻碍执行的时候会自动的在当前目录查找Makefile文件;如果Makefile文件不在当前目录,在使用make命令的时候,必须使用-C选项指定Makefile所在的目录
    make -C /home/student
  • 如果Makefile文件的名字不是Makefile,那么在make的时候需要通过-f选项指定make要执行的脚本文件的名字,比如当前工程中的make配置文件为maketest,使用make编译的时候,需要:
    make -f maketest

对于Makefile文件中的每一个或者多个目标可以单独执行

[root@localhost student_manager]# make stu.o
gcc -c stu.c -o stu.o
[root@localhost student_manager]# ls
head1.h  main.c   Makefile   stu.c            stu.h      stu.o
main     main.c~  Makefile~  student_manager  stu.h.bak

在Makefile中除了可以有一些编译指令以外,还可以包含linux shell命令
比如修改Makefile文件为如下:

student_manager:stu.o main.o
	gcc stu.o main.o -o student_manager
stu.o:stu.c stu.h
	gcc -c stu.c -o stu.o
main.o:main.c
	gcc -c main.c -o main.o
clean:
	rm -f *.o student_manager
[root@localhost student_manager]# make
gcc -c main.c -o main.o
gcc stu.o main.o -o student_manager
[root@localhost student_manager]# make clean
rm -f *.o student_manager

在编译完成以后可以使用make clean来删除所有编译产生的文件
在Makefile文件中,向clean这样的目标是没有依赖,只有命令,这样的目标叫做伪目标,一般情况下伪目标是用来进行管理(安装,清除等)

Makefile中变量的使用:
修改Makefile文件

VAR = gcc -c
student_manager:stu.o main.o
	gcc stu.o main.o -o student_manager
stu.o:stu.c stu.h
	$(VAR) stu.c -o stu.o
main.o:main.c
	$(VAR) main.c -o main.o
clean:
	rm -f *.o student_manager
all:student_manager
root@localhost student_manager]# make
gcc -c stu.c -o stu.o
gcc -c main.c -o main.o
gcc stu.o main.o -o student_manager

make中预先定义了一系列的变量:位置变量和编译选项变量
位置变量:
$ * : 不包括扩展名的目标文件名称 – $ *一定是用在包含扩展名的目标中表示目标的名字(不包括扩展名),对于那些本身就不包括扩展名的目标不能使用$*来表示
$+: 所有的依赖文件,以空格分隔
$<: 第一个依赖文件
$?: 所有的依赖文件
$@: 目标的完整名称
$^: 所有的依赖文件,不包括重复的文件

在Makefile文件中可以直接使用这些预定义位置变量:

VAR=gcc -c
student_manager:stu.o main.o
	gcc $+ -o $@
stu.o:stu.c stu.h
	$(VAR) $< -o $*.o
main.o:main.c
	$(VAR) $^ -o $@
clean:
	rm -f *.o student_manager
all:student_manager

Makefile文件也可以如下:

CC=gcc
VAR=$(CC) -c
CFLAGS=-W -o
student_manager:stu.o main.o
	$(CC) $+ $(CFLAGS) $@ 
stu.o:stu.c stu.h
	$(VAR) $< -o $*.o
main.o:main.c
	$(VAR) $^ -o $@
clean:
	rm -f *.o student_manager
all:student_manager
[root@localhost student_manager]# make clean
rm -f *.o student_manager
[root@localhost student_manager]# make
gcc -c stu.c -o stu.o
gcc -c main.c -o main.o
gcc stu.o main.o -W -o student_manager 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

javascript_good

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值