關於SQLite3 編譯及交叉編譯的一些問題

    SQLite3(http://www.sqlite.org)是一個非常強大的小型開源數據庫軟件,特別嵌入到一些軟件中存儲數據,當然,移植到嵌入式系統上也是非常有必要的。衆所周知的Symbian,Android,IOS這幾大移動平臺都是使用的sqlite作數據存儲,使用SQLite的廠商包括Adobe, Airbus, Apple,Dropbox, Mozilla, GE, Google, McAfee, Microsoft, PHP, Python,Toshiba等等。目前SQLite的贊助商包括Oracle, Adobe,Mozilla等。官網的介紹在這裏http://sqlite.org/about.html

    優點:
      1、體積非常小巧,shell版的可執行文件僅600K左右,所有運行庫加起來也不過3M多。
      2、性能很好,和mysql相比性能完全不在其之下。
      3、整個數據庫存儲在一個單一的文件裏,備份恢復都非常容易。
      
    缺點:
      對於併發的支持不好,其對於數據庫的讀寫是完全加鎖的。




   本文中系統平臺爲ubuntu 12.04.1LTS,開發板爲s3c2440實驗箱,使用的交叉編譯器爲3.4.6版。

   在ubuntu雖然可以通過
      sudo apt-get install sqlite3
   來安裝源裏面的sqlite3,不過卻不是最新版,之所以不用源裏面安裝的版本不僅僅是因爲那個版本有點老,而且有個很關鍵的問題,sqlite3只有在3.7.11之後的版本才支持insertinto table_namevalues(),(),()這種方式來一次性插入多條數據,而源裏面的版本是3.7.4的版本並不支持這個特性,所以用起來就很不方便,故選擇了自己編譯。本文以官網最新的3.7.14.1版爲例。


   sqlite3官網提供了兩種源代碼的方式,一種叫作amalgamation,另外一種叫作autoconf,這兩種源碼包有點不一樣。amalgamation的源碼包是把sqlite的所有源文件都集成到了sqlite3.c這一個文件裏面去,而且這個包只適合單獨編譯出一個shell版本的sqlite3,它並不會編譯出linux裏面常見的開發庫(也就是基於sqlite3編寫的軟件必須要依賴的sqlite3庫)。而autoconf版就很明顯了,是使用linux上面常見的./configuremake makeinstall方式來編譯sqlite3的,可以編譯出所有需要的依賴庫。雖然sqlite官方建議使用amalgamation包,但經過個人測試,使用autoconf的包對於sqlite開發者來說是必須的,對於ARM的交叉編譯來說就更是如此了。



   Amalgamation包編譯shell版sqlite3:
      解壓了下載下來的amalgamation的壓縮包之後,進入目錄,執行

         
gcc -o sqlite3 shell.c sqlite3.c -lpthread-ldl



      大約要10到20秒時間即可編譯出來一個可用的shell版sqlite3。之所以不推薦使用amalgamation包,是因爲使用這個包始終無法編譯出支持上下鍵選擇歷史命令記錄的功能,即使是安裝了libreadline-dev包並且加上-lreadline編譯參數也不可以,如有人能告訴我原因,不甚感激。



   Autoconf包編譯sqlite3及其開發庫:
      在編譯之前,還需要安裝libreadline庫,用以實現sqlite3按上下方向鍵實現重現歷史命令記錄的功能,此包不大,500k左右。(當然,ubuntu下面做開發必須要安裝的build-essential,libncurses5-dev, autoconf, automake這些基本包就不說了)

       
 sudo apt-get install libreadline-dev



      安裝好libreadline之後,執行如下命令編譯並安裝sqlite及開發庫:

         sudo ./configure
         sudo make
         sudo make install



      在執行完./configure之後,注意觀察一下輸出的結果,在靠後的部分,可以看到這樣的輸出:
         checking for library containing tgetent...-lncurses
         checking for library containing readline...-lreadline
         checking for readline... yes


      
      如果沒找到lncurses和lreadline這兩個庫,readline肯定就是no了,多半編譯完成之後的sqlite3不會支持按上下鍵調出歷史命令記錄這個實用功能。
      執行完這三條命令之後,sqlite3就已經被默認安裝到了/usr/local/bin裏面去了,但是還沒完呢,如果在終端直接執行一下sqlite3,多半會報錯,類似於這樣:

         SQLite header and source version mismatch
         2011-11-01 00:52:41c7c6050ef060877ebe77b41d959e9df13f8c9b5e
         2012-10-04 19:37:12091570e46d04e84b67228e0bdbcd6e1fb60c6bdb



      這個問題是因爲ubuntu裏面原來自帶了一個老版的sqlite運行庫,這個庫由一個庫文件和一個符號鏈接組成,位於/usr/lib/i386-linux-gnu目錄,分別是libsqlite3.so.0.8.6和一個符號鏈接到它的libsqlite3.so.0,由於上面進行的autoconf包的sqlite3並不是靜態編譯,所以就會出現庫不匹配的情況而程序拒絕執行的問題了。
      由於不知道系統自帶的那個老版的sqlite庫還會不會有用,我們就留着它:
 
        mv /usr/lib/i386-linux-gnu/libsqlite3.so.0.8.6/usr/lib/i386-linux-gnu/libsqlite3.so.0.8.6_bak


      然後把剛纔編譯好的autoconf包裏面的這個庫複製過去:
         cp .libs/libsqlite3.so.0.8.6/usr/lib/i386-linux-gnu


      
      OK,現在執行一下sqlite3,完全沒有問題了(如果前面沒有安裝libreadline和libncurses5-dev庫,按上下方向鍵就沒有顯示歷史命令記錄這個實用功能),同時其開發庫也已經安裝到系統裏了。





   下面是交叉編譯sqlite所有相關文件的問題。

      由於是交叉編譯,所以一些相關的依賴庫,比如libreadline和libncurses就不能直接安裝到系統裏面了(安裝了也沒用不會被交叉編譯器識別),而是應該安裝到交叉編譯器的目錄中。
      先分別去下面這兩個地方下載libreadline和ncurses的源碼包(之所以要安裝ncurses庫是因爲libreadline依賴於它,而且很多linux的軟件都會用到這個庫),注意是下載.tar.gz爲擴展名的包,一般都是下載最新版的。
http://ftp.gnu.org/gnu/readline/
http://ftp.gnu.org/gnu/ncurses/
      分別交叉編譯這兩個包:
      
         sudo ./configure --host=arm-linux--prefix=/opt/
         sudo make
         sudo make install



      --host接的是arm的交叉編譯器的名稱,--prefix接的是編譯好之後安裝到的路徑,這裏建議不要直接安裝到交叉編譯器的路徑,而是安裝到其它地方,等安裝完之後到目標目錄確認一下之後再手動拷到交叉編譯器的目錄裏面去。

      待兩個包編譯安裝完之後,還要手動拷到交叉編譯器的路徑裏面去,這裏我以安裝在/usr/local/arm/3.4.6目錄裏面的3.4.6版本的交叉編譯器爲例。進入到剛纔編譯安裝好的那兩個包的目錄,裏面應該有bininclude share lib等目錄,在那個目錄裏面,執行如下命令

         sudo cp -pR */usr/local/arm/3.4.6/arm-linux



      這裏有兩個個人認爲需要注意的問題。
      1. cp-p的參數是複製文件的屬性、擁有者、符號鏈接等所有屬性,而-R是遞歸複製,也就是拷貝下面的所有目錄和文件過去。而目標目錄並不是/usr/local/arm/3.4.6,而是其下面的arm-linux這個目錄,需要注意一下。當然3.4.6版本的交叉編譯器是這樣子的,別的版本的交叉編譯器請自行參考。
      2.這兩個庫不僅要安裝到交叉編譯器裏面去,更是建議把它安裝到開發板的根文件系統裏面去,因爲個人的2440的根文件系統是用nfs掛在pc上的,所以只要用cp-pR把所有東西直接拷過去就行了,其它方法做的根文件系統請自行想辦法解決。至少需要把libreadline的庫拷到根文件系統裏面去,不然交叉編譯好的sqlite3會因爲缺少libreadline的庫而拒絕執行。


      在上面的工作都準備好之後,進入以sqlite3-autoconf的目錄裏面去,執行:

         sudo ./configure --host=arm-linux--prefix=/opt/sqlite3


      
      這個configure的參數跟上面的編譯readline和ncurses是一樣的意思,跟上面在pc上configure之後輸出的信息一樣,也要找到有-lncurses和-lreadline且readline爲yes的時候,才能正常啓用上下鍵調出命令記錄的功能。

      然後執行
         sudo make
         sudo make install



      安裝完成之後,再把安裝目錄裏面的所有文件都拷到開發板的根文件系統裏面去,用minicom連接到2440的linux,執行一下sqlite3這個程序,如果你是按上文來做的話,應該不會有問題,而且可以支持上下鍵顯示歷史命令記錄這個實用功能了。

      另外還有一個比較有意思的問題,如果不給交叉編譯器加上ncurses和readline這兩個庫的支持,直接用上面的configure來生成makefile,make之後將會有有個錯誤無法通過編譯,只能手動去改makefile,好像是Makefile有個地方多了個斜槓,把那個斜槓去掉之後就可以編譯通過了。但是把交叉編譯器打上ncurses和readline庫之後,這個錯誤就不會再出現了。







   再下面就是做sqlite3應用開發的編譯上的小問題了。

      在pc上寫完代碼之後編譯的時候使用的選項應該是這樣的:
         gcc -o name name.c -lsqlite3


      最後那個-lsqlite3是引用sqlite3的開發庫。

      而交叉編譯的時候就有些不一樣了:
         arm-linux-gcc -o name name.c -I/opt/sqlite3/include -L /opt/sqlite3/lib -lsqlite3


      -I接的是交叉編譯後安裝的arm版的sqlite3目錄裏面的頭文件,而-L則是包含的庫文件。

      這樣的編譯選項編譯之後,拷到開發板上去,執行,OK!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章