数码相册——电子书编写通用的Makefile
- 硬件平台:韦东山嵌入式Linxu开发板(S3C2440.v3)
- 软件平台:运行于VMware Workstation 12 Player下UbuntuLTS16.04_x64 系统
- 参考资料:《嵌入式Linux应用开发手册》、《嵌入式Linux应用开发手册第2版》、《gcc中文手册》
- 开发环境:Linux 3.4.2内核、arm-linux-gcc 4.3.2工具链
- 源码仓库:https://gitee.com/d_1254436976/Embedded-Linux-Phase-3
目录
一、前言
对于之前的电子书,需要设计一个比较通用的Makefile
- 目的:当我们修改或在某个目录下添加文件时,修改Makefile时可以方便操作;Makefile可以只预处理编译汇编修改的文件与使用这个文件的文件,之后才进行整体的链接。
二、设计思路
1、Makefile的分布
分为如下3部分:
- 顶层目录的Makefile:定义obj-y来指定根目录下要编进程序去的文件、子目录外,主要是定义工具链、编译参数、链接参数。
- 顶层目录的Makefile.build:把某个目录及它的所有子目录中、需要编进程序去的文件都编译出来,打包为
built-in.o
。 - 各级子目录的Makefile:把当前目录下的
.c
文件编进程序里。
2、Makefile的使用与修改
2.1 顶层目录
- 把顶层
Makefile
,Makefile.build
放入程序的顶层目录 - 修改顶层
Makefile
2.1 修改工具链
2.2 修改编译选项、链接选项
2.3 修改obj-y
决定顶层目录下哪些文件、哪些子目录被编进程序
2.4 修改TARGET
,这是用来指定编译出来的程序的名字
2.2 各子目录
在各个子目录下都新建一个Makefile
,形式为:
其中subdir1/
:代表当前目录下的子目录
obj-y += file1.o
obj-y += file2.o
obj-y += subdir1/
obj-y += subdir2/
三、编写
1、顶层目录
Makefile
文件:
# 顶层目录Makefile
#
# 目的:
# 1、每个子目录都会建立一个Makefile,包含当前目录下的.c文件与.h文件
# 2、顶层目录下
# 交叉编译工具链
CROSS_COMPILE = arm-linux-
# 定义一些变量 $(CROSS_COMPILE):取出该变量的值 $(CROSS_COMPILE)gcc-->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
# := 简单扩展型变量的值是一次扫描永远使用
# CFLAGS 方便您利用隐含规则指定编译C语言源程序的旗标
# -Wall 帮助列出所有警告信息
# -02 多优化一些.除了涉及空间和速度交换的优化选项,执行几乎所有的优化工作
# -g 可以认为它是缺省推荐的选项
CFLAGS := -Wall -O2 -g
# 把当前目录下的include目录下指定为系统目录
# += 为已经定以过的变量的值追加更多的文本
# -I 指定搜寻包含makefile文件的路径
# $(shell pwd) 执行shell命令的pwd命令,获取执行命令的结果
CFLAGS += -I $(shell pwd)/include
# LDFLAGS 用于调用linker(‘ld’)的编译器的额外标志
# -l 连接库的搜寻目录 -lm调用math库 -lfreetype调用freetype库
LDFLAGS := -lm -lfreetype
# 取出变量的值
export CFLAGS LDFLAGS
TOPDIR := $(shell pwd)
export TOPDIR
# TARGET 目标变量
# := 简单扩展型变量的值是一次扫描永远使用
TARGET := show_file
obj-y += main.o
obj-y += display/
obj-y += draw/
obj-y += encoding/
obj-y += fonts/
# 规则 arm-linux-gcc -lm -lfreetype -o show_file built-in.o
all :
make -C ./ -f $(TOPDIR)/Makefile.build
$(CC) $(LDFLAGS) -o $(TARGET) built-in.o
# 规则 执行make -C 进入当前目录下 使用Makefile.built 进行make
built-in.o:
make -C ./ -f Makefile.build
# clean 删除所有make正常创建的文件
# 规则 找到所有make创建出来的.o文件进行删除
# 删除show_file
clean :
rm -f $(shell find -name "*.o")
rm -f $(TARGET)
# clean 比目标‘clean’ 删除更多的文件,例如,
# 配置文件或为编译正常创建的准备文件,甚至makefile文件自身不能创建的文件
# 规则 找到所有.o文件进行删除
# 找到所有.d文件进行删除
# 删除show_file
distclean:
rm -f $(shell find -name "*.o")
rm -f $(shell find -name "*.d")
rm -f $(TARGET)
Makefile.build
文件:
PHONY := __build
__build:
obj-y :=
subdir-y :=
# 包含当前目录下的Makefile,里面含有目标文件
include Makefile
# 例子 obj-y := a.o b.o c/ d/ 则subdir-y为c/ d/
# obj-y := a.o b.o c/ d/
# $(filter %/, $(obj-y)) : c/ d/
#
# filter 把不符合的指定格式的文件移走
#
# $(patsubst pattern,replacement,text)
# 在‘text’中 ----> $(filter %/, $(obj-y))
# 用‘replacement’ ----> %
# 代替匹配‘pattern’----> %/字
# __subdir-y : c d
#
# subdir-y : c d
__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y += $(__subdir-y)
# 例子 c/built-in.o d/built-in.o
# 对于cur_ojbs变量的每一个(foreach)成员,修改成这样的$(f)/built-in.o格式
subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)
# $(filter-out pattern...,text)
# 在‘text’中----> $(obj-y)
# 选择不匹配‘pattern’的字 -> %/
# cur_ojbs : a.o b.o
cur_ojbs := $(filter-out %/, $(obj-y))
# 对于cur_ojbs变量的每一个(foreach)成员,修改成这样的.$(f).d格式
dep_files := $(foreach f,$(cur_ojbs),.$(f).d)
# 筛选取出当前目录下已经存在的值为dep_files的文件
dep_files := $(wildcard $(dep_files))
# 如果dep_files变量不是空的话,则把生成的.$(f).d格式的文件包含进来
ifneq ($(dep_files),)
include $(dep_files)
endif
PHONY += $(subdir-y)
__build : $(subdir-y) built-in.o
# 对于每个子目录,都执行以下规则
# 规则 执行 make -C c d -f $(TOPDIR)/Makefile.build
$(subdir-y):
make -C $@ -f $(TOPDIR)/Makefile.build
# 规则(打包) 执行 arm-linux-ld -r -o built-in.o 所有得到的子目录/built-in.o
built-in.o : $(cur_ojbs) $(subdir_objs)
$(LD) -r -o $@ $^
# = 用来才赋值
dep_files = .$@.d
# 规则 执行 arm-linux-gcc -Wall -O2 -g -I -Wp,-MD,$(shell pwd)/include -c %.o %.c
%.o : %.c
$(CC) $(CFLAGS) -Wp,-MD,$(dep_files) -c -o $@ $<
.PHONY : $(PHONY)
2、各子目录
2.1 display
目录Makefile
# 子目录Makefile
obj-y += disp_manager.o
obj-y += fb.o
2.2 draw
目录Makefile
# 子目录Makefile
obj-y += draw.o
2.3 encoding
目录Makefile
# 子目录Makefile
obj-y += ascii.o
obj-y += encoding_manager.o
obj-y += utf-8.o
obj-y += utf-16be.o
obj-y += utf-16le.o
2.4 fonts
目录Makefile
# 子目录Makefile
obj-y += ascii.o
obj-y += fonts_manager.o
obj-y += freetype.o
obj-y += gbk.o