uclinux下的sqlite嵌入式数据库移植全攻略 [原创]

转载时请注明出处和作者联系方式:http://blog.csdn.net/mimepp

uclinux下的sqlite嵌入式数据库移植全攻略 [原创]

 

作者:余涛(yut616_at_sohu.com

 

关键字: sqliteuclinuxARM,嵌入式数据库

 

我们在这里讨论的是比较流行的嵌入式开发组合ARM+uclinux,即目标开发板为三星S3C4510,完成sqlite在其uclinux上的移植。

 

本文假设你已经具备正确编译uclinuxkernel的能力,即有能力完成make menuconfigmake depmake lib_onlymake user_onlymake romfsmake imagemake。而且还能将自己写的类似helloworld程序加到“用户自定义应用程序”中,即你能完成“uClinux-dist/Documentation/Adding-User-Apps-HOWTO”中所描述的“用户程序的订制”。

 

大多数需要移植sqliteuclinux的开发者,应该已经具备上面的能力,而只是不清楚如何修改sqlite来完成其在uclinux下的编译。如果你还不能完成上面的要求,那么请先做一定的准备工作,因为本范例所涉及到的内容主要是跟sqliteuclinux下的移植有关,其他的在这个过程中出现的问题,开发者需要自行处理。

 

本范例使用的uclinuxuClinux-dist-20030522.tar.gz,你可以从http://www.uclinux.org得到适合你的软件包。

交叉编译工具是arm-elf-tools-20030314.sh,你也可以在http://www.uclinux.org找到它。

本范例使用的sqlitesqlite-2.8.15.tar.gz,本文的方法也适合于2.8.x系列的sqlite;可能有部分内容不适用于3.0.x系列的sqlite,因为3.0.x中源代码有较大的变化。

1、    下载sqlite:你可以到http://www.sqlite.org/download.html,下载sqlite-2.8.15.tar.gz软件包;

2、    将下载的软件包解压缩到uClinux-dist/user目录下;

命令:

$tar zxvf sqlite-2.8.15.tar.gz -C uClinux-dist/user/

现在在uclinuxuser目录下,你应该可以看到sqlite目录了。解压缩到这个user目录主要是要将sqlite编译成一个普通的用户应用程序。

3、    用户应用程序的有关设置:

uClinux-dist/Documentation/Adding-User-Apps-HOWTO文档中说提到的,来添加sqlite作为一个用户应用程序,将其做成一个shell,这样就类似于uclinux自己的ps命令。

编辑文件

uClinux-dist/user/Makefile

uClinux-dist/config/Configure.help

uClinux-dist/config/config.in

我是在这些文件里查找“cpu”有关的项,然后在它的下面,加上自己的sqlite项,这个过程并不复杂。

通过上面的修改后,你现在就可以运行uclinuxmake menuconfig

选中“CustomizeVendor/User Settings”,再选中“Miscellaneous Applications”,可以看到它现在出现了一个新的“sqlite (NEW)”,这个就是我们刚添加进去的sqlite项。

 

在稍后的make romfs中,uclinux会将你的sqlite编译进来,做成romfs的一部分,因为你在uClinux-dist/user/Makefile中已经加上要编译sqlite项了。这样在移植后的uclinux/bin中将会有sqlite命令可以让你来执行。

 

好,现在我们就要对sqlite进行修改,来做移植工作。

在下面的描述中,我们将对以下几个文件进行一定的添加、修改,从而来完成sqliteuclinux下的编译:

sqlite/main.mk        修改

sqlite/Makefile       添加

sqlite/src/os.c        修改

sqlite/src/shell.c       修改

 

对这几个文件进行修改时,请自己做好这些文件的备份,比如你可以将它们拷贝一份,改名成文件名后面带.bak。这个很重要,可以避免你在修改的过程出现问题而无法还原。

 

一、修改sqlite/main.mk

1TCCX

TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src

修改为

TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src $(CFLAGS)

即加上$(CFLAGS)标记。

2 LIBOBJ

找到 # Object files for the SQLite library.

将其中的tclsqlite.o去掉。即去掉tcl有关的东西。

如果没有tclsqlite.o,那么不用处理它。

3 sqlite$(EXE)

找到类似sqlite$(EXE)的一句

sqlite$(EXE):       $(TOP)/src/shell.c libsqlite.a sqlite.h

       $(TCCX) $(READLINE_FLAGS) -o sqlite$(EXE) $(TOP)/src/shell.c /

              libsqlite.a $(LIBREADLINE) $(THREADLIB)

替换为

shell.o:       $(TOP)/src/shell.c sqlite.h

       $(TCCX) $(READLINE_FLAGS) -c $(TOP)/src/shell.c

 

sqlite$(EXE):       shell.o libsqlite.a

       $(TCC) $(LDFLAGS) -o $@ shell.o /

              libsqlite.a $(LIBREADLINE) $(THREADLIB) $(LDLIBS)

即在sqlite$(EXE)上一行加上shell.o,及在其后加上$(LDLIBS)标记。这个是对/src/shell.c的编译方法的修改。

4romfs

install:     sqlite libsqlite.a sqlite.h

       mv sqlite /usr/bin

       mv libsqlite.a /usr/lib

       mv sqlite.h /usr/include

替换为

romfs:     sqlite

       $(ROMFSINST) /bin/sqlite

即去掉make install项,加上make romfs项。 这个很重要,这将在romfs/bin目录下生成sqlite

5clean:

clean:     

       rm -f *.o sqlite libsqlite.a sqlite.h opcodes.*

       rm -f lemon lempar.c parse.* sqlite*.tar.gz

rm -f $(PUBLISH)

      rm -f *.da *.bb *.bbg gmon.out

      rm -rf tsrc

替换为

clean:     

       rm -f *.o sqlite libsqlite.a sqlite.h opcodes.* sqlite.gdb

      rm -f $(PUBLISH)

      rm -f *.da *.bb *.bbg gmon.out

      rm -rf tsrc

 

distclean: clean

       rm -f lemon lempar.c parse.* sqlite*.tar.gz

       rm -f config.h

即增加make distclean项。

 

二、在sqlite下增加Makefile文件

sqlite目录下应该没有Makefile文件,而只是有一个sqlite/Makefile.linux-gcc文件。我们要移植sqliteuclinux,那么就要自己写一个合适的Makefile

内容如下:

===========Makefile内容开始===========

#!/usr/make

#

# Makefile for SQLITE

#

# This is a template makefile for SQLite.  Most people prefer to

# use the autoconf generated "configure" script to generate the

# makefile automatically.  But that does not work for everybody

# and in every situation.  If you are having problems with the

# "configure" script, you might want to try this makefile as an

# alternative.  Create a copy of this file, edit the parameters

# below and type "make".

#

 

#### The toplevel directory of the source tree.  This is the directory

#    that contains this "Makefile.in" and the "configure.in" script.

#

TOP = .

 

#### C Compiler and options for use in building executables that

#    will run on the platform that is doing the build.

#

BCC = gcc -g -O2

#BCC = /opt/ancic/bin/c89 -0

 

#### If the target operating system supports the "usleep()" system

#    call, then define the HAVE_USLEEP macro for all C modules.

#

#USLEEP =

USLEEP = -DHAVE_USLEEP=1

 

#### If you want the SQLite library to be safe for use within a

#    multi-threaded program, then define the following macro

#    appropriately:

#

#THREADSAFE = -DTHREADSAFE=1

THREADSAFE = -DTHREADSAFE=0

 

#### Specify any extra linker options needed to make the library

#    thread safe

#

#THREADLIB = -lpthread

THREADLIB =

 

#### Leave MEMORY_DEBUG undefined for maximum speed.  Use MEMORY_DEBUG=1

#    to check for memory leaks.  Use MEMORY_DEBUG=2 to print a log of all

#    malloc()s and free()s in order to track down memory leaks.

#   

#    SQLite uses some expensive assert() statements in the inner loop.

#    You can make the library go almost twice as fast if you compile

#    with -DNDEBUG=1

#

#OPTS = -DMEMORY_DEBUG=2

#OPTS = -DMEMORY_DEBUG=1

#OPTS = -DNDEBUG=1

OPTS = -DMEMORY_DEBUG=1

 

#### The suffix to add to executable files.  ".exe" for windows.

#    Nothing for unix.

#

#EXE = .exe

EXE =

 

#### C Compile and options for use in building executables that

#    will run on the target platform.  This is usually the same

#    as BCC, unless you are cross-compiling.

#

TCC = $(CROSS)gcc

FLTFLAGS += -s 12000

#TCC = gcc -g -O0 -Wall

#TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage

#TCC = /opt/mingw/bin/i386-mingw32-gcc -O6

#TCC = /opt/ansic/bin/c89 -O +z -Wl,-a,archive

 

#### Tools used to build a static library.

#

AR = $(CROSS)ar cr

#AR = /opt/mingw/bin/i386-mingw32-ar cr

RANLIB = $(CROSS)ranlib

#RANLIB = /opt/mingw/bin/i386-mingw32-ranlib

 

#### Extra compiler options needed for programs that use the TCL library.

#

#TCL_FLAGS =

#TCL_FLAGS = -DSTATIC_BUILD=1

#TCL_FLAGS = -I/home/drh/tcltk/8.4linux

#TCL_FLAGS = -I/home/drh/tcltk/8.4win -DSTATIC_BUILD=1

#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux

 

#### Linker options needed to link against the TCL library.

#

#LIBTCL = -ltcl -lm -ldl

#LIBTCL = /home/drh/tcltk/8.4linux/libtcl8.4g.a -lm -ldl

#LIBTCL = /home/drh/tcltk/8.4win/libtcl84s.a -lmsvcrt

#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc

 

#### Compiler options needed for programs that use the readline() library.

#

READLINE_FLAGS =

#READLINE_FLAGS = -DHAVE_READLINE=1 -I/usr/include/readline

 

#### Linker options needed by programs using readline() must link against.

#

#LIBREADLINE =

#LIBREADLINE = -static -lreadline -ltermcap

 

#### Should the database engine assume text is coded as UTF-8 or iso8859?

#

# ENCODING  = UTF8

ENCODING = ISO8859

 

# You should not have to change anything below this line

###############################################################################

include $(TOP)/main.mk

===========Makefile内容结束===========

注:

1、  uclinux下的sqliteMakefile将不去用到TCL相关的库。

2、  uclinux下的sqliteMakefile将不去用到readline()

 

sqlite/README中有关于Makefile的一段描述:

The configure script uses autoconf 2.50 and libtool.  If the configure script does not work out for you, there is a generic makefile named "Makefile.linux-gcc" in the top directory of the source tree that you can copy and edit to suite your needs.  Comments on the generic makefile show what changes are needed.

你可以用sqlite/Makefile.linux-gcc作为蓝本来修改适合你自己的Makefile

你如果有兴趣的话,可以把上面的Makefile的内容和sqlite/Makefile.linux-gcc内容diff对比一下,看看uclinux下的sqlite编译有哪些不同的地方。

 

三、修改sqlite/src/os.c

如果你的sqlite包中包括os.c文件那么就对其进行修改,没有os.c文件可能是你的sqlite版本比较新,那么无须修改。

将所有你找到的

if( s!=0 )

if( s!=0 && errno != ENOSYS )

替换。

 

四、修改sqlite/src/shell.c

1struct previous_mode_data 结构定义项:

  int colWidth[100];

  int colWidth[20];

替换。

2struct callback_data 结构定义项:

 

int colWidth[100];

int actualWidth[100];

char outfile[FILENAME_MAX];

 

int colWidth[20];

int actualWidth[20];

char *outfilep;

对应替换。

 

再在结构下面增加:

#ifndef FILENAME_MAX

#define FILENAME_MAX     4095

#endif

char outfilename[FILENAME_MAX]; /* Filename for *out */

struct callback_data

{

...

};

#ifndef FILENAME_MAX

#define FILENAME_MAX     4095

#endif

char outfilename[FILENAME_MAX]; /* Filename for *out */

 

3、函数do_meta_command(...)中:

找到类似这样的一句

sqlite_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);

在它的前面有一句

memcpy(&data, p, sizeof(data));

现在在memcpy下面增加一行

data.cnt = 0;

即将结构中cnt的值赋为0

现在代码会被修改成类似:

open_db(p);

memcpy(&data, p, sizeof(data));

data.cnt = 0;

 

再继续

找到类似这样的一句

strcmp(azArg[1],"stdout")==0

在它的下面的括号中

      strcpy(p->outfile,"stdout");

      p->outfilep = "stdout";

来替换。

 

再在它下面的5-6行处

         strcpy(p->outfile,azArg[1]);

         strcpy(outfilename,azArg[1]);

               p->outfilep = outfilename;

替换。

 

再继续

找到类似这样的一句

fprintf(p->out,"%9.9s: %s/n","output",

 

fprintf(p->out,"%9.9s: %s/n","output", strlen(p->outfile) ? p->outfile : "stdout");

fprintf(p->out,"%9.9s: %s/n","output", p->outfilep && strlen(p->outfilep) ? p->outfilep : "stdout");

替换。

 

完成修改。

 

上面的所有的对sqlite的修改完成后,你就可以make depmake lib_onlymake user_onlymake romfsmake image了。

如果你对sqlite的修改,在make user_only过程中出现错误的话,你可以忽略make depmake lib_only命令,直接再次进行make user_onlymake romfsmake image;就可以了,而不用重复make depmake lib_only

make image会帮你生成romfs文件系统。现在在uClinux-dist/images下面就有编译生成的romfs文件系统了。这个就是我们需要的包含有sqliteromfs了。

在上面的过程中,你可以不用在“make image”后再去“make”生成kernel内核,因为你只需要生成romfs就可以了,它里面已经有sqlite了。

现在你就可以把你生成的含有sqlite应用程序的romfs下载到开发板上运行一下。

Welcome to

          ____ _  _

         /  __| ||_|                

    _   _| |  | | _ ____  _   _  _  _

   | | | | |  | || |  _ /| | | |/ // /

   | |_| | |__| || | | | | |_| |/    /

   |  ___/____|_||_|_| |_|/____|/_//_/

   | |

   |_|

 

GDB/ARMulator support by <[email protected]>

For further information check:

http://www.uclinux.org/

 

Command: /bin/ifconfig eth0 up 10.0.0.2

Execution Finished, Exiting

init: Booting to single user mode

 

Sash command shell (version 1.1.1)

/> cd bin

/bin> ls -l sqlite

-rwxr-xr-x  1 0        0          327072  Jan 01 00:00 sqlite

/bin >cd /tmp

/tmp>sqlite test.sqlite

sqlite> create table my(name varchar(80), num smallint);

sqlite> insert into my values('yutao', 100);

sqlite> insert into my values('uclinux', 99);

sqlite> select * from my;

yutao|100

uclinux|99

sqlite> .tables

my

sqlite> .schema

create table my(name varchar(80), num smallint);

sqlite> .q

/tmp>ls –l test.sqlite

 

你要保证你的/tmp是可写的目录。

 

好,现在你的sqlite就已经在uclinux运行起来了,感觉如何呀,在uclinux也可以玩玩“select * from”,感觉很爽吧。

 

 

作者联系方式:YU TAO <yut616 at sohu dot com>

把本人以前写的文章在blog里贴出来,有需要交流的可以在blog里留言。

更新时间:2007-3-15

你可能感兴趣的:(数据库,sqlite,嵌入式,compiler,makefile,linker)