了解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。
2. arm-none-linux-gnueabi交叉工具鏈與arm-linux-gcc 有區別嗎
eabi標準的要好些,可能arm-linux-gcc就是arm-none-linux-gnueabi的一個鏈接
終於,郁悶已久的問題攻破了,用了三種配置交叉編譯的方法,最終在開發板上實現成功了,現在想一想,有的時候真的也是運氣。
之前已經試驗過使用arm-linux-gcc-3.4.1配置交叉編譯編譯環境,配置成功了,在開發板上失敗了~
後來使用腳本創建交叉編譯環境(crosstool-0.43),配置成功了(這個用了相當長的時間),在開發板上失敗了~
終於,在一個偶然的機會(其實是瀏覽無數網頁後),我終於找到了一個好的方法,並成功在開發板上運行。先說一下網上的一些方法,有些所謂的默認安裝了一些程序,但是在實際運行時發現根本沒有安裝,而且很多地方不知道該如何安裝。再有就是文章一上來就說安裝什麼什麼軟體,但是在網上搜根本找不到。只能說很多人只轉載文章,根本沒有試驗過。但是我還是幸運的找到了一個靠譜的文章http://www.adamjiang.com/pukiwiki/index.php?%E7%BC%96%E8%AF%91mini2440%E5%B7%A5%E5%85%B7%E9%93%BE
根據上面的做法,我成功了,在此小做總結。
首先下載工具鏈,幸好這篇文章給出了這個網站,要不還不知道要找多久。
http://www.codesourcery.com/.../arm-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
70多M很快就下完了,若不是root用戶下,可以將文件解壓到home的某個目錄下。
tar xjvfo arm-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 -C /home/..../arm
那麼,在這個目錄下會生成一個arm-2008q3文件夾。
更改路徑不用說了,或者臨時或者非臨時。我就直接改~/.bashrc了,在最後加:
export PATH=/usr/local/arm-2008q3/bin:${PATH}
ok~現在使你路徑生效吧:
source ~/.bashrc
再輸入:export CROSS_COMPILE=arm-none-linux-gnueabi-
作用是:當你編譯軟體的時候,Makefile在大多數情況向會取得CROSS_COMPILE所指定的交叉編譯工具。
也可以輸入:export CROSS_COMPILE=/usr/local/arm-2008q3/bin/arm-none-linux-gnueabi-
這種種方法是通過絕對路徑來指定交叉編譯工具,這樣做可以更精確的為交叉編譯定位,同時可以避免很多錯誤。你可以通過下面這樣的例子指定交叉編譯工具的絕對路徑。
現在一切就緒,隨便編譯個hello world.c文件,用arm-none-linux-gnueabi-gcc helloworld.c -o helloworld,生成的helloworld文件通過nfs掛載到板子上。
最最後,在minicom下輸入:./helloworld。
就會顯示你希望見到的輸出了。。。。。。
首先,從下面的地址下載工具鏈
http://www.codesourcery.com/.../arm-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
等待下載完成後,將工具鏈解壓到/usr/local/目錄,如果你沒有編譯主機上的root許可權的話,你可以將工具鏈解壓到Linux用戶的home目錄中的某個位置(比如${HOME}/bin)
tar xjvfo arm-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 -C /usr/local
這個操作將會在/usr/local目錄中創建一個么名為arm-2008q3的目錄。
接下來,你需要將這個新進添加的工具鏈的位置添加到PATH變數之中。編譯你的~/.bashrc文件,在其中加入新的PATH變數
export PATH=/usr/local/arm-2008q3/bin:${PATH}
使用source命令在當前shell中啟用這個變化,這樣你就不需要重新登入系統使用新變數了。
source ~/.bashrc
或者直接在shell中使用export對當前shell做同樣的操作。
export PATH=/usr/local/arm-2008q3/bin:${PATH}
如果你並不是bash用戶,你可以修改你使用的shell所對應的環境設置文件,比如,對於zsh來說,您應該修改~/.zsh文件。或者,你需要在每次登入shell後首先運行上面的export操作。
因為在開發主機上進行交叉編譯意味著使用開發主機的能力生成另外一個體系結構上運行的二進制代碼,所以,一般來說,你需要編譯的軟體通常都會接受一個叫做CROSS_COMPILE的變數來指定產生哪個體系結構的代碼。所以,配置工具鏈的最後一個步驟就是設置這個變數。如果你現在使用ls命令查看以下
ls /usr/local/arm-2008q3/bin/
目錄的話,你會看到很多以arm-none-linux-gnueabi-開始的可執行文件,而這個共同的前綴就是你需要的CROSS_COMPILE變數。現在,使用export命令設置環境變數
export CROSS_COMPILE=arm-none-linux-gnueabi-
現在,當你編譯軟體的時候,Makefile在大多數情況向會取得CROSS_COMPILE所指定的交叉編譯工具。當然,前提是,這些交叉編譯工具在你的PATH變數上。還有一種方法是通過絕對路徑來指定交叉編譯工具,這樣做可以更精確的為交叉編譯定位,同時可以避免很多錯誤。你可以通過下面這樣的例子指定交叉編譯工具的絕對路徑。
export CROSS_COMPILE=/usr/local/arm-2008q3/bin/arm-none-linux-gnueabi-
在大多數情況下,你並不需要將上面的export命令加入~/.bashrc這樣的文件,因為,你並不總是需要它們來做交叉編譯。比如,你僅僅希望編譯運行在開發主機上的程序時。
這樣,工具鏈就准備好了。
3. arm嵌入式linux系統為什麼要在Linux主機上編譯後下載到開發板呢為什麼
單片機很少跑操作系統,arm嵌入式系統如果不跑操縱系統,當然用IAR,KEIL等等集成開發環境也可以編譯出來程序,但是如果要跑操作系統,目前主流的都是跑的基於linux內核的操作系統。
既然使用的是基於linux的系統,那在linux下用交叉編譯環境編譯出程序就是自然而然的。就好像你要寫一個windows下運行的程序,自然首選是在windows下開發。
搭建linux的編譯環境很簡單。即使是windows的系統,裝個虛擬機,安裝一下交叉編譯環境,也就可以了。
搭建windows編譯環境的方法基本都是先安裝一個類linux環境的軟體,比如cgwin,然後和linux下步驟基本相同,沒多大區別。
你想用windows的環境,應該是對linux不熟悉吧。但是,學習linux是做嵌入式省不了的,是必須的。我也是這么一步一步走來的,推薦從單片機裸奔(無操作系統)過渡到ARM linux的一本書《linux c 一站式學習》
4. 深度linux的arm-linux-gnueabihf-gcc編譯參數如何配
一般來說,交叉編譯工具是用於在一種架構的主機(例如x86)上,編譯另一種主機(例如arm)運行的程序,在這個編譯期間,需要用到的頭文件/庫,往往需要從一個叫目標文件系統(sysroot)的路徑開始查找。
sysroot里包含usr,lib,usr/lib usr/include等文件夾結構和必要的頭文件和庫,你理解為目標機器上的整個文件系統,搬到你這台電腦上,然後作為一個文件夾存在。
交叉編譯原則上不能用主機(host)的頭文件,
這首先是因為編譯器在查找頭文件的相對路徑時,交叉編譯器會配置為查找目標平台架構的位置,和主機的gcc不一樣,這也是為什麼它去arm-linux-gnueabihf這個目錄去尋找的原因。
其次主機和目標機的系統版本有差異,再加上處理器架構的差異,往往有很多兼容性問題,甚至有難以解決的編譯錯誤。
如果一定要用本機的頭文件系統來湊合,那麼需要把所有的-I都列出來,即不僅需要-I/usr/include,還需要-I/usr/include/xxx,甚至要創建一些文件夾的符號鏈接指向你主機的這些頭文件文件夾。即使這些,往往也未必成功,有些頭文件不同的系統架構,會不完全一樣甚至缺失。
交叉編譯一般無法使用主機的庫(so)文件
主機和目標機往往架構不同,庫完全不能使用
可能遇到主機和目標機架構相同的情況,比如你在intel64上編譯一套運行在intel64位手機的程序,但是庫兼容性的問題仍然存在。
最後結論:你這個問題,如果你是為了另一套機器(比如arm開發板編譯),那麼需要搞一套目標機的文件系統才能順利編譯。
對了,目標文件系統需要編譯了python和dev頭文件/庫,好多嵌入式設備裁剪的很厲害,都不用python。
5. 交叉編譯幾種常見的報錯
(1)交叉編譯器
在主機上用來編譯其它類型機器上可執行代碼的編譯器就叫交叉編譯器,我們進行嵌入式linux的開發主機大部分都是X86,而我們的嵌入式系統的處理器有可能是ARM/MIPS等非X86處理器,這時候就必須使用ARM/MIPS的交叉編譯器才能編譯出在這些處理器上能夠執行的代碼。這里我們使用的是ARM最新的EABI編譯器。
交叉編譯器在編譯的時候,對於浮點運行會預設硬浮點運算FPA(float point architecture),而沒有FPA的CPU,比如三星的2440等,會使用FPE(float point emulation即軟浮點),這樣在速度上就會受到極大限制。使用EABI(embeded application binary interface)則可以對此改善處理。
(2)不修改MAKEFILE來建立編譯環境
將arm-2008q3.tar.bz2拷貝到ubuntu系統的某個目錄,解壓後。使用VI編輯/etc/bash.bashrc,在文件最後加入環境變數設置(註:加bin的含義是交叉編譯器工具目錄):
保存後,用source運行一次該文件,就可以了。
(3)gcc: error trying to exec 'cc1': execvp: No such file or directory 的解決
今天在編譯開發板環境時,明明設置好編譯器的環境變數了,編譯時就是會出現:gcc: error trying to exec 'cc1': execvp: No such file or directory 錯誤提示。後來發現一個方法可以解決,輸入:whereis gcc,就可以了發現好幾個gcc,包括/usr/bin/gcc,所以我就把PATH路徑設過去,就OK了。
(4)Clock skew detected. Your build may be incomplete
如果你裝了Windows Linux雙系統,系統時間很可能出問題,從而造成文件修改時間比系統時間晚,兩種辦法:
1,應該是你的PC的系統時鍾錯誤,在BIOS中修改正確。
2,使用touch命令將所有文件的時間戳修改為你系統的當前時間。解決方法:find ./-name "*" -exec touch {} \;