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、整个数据库存储在一个单一的文件里,备份恢复都非常容易。
缺点:
对于并发的支持不好,其对于数据库的读写是完全加锁的。
sqlite3官网提供了两种源代码的方式,一种叫作amalgamation,另外一种叫作autoconf,这两种源码包有点不一样。amalgamation的源码包是把sqlite的所有源文件都集成到了sqlite3.c这一个文件里面去,而且这个包只适合单独编译出一个shell版本的sqlite3,它并不会编译出linux里面常见的开发库(也就是基于sqlite3编写的软件必须要依赖的sqlite3库)。而autoconf版就很明显了,是使用linux上面常见的./configure make make install方式来编译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不会支持按上下键调出历史命令记录这个实用功能。
PC端编译环境的安装:
此处使用的为SQLite版本为sqlite-autoconf-3080100.tar.gz。
将此压缩包拷贝到 /home/lzc目录下,在终端中进入此目录,并解压压缩包:
[root@localhost~]# ./configure –prefix=路径 --disable-tcl
配置结束后进行编译并且将所生成的文件安装:
[root@localhost~]#make
[root@localhost~]#makeinstall
Makeinstall 安装以后会生成以下文件,系统默认的目录为 /路径:
lib: libsqlite3.a libsqlite3.so libsqlite3.so.0 libsqlite3.so.0.8.
目录文件 |
说明 |
/usr/bin/sqlite3 |
sqlite3命令文件 |
/usr/include/sqlite3.h |
sqlite头文件,定义了API接口 |
/usr/lib/libsqlite3.so.0。8.6 |
sqlite动态库libsqlite3.so libsqlite3.so.0是软链接 |
/usr/lib/libsqlite3.a |
sqlite静态库 |
/usr/lib/libsqlite3.la
.so 为共享库,是shared object,用于动态连接的,和dll差不多
.a为静态库,是好多个.o合在一起,用于静态连接
.la为libtool自动生成的一些共享库,vi编辑查看,主要记录了一些配置信息。可以用如下命令查看 *.la文件的格式 $file *.la
ln -s是用来创建软链接,也就相当于windows中的快捷方式,在当前目录中创建上一级目录中的文件 ttt的命名为ttt2软链接的命令是ln -s ../ttt ttt2,如果原文件也就是ttt文件删除的话,ttt2也变成了 空文件。
ln -d是用来创建硬链接,也就相当于windows中文件的副本,当原文件删除的时候,并不影响“副本 ”的内容。
GCC编译使用动态链接库和静态链接库
http://blog.csdn.net/orzlzro/article/details/6460058
SQLite3 编译及交叉编译
下面是交叉编译sqlite所有相关文件的问题。
由于是交叉编译,所以交叉编译环境一定要有并且好使。分别交叉编译这两个包:
./configure --host=arm-linux --prefix=/usr/local/CC=arm-linux-gcc--disable-tcl
make
make install
--host接的是目标平台的名称,写交叉编译器名就可以。这个是必须的。--prefix接的是编译好之后安装到的路径,CC是make时使用的编译器 默认是GCC。这个也是必须的。最后一个参数可有可无,就是支持TCL。
编译安装完之后,把/usr/local/里与sqlite相关进行打包,执行如下命令
cp -pR * /usr/local/ /自己找个目录
tar -cvf ./local.tar.gz local/
说明:
1. cp -p的参数是复制文件的属性、拥有者、符号链接等所有属性,而-R是递归复制,就是拷贝下面的所有目录和文件过去。
2.如果是直接挂上去的只要用cp -pR把所有东西直接拷过去就行了。现有环境使用ftp或是tftp传过去解压(# tar -xvf local.tar.gz)之后放到与在x86平参安装相关地方就可以。
3.libreadline库的编译与sqlite相同。
卸载设备上的sqlite直接删除文件就可以
# rm_sqlite.sh
rm -rf local/include/sqlite3ext.h
rm -rf local/include/sqlite3.h
rm -rf local/bin/sqlite3
rm -rf local/lib/libsqlite3.so.0.8.6
rm -rf local/lib/libsqlite3.a
rm -rf local/lib/libsqlite3.so.0
rm -rf local/lib/libsqlite3.so
rm -rf local/lib/pkgconfig/
rm -rf local/lib/libsqlite3.la
#
测试代码:
#include
#include
#include
#include "/usr/local/include/sqlite3.h" //包含SQLite的头文件
char sql[512]={0};
int main( void )
{
sqlite3 *db=NULL;
char *zErrMsg = 0;
int rc;
int nrow = 0, ncolumn =0; //保存获取信息的行数和列数
int i, j;
char **azResult; //二维数组存放结果
system("clear");
rc =sqlite3_open("/home/liuzc.db", &db);
if( rc ) //如果出错,给出提示信息并退出程序
{
fprintf(stderr, "Can'topen database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}
else
{
printf("opened orcreate a sqlite3 database /home/liuzc.db successfully!\n");
}
strcpy(sql ,"CREATE TABLETestTable(ID INTEGER PRIMARY KEY,Name TEXT,Amount INTEGER);");
sqlite3_exec( db , sql , 0 , 0, &zErrMsg ); //创建一个表
strcpy(sql ,"INSERT INTOTestTable VALUES( 001 ,'nokia', 39);" );
sqlite3_exec( db , sql , 0 , 0, &zErrMsg );
strcpy(sql ,"INSERT INTOTestTable VALUES( 002 , 'iphone' , 26);");
sqlite3_exec( db , sql , 0 , 0, &zErrMsg );
strcpy(sql ,"INSERT INTOTestTable VALUES( 003 , 'palm' , 11);" );
sqlite3_exec( db , sql , 0 , 0, &zErrMsg );
printf("\nInserts 3records success\nselect table info\n\n");
strcpy(sql ,"SELECTID,name,Amount FROM TestTable;");
sqlite3_get_table( db , sql ,&azResult , &nrow , &ncolumn , &zErrMsg );
for(i = 0; i < (nrow + 1);i++)
{
for(j = 0; j < ncolumn;j++)
{
printf("%s\t\t",azResult[nrow* i + j]); //打印查询信息
}
printf("\n");
}
printf("\nIf you need todelete a table liuzc.db can directly execute the command: rm -rf/home/liuzc.db");
sqlite3_close(db); //关闭数据库
return 0;
}
//编译命令如下:
//tile-gcc -o sqlite_text sqlite_text.c -lsqlite3 -L /usr/local/lib
两个错误信息:
SQLite header and source version mismatch
2011-11-01 00:52:41 c7c6050ef060877ebe77b41d959e9df13f8c9b5e
2012-10-04 19:37:12091570e46d04e84b67228e0bdbcd6e1fb60c6bdb
这个错误一般不会出现。在安装完之后,把local文件移到别的地方时一定会出现这个问题,有那时间还不如重新安装一个。
执行完这三条命令之后,sqlite3就已经被默认安装到了/usr/local/bin里面去了,但是还没完呢,如果在终端直接执行一下sqlite3,多半会报错,类似于这样:
这个问题是因为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库,按上下方向键就没有显示历史命令记录这个实用功能),同时其开发库也已经安装到系统里了。
error while loading sharedlibraries: xxx.so.x
一般我们在Linux下执行某些外部程序的时候可能会提示找不到共享库的错误,比如:
tmux: error while loading shared libraries:libevent-1.4.so.2: cannot open shared object file: No such file or directory
原因一般有两个:
一、是操作系统里确实没有包含该共享库(lib*.so.*文件)或者共享库版本不对,遇到这种情况那就去网上下载并安装上即可.
二、是已经安装了该共享库,但执行需要调用该共享库的程序的时候,程序按照默认共享库路径找不到该共享库文件.
所以安装共享库后要注意共享库路径设置问题,如下:
1)如果共享库文件安装到了/lib或/usr/lib目录下,那么需执行一下ldconfig命令
ldconfig命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如lib*.so*),进而创建出动态装入程序(ld.so)所需的连接和缓存文件.缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表.
2)如果共享库文件安装到了/usr/local/lib(很多开源的共享库都会安装到该目录下)或其它"非/lib或/usr/lib"目录下,那么在执行ldconfig命令前,还要把新共享库目录加入到共享库配置文件/etc/ld.so.conf中,如下:
#cat/etc/ld.so.conf
include ld.so.conf.d/*.conf
#echo"/usr/local/lib" >> /etc/ld.so.conf
# ldconfig
3)如果共享库文件安装到了其它"非/lib或/usr/lib"目录下,但是又不想在/etc/ld.so.conf中加路径(或者是没有权限加路径).那可以export一个全局变量LD_LIBRARY_PATH,然后运行程序的时候就会去这个目录中找共享库.
LD_LIBRARY_PATH的意思是告诉loader在哪些目录中可以找到共享库.可以设置多个搜索目录,这些目录之间用冒号分隔开.比如安装了一个mysql到/usr/local/mysql目录下,其中有一大堆库文件在/usr/local/mysql/lib下面,则可以在.bashrc或.bash_profile或shell里加入以下语句即可:
exportLD_LIBRARY_PATH=/usr/local/mysql/lib:$LD_LIBRARY_PATH
一般来讲这只是一种临时的解决方案,在没有权限或临时需要的时候使用.