[韦东山]嵌入式Linux应用开发 lecture2 Makefile

  • Makefile格式:

    目标文件:依赖文件

    [Tab]           命令

  • Makefile规则:

1. 当"目标文件"不存在或某个依赖文件比目标文件"新"时则执行"命令";

2. 使用make命令时[make 目标],若指定目标不存在,默认为第一个目标;

新建一个名为Makefile的文件,写入:

----------------------------------------------

        test:a.o b.o

                gcc -o test a.o b.o

        a.o:a.c

                gcc -c -o a.o a.c

        b.o:b.c

                gcc -c -o b.o b.c

-----------------------------------------------

[make]执行(会自动执行当前Makefile文件中的第一个目标——规则二)

第一次执行:gcc -c -o a.o a.c   gcc -c -o b.o b.c   gcc -o test a.o b.o   

修改a.o后第二次执行:gcc -c -o a.o a.c   gcc -o test a.o b.o

(会根据文件更新的时间戳来决定哪些文件需要重新编译——规则一)

通配符:$@表示目标   $<表示第一个依赖   $^表示所有依赖

等价Makefile文件:

----------------------------------------------

        test:a.o b.o

                gcc -o test $^

        %.o:%.c

                gcc -c -o $@ $<

-----------------------------------------------

新建一个名为Makefile的文件,写入:

----------------------------------------------

        test:a.o b.o

                gcc -o test $^

        %.o:%.c

                gcc -c -o $@ $<

        clean:

                rm *.o test

-----------------------------------------------

[make clean]执行         

若当前目录下有clean的同名文件,该操作会因缺少依赖文件而报错

解决办法:

使用关键字PHONY将clean作为假想目标

----------------------------------------------

        test:a.o b.o

                gcc -o test $^

        %.o:%.c

                gcc -c -o $@ $<

        clean:

                rm *.o test

        .PHONY:clean

-----------------------------------------------

Makefile中的变量:

        即时变量(简单变量):变量的值在定义时即刻确定;

        延时变量:变量的值在使用时才确定;

运算符确定的变量类型:

:=   即时变量

=    延时变量

?=  延时变量  (首次定义时有效,若变量已被定义则忽略此句)

+=  即时变量还是延时变量取决于先前定义

Makefile的文件[make]执行输出

        A:=$(D)

        B=$(D)

        C=abc

        C?=123

        D=smile

        all:

               @echo A=$(A)

               @echo B=$(B)

               @echo C=$(C)

        D+=aaa

        A=

        B=smileaaa

        C=abc

tip:

        echo 在shell中显示该条命令和其输出结果

        @echo 不在shell中显示该条命令,只显示其输出结果

Makefile中的函数:

1.$(foreach var,list,text)   对list中的每个var都执行text操作

Makefile的文件[make]执行输出

        A=a b c

        B=$(foreach f,$(A),$(f).o)

        all:

                @echo B=$(B)

        B=a.o b.o c.o

2.$(patsubst pattern,replacement,text)   将text中取出的pattern格式替换成replacement格式

(text中不符合pattern格式的不会被替换)

Makefile的文件[make]执行输出

        A=a.c b.c c.c 123

        B=$(patsubst %.c,%.o,$(A))

        all:

                @echo B=$(B)

        B=a.o b.o c.o 123

3.$(wildcard pattern)    取出该目录下所有pattern格式的文件名

Makefile的文件[make]执行输出

        files=$(wildcard *.o)

        all:

                @echo files=$(files)

        files=a.o b.o c.o

4.$(filter pattern...,text)   在text中取出符合pattern格式的值

   $(filter-out pattern...,text)   在text中取出不符合pattern格式的值

Makefile的文件[make]执行输出

        A=a b c d/

        B=$(filter %/,$(A))

        C=$(filter-out %/,$(A))

        all:

                @echo B=$(B)

                @echo C=$(C)

        B=d/

        C=a b c

Makefile中的依赖:

gcc -M c.c 打印c.c的依赖文件
gcc -M -MF c.d c.c 把依赖文件写入c.d
gcc -c -o c.o c.c -MD -MF c.d编译c.o成c.c,同时把依赖文件写入c.d

新建一个名为Makefile的文件,写入:

----------------------------------------------

        test:a.o b.o c.o

                gcc -o test $^

        %.o:%.c

                gcc -c -o $@ $<

        clean:

                rm *.o test

        .PHONY:clean

-----------------------------------------------

[make]执行         

若修改c.c的头文件c.h再执行,该操作会因未更新依赖文件而失效

解决办法:

更新依赖时生成.d文件,根据.d文件是否存在进行判断然后更新

----------------------------------------------

        objs = a.o b.o c.o

        dep_files := $(patsubst %,.%.d, $(objs))     //将objs中的文件xx变成.xx.d

        dep_files := $(wildcard$(dep_files))            //dep_files :=.a.o.d .b.o.d .c.o.d

        test:$(objs)

                gcc -o test $^

        ifneq ($(dep_files),)                                     //若dep_files为空则include

        include $(dep_files)

        endif

        %.o:%.c

                gcc -c -o $@ $< -MD -MF .$@.d

        clean:

                rm *.o test

        distclean:

                rm $(dep_files)

        .PHONY:clean

-----------------------------------------------

本程序的Makefile分为3类: 1. 顶层目录的Makefile 2. 顶层目录的Makefile.build 3. 各级子目录的Makefile 一、各级子目录的Makefile: 它最简单,形式如下: EXTRA_CFLAGS := CFLAGS_file.o := obj-y += file.o obj-y += subdir/ "obj-y += file.o" 表示把当前目录下的file.c编进程序里, "obj-y += subdir/" 表示要进入subdir这个子目录下去寻找文件来编进程序里,是哪些文件由subdir目录下的Makefile决定。 "EXTRA_CFLAGS", 它给当前目录下的所有文件(不含其下的子目录)设置额外的编译选项, 可以不设置 "CFLAGS_xxx.o", 它给当前目录下的xxx.c设置它自己的编译选项, 可以不设置 注意: 1. "subdir/"中的斜杠"/"不可省略 2. 顶层Makefile中的CFLAGS在编译任意一个.c文件时都会使用 3. CFLAGS EXTRA_CFLAGS CFLAGS_xxx.o 三者组成xxx.c的编译选项 二、顶层目录的Makefile: 它除了定义obj-y来指定根目录下要编进程序去的文件、子目录外, 主要是定义工具链前缀CROSS_COMPILE, 定义编译参数CFLAGS, 定义链接参数LDFLAGS, 这些参数就是文件中用export导出的各变量。 三、顶层目录的Makefile.build: 这是最复杂的部分,它的功能就是把某个目录及它的所有子目录中、需要编进程序去的文件都编译出来,打包为built-in.o 详细的讲解请看视频。 四、怎么使用这套Makefile: 1.把顶层Makefile, Makefile.build放入程序的顶层目录 在各自子目录创建一个空白的Makefile 2.确定编译哪些源文件 修改顶层目录和各自子目录Makefile的obj-y : obj-y += xxx.o obj-y += yyy/ 这表示要编译当前目录下的xxx.c, 要编译当前目录下的yyy子目录 3. 确定编译选项、链接选项 修改顶层目录Makefile的CFLAGS,这是编译所有.c文件时都要用的编译选项; 修改顶层目录Makefile的LDFLAGS,这是链接最后的应用程序时的链接选项; 修改各自子目录下的Makefile: "EXTRA_CFLAGS", 它给当前目录下的所有文件(不含其下的子目录)设置额外的编译选项, 可以不设置 "CFLAGS_xxx.o", 它给当前目录下的xxx.c设置它自己的编译选项, 可以不设置 4. 使用哪个编译器? 修改顶层目录Makefile的CROSS_COMPILE, 用来指定工具链的前缀(比如arm-linux-) 5. 确定应用程序的名字: 修改顶层目录Makefile的TARGET, 这是用来指定编译出来的程序的名字 6. 执行"make"来编译,执行"make clean"来清除,执行"make distclean"来彻底清除
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值