Linux學習筆記——如何在交叉編譯時使用共享庫
阿新 • • 發佈:2019-01-02
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.so4.執行 【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系統自動查詢。 最後,發現博文寫多了自己感覺好累啊,希望這些總結對大家有用。
本例先製作一個非常簡單的共享庫,共享庫包含兩個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
從控制檯的輸出資訊可以看出,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
從控制檯的輸出可以看出,該可執行檔案執行平臺為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.so4.執行 【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系統自動查詢。 最後,發現博文寫多了自己感覺好累啊,希望這些總結對大家有用。