1.框架

1. 顶层目录的Makefile
2. 顶层目录的Makefile.build
3. 各级子目录的Makefile

2.概述

1.各级子目录的Makefile:
它最简单,形式如下:
obj-y += file.o
obj-y += subdir/ "obj-y += file.o"表示把当前目录下的file.c编进程序里,
"obj-y += subdir/"表示要进入subdir这个子目录下去寻找文件来编进程序里,是哪些文件由subdir目录下的Makefile决定。 注意: "subdir/"中的斜杠"/"不可省略 2.顶层目录的Makefile:
它除了定义obj-y来指定根目录下要编进程序去的文件、子目录外,主要是定义工具链、编译参数、链接参数──就是文件中用export导出的各变量。 3.顶层目录的Makefile.build:
这是最复杂的部分,它的功能就是把某个目录及它的所有子目录中、需要编进程序去的文件都编译出来,打包为built-in.o
详细的讲解请看视频。

3.解析

顶层Makefile

注:=为延时变量;:=为立即变量

CROSS_COMPILE = arm-linux-

编译器前缀这里使用arm-linux-(交叉编译器);不使用arm-linux-则使用gcc编译器

AS		= $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump export AS LD CC CPP AR NM
export STRIP OBJCOPY OBJDUMP

这里两句:导出变量(AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMP)使子目录也能直接使用

CFLAGS := -Wall -O2 -g

指定优化选项:

-Wall:打开所有警告

-O2:优化选项

-g:加上调试信息

CFLAGS += -I $(shell pwd)/include

指定目录当前目录下include目录

-I:指定目录

$():引用

$(shell pwd):引用shell命令中的pwd,

LDFLAGS := -lm -lfreetype

链接数学库和freetype库

export CFLAGS LDFLAGS

TOPDIR := $(shell pwd)
export TOPDIR TARGET := show_file

make时生成show_file文件

obj-y += main.o
obj-y += display/
obj-y += draw/
obj-y += encoding/
obj-y += fonts/

把当前目录中的.o文件编译进来

all :
make -C ./ -f $(TOPDIR)/Makefile.build
$(CC) $(LDFLAGS) -o $(TARGET) built-in.o

-C:进入某个目录

-f:指定文件

用Makefile.build编译出来的build-in.o来make

clean:
rm -f $(shell find -name "*.o")
rm -f $(TARGET)

删除所有.o文件和make时生成的编译文件

distclean:
rm -f $(shell find -name "*.o")
rm -f $(shell find -name "*.d")
rm -f $(TARGET)

顶层中的Makefile.build

PHONY := __build

伪目标(PHONY)依赖于 __build。伪目标也就是总是执行的意思

__build:

obj-y :=

obj-y :=空值

subdir-y :=

子目录也为空

include Makefile

包含当前目录下的Makefile

# obj-y := a.o b.o c/ d/
# $(filter %/, $(obj-y)) : c/ d/
# __subdir-y : c d
# subdir-y : c d
__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y += $(__subdir-y)

取出子目录(看上述的注释)

$(filter %/, $(obj-y)):过滤出%/

patsubst %/,%,$(filter %/, $(obj-y)):把%/ --(替换)--> %

# c/built-in.o d/built-in.o
subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)

对于每个当前目录下的子目录,会生成子目录的c/built-in.o d/built-in.o

# a.o b.o
cur_objs := $(filter-out %/, $(obj-y))

排除当前目录下的子目录,即现在cur_objs 为当前目录下的文件

dep_files := $(foreach f,$(cur_objs),.$(f).d)

依赖文件(dep_files )改写为.$(f).d即(.xxx.d)

dep_files := $(wildcard $(dep_files))

展开依赖文件(dep_files )和上诉一起完成(.xxx.d)

ifneq ($(dep_files),)
include $(dep_files)
endif

如果依赖文件存在,把它包含进来

PHONY += $(subdir-y)

当前目录下的子目录

__build : $(subdir-y) built-in.o

$(subdir-y):
make -C $@ -f $(TOPDIR)/Makefile.build

进入子目录使用Makefile.build进行编译

built-in.o : $(cur_objs) $(subdir_objs)
$(LD) -r -o $@ $^ dep_file = .$@.d %.o : %.c
$(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<

-Wp,-MD:生成相应的依赖

.PHONY : $(PHONY)

子目录中的Makefile文件

obj-y += disp_manager.o
obj-y += fb.o

把上诉.o文件编译进内核

obj-y += test/

把test文件目录编译进内核(注test中的Makefile先执行)

4.使用方法

1.把顶层Makefile, Makefile.build放入程序的顶层目录
2.修改顶层Makefile
2.1 修改工具链
2.2 修改编译选项、链接选项
2.3 修改obj-y决定顶层目录下哪些文件、哪些子目录被编进程序
2.4 修改TARGET,这是用来指定编译出来的程序的名字 3. 在各一个子目录下都建一个Makefile,形式为:
obj-y += file1.o
obj-y += file2.o
obj-y += subdir1/
obj-y += subdir2/ 4. 执行"make"来编译,执行"make clean"来清除,执行"make distclean"来彻底清除

eg:

CROSS_COMPILE = arm-linux-
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump export AS LD CC CPP AR NM
export STRIP OBJCOPY OBJDUMP CFLAGS := -Wall -O2 -g
CFLAGS += -I $(shell pwd)/include LDFLAGS := -lm -lfreetype -lts -lpthread export CFLAGS LDFLAGS TOPDIR := $(shell pwd)
export TOPDIR TARGET := show_file obj-y += main.o
obj-y += display/
obj-y += draw/
obj-y += encoding/
obj-y += fonts/
obj-y += input/ all :
make -C ./ -f $(TOPDIR)/Makefile.build
$(CC) $(LDFLAGS) -o $(TARGET) built-in.o clean:
rm -f $(shell find -name "*.o")
rm -f $(TARGET) distclean:
rm -f $(shell find -name "*.o")
rm -f $(shell find -name "*.d")
rm -f $(TARGET)

最新文章

  1. javascript面向对象(一):封装
  2. 在SSMS里批量删除表、存储过程等各种对象
  3. Android UI之下拉刷新上拉刷新实现
  4. BestCoder15 1002.Instruction(hdu 5083) 解题报告
  5. Mybatis的分页插件PageHelper
  6. VM8下安装Mac OS X 10.7
  7. Oracle11G 数据库 expdp、impdp使用示例
  8. C# 截取字符串某个字符分割的最后一部分
  9. layui的几个简单使用(简单弹窗,加载效果,移除加载效果)
  10. 实战经验丨CTF中文件包含的技巧总结
  11. JavaScript继承的几种实现
  12. java当中的强引用,软引用,弱引用,虚引用
  13. odoo二次开发 tips
  14. Excel中Sumproduct函数的使用方法
  15. mysql帮助命令
  16. SpringBoot 使用Hikaricp连接池
  17. ECMAScript2017之async function
  18. Mac用户抓包软件Charles 4.0 破解 以及 抓取Https链接设置
  19. MFQ
  20. 利用CA私钥和证书创建中间CA

热门文章

  1. knn 数字识别
  2. JS中的字符串可以直接调用字符串对象的属性和方法
  3. ARM架构安装Anaconda3出现错误:cannot execute binary file: Exec format error
  4. Hadoop3.1.1源码Client详解 : 写入准备-RPC调用与流的建立
  5. jsTree的checkbox默认选中和隐藏
  6. 连通数[JSOI2010]-洛谷T4306
  7. ie8无法拉伸背景图
  8. STM32F030 启用内部晶振并配置系统时钟为48M
  9. windowsCMD常用工具
  10. java 生成/解读 二维码