uClinux中Makefile檔案整體分析(ZT)

來源:互聯網
上載者:User
uClinux中Makefile檔案整體分析 
作者:佚名 來源:不詳 發布時間:2006-9-21 8:15:08 發布人:zangyl 
減小字型 增大字型 

(轉載) 
1、概述 
uClinux/目錄下的這個Makefile 是個總領式的檔案,通過它又層層包含調用各個目錄、子目錄下面對應Makefile,就這樣層層調用下去,從而完成整個軟體系統的編譯。 

2、具體分析 

下面根據uClinux/Makefile 檔案的內容(內容有刪節)大致介紹一下整個編譯的調用關係。 

---------------------------------------------------------------------------------------- 
include common.mk 
---------------------------------------------------------------------------------------- 

首先包含common.mk,它裡面定義了一些通用的全域變數,例如:common.mk 檔案中有如下內容: 
.EXPORT_ALL_VARIABLES: 
(相當於C 中的extern 關鍵字,表示下面的宏變數可以為其它檔案所使用) 
ROOTDIR = $(shell pwd) 
TOOLS = $(ROOTDIR)/tools 

---------------------------------------------------------------------------------------- 
.EXPORT_ALL_VARIABLES 
---------------------------------------------------------------------------------------- 

輸出下面所有全域變數 

---------------------------------------------------------------------------------------- 
IMAGEFILE = image.bin 
IMAGEZFILE = imagez.bin 
ELFFILE = image.elf 
SRECFILE = image.srec 
IMAGE = $(ROOTDIR)/images/$(IMAGEFILE) 
IMAGEZ = $(ROOTDIR)/images/$(IMAGEZFILE) 
ELFIMAGE = $(ROOTDIR)/images/$(ELFFILE) 
SRECIMAGE = $(ROOTDIR)/images/$(SRECFILE) 
ROMFS = $(ROOTDIR)/romfs 
ROMFSIMG = $(ROOTDIR)/images/romfs.img 
TOPDIR = $(ROOTDIR)/linux 
HOSTCC = unset GCC_EXEC_PREFIX ; gcc -I$(TOPDIR)/include 

DIRS = linux lib user 
---------------------------------------------------------------------------------------- 

all 告訴編譯器執行make 都要分完成哪些工作步驟,這是最重要的地方! 
看一個Makefile 首先要從它的all 看起,就相當於C 語言的main()函數的作用。 
然後再從all 層層分析下去。 

---------------------------------------------------------------------------------------- 
all: config-test subdirs build-romfs $(IMAGE) 
---------------------------------------------------------------------------------------- 

這裡共四步工作,即: 

---------------------------------------------------------------------------------------- 
* config-test 
* subdirs 
* build-romfs 
* $(IMAGE),即上面的IMAGE 變數,Makefile 中用$(變數名)來使用變數,這中用法對許多熟悉各種指令碼語言的使用者並不陌生。 

下面在Makefile 分別找到各步工作對應的部分: 

---------------------------------------------------------------------------------------- 
(1) config-test: 
@if [ ! -f .config -o ! -f linux/.config -o ! -f 
vendors/.config ]; then / 
---------------------------------------------------------------------------------------- 

若找不到.config 檔案或者找不到linux/.config 或者找不到 
vendors/.config 檔案,就提示需要make config 或者make xconfig 

---------------------------------------------------------------------------------------- 
echo "ERROR: you need to do a 'make config' first" ; / 
exit 1 ; / 
fi 
@if [ ! -d romfs ]; then / 
【必須有romfs 這個目錄】 
echo "ERROR: you need to run 'make romfs' as root first" ;/ 
exit 1 ; / 
fi 

(2)subdirs 

subdirs: 
@if [ ! -f linux/.depend ] ; then / 
【若沒找到linux/.depend 檔案,就提示要make dep】 
echo "ERROR: you need to do a 'make dep' first" ; 
exit 1 ; / 
fi 
for dir in $(DIRS) ; do make -C $$dir || exit 1 ; done 
---------------------------------------------------------------------------------------- 

【上面這一句雖短,但確是最主要的工作所在,注意到前面定義了: 
DIRS = linux lib user 
因此這一句: 
make -C $$dir 
就完成了對核心(linux 目錄)的編譯、對libC 庫(lib)的編譯、對所有應用程式(user 下所有指定要編譯的目錄)的編譯。 
make -C $$dir 就調用對應那個目錄下的Makefile , 即分別是linux/Makefile,lib/Makefile 和user/Makefile,這Makefile 又層層包含調用下面的各個目錄的Makefile,從而完成整個編譯過程。】 

其中編譯user 下各個應用程式時,每個應用程式目錄下的Makefile 中都要執行如下一句: 
$(CONVERT) 
這個宏是在uClinux/user/arch/coldfire/目錄下的build.mk 檔案中指定的,這個檔案的作用就相當於uClinux/common.mk,它為應用程式的編譯定義了許多公用的宏,例如所採用的編譯器(CC)等。LINUX 核心都是用m68k-coff-gcc 編譯的,但應用程式可以採用不同的gcc 編譯器。 

這個檔案的部分內容如下: 
.EXPORT_ALL_VARIABLES: 
CC = $(TOOLS)/m68k-elf-gcc 
CXX = $(TOOLS)/m68k-elf-g++ 
AR = $(TOOLS)/m68k-elf-ar 
LD = $(TOOLS)/m68k-elf-ld 
OBJCOPY = $(TOOLS)/m68k-elf-objcopy 
RANLIB = $(TOOLS)/m68k-elf-ranlib 
ELF2FLT = $(TOOLS)/elf2flt 
GCC_EXEC_PREFIX = $(TOOLS)/m68k-elf- 
LIBC = $(ROOTDIR)/lib/libc/libc.a 
LIBM = $(ROOTDIR)/lib/libm/libmf.a 
LIBNET = $(ROOTDIR)/lib/libnet/libnet.a 
LIBDES = $(ROOTDIR)/lib/libdes/libdes.a 
LIBPCAP = $(ROOTDIR)/lib/libpcap/libpcap.a 
LIBSSL = $(ROOTDIR)/lib/libssl/libssl.a 
LIBCRYPTO = $(ROOTDIR)/lib/libssl/libcrypto.a 
LIBGCC = $(TOOLS)/gcc-lib/libgcc.a 
ARCH = -m5200 -Wa,-m5200 -DCONFIG_COLDFIRE 
DEFS = -Dlinux -D__linux__ -Dunix -DEMBED 
INCS = $(INCGCC) $(INCLIBC) $(INCLIBM) $(INCVEND) 
CCFLAGS = -O2 -msoft-float 【編譯參數】 
CFLAGS = $(DEBUG_CFLAGS) $(ARCH) $(DEFS) $(CCFLAGS) $(INCS) - 
fno-builtin 【編譯參數】 
LDFLAGS = --sort-common -r $(STARTUP) 【連結參數】 
最後定義了CONVERT 宏: 
CONVERT = mv $$@.elf .$$@.elf; / 
$(LD) -T $(LDSCRIPT) -Ur -o $$@.elf .$$@.elf; / 
$(LD) -T $(LDSCRIPT) -o $$@.gdb .$$@.elf; / 
rm -f .$$@.elf; / 
$(ELF2FLT) $$(FLTFLAGS) -o $$@ $$@.elf 
它採用elf2flt 工具將編譯產生的ELF 格式可執行檔轉換為uClinux 所支援的FLAT 檔案格式。 
【注】 
uClinux 唯一支援的可執行檔格式就是FLAT 格式。其它都不支援。 
所以所有要在uClinux 上跑的應用都必須轉換為FLAT 格式。PC REDHATLINUX 不支援這種格式的可執行檔,所以這些可執行檔都無法在PC 上 
執行。 

(3)build-romfs 

build-romfs: images 
make -f romfs.mk 
build-romfs 後面跟了images,表明它依賴於images 先執行的結果: 
images: 
[ -d images ] || mkdir images 
images 只是檢查是否有images 目錄,若沒有就建立該目錄。 
下面的make -f romfs.mk 就調用執行romfs.mk。 
下面是romfs.mk 檔案中的內容: 
這也是個Makefile,因此如前所述,要從它的all 入口看起: 
all: copy-files 
$(TOOLS)/genromfs -v -V "ROMdisk" -f $(ROMFSIMG) -d 
$(ROMFSDIR) 
all 要先依賴copy-files 部分的完成: 
copy-files: 
cp $(RAMFSy) romfs/etc/ramfs.img 
[ ! "$(BINy)" ] || cp $(BINy) romfs/bin/. 
rm romfs/etc/services 
rm romfs/etc/inetd.conf 
make -C user build-romfs 
-find romfs -name CVS | xargs rm -rf 
這裡主要的工作就是一句: 
[ ! "$(BINy)" ] || cp $(BINy) romfs/bin/. 
完成user/下各個參與的應用程式目錄下的編譯產生的可執行檔的收集,將它們複製到romfs/bin/目錄下。 
下一步就是romfs 目錄的打包,產生romfs.img 二進IMAGE 檔案,它就是我們常說的ROMFS 檔案系統的映像檔案: 
$(TOOLS)/genromfs -v -V "ROMdisk" -f $(ROMFSIMG) -d $(ROMFSDIR) 
至此就完成了romfs.mk 中的工作,下面返uClinux/Makefile 的內容繼續: 

(4) $(IMAGE) 

IMAGE 變數為: 
IMAGE = $(ROOTDIR)/images/image.bin 
這就是最後被複製到/tftpboot/目錄下的image.bin 檔案,也就是最後可以燒寫或下載的二進位IMAGE 檔案。 
$(IMAGE): images images/linux.bin 
cat images/linux.bin $(ROMFSIMG) > $(IMAGE) 
$(TOOLS)/cksum -b -o 2 $(IMAGE) >> $(IMAGE) 
cp $(IMAGE) /tftpboot 
首先依賴於images 和image/linux.bin。 
images/linux.bin: images linux/linux 
$(TOOLS)/m68k-elf-objcopy -O binary 
--set-section-flags=.romvec=CONTENTS,ALLOC,LOAD,READONLY,CODE 
linux/linux images/linux.bin 
image/linux.bin 又依賴linux/linux,它是前面make –C linux 時根據linux 目錄下的Makefile 規則編譯產生的。然後用m68k-elf-objcopy 將linux/linux 檔案轉換為二進位檔案images/linux.bin。 
然後用: 
cat images/linux.bin images/romfs.img > images/image.bin 
最後,將images/image.bin 複製到/tftpboot 目錄下,從而完成整個編譯過程。 
【注意】 
  Makefile 中使用了許多.PHONY:節,它並沒有什麼作用,只是告知編譯器,它的:號後面並不是一個檔案。例如: 
.PHONY: romfs (沒有這句也可以,但是若目錄下有一個檔案名稱字叫做romfs,則會報錯make: ` ‘romfs’ is up to date。加了PHONY 就是通知編譯器,不要把romfs 看作一個目標檔案。) 
romfs: 
…… 
Makefile 還提供了許多獨立的目標,可以直接用make 命令指定目標單獨編譯。例如: 
dep: 
@if [ ! -f linux/.config ] ; then / 
echo "ERROR: you need to do a 'make config' 
first" ; / 
exit 1 ; / 
fi 
make -C linux dep 
就可以直接make dep 執行。 
romfs: 
make -f romfs_cvs.mk 
[ "$(CONFIG_VENDOR)" ] || echo "******/nrun 'make config' 
first/n******" 
make -C vendors/$(CONFIG_VENDOR)/$(CONFIG_PRODUCT)/. romfs 
就可以直接make romfs 執行。 
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.