1. 如何使用自己的makefile編譯android ndk項目
android ndk提供了一套自己的makefile管理方式,要將源碼項目移植到android平台,需要按照android的makefile規則編寫makefile,還要按android的規則部署源碼目錄,對一個有自己的makefile管理方法的大型項目來說,只是做一下makefile遷移工作就是一件很麻煩的事。
其實android ndk上的編譯說到底也就是交叉編譯,只要配置好交叉編譯工具鏈,使用原有的makefile也是可以編譯出在android運行的c、c++程序的。
以android-ndk-r4-crystax的ndk版本為例:
編譯器路徑 android-ndk-r4-crystax/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin
名稱前綴 arm-eabi-
頭文件目錄 android-ndk-r4-crystax/build/platforms/android-3/arch-arm/usr/include
庫文件目錄 android-ndk-r4-crystax/build/platforms/android-3/arch-arm/usr/lib
你可以試一下上面的配置,如果編譯鏈接都沒有問題,可以adb push到android設備上運行看看,什麼結果?
有點崩潰,根本運行不起來,你也許想試試看android自帶的ndk例子,確實是能夠運行的,問題在哪兒呢?
只是正確配置了編譯器、頭文件、庫文件還不夠,還需要配置編譯、鏈接的參數,android例子中編譯鏈接的參數是什麼呢?你也許想深究一下android的makefile,可是不久你會發現那是更崩潰的事情,裡面用了很多的make腳本函數。其實android的makefile是可以把執行的詳細命令輸出來的,只要make的時候加上V=1即可。可以看到確實帶了很多參數
編譯參數:
-fpic
-mthumb-interwork
-ffunction-sections
-funwind-tables
-fstack-protector
-fno-short-enums
-Wno-psabi
-march=armv5te
-mtune=xscale
-msoft-float
-mthumb
-fomit-frame-pointer
-fno-strict-aliasing
-finline-limit=64
-Wa,--noexecstack
-D__ARM_ARCH_5__
-D__ARM_ARCH_5T__
-D__ARM_ARCH_5E__
-D__ARM_ARCH_5TE__
-DANDROID
鏈接參數:
-nostdlib
-Bdynamic
-Wl,-dynamic-linker,/system/bin/linker
-Wl,--gc-sections
-Wl,-z,noreloc
-Wl,--no-undefined
-Wl,-z,noexecstack
-L$(PLATFORM_LIBRARY_DIRECTORYS)
crtbegin_static.o
crtend_android.o
這其中鏈接參數中的-Wl,-dynamic-linker,/system/bin/linker、crtbegin_static.o、crtend_android.o是最關鍵的,android使用了自己的進程載入器,並且自定義了c運行時的啟動結束。難怪先前編譯的進程啟動不了。
2. 交叉編譯busybox顯示libc.so.6丟失!
拷貝C 庫
交叉應用程序的開發需要用到交叉編譯的鏈接庫,我們在移植應用程序到我們的目標板的時
候,需要把交叉編譯的鏈接庫也一起移植到目標板上,這里我們用到的交叉工具鏈的路徑是
/usr/local/arm/...../,鏈接庫的目錄是/usr/local/arm/...../arm-linux/lib,將其中部分庫文件及符號鏈接拷貝到root_nfs(你創建的busybox的根目錄)文件夾下的lib文件夾中。
部分庫文件及符號鏈接有:ld-2.3.2.so,ld-linux.so.2,libc-2.3.2.so,libc.so.6
3. 交叉編譯python-從入坑到入墳
了解Python的交叉編譯過程,可以分為兩大部分:主機端Python的編譯與設備端Python的編譯。首先,主機端Python需要從官網下載並解壓所需的Python版本源碼。若電腦端已安裝Python,且想在設備端安裝相同版本的Python,則可直接跳過本步驟。
主機端Python的編譯流程包括配置、編譯與安裝。編譯後的主機端Python會被保存在`build_pc`文件夾下,並可復制到其他位置,以防後續編譯設備端Python時被清理。
接著,進行設備端Python的編譯。這包括編譯第三方依賴庫,主要有zlib、ffi與openssl。首先,編譯zlib,完成配置、編譯與安裝。zlib會被安裝在當前文件夾`zlib_arm/`下,以便備用。同樣,編譯ffi並安裝在`ffi_arm/`下,供後續使用。
完成依賴庫的編譯後,進行設備端Python的編譯。這包括配置、編譯與安裝步驟。編譯好的設備端Python庫會被安裝在`build_arm/`文件夾下。
設備端Python編譯完成,還需進行組合與下機測試。在開發板上下載Python前,需將zlib與ffi對應的動態庫放置在`Pythonlib/python3.x/lib-dynload`文件夾內。進行打包下載至開發板,並進行環境配置。配置好環境變數後,在開發板上進行測試。如出現缺少庫錯誤,需搜索工具鏈路徑下對應的庫,並將這些庫及其存放路徑加入到開發板的`LD_LIBRARY_PATH`環境變數中。
在確保所有庫轉移至開發板並正確加入`LD_LIBRARY_PATH`後,重新執行`python3 -V`命令,應能不報錯並正確顯示Python版本號。
交叉編譯第三方庫如numpy、pyserial與opencv等至開發板時,首先需在電腦端安裝交叉編譯庫`cross_env`。配置激活虛擬環境後,按照指定路徑執行交叉編譯步驟。以numpy為例,配置好虛擬環境後,將numpy包拷貝至設備端python的`site-packages/`路徑下,並在開發板上驗證安裝是否成功。
交叉編譯opencv時,流程包括配置、編譯、拷貝動態庫到開發板並配置`LD_LIBRARY_PATH`環境變數,以及上板測試。完成所有交叉編譯步驟後,對生成的Python包進行裁剪壓縮。通過刪除Python runtime中不必要的文件、使用`strip`工具對動態庫與可執行文件進行裁剪,最終將包壓縮至較小的體積。經過此流程,整個Python包被成功壓縮至48M。