1. 程式人生 > >SQLITE+PYTHON成功移植到ARM開發板執行

SQLITE+PYTHON成功移植到ARM開發板執行

下載原始碼:
Sqlite 3.6.23.1 http://www.sqlite.org/sqlite-3.6.23.1.tar.gz
Python 2.6.5 http://www.python.org/ftp/python/2.6.5/Python-2.6.5.tar.bz2

由於sqlite是python的標準組件所以我們要先進行sqlite的移植。
交叉編譯sqlite:
配置編譯選擇:

1
2
3
4
5
tar xvf sqlite-3.6.23.1.tar.gz
mkdir sqlite-build
cd sqlite-3.6.23.1
./configure --host=arm-linux --
prefix=/home/lzz/working/apps/sqlite-build --enable-shared --disable-readline --disable-dynamic-extensions

以上的命令我們先解壓了原始碼,然後進入原始碼目錄執行configure來配置編譯選項, 各個引數的意思是:–host=arm-linux 說明我們要編譯arm版本的sqlite;–prefix=/home/lzz/working/apps/sqlite-build 說明我們要把編譯好的sqlite安裝到sqlite-build目錄;–enable-shared 生成動態連結庫;–disable-readline 禁用sqlite的readline;–disable-dynamic-extensions 禁用sqlite的動態擴充套件。

紅色標記是你make install 以後的安裝路徑
編譯和安裝:

1
2
Make
Make install

這兩個命令就不用解釋了吧。執行完這兩個命令後就可以在sqlite-build目錄下看到三個目錄分別是bin,include和lib目錄,把bin目錄下的sqlite3拷到檔案系統的bin目錄下,把lib目錄下的內容拷到檔案系統的/lib目錄下就ok了(注意:如果出現sqlite不能在開發板上執行的情況,很可能是由於缺少相應的庫檔案導致的,你只需要按照錯誤提示在你的交叉編譯環境中找到相應的庫檔案拷到檔案系統的lib目錄下即可)。下圖是在我的tq2440上執行的效果

交叉編譯Python:


解壓Python

1
2
tar xvf Python-2.6.5.tar.bz2

編譯PC版的Python:

1
2
3
4
5
cd Python-2.6.5
mkdir python-pc
cd python-pc
../configure
make

有人可能會問,我們為什麼要編譯pc版的python。其實原因是這樣的,在python編譯過程中,第一階段會產生一個python的可執行版本,然後會進入第二階段去按照setup.py來定義去編譯附加的python模組。而在處理setup.py時其實就需要用到python解析器了,但是我們如果是在編譯嵌入式版本的話,那麼第一階段產生的python可執行程式是arm版本的,它不能執行在我們的pc機上所以不能用它來處理setup.py。所以我們要提前編譯一個pc 上的python來處理setup.py。
這時在當前的python-pc目錄下就會出現python直譯器了。
修改configure檔案:
由於configure檔案在檢測編譯器的printf是否支援%zd的時候如果發現是在cross compile就會退出,所以我們要先去掉這段檢測程式碼用vim開啟configure檔案查詢%zd printf()就會發現如下程式碼:

1
2
3
4
{ echo "$as_me:$LINENO: checking for %zd printf() format support" >&5
echo $ECHO_N "checking for %zd printf() format support... $ECHO_C" >&6; }
if test "$cross_compiling" = yes; then
{ { echo "$as_me:$LINENO: error: cannot run test program while cross compiling

然後往下找,一直找到這裡

1
2
3
4
5
6
( exit $ac_status )
{ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6; }
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi

刪掉或註釋掉這兩段以及中間的部分就可以了。
編譯arm版本的python:

1
2
3
4
mkdir python-arm
cd python-arm
../configure --host=arm-linux --prefix=/home/lzz/working/apps/python-build
 --disable-ipv6 --enable-shared

上面的編譯選項的意思和sqlite的相同就不再解釋了。
然後我們修改生成的Makefile檔案去掉除錯資訊,方法是在Makefile檔案中查詢OTP找到 OPT= -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes 這一行把-g選項去掉,如果空間緊張的話,還可以把-O3改成-O2。
繼續查詢PGEN,在PGEN = Parser/pgen$(EXE)一行的下面新增PGEN_HOST= ../build-pc/Parser/pgen$(EXE)
在要使用PGEN進行解釋的地方使用PGEN_HOST大約在Makefile檔案的540

1
2
3
$(GRAMMAR_H) $(GRAMMAR_C): $(PGEN) $(GRAMMAR_INPUT)
-@$(INSTALL) -d Include
-$(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H)               $(GRAMMAR_C)

改為

1
2
3
$(GRAMMAR_H) $(GRAMMAR_C): $(PGEN) $(GRAMMAR_INPUT)
-@$(INSTALL) -d Include
-$(PGEN_HOST) $(GRAMMAR_INPUT) $(GRAMMAR_H)          $(GRAMMAR_C)

修改所有使用新生成的arm版的python的地方,把所有./$(BUILDPYTHON)的地方都改成../build-pc/python$(EXE),這樣的地方比較多,大家可以用在vim在打:號然後輸入%s/\.\/\$(BUILDPYTHON)/\.\.\/build-pc\/python\$(EXE)/g命令來替換。
修改setup.py檔案:
setup.py負責編譯python的各個擴充套件模組。但是,由於python完全沒有考慮cross compile,所以要做一些修改。
我們需要修改 PyBuildExt類中的幾個部分
build_extension函式:
這個函式在編譯了所有的extension後,會去load這些剛編譯好的extension, 但我們在i686的電腦上顯然不能load,所以要跳過這些操作。 大概在238行在 build_ext.build_extension(self, ext)後面直接寫一個return,不做load。
去掉無用的搜尋目錄:
函式的前兩行是把/usr/local加到搜尋目錄中,我們的cross compiler一般不會直接安裝在 /usr/local裡面的,所以這兩行去掉(大概在314行):

1
2
add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')

去掉不被支援的模組
由於python本身的問題,現在ctypes還不能在除i386以外的機器上執行,所以去掉 ctypes。大概在1275行,把它註釋掉就可以了

1
self.detect_ctypes(inc_dirs, lib_dirs)

還可以根據自己的需要去掉不用的模組,方法是在detect_modules函式中註釋掉相應的項,比如我要去掉cmath模組

1
2
# complex math library functions
exts.append( Extension('cmath', ['cmathmodule.c'],libraries=math_libs) )

就可以把上面幾行註釋掉就可以了。
修改sqlite的編譯選項
我們要把setup.Py檔案中對sqlite的引用路徑改成我們安裝sqlie的目錄,大概在910行,我們把

1
for d in inc_dirs + sqlite_inc_paths:

改成

1
for d in ['/home/lzz/working/apps/sqlite-build/include']:

修改main函式
最後我們把main函式中的scripts那一部分改成空,大大概在1913行把

1
2
3
scripts = ['Tools/scripts/pydoc', 'Tools/scripts/idle',
'Tools/scripts/2to3',
'Lib/smtpd.py']

改成
scripts=[]
編譯安裝python:
最後

1
2
make
make install

就可以了,編譯完成後我們會在python-build目錄下發現四個目錄,我們只要bin和lib目錄中的內容。我們把bin目錄中的檔案拷到我們的檔案系統的/usr/bin目錄,然後把lib目錄中的檔案拷到檔案系統的/usr/lib目錄中就ok了。

注意:如果出現python不能執行的情況很可能是缺少相應的庫,你需要到你的交叉編譯環境中去拷相應的庫檔案。
如果出現下面的錯誤提示就是你沒有設定python的環境變數

1
2
Could not find platform dependent libraries <exec_prefix>                      
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]

這時你需要設定PYTHONHOME,如果出現下面的錯誤
‘import site faild’
這時你需要設定PYTHONPATH 。
最好是在你的檔案系統的etc目錄下的profile檔案中加入下面的語句

1
2
3
export PYTHONHOME=/usr/lib/python2.6
export PYTHONPATH=.:$PYTHONHOME:$PYTHONHOME/site-packages
export PATH=$PATH:$PYTHONHOME:$PYTHONPATH

這樣就不會出現上面的錯誤了。
裁減python:
我們發現我們編譯出來的python的庫檔案有57M,如果你空間緊張可以刪除庫檔案中副檔名為py和pyc的檔案,只留下pyo的檔案。不過這樣做之後我們執行python就要加上-OO的引數如下圖就是帶-OO選項的執行情況