數碼相冊——電子書編寫通用的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工具鏈
目錄
一、前言
對於之前的電子書,需要設計一個比較通用的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