第4课.编写通用的Makefile
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)
第4课.编写通用的Makefile的更多相关文章
- 编写通用的Makefile
一个应用程序的形成是少不了一下几个步骤的. 1. 预处理 #检查语法错误.包含头文件.展开#if.#define等宏定义 2. 编译 #把.c文件转换为汇编文件.s 3. 汇编 #把.s汇编转换为机器 ...
- 编写一个通用的Makefile文件
1.1在这之前,我们需要了解程序的编译过程 a.预处理:检查语法错误,展开宏,包含头文件等 b.编译:*.c-->*.S c.汇编:*.S-->*.o d.链接:.o +库文件=*.exe ...
- 缓冲区溢出分析第05课:编写通用的ShellCode
前言 我们这次的实验所要研究的是如何编写通用的ShellCode.可能大家会有疑惑,我们上次所编写的ShellCode已经能够很好地完成任务,哪里不通用了呢?其实这就是因为我们上次所编写的ShellC ...
- Linux C编程学习之开发工具3---多文件项目管理、Makefile、一个通用的Makefile
GNU Make简介 大型项目的开发过程中,往往会划分出若干个功能模块,这样可以保证软件的易维护性. 作为项目的组成部分,各个模块不可避免的存在各种联系,如果其中某个模块发生改动,那么其他的模块需要相 ...
- 通用的 makefile 小工具分享 - Easymake 使用说明
Easymake 使用说明 介绍 Easymake 是一个在linux系统中 C/C++ 开发的通用 makefile.在一个简单的 C/C++ 程序中使用 easymake,你甚至可以不写一行 ma ...
- 如何快速编写大项目的Makefile文件
在构建C++的后台服务时,经常需要自己来编写makefile文件,而如果没有合适的方法或模板时,编写makefile文件是一件很费时费力的事情.因此,为了帮助程序员高效准确的编写makefile文件, ...
- <五>JDBC_利用反射及JDBC元数据编写通用的查询方法
此类针对javaBean类写了一个通用的查询方法,List<javaBean> 通用查询更新中...:通过学习,深刻体会到学会反射就等于掌握了java基础的半壁江山! 一.使用JDBC驱动 ...
- JDBC学习笔记(5)——利用反射及JDBC元数据编写通用的查询方法
JDBC元数据 1)DatabaseMetaData /** * 了解即可:DatabaseMetaData是描述数据库的元数据对象 * 可以由Connection得到 */ 具体的应用代码: @Te ...
- 一步一步写一个简单通用的makefile(三)
上一篇一步一步写一个简单通用的makefile(二) 里面的makefile 实现对通用的代码进行编译,这一章我将会对上一次的makefile 进行进一步的优化. 优化后的makefile: #Hel ...
随机推荐
- C#中发ref和out
ref--Reference 引用 out--Output 输出 相同点: 代入参数时,前面必须加上ref out 关键字 都能在方法内对外部的变量的值进行更改 不同点: ref代入的参数必须 ...
- 前端开发:mock.js的简单应用(生成随机数据,拦截 Ajax 请求)
摘要 在前端开发过程中,后端接口还没有完全开发完成时,前端开发人员就需要学会自己模拟后端接口数据,更快更好的完成开发任务.模拟后端接口数据的js库有很多,今天就简单就简单的分享下mock.js在前端开 ...
- 解决vim选中文字不能复制的问题
转载自本人独立博客:https://liushiming.cn/2020/01/18/vim-copy-issue-in-iterm2/ 概述 最近发现在iterm2中打开vim,用鼠标选中文字,并用 ...
- Dart语言学习(三)Dart数值型
一.类型 数值型有 num,int, double num a = ; a = 12.5; print(a); print(a.runtimeType); ; // b = 20.5; print( ...
- Foreach报错
List<String> a = new ArrayList<String>(); 2 a.add("1"); 3 a.add("2") ...
- AtCoDeer and Election Report
问题 G: AtCoDeer and Election Report 时间限制: 1 Sec 内存限制: 128 MB[提交] [状态] 题目描述 AtCoDeer the deer is seei ...
- 13,viewport
set viewport:~是一种函数,功能是为图形输出设置当前视口. 怎样处理移动端1px被渲染成2px的问题(略)
- 模板元编程(Template metaprogramming)
https://en.wikipedia.org/wiki/Template_metaprogramming 没看懂...只知道了模板元编程的代码是在编译期运行的... 敲了2个例子: 1. #inc ...
- ASP.NET Core搭建多层网站架构【8.1-使用ViewModel注解验证】
2020/01/29, ASP.NET Core 3.1, VS2019 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构[8.1-使用ViewModel注解验证] 使用V ...
- 「CF911F」Tree Destruction
传送门 Luogu 解题思路 显然的贪心策略,因为每次都要尽量使得删点后的收益最大. 我们可以求出树的直径(因为树上的任意一个节点与其距离最远的点一定是直径的端点). 然后我们对于所有不是直径上的点, ...