GNU中的make和makefile

本文介绍了Make工具的基本使用方法,包括make命令的常见选项、makefile文件的编写规则、宏定义及条件编译等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    说来惭愧呀,调试驱动代码的时候每天都在使用make命令,却不知道make命令究竟是用来做什么的,上周有个师弟问我make和makefile究竟是用来做什么的,我只是根据自己的理解给他说了一下,回头想想自己说的也不对呀,所以才回过头来好好再学习一下make命令和makefile.这部分的内容主要参考了《Linux程序设计第四版》和http://hi.baidu.com/tvbljlqlfkaejwr/item/75de403d5ea908f2e6bb7a3c这位高手的博客

     人们都是喜欢怀旧的,人也是有感情的,所以人们对于自己的第一次经历的东西,往往刻骨铭心。,比如说我们的初恋,还有我们的.......,比如说我的第一首能用吉他结结巴巴弹出来的歌。比如说我用gcc编译的第一个程序,gcc -o test test.c

     但是对于我这种没有亲自编写过大项目的“大水”来说,一个gcc -o基本上就可以把所有的程序给编译出来,但是对于一些大的项目来说,通常有很多的源文件,不可能一条条的来用gcc来编译,这时候我们就可以使用make工具来自动完成编译任务。

其实这里面还有一个好处就是:当我们只修改了其中的某几个头文件的源文件的时候,很多其他的源文件都没有修改,这时候我们并不需要把所有的源文件再重新编译一下,因为其中很多的源文件跟我们修改过的源文件并没有依赖关系,这时候使用这种自动编译可以大大的简化开发工作,避免不必要的重新编译。(如果这里看不明白的话,可以参考Linux程序设计第四版317页上面的例子,简单明了)

 

Make基础知识:

首先来说一下make吧:

Make有很多的选项(这个是大牛说的),常用的主要有下面3个:

-k:make命令在发现错误的时候仍然继续执行,而不是在检测到一个错误的时候就停下来。

-n:这个就是告诉make输出将要执行的操作不走,而不是真正的去执行,

-f:这个家伙比较厉害,用来告诉make命令哪个文件来作为makefile,不过一般人都这么干,我是一般人,所以也不这么干。

补充其他的如下:

 

命令行选项               含义
-C DIR               在读取 makefile 之前改变到指定的目录 DIR。
-f FILE              以指定的 FILE 文件作为 makefile。
-h                   显示所有的 make 选项。
-i                   忽略所有的命令执行错误。
-I DIR               当包含其他 makefile 文件时,可利用该选项指定搜索目录。
-n                   只打印要执行的命令,但不执行这些命令。
-p                   显示 make 变量数据库和隐含规则。
-s                   在执行命令时不显示命令。
-w                   在处理 makefile 之前和之后,显示工作目录。
-W FILE              假定文件 FILE 已经被修改。

 

通常情况下,我们使用make工具的时候,我们通常通过一个称为makefile的文件来完成并自动维护编译工作。当然这个makefile中的语法是按照某种语法规则来写的。主要说明了如何编译各个源文件并将之链接成为一个可执行的文件。同时定义了各个源文件之间的依赖关系,如果其他的源文件依赖于该文件的话,那么也需要重新编译所有依赖于这个文件的源文件。

这里我们说的make工具是GUN make工具,这个强大的工具(据说很强大哦,我还没有深刻体会到)会在当前的目录下按照下面的顺序来寻寻觅觅makefile

GNUmakefile

Makefile

Makefile

 

当然也可以指定其他名字的文件;来作为makefile,一般人都不这么做,我是一般人,所以也不会这么做。

 

Makefile中的基础知识和一些基本概念:

 

Makefile中一般包含下面的内容:

*需要make来创建的项目,通常是目标文件和可执行文件,通常使用“target”来表示要创建的项目

*要创建的项目需要依赖哪些文件

*创建每个项目的时需要运行的命令

 

通常情况下,一个makefile文件中可以有多个目标,利用make target命令可以指定要编译的目标。举个例子来说就是:

 

test: test.o related.o

test1: test1.o related.o

...

我们可以使用make test和make test1来分别编译不同的目标,如果没有指定的话,通常情况下,则是使用的第一个目标。

 

通常情况下,一个makefile通常由一系列的规则组成,而在一条规则中通常由一个目标,条件,和命令组成

下面举个规则的例子来看一下:

 

main: main.o stack.o maze.o

gcc main.o stack.o maze.o -o main

在这个东东中,main是这个规则的目标,main.o stack.o maze.o是这个规则的条件。目标和条件的关系是:欲更新目标,必须先更新它所有的条件,下面这行就是传说中的命令了,需要特别注意的是命令列表中每个命令必须以一个tab来开头,而不能使用几个空格代替,(这是什么破规定呀)

 

通常情况下,makefile中会有一个clean规则,这个通常情况下是用来清理一些东西的,通常是编译过程中产生的二进制文件,而保留源文件。这个东西我们经常在编译驱动的时候用到的。

Clean规则和前面介绍的规则不同,clean目标不依赖于任何条件,并且执行它的命令不会生成clean这个文件。

其实吧clean在makefile中是一个约定俗成的名字,还有其他的名字

all:执行主要的编译工作,这个是一个伪代码,它可以一次用来创建多个文件。

Install:执行编译后的安装工作,把可执行文件配置文件问道分别cp到不同的安装目录

Clean:删除

 

 

Makefile中的注释:

Makefile中的注释一般以#开头,一直延续到这一行的结尾,说道井了我就邪恶的想起了big笑工坊中一期中论名字的重要性了。

在这里再提一下自己想到的makefile中的其他的一些符号以及它们的含义:

$:这个符号表示的是引用变量

-:嗯?一个减号,这是啥玩意,这个是告诉make命令你忽略所有的的错误,做你自己的事情就可以了,我们通常在使用rm和mkdir命令的时候前面会添加-符号

@:这个用来告诉make,你在执行这条命令的视乎不要将命令显示在标准输出上面,不要显示命令本身,只要显示它的结果就可以了。要低调行事。

 

 

 

 

Makefile文件中的变量和宏

 

说到宏,心底油然升起一种亲切感,就像在成都呆了两年之后发现了一家正宗的河南烩面馆一样。这样我想起了上次去都江堰的时候的坑爹经历,那次看见一件小饭馆上面有烩面,我就忍住内心的激动点了一份,我去,等上来之后我就晕了,老板,你以前吃过面没?面条和面片你都分不清呀。亲切归亲切,还是有区别的,这里的宏定义和C中是不一样 。各位看官请看下面定义:

# Define macros for name of compiler
CC = gcc
# Define a macr o for the CC flags
CCFLAGS = -D_DEBUG -g -m486
# A rule for building a object file
test.o: test.c test.h
     $(CC) -c $(CCFLAGS) test.c

在上面的例子中,CC 和 CCFLAGS 就是 make 的变量,关于变量和宏,这个就和我们C语言中的概念不太一样了,在GUN的make中把这部分称为宏,在其他的Unix中就称为变量。实际上两者是同一个东东,在makefile中引用变量的时候通常前面需要添加$符号

 

 

Makefile中的主要预定义变量:(这部分内容是我直接从高手的博客中复制出来的)

 

预定义变量                       含义
$*               不包含扩展名的目标文件名称。
$+               所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件。
$<               第一个依赖文件的名称。
$?               所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚。
$@               目标的完整名称。
$^               所有的依赖文件,以空格分开,不包含重复的依赖文件。
$%               如果目标是归档成员,则该变量表示目标的归档成员名称。例如,如果目标名称
                 为 mytarget.so(image.o),则 $@ 为 mytarget.so,而 $% 为 image.o。
AR               归档维护程序的名称,默认值为 ar。
ARFLAGS          归档维护程序的选项。
AS               汇编程序的名称,默认值为 as。
ASFLAGS          汇编程序的选项。
CC               C 编译器的名称,默认值为 cc。
CCFLAGS          C 编译器的选项。
CPP              C 预编译器的名称,默认值为 $(CC) -E。
CPPFLAGS         C 预编译的选项。
CXX              C++ 编译器的名称,默认值为 g++。
CXXFLAGS         C++ 编译器的选项。
FC               FORTRAN 编译器的名称,默认值为 f77。
FFLAGS           FORTRAN 编译器的选项。

 

如何在Makefile中定义宏进行条件编译-- “-D”

在源代码里面如果这样是定义的: 
#ifdef MACRONAME 
//可选代码   
#endif          
    
那在makefile里面
gcc   -DMACRONAME=MACRODEF   
或者   
gcc   -DMACRONAME       
这样就定义了预处理宏,编译的时候可选代码就会被编译进去了。

举例说明:

-Dmacro=string,等价于在头文件中定义:#define   macro   string。
-DTRUE=true,等价于在头文件中定义:#define   TRUE   true   
-Dmacro,等价于在头文件中定义:#define   macro   1,实际上也达到了定义:#define   macro的目的。
-DLINUX,等价于:#define   LINUX   1(与#define   LINUX作用类似)。   
--define-macro   macro=string与-Dmacro=string作用相同。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值