標籤:makefile 共用庫
0.前言 在較為複雜的項目中會利用到交叉編譯得到的共用庫(*.so檔案)。在這種情況下便會產生以下疑問,例如: 【1】交叉編譯時間的共用庫是否需要放置於目標板中,如果需要放置在哪個目錄中。 【2】交叉編譯時間的共用庫是否需要放置於宿主機中,如果需要放置於哪個目錄中。 【3】交叉編譯時間如何指定共用庫 【4】程式運行時如何尋找共用庫 等等問題。 博文總結了使用共用庫的一般方法,並通過一個例子說明問題。如果已經有了交叉編譯好的共用庫,可以從【2】開始,步驟【1】只是為了說明問題,捏造一個簡單的共用庫試圖說明問題。 【1】交叉編譯獲得連結庫 【2】交叉編譯源檔案並加入連結庫 【3】移動動態連結程式庫 【4】執行
【必要說明】 【宿主機】Ubuntu 14.04 AMD64 【目標板】樹莓派 【相關博文】 【例說makefile索引博文】 【樹莓派學習筆記——交叉編譯工具鏈】
【代碼倉庫】——makefile-example 代碼倉庫位於bitbucket,可藉助TortoiseHg(GUI工具)複製代碼或者在網頁中直接下載zip包。
1.交叉編譯獲得動態連結程式庫
本例先製作一個非常簡單的共用庫,共用庫包含兩個API——add和sub。 【libtest.h】 指定介面,給出相應聲明#ifndef __LIBTEST_H#define __LIBTEST_Hint sub(int a, int b);int add(int a, int b);#endif 【test-add.c】int add(int a, int b){ return a+b;} 【test-sub.c】int sub(int a, int b){ return a-b;} 【makefile】 在同目錄下包含makefile檔案,請替換其中的[tab],並以代碼倉庫中的makefile檔案為主。編譯完成之後,把libtest.so移動到上級lib目錄中。請注意此時的交叉工具鏈為arm-linux-gnueabihf-gcc ,目標b
# 指令編譯器和選項CC = arm-linux-gnueabihf-gccCFLAGS = -Wall -std=gnu99# 目標檔案TARGET = libtest.so# C檔案SRCS = test-add.c test-sub.c# 目標檔案OBJS = $(SRCS:.c=.o)# 連結為可執行檔$(TARGET):$(OBJS)[tab]$(CC) -shared -o [email protected] $^[tab]mv $(TARGET) ../libclean:[tab]rm -rf $(TARGET) $(OBJS)# 編譯規則 [email protected]代表目標檔案 $< 代表第一個依賴檔案%.o:%.c[tab]$(CC) $(CFLAGS) -o [email protected] -fPIC -c $< 【必要的驗證】 使用file指令查看libtest.so資訊。 file libtest.solibtest.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=e22558b8cf089b92e5534b636c6d501f1cc54581, not stripped
從控制台的輸出資訊可以看出,libtest.so運行於ARM平台,而不是宿主機的AMD64平台。
2.交叉編譯源檔案並加入動態連結程式庫 【源檔案】#include <stdio.h>#include <libtest.h>int main(void){ int a = 3; int b = 2; printf("a=%d\n", a); printf("b=%d\n", b); printf("a+b=%d\n", add(a, b)); printf("a-b=%d\n", sub(a, b)); return 0;} 【makefile檔案】 # 指定編譯器和選項# 指定樹莓派交叉編譯器CC = arm-linux-gnueabihf-gccCFLAGS = -Wall -std=gnu99# 目標檔案TARGET = test# C檔案SRCS = test.c# 標頭檔尋找路徑INC = -I.# 庫檔案和庫尋找路徑DLIBS = -ltestLDFLAGS = -L./lib# 目標檔案OBJS = $(SRCS:.c=.o)# 連結為可執行檔$(TARGET):$(OBJS)[tab]$(CC) -o [email protected] $^ $(LDFLAGS) $(DLIBS)clean:[tab]rm -rf $(TARGET) $(OBJS)# 編譯規則 [email protected]代表目標檔案 $< 代表第一個依賴檔案%.o:%.c[tab]$(CC) $(CFLAGS) $(INC) -o [email protected] -c $< 【說明】 【1】交叉工具鏈為arm-linux-gnueabihf-gcc 【2】指定了交叉編譯之後的共用庫和共用庫路徑,連結共用庫使用-ltest,共用庫位於lib目錄下。請注意-ltest對應libtest.so。 【3】make之後可獲得可執行檔,通過file test查看資訊。test: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=88e4142dceabd295369657b29757141f98a03753, not stripped
從控制台的輸出可以看出,該可執行檔運行平台為ARM,而不是AMD64。
3.移動動態連結程式庫 【移動共用庫至目標板/usr/lib目錄中】 通過FTP工具把共用庫傳輸至樹莓派中,然後通過cp指令複製到/usr/lib中 sudo cp libtest.so /usr/lib linux系統中預設的搜多重路徑為/lib和/usr/lib,libtest.so可以複製到任何目錄中。 修改libtest.so的執行許可權。 sudo chmod 775 libtest.so
4.執行 【FTP上傳】 通過FTP工具把可執行檔test複製到樹莓派中,然後通過ldd指令查看共用庫連結狀態。 【檢驗】 ldd test/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so (0xb6f7f000)
libtest.so => /usr/lib/libtest.so (0xb6f6b000)
libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6e3b000)
/lib/ld-linux-armhf.so.3 (0xb6f8d000)
從控制台的輸出可以看出,test成功連結了位於/usr/lib中的libtest.so
【執行】 ./test
a=3
b=2
a+b=5
a-b=1 從執行結果看,前面所做的努力是正確的。
5.總結 回答在前言中的問題。 【1】交叉編譯時間的共用庫是否需要放置於目標板中,如果需要放置在哪個目錄中。 交叉編譯之後的共用庫需要複製到目標板中,最好放置於/usr/lib或/lib中,當然也有其他的方法,在這裡不詳細說明。
【2】交叉編譯時間的共用庫是否需要放置於宿主機中,如果需要放置於哪個目錄中。 交叉編譯時間確切的說連結過程中需要指定共用庫的問題,通過-L指定目錄,通過-l指定共用庫名稱。但是此時交叉編譯的共用庫最好不要放置於宿主機的/lib或/usr/lib中,以免產生混淆。 綜合【1】和【2】,libtest.so同時存在於目標板和宿主機中。
【3】交叉編譯時間如何指定共用庫 通過-L指定目錄,通過-l指定共用庫名稱
【4】程式運行時如何尋找共用庫 最直觀的方法,複製到/usr/lib目錄中,讓linux系統自動尋找。
最後,發現博文寫多了自己感覺好累啊,希望這些總結對大家有用。