-
Makefile
学习笔记:
为什么要学习
makefile
:
工作经验让我认识到
会不会写
makefile
从一个
< br>侧面说明了一个人是否有完成大型工程的
能力,
make
file
关系到整个工程的编译规则,一个工程的文件不计其数,其按类型,功能,<
/p>
模块分别放在不同的目录下,
makefile
< br>定义了一些规则来指定,哪些文件需要先编译,哪些
文件需要重新编译,甚至进行
更复杂的功能操作,因为
makefile
就像一个
shell
脚本一样,
其中也可以执行操作系统命
令。
而
make
只是一个命令工具,是一个解释
makefile
中的指令的命令工具,一般来说
IDE<
/p>
即
集成开发环境都有这个命令。
Makefile
的环境:
我是在
linux
下进行的实验
linux
系列下,
我用的是
ubuntu
,
当然你可以用
redhat
红旗后
其他,我想都没有什么问题的。在做实验的时候我会做一些
p>
linux
写的
c/c++
例子来演示,
以加深理解。
关于程序的编译和链接:
一般来说,
c
或者是
c++
,首先把源文件
(
*.c
或
*.cpp
)编译成为中间代码文件,这个
中间代码文件在
windows
下是<
/p>
*.obj
文件在
linux
或
unix
是
*.o
文件即
object file
目标文
件这个动作就叫做编译,即把源文件编译成目标文件的过程就叫做编译(
p>
compile
)
。这
以后,再把大量的
*.obj
或
*.o
目标文件合成一个可以执行的文件,这个工程就叫做链
接
link
。编译时,主要是检查程序
的语法是否正确,函数,变量是否都有声明。至于链
接呢,主要是链接函数,和全局变量
。
一.
M
akefile
的规则
Target
:
prerequisites
Command
。
。
。
。
。
。
。
。
。
p>
Target
就是一个目标文件,可以使
o
bj
或是可执行文件还可以是一个标签
label
,关于标
签
label
会在
下面的文目标中讲解。所以我们现在只关注
obj
和可执行文
件即可,其实
大部分还都是
obj
文件
,或许可执行文件就只有一个。
Prerequisites
是先决条件的意识,
其实在这里只是依赖的意思,
prerequisites
在这里是生
成
target
的所需要的文件或目标。
Comm
and
就是
make
需要执行的命
令的,
任意的
shell
的命令,如果
prerequisites
中有一个以上的文件比
target
文件要新的话吗,
command<
/p>
所
定义的命令的就会被执行。这就是
ma
kefile
的规则,也是
makefile
< br>中最核心的东西。
一个例子:
这个
makefile
有六个源文件<
/p>
和六个头文件
分别是:
func1.c
func2.c
func3.c
func4.c
func5.c
main.c
head1.h
head2.h
head3.h
head4.h
head5.h
head.h
上
面的
c
源文件
分别会用到其下的
头文件
各个文件的内容分别是:
func1.c
文件
#include
#include
void f1()
{
struct student1 stu;
= 10101;
strcpy(,
= 'm';
printf(
}
func2.c
文件
#include
#include
void f2()
{
struct student2 stu;
= 10102;
strcpy(,
= 'm';
printf(
}
func3.c
文件
#include
#include
void f3()
{
struct student3 stu;
= 10103;
strcpy(,
= 'm';
printf(
}
func4.c
文件
#include
#include
void f4()
{
struct student4 stu;
= 10104;
strcpy(,
= 'm';
printf(
}
func5.c
文件
#include
#include
void f5()
{
struct student5 stu;
= 10105;
strcpy(,
= 'm';
printf(
}
main.c
文件
#include
extern void f1();
extern void f2();
extern
void f3();
extern void f4();
extern void f5();
int main()
{
f1();
f2();
f3();
f4();
f5();
printf(
return 0;
}
以上是这个工程的的所有源文件及其代码
head1.h
头文件
struct student1
{
int id;
char name[20];
char sex;
};
head2.h
头文件
struct student2
{
int id;
char name[20];
char sex;
};
head3.h
头文件
struct student3
{
int id;
char name[20];
char sex;
};
head1.h
头文件
struct student3
{
int id;
char name[20];
char sex;
};
head4.h
头文件
struct student4
{
int id;
char name[20];
char sex;
};
head51.h
头文件
struct student5
{
int id;
char name[20];
char sex;
};
head.h
头文件
#include
#include
#include
以上是头文件的内容
以上文件都准备好后
就要开始写
makefile
文件了
Makefile
文件的可以这么写:
exefile
: main.o func1.o
func2.o func3.o func4.o func5.o
gcc -o
exefile
main.o func1.o
func2.o func3.o func4.o func5.o
main.o
:main.c
head.h
gcc -c
main.c
func1.o
:func1.c head.h
head1.h
gcc -c
func1.c
func2.o
:func2.c head.h
head2.h
gcc -c
func2.c
func3.o
:func3.c head.h
head3.h
gcc -c
func3.c
func4.o
:func4.c head.h
head4.h
gcc -c
func4.c
func5.o
:func5.c head.h
head5.h
gcc -c
func5.c
clean:
rm -f *.o
exefile
在这个
makefile
中
蓝色的就是目标文件
或
可执行文件
目标文件时那些
*.o
文件,
可执
行文件就是
exefile
文件,它是最终可以执行的文件。依赖文件就是那些
*.c
和
*.h
文件。
每一个
*.o
文件都有一组依赖文件,
*.o
文件
就是靠这些依赖文件生成。而生成的这些
*.o
文件又都是
p>
exefile
可执行文件的依赖文件,
他们生成
exefile
可执行文件。
依赖关系
其实
就是
说明了
目标文件是由哪些文件生成的
,换言之,就是目标文件是由哪些文件更新的。
定义好依赖关系下一行就是
make
执行的命令,
这个命令定义了操作系统如何生成这些目标
文件的
。命令行开始一定要以
tab
键开头。其执行过程就是
make
会比较
target
文件
和
prerequisites
文件
的修改日期,如果
prerequisites
文件的日期比
target
文件的日期要新,或
p>
者
target
不存在的话,
make
就会执行后续定义的命令。
讲解:
exefile: main.o func1.o func2.o func3.o
func4.o func5.o
gcc -o exefile main.o func1.o func2.o
func3.o func4.o func5.o
exefile
依赖
main.o
func1.o func2.o func3.o func4.o func5.o
这些
*.o
文件,
也即是说
exefile
就
是开这些文件生成的。一开始
这些
*.o
文件是不存在的,那么
ma
ke
就会往下执行语句,而
暂时先不执行
gcc -o main main.o func1.o func2.o func3.o
func4.o func5.o
这句命令。
main.o:main.c head.h
gcc -c main.c
main.o
依赖
main.c
head.h
这两个文件
执行其命令生成
main.o
目标文件,
指着往下执行。
。
。
func1.o:func1.c head.h head1.h
gcc -c func1.c
同
main.o
的执行。
。
。
func2.o:func2.c head.h head2.h
gcc -c func2.c
同
main.o
的执行。
。
。
func3.o:func3.c head.h head3.h
gcc -c func3.c
同
main.o
的执行。
。
。
func4.o:func4.c head.h
head4.h
gcc -c func4.c
同
main.o
的执行。
。
。
func5.o:func5.c head.h
head5.h
gcc -c func5.c
同
main.o
的执行。
。
。
当这些
*.o
文件都别生成了后
make
就会执行
第一个依赖和第一个
依赖之后的命令
exefile:
main.o func1.o func2.o func3.o func4.o func5.o
gcc -o exefile
main.o func1.o func2.o func3.o func4.o func5.o
最终生成
exefile
之可行文件。
clean:
rm -f *.o
exefile
clean
后面没有依赖文件,
make
是不会执行
其后的命令的
,只能
make clean
显视
的执
行
。这句就是伪命令,就是做一些清理,把
生成的
目标文件
*.o
文件
和
exefile
删掉。
Make
后执行结果:
[yanggentao@wkp mfile]$$ make clean
rm -f *.o exefile
[yanggentao@wkp mfile]$$ make
gcc -c main.c
gcc -c func1.c
gcc -c func2.c
gcc -c
func3.c
gcc -c func4.c
gcc
-c func5.c
gcc -o main main.o func1.o
func2.o func3.o func4.o func5.o
[yanggentao@wkp mfile]$$
Make clean
后执行结果:
[yanggentao@wkp mfile]$$ make clean
rm -f *.o exefile
[yanggentao@wkp mfile]$$
根据
makefile
的依赖规则我
们还可以这样写,至于为什么这样写,我们先且不说。
exefile: main.o func1.o func2.o func3.o
func4.o func5.o
gcc -o exefile main.o func1.o func2.o
func3.o func4.o func5.o
main.o:main.c
gcc -c main.c
func1.o:func1.c
gcc -c func1.c
func2.o:func2.c
gcc -c func2.c
func3.o:func3.c
gcc -c func3.c
func4.o:func4.c
gcc -c func4.c
func5.o:func5.c
gcc -c func5.c
clean:
rm -f *.o
exefile
这样写是把头文件都给去掉了,这样也对的
,
makefile
的隐式规则会自动找这些在文件里包
含的头文件的。
其实
Makefile
中的命令就像是
shell
里一样
可以使用变量
二.
Makefile
中使用变量
Makefile
中的变量就像是
c
语言的中宏一样
怎样定义变量呢?
我们在
makefile
最上面定义
一个变量
OBJS =
main.o func1.o func2.o func3.o func4.o
func5.o
引用变量
$$(OBJS)
这就等价于
main.o func1.o func2.o
func3.o func4.o func5.o
就像宏一样的
会被替换掉。所以我们的
makefile
可以这样写了:
OBJS = main.o func1.o func2.o func3.o
func4.o func5.o
exefile:
$$(OBJS)
gcc -o exefile
$$(OBJS)
main.o:main.c
gcc -c main.c
func1.o:func1.c
gcc -c func1.c
func2.o:func2.c
gcc -c func2.c
func3.o:func3.c
gcc -c func3.c
func4.o:func4.c
gcc -c func4.c
func5.o:func5.c
gcc -c func5.c
clean:
rm -f $$(OBJS) exefile
这样写很方便,如果你想在这个工
程里面加一个文件的话就不会很麻烦。
三.
让
ma
ke
自动推导
Gnu
的
make
功能很强大他可以自动推
导文件及文件的依赖关系后面的命令所以我们没有
必要去为
*.
O
文件都写出其命令。
只要
make
看到一个
*.o
文件,
它就会自动的吧
*.c
文件
加到
依赖关系中,
如果
make
找到
一个
func2.o
那么
func2.c
就会使
func2.o
的依赖文件。并且
gcc
–
c
func2.c
也会被推导出
来。所以我们的
makefile
p>
就会简单多了:
我们还可以这样写:
OBJS = main.o func1.o func2.o func3.o
func4.o func5.o
exefile:
$$(OBJS)
gcc -o exefile
$$(OBJS)
clean:
rm -f $$(OBJS) exefile
有时候我们会这样写:
OBJS =
main.o func1.o func2.o func3.o func4.o func5.o
exefile: $$(OBJS)
gcc -o exefile $$(OBJS)
.PHONY:clean
clean:
rm -f $$(OBJS) exefile
.PHONY
:
clean
是声明一下
clean
是一个伪命令。
到这里
makef
ile
的基本东西已经讲完了。还有很多细节,下面来看一下。
四.
Makefile
的
5
个内容
1.
显示规则
2.
隐晦规则
3.
变量的定义
4.
文件指示
5.
注释
1.
显示规则:就是显示的在命令行中写出目标文件的依赖关系
2.
隐晦规则:就是利用
make
的
自动推导的功能
3.
变量的定义:就变量的宏替换
4.
文件指示:其中包括三部分的内
容,一个是在一个
makefile
中引用另一个
makefile
,就
像
c
语言中的
include
一样;另一
个是根据某些情况指定
makefile
中的有效部分,就像<
/p>
c
语言的预编译
#ifdef
一样;还有一个就是定义一个多行的命令。
-
-
-
-
-
-
-
-
-
上一篇:ACFUN正式会员答题题库(全答案)
下一篇:ACFUN正式会员答题题库改良版