Makefile的编写

Makefile的编写

                                               ——揭开makefile的神秘面纱

作者:zccst

 

06年秋天开始接触Linux以来,竟然在今年3月份时对makeMakefile是什么,感觉还很玄,以为是高深的东西,可见在学校读书这几年里,我学到了多少知识。而且更重要的是养成了很多坏习惯,比如浮躁,重理论轻实践,而在学习理论时又不求甚解,看书时要么一下子看完了,很多不明白的问题一带而过,后来用到时还是不懂。要么看的很慢,看完一个内容,要很久才看得进去下一个内容。

 

言归正传,make工作原理:make是由开发大型程序与提高编写程序效率而提出。一个上百个源代码文件组成的项目,只对其中一个或少数几个做了修改,如果按照之前的方法直接使用gcc编译器,则不得不把整个项目里的所有文件都重新编译一遍,可想这将是多么大的工作量,而实际上那些没有改动的源代码文件根本不需要重新编译。make工具管理器能在执行makefile文件时,自动发现makefile文件里更新的文件,然后只编译他们,这样大大减少了工作量。

 

Makefile文件通常包括如下内容:

1,  需要由make工具创建的目标体(target),通常是目标文件或可执行文件。

2,  要创建的目标所依赖的文件。

3,  创建每个目标体时需要运行的命令。

 

Makefile的书写规则:

目标文件:依赖文件

(Tab)产生目标文件的命令

 

为方便讲清楚,举一个具体的例子:要求把3道题的题目存在二维数组中,调用自定义函数生成一个随机数,随机数传回主函数。主函数用随机数做下标,输出相应数组中的题目。

分析:此程序有主函数main和自定义函数fun_shuiji两个”.c”文件,把函数声明、用到的库函数写成一个独立的头文件”shuiji.h”,因此本题目程序分成3个文件。

 

步骤一:编写源码。

为简便起见,三道题目均简写为:“first.”,“second!”,“third?”。完整代码分别如下:

(1)vi 2-6-main.c  添加如下内容

#include "shuiji.h"

int main()

{

  int n;

  static char str[3][80] = {"firist.","second!","third?"};

  n = fun_shuiji();

  printf("the number you choice is:%d/n", n+1);

  printf("the %d number:", n+1);

  puts(str[n]);

}

 

(2)vi 2-6-shuiji.c  添加如下内容

#include "shuiji.h"

int fun_shuiji()

{

  srand(time(NULL));

  int a;

  a = (rand() % 3);

  return a;

}

 

(3)vi shuiji.h  添加如下内容

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

int fun_shuiji();

 

 

步骤二:编写Makefile文件

Makefile有两种写法,一种是直接写,另一种则引用变量。根据需要选择其一即可。

1,  直接写。对照前面Makefile书写规则。

2-6:2-6-main.o 2-6-fun_shuiji.o

        gcc 2-6-main.o 2-6-fun_shuiji.o -o 2-6

2-6-main.o:2-6-main.c shuiji.h

        gcc 2-6-main.c -c

2-6-shuiji.0:2-6-shuiji.c

        gcc 2-6-shuiji.c –c

注:Makefile文件里的gcc前面不是空格,而是按tab键生成。下同。

 

2,  引用变量。本文采用第2种方法,所以重点讲解。

CC = gcc

objects = 2-6-main.o 2-6-fun_shuiji.o

2-6:$(objects)

        $(CC) $(objects) -o 2-6

2-6-main.o:2-6-main.c shuiji.h

        gcc 2-6-main.c -c

2-6-shuiji.0:2-6-shuiji.c

        gcc 2-6-shuiji.c -c

注:实际中的makefile文件里常常有4中变量,分别为预定义变量,用户自定义变量,自动变量和环境变量。例子中的“CC”是预定义变量,“object”是用户自定义变量。

常见预定义变量有:

Makefile中常见预定义变量

   

AR

库文件维护程序的名称,默认值为ar

AS

汇编程序的名称,默认值为as

CC

C编译器的名称,默认值为cc

CPP

C预编译器的名称,默认值为$(CC) –E

CXX

C++编译器的名称,默认值为g++

FC

FORTRAN编译器的名称,默认值为f77

RM

文件删除程序的名称,默认值为rm –f

ARFLAGS

库文件维护程序的选项,无默认值

ASFLAGS

汇编程序的选项,无默认值

CFLAGS

C编译器的选项,无默认值

CPPFLAGS

C预编译的选项,无默认值

CXXFLAGS

C++编译器的选项,无默认值

FFLAGS

FORTRAN编译器的选项,无默认值

 

常见自动变量有:

Makefile中常见自动变量

命令格式

   

$*

不包含扩展名的目标文件名称

$+

所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件

$<

第一个依赖文件的名称

$?

所有时间戳比目标文件晚的依赖文件,并以空格分开

命令格式

   

$@

目标文件的完整名称

$^

所有不重复的依赖文件,以空格分开

$%

如果目标是归档成员,则该变量表示目标的归档成员名称

 

 

 

步骤三:用make编译程序

make –f makefile2.6

输出结果:

[root@localhost c]# make -f makefile2.6

gcc 2-6-main.c -c

gcc    -c -o 2-6-fun_shuiji.o 2-6-fun_shuiji.c

gcc 2-6-main.o 2-6-fun_shuiji.o -o 2-6

注:make默认为在当前目录下找寻makefile文件,如果指定则后面加:“-f(ile) 文件名”。

 

 

步骤四:再次编译

为了体现Makefile的精华部分,再次编译,此时你会发现只编译了改动部分的源程序,而没改动的部分根本没有重新编译。

输出结果:

[root@localhost c]# make -f makefile2.6

gcc 2-6-main.c -c

gcc 2-6-main.o 2-6-fun_shuiji.o -o 2-6

 

步骤五:运行

./2-6

输出结果:

[root@localhost c]# ./2-6

the number you choice is:3

the 3 number:third?

 

在默认情况下,make(GNU)工作时执行的步骤:

1,  make在当前目录下查找名字为“makefile文件”或“makefile文件夹”(注:一些make对大小写不敏感,但大多数支持小写makefile)。如果找到,make继续找文件中的第一个目标文件(target)。如例子中的2-6这个文件,如果不存在或2-6所依赖的后面的.o文件修改时间比2-6文件更新,则会执行后面所定义的命令来生成2-6文件。

2,  如果2-6所依赖的.o文件也存在,make会在当前文件中找.o文件的依赖性,如果找到,则会生成.o文件。

3,  当然,.c文件和.h文件如果找到,make会生成.o文件,然后用.o文件生成make的最终结果,也就是可执行文件2-6.

这就是整个make的依赖性,make会一层层地去找文件的依赖关系(有点像数据结构中的深度优先遍历,一直找到最深的节点,再一步步往回走),直到最终编译出第一个目标文件。如果在找寻过程中出现错误,则make退出并报错。如果在make找到了依赖关系,但冒号后面的文件不存在,make也不工作。

 

 

通过本文及一个例子,你已经初步了解make的强大功能,及makefile怎样帮助make完成它的使命,但要承认的是编写makefile不是一件轻松的事情,尤其对一个较大的项目而言,而且还存在版本的通用性问题。那么有没有一种更轻松的方式?答案是肯定的:“有,比如autotools系列工具”。使用autotools,你只需要输入简单的目标文件、依赖文件、文件目录等,就可以轻松地生成makefile了。autotools的具体使用请读者查阅相关资料。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值