提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔
文章目錄
- 前言
- 一、幾個點
- 二、回顧過程
- 1.上來就執行Makefile
- 2.編譯第三方開源庫.a文件
- 2.1 build.sh腳本
- 2.2?Makefile
- 3.最終編譯
- 三、其它知識點
- 總結
前言
提示:這里可以添加本文要記錄的大概內容:
在編譯arm平臺so文件時,完成了以下的幾個點:
1、根據第三方開源的build.sh文件編譯第三方開源庫,至于build.sh文件怎么寫,大概是看開源倉的README文件吧。
2、寫了一個MakeFile文件并運行編譯了.a文件。最近查資料的時候獲取到一個知識點就是,其實.a就是所有.o文件的集合。
3、根據子文件夾Makefile文件編譯子文件夾.a文件。
4、解決編譯過程中的多個問題
一、幾個點
1、目標
在arm機器上編譯出arm平臺上可用的so文件
2、機器系統
[root@ncn4a-mapopenservice-34-12-242 ~]# uname -a
Linux ncn4a-mapopenservice-34-12-242 4.19.36-vhulk1907.1.0.h1393.eulerosv2r8.aarch64 #1 SMP Thu Jan 5 17:52:22 UTC 2023 aarch64 aarch64 aarch64 GNU/Linux
3、build.sh和Makefile領悟
接前言。現在理解了build和Makefile的區別。源于我將makefile的文件內容放在了build.sh腳本中。然后感覺突然恍然大悟。
Makefile文件是用來編譯代碼的。里面是有CXXFLAGS,就是將.c//cpp文件編譯成.a文件。
OBJ關鍵詞就要編譯成.a還是.so文件格式。
而build.sh文件其實就是linux指令集合文件,里面寫了編譯庫的很多指令。其中就包括調用makefile的一步,即調用make指令。
所以build.sh和makefile是有比較大的區別的。
而且自己寫的代碼只需要編寫Makefile就可以了,即只需要Makefile就可以了。因為用不到第三方開源庫的.configure、make install。只需要一個make就可以了,所以寫個make就可以執行了。
二、過程回顧
1.上來就執行Makefile
拿到studio_compile工程后,以為是直接執行build就可以了。但是執行時報了一個文件格式不對的錯誤
[2023-12-06 16:38:38] [root@ncn4a-mapopenservice-34-12-242 compile_wrapper]# ll
[2023-12-06 16:38:39] total 16
[2023-12-06 16:38:39] drwxrwxr-x 2 root root 4096 Apr 27 2023 include
[2023-12-06 16:38:39] -rw-rw-r-- 1 root root 1926 Apr 27 2023 Makefile
[2023-12-06 16:38:39] drwxrwxr-x 2 root root 4096 Apr 27 2023 src
[2023-12-06 16:38:39] drwxrwxr-x 2 root root 4096 Apr 27 2023 vs
[2023-12-06 16:38:39] [root@ncn4a-mapopenservice-34-12-242 compile_wrapper]# make -jm98
[2023-12-06 16:38:47] g++ -Werror=return-type -std=c++0x -Wl,-z,relro,-z,now,-z,noexecstack -D_FORTIFY_SOURCE=2 -O2 -s -ftrapv -fPIC -fstack-protector-all -w -c -shared -o -D__STDC_LIMIT_MACROS -Dlinux -I. -I./include -I../model/include -I../common/include -I../compiler/include -I../configurator/include -I../operation/include -I../preprocessor/include -I../pbencoder/include -I../../../3rd/gdal/include/linux -I../../../3rd/gdal/src/libtiff\include -I../../../3rd/boost/include -I../../../3rd/jni/include/linux -I../../../3rd/protobuf/include -I../../../3rd/sqlite/include -I../../../3rd/zlib/include/linux -I../../../platform/HuaweiSecureC/include src/com_huawei_mobilegis_data_studiocompile_engine_NativeEngine.cpp -o src/com_huawei_mobilegis_data_studiocompile_engine_NativeEngine.o
[2023-12-06 16:38:47] g++ -Werror=return-type -std=c++0x -Wl,-z,relro,-z,now,-z,noexecstack -D_FORTIFY_SOURCE=2 -O2 -s -ftrapv -fPIC -fstack-protector-all -w -c -shared -o -D__STDC_LIMIT_MACROS -Dlinux -I. -I./include -I../model/include -I../common/include -I../compiler/include -I../configurator/include -I../operation/include -I../preprocessor/include -I../pbencoder/include -I../../../3rd/gdal/include/linux -I../../../3rd/gdal/src/libtiff\include -I../../../3rd/boost/include -I../../../3rd/jni/include/linux -I../../../3rd/protobuf/include -I../../../3rd/sqlite/include -I../../../3rd/zlib/include/linux -I../../../platform/HuaweiSecureC/include src/CompileLayerWrapper.cpp -o src/CompileLayerWrapper.o
[2023-12-06 16:38:47] g++ -Werror=return-type -std=c++0x -Wl,-z,relro,-z,now,-z,noexecstack -D_FORTIFY_SOURCE=2 -O2 -s -ftrapv -fPIC -fstack-protector-all -w -c -shared -o -D__STDC_LIMIT_MACROS -Dlinux -I. -I./include -I../model/include -I../common/include -I../compiler/include -I../configurator/include -I../operation/include -I../preprocessor/include -I../pbencoder/include -I../../../3rd/gdal/include/linux -I../../../3rd/gdal/src/libtiff\include -I../../../3rd/boost/include -I../../../3rd/jni/include/linux -I../../../3rd/protobuf/include -I../../../3rd/sqlite/include -I../../../3rd/zlib/include/linux -I../../../platform/HuaweiSecureC/include src/ParseJNIObj.cpp -o src/ParseJNIObj.o
[2023-12-06 16:38:47] g++ -Wl,-z,relro,-z,now,-z,noexecstack -D_FORTIFY_SOURCE=2 -O2 -s -ftrapv -fPIC -fstack-protector-all -static-libstdc++ -shared -o libcompile_wrapper.so ./src/com_huawei_mobilegis_data_studiocompile_engine_NativeEngine.o ./src/CompileLayerWrapper.o ./src/ParseJNIObj.o -L../../../build/lib/linux -lcompiler -lconfigurator -lpreprocessor -lpbencoder -loperation -lcommon -L../../../3rd/gdal/lib/linux -lgdal -lgeos_c -lgeos -lproj -ljson-c -L../../../3rd/boost/lib/linux -lboost_serialization -lboost_filesystem -lboost_system -lboost_thread -L../../../3rd/protobuf/lib/linux -lprotobuf -L../../../3rd/sqlite/lib/linux/ -lsqlite3 -L../../../3rd/zlib/lib/linux/ -lz -L../../../3rd/gdal/src/libtiff/lib -ltiff -L../../../platform/HuaweiSecureC/lib/linux/ -lsecurec -ldl -lpthread
[2023-12-06 16:39:02] /usr/bin/ld:../../../3rd/gdal/lib/linux/libgdal.a: file format not recognized; treating as linker script
[2023-12-06 16:39:02] /usr/bin/ld:../../../3rd/gdal/lib/linux/libgdal.a:1: syntax error
[2023-12-06 16:39:02] collect2: error: ld returned 1 exit status
[2023-12-06 16:39:02] make: *** [Makefile:43: all] Error 1
即這一條:
/usr/bin/ld:../../../3rd/gdal/lib/linux/libgdal.a: file format not recognized; treating as linker script
然后就查看一下libgdal.a文件格式,使用file (filename)指令
[2023-12-06 17:41:48] [root@ncn4a-mapopenservice-34-12-242 linux]# file libgdal.a
[2023-12-06 17:41:58] libgdal.a: ASCII text
[2023-12-06 17:41:58] [root@ncn4a-mapopenservice-34-12-242 linux]# timed out waiting for input: auto-logout
這個顯示情況其實還看不出來文件格式。這個ACII text文件其實是因為.a文件在windows環境下解壓導致文件格式出問題了。但是其實正常的,也會是x86的格式,不是arm的格式。總而言之,就是報錯格式不對。
這個文件是第三方開源庫靜態庫文件,所以需要編譯第三方開源靜態庫。
其實后來按照心哥的說法,即便格式沒有變成ASCII碼也是需要重新編譯第三方開源庫的,因為平臺變了,之前的.a文件是x86格式的。
這邊不得不吐槽,上傳到git上的.a文件真是一點用沒有啊。
2、編譯第三方開源庫.a文件
先后編譯boost庫、protobuf、sqlite、zlib、gdal庫。其中有兩個點需要單獨領出來看。一個就是gdal庫,還有一個就是沒有Makefile然后我自己寫的makefile文件編譯的。
先說gdal庫。gdal需要依賴tiff庫、json-c庫、geos庫、proj庫,最后才是安裝gdal庫。這邊也是這次才理解的就是。就是對于這幾個庫,自己感覺是編譯,其實也是在機器上安裝這個庫。可以用-- v查看版本號的。
然后這幾個開源庫用的build.sh腳本編譯的。
2.1 build.sh
build.sh基本格式就是以下形式
????????????????????????PREFIX_INC_PATH=$(cd?"$(dirname?"$0")";pwd)? ? ? ? //獲取當前路徑
git下載 | 備注 | |
解壓 | ||
更改文件夾名(可選) | 可選 | |
進入含有configure文件的文件夾中 | ||
執行./configure | --prefix=【】,//設置安裝路徑 | |
--enable-xxx? /? ?--disable-xxx | 不懂 | |
--with-xxx? /? --without-xxx | 不懂 | |
--build=arm-linux? //設置編譯環境 | 國產arm機器需要設置平臺環境,不然會configure失敗,導致build.sh失敗 | |
SQLITE3_CFLAGS=路徑 | 不懂 | |
SQLITE3_LIBS=路徑 -lsqlite3 | 不懂 | |
sh?autogen.sh /?autoreconf | 不懂,但是要安裝autoconf全家桶,可以參考本人帖子 | |
make -j8 | ||
make install | ||
移動OBJ文件 | 可選 | |
【完成】 |
2.2 Makefile
Makefile的格式大概如下
CXXFLAGS= | 用于將.c或.cpp文件編譯成.o文件,編譯格式為 $(CXX) $(CXXFLAGS) $*.cpp -o $@ | |
CXX= | CXX = xxx指定編譯器 | |
搜到這個帖子說的比較詳細:Linux Makefile入門總結-CSDN博客
看完這個貼子,增加了對以下幾個知識點的了解
元素 | 說明 | 備注 |
目標文件 : 依賴文件 [TAB]命令 | [TAB]:是你鍵盤左邊tab鍵 | |
-c | -c 是生成 .o 文件的必要參數! | gcc -c main.c -o main.o |
?.PHONY: clean | 用來屏蔽同名clean的文件夾或文件 | |
=?:變量(可修改) +=?:追加 :=?:常量(不可修改) | TARGET = test CXX := g++ | |
$(TARGET)? ? ? ? | #?相當于C語言的宏定義 | |
%c、%cpp、%o? | 隱含規則:?任意的.c 或 任意的.cpp 或 任意的.o | 使用%c 或 %cpp 或 %o 或 %h 時,優先加點'.'使用,如:%.c、%.cpp、%.o、%.h |
*.c、*.cpp、*.o | 所有的.c 或 所有的.cpp 或 所有的.o | |
$^ | 所有的依賴文件 依賴文件:我要做這個操作,依賴哪些東西 | $(TARGET): ?$(OBJ) ????????$(CXX) $^ -o $@ |
$< | 所有依賴文件的第一個文件(應該也是最匹配的一個文件) | %.o: %cpp ?$(CXX) ????????$(CXXFLAGS) $< -o $@ |
$@ | 所有的目標文件 目標文件:我要做這個操作,要生成的東西; | |
CXXFLAGS | CXXFLAGS = -c -Wall 類似于宏替換 | |
SRC = $(wildcard?*.cpp) | 獲取項目路徑下的所有.cpp源文件 | |
OBJ = $(patsubst %.cpp, %.o, $(SRC))? | 根據源文件鏈接成 .o 文件 | wildcard 和?patsubst 是Makefile函數的用法 |
-wall? | 編譯后顯示所有警告 | Makefile 中 -g、-o、-c、-f 、-D、-Wall、-L、含義 | 碼農家園 |
這個帖子絕佳,搞明白很多之前的疑問,贊!Makefile 中 -g、-o、-c、-f 、-D、-Wall、-L、含義 | 碼農家園
3、最終編譯
繼續回顧流程,顯示用各個開源庫的build.sh腳本把各個開源庫編譯一遍。再把子文件夾用Makefile編譯一遍,這個上面的帖子也說了,每個子文件夾都有一個Makefile
這其中還有一個很奇怪的一個點,就是工程寫了一個build.sh腳本,是進入每個子文件夾分別執行Makefile,這個也是一個知識點。但這不是重點,重點是用這個build.sh腳本執行編譯時,過程中會因為MobaXterm出現network斷開導致編譯失敗,所以我是對子文件夾單獨編譯的。可以編好。就很奇怪。
到此第三方開源庫、子文件的靜態庫都編好了。其中過程中遇到好幾個問題,通過百度都解決了,也記錄在自己的文章中了。報錯處理集-CSDN博客,現在就開始編譯最終的so文件了。
這其中還有一個知識點就是,其實我之前理解的所謂交叉編譯環境是在x86機器上安裝檢查編譯工具。但是過程中問了心哥知道其實我用的這個歐拉系統是arm環境,所以交叉編譯是不是只能用arm機器呢,這個問題留存解決。
解釋:百度了一下,理解了,意思就是交叉編譯是因為目標平臺可能不支持編譯或者資源不夠,跨平臺編譯就叫交叉編譯。如果像我這樣就不算交叉編譯了吧。
【百度百科:
一個經常會被問到的問題就是,“既然我們已經有了主機編譯器,那為什么還要交叉編譯呢?”其實答案很簡單。有時是因為目的平臺上不允許或不能夠安裝我們所需要的編譯器,而我們又需要這個編譯器的某些特征;有時是因為目的平臺上的資源貧乏,無法運行我們所需要編譯器;有時又是因為目的平臺還沒有建立,連操作系統都沒有,根本談不上運行什么編譯器。
另一個經常會被問到的問題就是:“既然可以交叉編譯,那還要主機編譯干嗎?”其實答案也很簡單,交叉編譯是不得已而為之!與主機編譯相比,交叉編譯受的限制更多,雖然在理論上我們可以做任何形式的交叉編譯,但事實上,由于受到專利、版權、技術的限制,并不總是能夠進行交叉編譯,尤其是在業余條件下!舉例來說,我們至今無法生成惠普公司專有的som格式的可執行文件,因此我們根本無法做目的平臺為HPPA-HPUX的交叉編譯。來源:交叉編譯_百度百科】
還有一點就是這次編譯過程比較復雜,一方面是因為集氣室離線的,很多是要離線安裝的。但是問了心哥,說可以用yum install在線安裝,試了確實可以。這個可能跟是歐拉系統有關。
三、其他知識點
1、這邊還有一個關于x86和arm平臺區別的知識點,找到這篇帖子:https://www.cnblogs.com/kin-zhang/p/15031633.html
2、Makefile里面可以直接把.a換成.so嗎?編譯.a和編譯.so的Makefile有什么區別?
這個需要后面了解下
Makefile鏈接靜態庫.a編譯成動態庫.so_makefile 鏈接.a-CSDN博客
3、linux安裝git的用戶設置
當時準備安裝git拉取代碼的,不過發現并不可行,所以沒有深究下去。后面可以了解下。
4、LIB = ar cr什么意思,未知,后面要了解下
總結
????????對整個編譯過程進行了總結,是有意義的,編成功了。但是經驗不復用應該是不好的,需要把經驗積累下來。突然想起來強哥之前一直說要經驗復用,大概也是指的這個意思吧。