概述
SQLite是符合ANSI-C规范的源码,在使用的时候必须编译成机器码.本文档是各种编译SQLite的方法指南.
本文档并不包含事无巨细的编译细节,这将是比较困难的,因为各个开发环境是不同的. 本文档描述说明了编译SQLite的原则,并提供了典型的编译命令, 开发人员可以根据这些编译命令, 定制自己的编译流程.也就是说, 本文档提供了编译SQLite的一些思想和见解,但不是一个交钥匙的解决方案.
1.合并文件与未合并文件
SQLite工程包含超过100多个C源码文件和脚本文件,这些文件分布在多个目录之中.尽管SQLite是由纯ANSI-C实现的, 但是在编译SQLite之前, 有些C源码文件是由其他辅助C程序或者AWK, SED和TCL脚本生成或者转换而来的, 这将是一个复杂的处理过程.
为了简化这个问题, SQLite提供了一种经过预处理的合并形式的源码文件:sqlite3.c, 该文件是一个单独的ANSI-C源码文件, 包含整个SQLite库执行逻辑.因为是一个单独的文件,所以很容易浏览其C源码程序实现细节,也很容易编译处理. 该合并文件中已经包含了那些辅助程序和脚本生成的代码, 同时,也因为只有一个翻译单元,编译器也能执行一些高级的优化, 有5%-10%的性能提升.因为如上这些原因, 推荐使用合并文件的形式(“sqlite3.c“).
更多关于合并文件信息请参考这里.
当然,直接编译未合并文件肯定是可以的, 但并不推荐.对一些特殊的应用程序,需要修改编译处理,而合并文件不能满足要求的情况下,推荐使用定制的合并文件(参考本文档第四部分). 也就是说, 即使工程需要编译未合并文件,也推荐使用合并文件作为编译的中间步骤.
2.编译CLI(Command-Line Interface)
编译CLI需要3个源代码文件:
- sqlite3.c: 合并形式的源码文件
- sqlite3.h: 头文件,定义了SQLite的C语言接口
- shell.c: CLI程序本身.该C源码文件包含的main()执行入口,和循环处理用户在控制终端的输入参数.
这三个文件被归档在一个tar包里面, 可以从下载页面获得.
为了编译CLI, 只需要将这三个文件放到同一个目录下面进行编译即可.使用MSVC进行编译的命令如下:
cl shell.c sqlite3.c -Fesqlite3.exe
在类unix操作系统上,( 或者在配置了cygwin 或者mingw+msys的Windows操作系统下),典型的编译命令如下:
gcc shell.c sqlite3.c -lpthread -ldl
线程库是为了使SQLite是线程安全的,因为CLI是单线程的,因此可以忽略线程库而编译一个非线程安全模式的SQLite:
gcc -DSQLITE_THREADSAFE=0 shell.c sqlite3.c -ldl
动态链接库是为了支持接口 sqlite3_load_extension()和 load_extension() 装载扩展库及其符号函数.可以在编译时通过定义 SQLITE_OMIT_LOAD_EXTENSION去掉这些特性:
gcc -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION shell.c sqlite3.c
你也可以提供其他的编译选项,比如 -DSQLITE_ENABLE_FTS4 或者-DSQLITE_ENABLE_FTS5来控制全文搜索, -DSQLITE_ENABLE_RTREE用来控制R*Tree搜索引擎扩展, -DSQLITE_ENABLE_JSON1来控制JSON SQL函数, -DSQLITE_ENABLE_DBSTAT_VTAB用来控制虚表, -DSQLITE_ENABLE_EXPLAIN_COMMENTS用来控制 EXPLAIN.在Unix操作系统上,通过定义-DHAVE_USLEEP=1来支持usleep()系统调用.定义 -DHAVE_READLINE并链接-lreadline 和 -lncurses库,来支持命令行编辑.官方文章编译的CLI的优化选项是”-Os”, 你也可以指定其他的编译优化开关.编译一个全功能的CLI的命令如下所示:
gcc -Os -I. -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \
-DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DHAVE_USLEEP -DHAVE_READLINE \
shell.c sqlite3.c -ldl -lreadline -lncurses -o sqlite3
这里的关键点是,编译CLI时,需要编译2个C源码文件.shell.c文件包含执行入口和用户输入处理,合并文件sqlite3.c包含完整的SQLite库执行逻辑.
3.编译TCL接口
TCL接口是SQLite的一个小的模块,其实现逻辑在另一个合并文件中:”tclsqlite3.c“.可以编译该文件为共享库, 使用标准的tclsh或者wish的TCL load命令进行装载,或者生成独立的tclsh而嵌入SQLite之中.可以从下载页中活动该合并文件的归档打包文件.
为了生成TCL可以装载的共享库, 在Linxu操作系统下,使用如下编译命令:
gcc -o libtclsqlite3.so -shared tclsqlite3.c -lpthread -ldl -ltcl
但是,在Mac OS X和Windows操作系统下编译该共享库并不是如此简单,在这两个平台下,最好使用归档tar包中的配置脚本和makefile进行编译.
为了生成可以静态链接进SQLite的独立的tclsh,使用如下编译命令:
gcc -DTCLSH=1 tclsqlite3.c -ltcl -lpthread -ldl -lz -lm
这里的技巧就是-DTCLSH=1,当定义这个编译选项时, TCL接口模块包含main()执行入口,其初始化一个TCL解释器并且进入命令行处理循环.上面的编译命令在Linux和Mac OS X操作系统中都是可用的,但是不同的平台下,可能需要调节链接库选项,以及TCL链接库的版本.
4.生成定制的合并文件
官网下载页提供的SQLite合并文件对于大多数用户都是适用的,但是一些工程可能需要生成定制的合并文件.因为他们需要编译配置选项定制SQLite库的功能.回想之前的说明,SQLite包含辅助程序和脚本生成的C源代码,辅助程序和脚本使用一些列的编译选项来生成C源代码文件,随后这些生成的C源代码被整合到合并文件中.辅助程序和脚本使用的编译选项可能随着SQLite的版本变化而变化, 在SQLite 3.6.20版本中,辅助程序和脚本使用如下编译选项:
- SQLITE_ENABLE_UPDATE_DELETE_LIMIT
- SQLITE_OMIT_ALTERTABLE
- SQLITE_OMIT_ANALYZE
- SQLITE_OMIT_ATTACH
- SQLITE_OMIT_AUTOINCREMENT
- SQLITE_OMIT_CAST
- SQLITE_OMIT_COMPOUND_SELECT
- SQLITE_OMIT_EXPLAIN
- SQLITE_OMIT_FOREIGN_KEY
- SQLITE_OMIT_PRAGMA
- SQLITE_OMIT_REINDEX
- SQLITE_OMIT_SUBQUERY
- SQLITE_OMIT_TEMPDB
- SQLITE_OMIT_TRIGGER
- SQLITE_OMIT_VACUUM
- SQLITE_OMIT_VIEW
- SQLITE_OMIT_VIRTUALTABLE
为了生成定制的合并文件, 首先下载原始的未合并文件到类unix操作系统,请确认下载的是原始文件,而不是经过预处理的源代码文件.可以通过官网的下载页获得原始的未合并的源码文件,和可以从SQLite的配置管理系统获得这些文件.
假设SQLite的源码树存储于目录”sqlite”中,计划生成的合并文件位于并行的目录”bld”中.在SQLite的源码树的根目录下运行配置脚本或者拷贝一个Makefile文件模板来生成一个Makefile文件,然后手工编辑这个Makefile文件,包含需要的编译配置选项.最后,运行如下命令:
make sqlite3.c
或者在安装有MSVC编译环境的Windows操作系统中,运行如下命令:
nmake /f Makefile.msc sqlite3.c
make的执行目标”sqlite3.c”将自动生成合并文件”sqlite3.c“,及其头文件”sqlite3.h“,和包含TCL接口的合并文件”tclsqlite3.c“.然后,根据需要拷贝这些文件到工程目录, 使用上面说明的编译流程编译这些文件.
5.编译Windows DLL
为了在Windows操作系统下,将SQLite编译成DLL,首先获得合适的合并文件sqlite3.c 和 sqlite3.h.这两个文件可以从官网下载,也可以使用之前提到的定制合并文件的方式生成.
使用MSVC编译SQLite DLL的命令如下:
cl sqlite3.c -link -dll -out:sqlite3.dll
上面的命令应该运行在MSVC Native Tools Command Prompt命令终端下.对于安装在你的机器上的MSVC, 可能存在多个版本的命令终端,比如x86和x64下的命令终端,或者跨平台的ARM下的命令终端.根据你需要的DLL,使用适当的命令终端.
如果使用MinGW编译器, 编译命令如下:
gcc -shared sqlite3.c -o sqlite3.dll
需要注意的是, MinGW只能生成32位的DLL,使用MinGW64生成64位的DLL.二者的命令行语法应该是相似的.另一个需要注意的是,新版本的MSVC生成的DLL将不再兼容WinXP及以前的Windows系统.因此为了生成兼容的DLL, 推荐使用MinGW编译器.可以使用MinGW生成32位的DLL, 使用MSVC生成64位的DLL.
在多数情况下,你可以在这些基本命令中使用适当的编译选项,比较常用的编译选项包括:
- Os 优化大小,使生成的DLL尽可能的小.
- O2 优化速度,DLL将变大一些由于函数內联和循环展开.
- -DSQLITE_ENABLE_FTS4 包含全文搜索引擎.
- -DSQLITE_ENABLE_RTREE 包含R-tree扩展.
- -DSQLITE_ENABLE_COLUMN_METADATA 为一些公共系统,比如Ruby-on-Rails,提供一些额外的API支持.
====================================分割线==========================================
原文链接:https://www.sqlite.org/howtocompile.html
注:
SQLite的源码仓库使用Fossil管理的,请参考其使用说明.