makefile学习(一)

        今天是学习makefile的第二天了。

        在昨天的makefile中仅仅只包含两个文件和一个命令,过于简单。不过简单归简单,对于初学者这是必经之地。今天呢学习一些较为复杂的makefile以及命令。首先对下面的稍微复杂的makefile进行一下解析:

        sunq:kang.o yul.o

                Gcc kang.o bar.o -o myprog

        kang.o : kang.c kang.h head.h

                Gcc –Wall –O -g –c kang.c -o kang.o

        yul.o : bar.c head.h

                Gcc - Wall –O -g –c yul.c -o yul.o

    在这个makefile中包含三个目标(target):sunq   kang.o和yul.o。第一个目标文件sunq依赖于后面的两个目标。如果你使用命令“make qunq”,则make管理器就会自动找到sunq的目标体进行执行,同时,make也会检查相关文件的时间戳。首先在检查kang.o  yul.o和sunq的时间戳前,make会向下查找以kang.o  yul.o为目标文件的时间戳。kang.o文件依赖于kang.c kang.h head.h三个文件,如果这些文件有一个的时间戳比kang.o的时间戳晚,make就会重新根据命令“Gcc –Wall –O -g –c kang.c -o kang.o”编译kang.o目标,从而使目标文件kang.o时间戳更新。当更新完两个依赖文件后,make会检查最初的sunq   kang.o和yul.o三个目标文件,只要kang.o和yul.o有一个文件的时间戳比sunq目标文件新,make就会执行命令“Gcc kang.o bar.o -o myprog”。这样make就完成了自动检查时间戳的工作,开始执行编译工作,这是make的基本流程。

    

接下来,为了进一步简化编辑和维护Makefilemake允许在Makefile中创建和使用变量。变量是在Makefile中定义的名字,用来代替一个文本字符串,该文本字符串称为该变量的值。在具体要求下,这些值可以代替目标体、依赖文件、命令以及makefile文件中其它部分。在Makefile中的变量定义有两种方式:一种是递归展开方式,另一种是简单方式。

    递归展开方式定义的变量是在引用在该变量时进行替换的,即如果该变量包含了对其他变量的应用,则在引用该变量时一次性将内嵌的变量全部展开,虽然这种类型的变量能够很好地完成用户的指令,但是它也有严重的缺点,如不能在变量后追加内容(因为语句:CFLAGS = $(CFLAGS) -O在变量扩展过程中可能导致无穷循环)。

    为了避免上述问题,简单扩展型变量的值在定义处展开,并且只展开一次,因此它不包含任何对其它变量的引用,从而消除变量的嵌套引用。

    递归展开方式的定义格式为:VAR=var

    简单扩展方式的定义格式为:VAR=var

        Make中的变量使用均使用格式为:$(VAR)

注意:

    变量名是不包括“:”、“#”、“=”结尾空格的任何字符串。同时,变量名中包含字母、数字以及下划线以外的情况应尽量避免,因为它们可能在将来被赋予特别的含义。

    变量名是大小写敏感的,例如变量名“foo”、“FOO”、和“Foo”代表不同的变量。

    推荐在makefile内部使用小写字母作为变量名,预留大写字母作为控制隐含规则参数或用户重载命令选项参数的变量名

   

    下面给出了上例中用变量替换修改后的Makefile,这里用OBJS代替kang.oyul.o,用CC代替Gcc,用CFLAGS代替“-Wall -O –g”。这样在以后修改时,就可以只修改变量定义,而不需要修改下面的定义实体,从而大大简化了Makefile维护的工作量。

经变量替换后的Makefile如下所示: 

    OBJS = kang.o yul.o

    CC = Gcc

    CFLAGS = -Wall -O -g

    sunq : $(OBJS)

           $(CC) $(OBJS) -o sunq

    kang.o : kang.c kang.h

           $(CC) $(CFLAGS) -c kang.c -o kang.o

    yul.o : yul.c yul.h

           $(CC) $(CFLAGS) -c yul.c -o yul.o

可以看到,此处变量是以递归展开方式定义的。

    Makefile中的变量分为用户自定义变量、预定义变量、自动变量及环境变量。如上例中的OBJS就是用户自定义变量,自定义变量的值由用户自行设定,而预定义变量和自动变量为通常在Makefile都会出现的变量,其中部分有默认值,也就是常见的设定值,当然用户可以对其进行修改。

    预定义变量包含了常见编译器、汇编器的名称及其编译选项。下表3.14列出了Makefile中常见预定义变量及其部分默认值。

3.14                                                  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编译器的选项,无默认值

可以看出,上例中的CCCFLAGS是预定义变量,其中由于CC没有采用默认值,因此,需要把“CC=Gcc”明确列出来。

    由于常见的Gcc编译语句中通常包含了目标文件和依赖文件,而这些文件在Makefile文件中目标体的一行已经有所体现,因此,为了进一步简化Makefile的编写,就引入了自动变量。自动变量通常可以代表编译语句中出现目标文件和依赖文件等,并且具有本地含义(即下一语句中出现的相同变量代表的是下一语句的目标文件和依赖文件)。下表3.15列出了Makefile中常见自动变量。

3.15                                                    Makefile中常见自动变量

命令格式

含   义

$*

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

$+

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

$<

第一个依赖文件的名称

$?

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

$@

目标文件的完整名称

$^

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

$%

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

自动变量的书写比较难记,但是在熟练了之后会非常的方便,我呢在这一块试着改写了上面的那个makefile如下:

    OBJS = kang.o yul.o

    CC = Gcc

    CFLAGS = -Wall -O -g

    sunq : $(OBJS)

           $(CC) @^ -o $@

    kang.o : kang.c kang.h

           $(CC) $(CFLAGS) -c $< -o $@

    yul.o : yul.c yul.h

           $(CC) $(CFLAGS) -c $< -o $@

    对于makefile的自动变量我还一时半会记不住,以后一定加强记忆。

    另外Makefile中还可以使用环境变量。使用环境变量的方法相对比较简单,make在启动时会自动读取系统当前已经定义了的环境变量,并且会创建与之具有相同名称和数值的变量。但是,如果用户在Makefile中定义了相同名称的变量,那么用户自定义变量将会覆盖同名的环境变量。

 

注:本内容基本来自《嵌入式Linux应用程序开发详解》,但是都是看了之后为了加强记忆才这样敲进去的,以后有了自己的见解就会出点实际的东西。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值