5.Makefile简单使用实例 您所在的位置:网站首页 linux使用make命令编译脚本 5.Makefile简单使用实例

5.Makefile简单使用实例

#5.Makefile简单使用实例| 来源: 网络整理| 查看: 265

目录

1.什么是Makefile?

2.Makefile引入

3.Makefile的基本规则

4.Makefile实例

5.Makefile简单语法

6.Makefile 函数

     6.1.foreach 函数

     6.2.过滤函数 -filter

     6.3.获取匹配模式文件名函数— wildcard

     6.4.模式替换函数— patsubst 

7.Makefile 综合例子

 

   1.什么是Makefile?

makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。

makefile的好处就是:

—“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具

 

2.Makefile引入

例子1:

新建两个c文件,分别是A.c和B.c内容如下:

上传到Linux系统使用gcc进行编译

使用命令:gcc -o out A.c B.c

解释:

虽然在在编译A.c和B.c文件,然后把它们连接在一起,只使用了一个命令,他们需要经过四个过程才能生成可执行文件out

这四个过程分别为:

①预处理:预处理就是将要包含(include)的文件插入原文件中、将宏定义展开、根据条件编译命令选择要使用的代码,最后将这些东西输出到一个“.i”文件中等待进一步处理。

② 编译:编译就是把 C/C++代码(比如上述的“.i”文件)“翻译”成汇编代码

③汇编:汇编就是将第二步输出的汇编代码翻译成符合一定格式的机器代码,在 Linux 系统上一般表现为 ELF 目标文件(OBJ 文件)

④链接:连接就是将上步生成的 OBJ 文件和系统库的 OBJ 文件、库文件连接起来,最终生成了可以在特定平台运行的可执行文件。

注意:一般把前面三个步骤统称为编译。

其生成步骤的文件大致如下:

对于命令gcc -o out A.c B.c ,加入我们修改了A.c文件的内容,那么需要重新汇编生成x.o文件,虽然没有修改B.c文件,此时gcc还是会默认再生成一次y.o文件,然后把x.o和y.o文件进行链接,这并不是我们想要的(我们想要的是如果y.o没有修改就不需要去重新生成一次了,直接使用旧的y.o文件),在文件很少的情况下几乎看不出有什么缺点,但是当文件很多的时候编译的时候就会花上很长的时间。这也是gcc的一个缺点。那如何改善呢?

解决方案:

1).对于每个c文件都分开编译(通常说的编译由三部分组成:预处理、编译、汇编,使用gcc命令:gcc -c -o x.o A.c和gcc -c -o  y.o B.c),最后链接起来(使用命令:gcc -o out x.o y.o)

2).每次编译之前判断.c文件的内容是否比.o文件新,如果.c比.o新,或者.o文件不存在,那么就要重新进行编译和汇编的过程,        生成相应的.o文件。

那么上述的例子可以用下面的三条语句进行编译:

gcc -c -o x.o A.c gcc -c -o y.o B.c gcc -o out x.o y.o

解释:如果在第一次编译的时候,还没有生产x.o和y.o文件,所以会生成这两个文件,然后把这两个文件链接在一起生成out可执行程序,此时如果只修改了A.c的话,那我们只需要去重新生成 x.o文件即可,然后再和旧的y.o重新连接在一起生成新的out就可以,第二条语句没有必要执行。

那如何判断文件是否被修改呢?

通过判断文件的修改时间

1.当A.c的修改时间比x.o的时间新的话或者x.o不存在,那么就需要执行gcc -c -o  x.o A.c 语句,生成 x.o文件,B.c同理

2.当 x.o 或 y.o 比out文件新的话或out不存在,那么就需要执行gcc -o out x.o y.o 把x.o和y.o链接重新生成out文件

那我们需要在程序中去判断时间吗?

不需要的,因为这个步骤Makefile已经帮我们做好了,我们只需要遵循Makefile的语法即可

3.Makefile的基本规则 target:prerequisites command ... ... ===================== 目标 : 依赖文件 [tab键] 命令 ... ...

target:是目标文件,可以是object file,也可以是执行文件,还可以是一个标签label。

prerequisites:就是要生成那个target所需要的文件或者目标。

command:也就是make需要执行的命令-。

  这是一个文件以来关系,也就是说target是由一个或多个目标文件依赖于prerequisites中的文件,其生成规则定义在command中,而且只要prerequisites中有一个以上的文件比target文件更新的话,command所定义的命令就会被执行,这是makefile的最基本规则,也是makefile中最核心的内容。

当 “依赖文件(prerequisites)”   比  “目标文件(target)”   新     =========>执行命令(command)

以上面的例子来分析写Makefile

分析:

现在我们的目标是生成   out  的目标文件,他们的依赖是 x.o 和 y.o  (把它们连接在一起生成out),可以这样写:

out : x.o y.o [tab键]  gcc -o out x.o y.o

那么x.o 呢? 它是由A.c生成的,所以x.o的依赖是 A.c.可以这样写:

x.o : A.c [tab键] gcc -c -o x.o A.c

那么y.o 呢? 它是由B.c生成的,所以y.o的依赖是 B.c.可以这样写

y.o : B.c [tab键] gcc -c -o y.o B.c

在Linux系统终端中,直接输入make命令就可以实现自动编译了,输入make命令,执行结果大致如下描述:

1.首先生成out目标文件,这个文件依赖于x.o和y.o,发现没有x.o那么向下寻找

2.找到 x.o 这个文件依赖于 A.c ,而x.o这个文件还不存在,系统认为A.c比x.o新,执行gcc -c -o x.o A.c 命令,生成x.o,

   生成b.o的过程同理。

3.生成了a.o和b.o了之后,test的依赖文件都有了,而且判定比out新,所以使用命令:gcc -o out x.o y.o,生成out的目标文件。

4.假设现在修改了A.c,再次执行make命令,我们的目的是想要生成第一个目标out,发现x.o和y.o其中有一个比out新,那么就需要     重新执行下面的命令,可知是a.o比out新,那么找到生成a.o目标文件的依赖,然后执行gcc -c -o x.o A.c,重新生成x.o文件。       而B.c文件并没有比y.o文件新,所以不执行命令,最终把新生成的x.o和旧的y.o重新连接生成out目标文件。

4.Makefile实例

例子1:

在上面例子的基础增加一个Makefile:

新建一个名为 Makefile 的文件:

上传到Linux系统进行编译:

现在修改一下A.c文件,然后再尝试make一下:

重新上传A.c到Linux系统,编译

如果再次执行一次make是什么反应呢?

提示 out 这个目标文件已经是最新的了,检测到没有修改,所以不需要重新生成,这样就可大大提高我们工作的效率,智能检测我们的文件是否被修改,哪个文件需要重新生成。

5.Makefile简单语法

5.1.通配符

重新看一看上边所写的Makefile文件:

当文件很少的时候,可以这样写,但是当你需要编译的文件很大呢,一万个?你需要写一万个这样的语句吗吗?

这个时候我们就可以使用通配符。

通配符符号:%

①: $@   表示目标文件

②: $ 和 #include " " 的区别:

#include " "   表示在当前路径搜索头文件

#include < >  引用的是编译器的类库路径里面的头文件,一般是指定的路径

现在新建一个include文件夹,然后把所有的头文件放进去编译试一下:

  

创建include目录:

Makefile文件内容如下:

val = A.o B.o C.o CFLAG = -Werror #给val中所有的文件加上前缀和后缀,结果如下: # dep_files = .A.o.d .B.o.d dep_files :=$(patsubst %,.%.d,$(val)) #检测 dep_files 是否真实存在,只提取存在的文件 dep_files :=$(wildcard $(dep_files)) #生成目标文件out也是默认生成的文件 out :$(val) gcc -o out $^ #如果dep_files不为空,说明有依赖文件,包含进来 ifneq ($(dep_files),) include $(dep_files) endif %.o:%.c gcc $(CFLAG) -c -o $@ $< -MD -MF [email protected] clean: rm *.o out #删除依赖 disclean: rm $(dep_files) .PHONY:clean

现在Makefile中先不加 -I 参数指定头文件搜索路径,试着上传编译一下:

现在使用参数  I 指定gcc的头文件默认搜索路径:

上传Makefile再次编译一下:

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有