如何交叉編譯 應用程式,技巧,注意事項。
最近大家都涉及交叉編譯應用程式, 感覺大家的路子有點偏 ,覺得有必要糾正一下。
一般的應用程式 ,編譯的步驟無外呼 ./configure && make && make install
但是對于 交叉編譯不能照搬 , 尤其要注意不能輕易make install (當然如果指定了 --prefix就無所謂了, 否則可能會覆寫标準路徑的程式就慘了)
這裡有兩個思路:
1>對于剛開始交叉編譯的人來說, 往往很暈 , 總想借助 ./configure 後面加一堆參數來解決 ,比如 ./configure --target=arm-9tdmi-linux-gnu --host=arm-9tdmi-linux-gnu 來搞定 ,
對于一般的小的程式來說, 應該沒有問題, 而且也推薦大家這樣用, 但是要注意 , 這樣作之前 ,先要 ./configure --help |grep --host ,看看有沒有這樣的選項, 如果沒有呢?
想想也可能, 如果程式的作者根本沒有考慮到除了x86的平台呢?你隻能自己改寫Makefile 了。
是以 ,./configure 不是萬能的,而且文法很混亂 ,不要指望 ./configure 給你作一切。而且局限很大。
2>是以這個時候 ,就要求交叉編譯的第二個層次, 自己改寫Makefile ,想怎麼改就怎麼改,靈活性最大 需要你開始就./configure 一下, 跟平台有關的參數一律不加。
./configure 過後就會生成Makefile 了, 裡面的gcc相關的參數,包括lib的路徑當然是x86下的了, 比如 /usr/local/lib/ , /usr/lib/ ,/lib/ 什麼的, 改掉就是了。 或者注釋掉。
gcc 要換成 arm-linux-gcc一類的編譯器, (如果不想每次都改, 參考下面的 include prerules.mk的做法) ,
總之, 這要求你的Makefile掌握的很熟練, 思路就是 邊編譯 ,發現問題,再改, 即使一開始Makefile不熟練, 到後來,也熟練了。 是個練習Makefile的好方式。
總之, 我們最後要的就是Makefile , 看你怎麼能得到它。
一個最标準的Makefile (去掉很多無用的東西)
通過./configure 生成的Makefile ,你會發現備援的地方非常多, 其實關鍵的地方,就那麼20幾條, 可以試着精簡一下, 這樣對程式的組織架構會熟悉的快一些, 畢竟Makefile反應了
程式(具體就是 .c 和 .h )之間的依賴關系 。
openssh 的Makefile我沒有精簡過(當然要精簡也很容易), 舉個telnetd的例子,
說明一下:
---------------------------telnetd ----------------------------------------
#-----------------------------------------------------
TOPDIR := $(shell /bin/pwd)
TOPDIR := $(TOPDIR)/..
#prerules.mk 包含了這些變量的定義, 比如 $CC , $CPP , $CXX , $CFLAGS 等等。
#盡量不要在這裡出現, CC=arm-linux-gcc這樣的定義,擴充性不好, 盡量用 全局變量,便于管理和拓展。
include $(TOPDIR)/prerules.mk
#-----------------------------------------------------
EXEC = telnetd
#好的Makefile都是這樣寫的, 也就是具體生成一個可執行檔案或者lib庫, 需要哪些.o , 這些.o 會依據後面的 .c.o : 規則來編譯出來的。
OBJS = telnetd.o state.o termstat.o slc.o sys_term.o \
utility.o global.o authenc.o logwtmp.o logout.o
#$(CC) 的編譯選項, 一般程式自己的帶的,不要改它, 而且一般都是+= , 不要用 = ,
CFLAGS += -DEMBED -DPARANOID_TTYS -DUSE_TERMIO -DKLUDGELINEMODE -D_GNU_SOURCE -Wall
ifdef CONFIG_DEFAULTS_LIBC_UCLIBC
LDLIBS := -lutil $(LDLIBS)
endif
all: $(EXEC) #很顯然all是最關鍵的了, 也要發在最開始的地方。 這樣make 就相當于make all , 這是大家的潛規則。
.c.o:
$(CC) -c -o $@ $
$(EXEC): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS$(LDLIBS_$@)) #這裡的LDFLAGS=-lcrypt -lzlib -L../lib -L. 總之根據自己的需要往裡面增加。
$(STRIP) telnetd #如果不需要調試, 一定要strip一下, 比如 15M的file ,strip過後, 可能變成 3M , 還不影響功能。
install:
cp $(EXEC) $(T_USBIN) #自己寫install , 不要用原來的, 可以copy到自己的ramdisk中去。
clean:
-rm -f $(EXEC) *.elf *.gdb *.[do]
$(OBJS): defs.h ext.h pathnames.h telnetd.h logwtmp.h logout.h