|
我们在这里讨论的是基于Coldfire + uclinux,主芯片为mcf5249,完成sqlite在其uclinux上的移植。Motorola推出的MCF5249是以ColdFire
32位微处理机体系结构为基础,带有96KB的芯片内SRAM,8KB的指令高速缓存、两个独立的UART和16位计时器、以及一个PLL时钟。工作频率为140 MHz时性能可达125 Dhrystone 2.1 MIPS,而功耗仅为每兆赫1.3mW。
本文假设你已经具备正确编译uclinux的kernel的能力,即有能力完成make menuconfig;make dep;make lib_only;make user_only;make romfs;make image;make。而且还能将自己写的类似helloworld程序加到“用户自定义应用程序”中,即你能完成“uClinux-dist/Documentation/Adding-User-Apps-HOWTO”中所描述的“用户程序的订制”。
大多数需要移植sqlite到uclinux的开发者,应该已经具备上面的能力,而只是不清楚如何修改sqlite来完成其在uclinux下的编译。如果你还不能完成上面的要求,那么请先做一定的准备工作,因为本范例所涉及到的内容主要是跟sqlite在uclinux下的移植有关,其他的在这个过程中出现的问题,开发者需要自行处理。
本范例使用的交叉编译工具是m68k-elf-tools-20031003.sh,你可以从http://www.uclinux.org/pub/uClinux/m68k-elf-tools/ 得到这个软件包。 本范例使用的sqlite是sqlite-2.8.15.tar.gz,本文的方法也适合于2.8.x系列的sqlite;可能有部分内容不适用于3.0.x系列的sqlite,因为3.0.x中源代码有较大的变化。 1、 下载并安装交叉编译工具 命令: su wget http://www.uclinux.org/pub/uClinux/m68k-elf-tools/m68k-elf-tools-20031003.sh chmod 777 m68k-elf-tools-20031003.sh ./ m68k-elf-tools-20031003.sh 你需要是root来安装交叉编译工具。 2、 下载sqlite:你可以到http://www.sqlite.org/download.html,下载sqlite-2.8.15.tar.gz软件包; 3、 将下载的软件包解压缩到你的工作目录下,如,我的工作目录是/home/yutao; 命令: $tar zxvf sqlite-2.8.15.tar.gz -C /home/yutao 现在在你的工作目录下,你应该可以看到sqlite目录了。 4、 对sqlite进行修改: 好,现在我们就要对sqlite进行修改,来做移植工作。 在下面的描述中,我们将对以下几个文件进行一定的添加、修改,从而来完成sqlite在uclinux下的编译: sqlite/main.mk 修改 sqlite/Makefile 添加 sqlite/src/os.c 修改 sqlite/src/shell.c 修改
对这几个文件进行修改时,请自己做好这些文件的备份,比如你可以将它们拷贝一份,改名成文件名后面带.bak。这个很重要,可以避免你在修改的过程出现问题而无法还原。
一、修改sqlite/main.mk 1、TCCX 将 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) -lc 即在sqlite$(EXE)上一行加上shell.o,及在其后加上$(LDLIBS)标记。这个是对/src/shell.c的编译方法的修改。在进行链接时,要用到libc库,而且需要你将“-lc”加在“libsqlite.a”的后面,这样才不会链接出错,这一点要特别注意。 4、romfs 将 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项。 5、clean: 将 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文件。我们要移植sqlite到uclinux,那么就要自己写一个合适的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. # CROSS = /usr/local/m68k-elf/bin/ CFLAGS = -Wall -Os -m5307 -DCONFIG_COLDFIRE -fno-builtin -msep-data LDFLAGS = -Os -m5307 -fno-builtin -msep-data -Wl,-elf2flt="-s 65536" -Wl,-move-rodata -lc -s 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下的sqlite的Makefile将不去用到TCL相关的库。 2、 在uclinux下的sqlite的Makefile将不去用到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编译有哪些不同的地方。
其中 CROSS = /usr/local/m68k-elf/bin/ CFLAGS = -Wall -Os -m5307 -DCONFIG_COLDFIRE -fno-builtin -msep-data LDFLAGS = -Os -m5307 -fno-builtin -msep-data -Wl,-elf2flt="-s 65536" -Wl,-move-rodata -lc –s 对应的内容需要特别注意。如果你的Coldfire平台有其他的不同,那么可能还要对其进行修改。
三、修改sqlite/src/os.c 如果你的sqlite包中包括os.c文件那么就对其进行修改,没有os.c文件可能是你的sqlite版本比较新,那么无须修改。 将所有你找到的 if( s!=0 ) 用if( s!=0 && errno != ENOSYS ) 替换。
四、修改sqlite/src/shell.c 1、struct previous_mode_data 结构定义项: 将 int colWidth[100]; 用 int colWidth[20]; 替换。 2、struct 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了,这个过程不会提示错误,并且生成sqlite可执行文件。我生成的文件大小约为300K。 现在你就可以把你生成的sqlite应用程序下载到开发板上运行一下。
/> cd /tmp /tmp > ls -l sqlite -rwxr-xr-x 1 0 0 291200 Jan 01 00:00 sqlite /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就已经在5249上运行起来了,玩玩“select * from”,感觉如何? |