如何编译 SQLite
How To Compile SQLite

概述

SQLite 是 ANSI-C 源代码。它必须被编译成机器代码才能使用。本文是对编译 SQLite 的各种方式的指南。

本文不包含编译 SQLite 的分步指南。这将是困难的,因为每个发展情况都不同。相反,本文描述并说明了 SQLite 编译背后的原则。典型的编译命令作为示例提供,希望应用程序开发人员可以使用这些示例作为开发自己的自定义编译过程的指南。换句话说,本文提供的是想法和见解,而不是交钥匙解决方案。

1.合并与单独的源文件

SQLite 由分布在多个目录中的一百多个 C 代码和脚本文件构建而成。SQLite 的实现是纯 ANSI-C,但许多 C 语言源代码文件是在合并到完成的 SQLite 库之前由辅助 C 程序和 AWK、SED 和 TCL 脚本生成或转换的。构建必要的 C 程序以及转换和/或创建 SQLite 的 C 语言源代码是一个复杂的过程。

为了简化问题,SQLite 也可以作为预打包的 合并源代码文件提供:sqlite3.c合并是实现整个 SQLite 库的单个 ANSI-C 代码文件。合并更容易处理。一切都包含在一个代码文件中,因此很容易放入更大的 C 或 C++ 程序的源代码树中。所有代码生成和转换步骤都已执行,因此无需配置和编译辅助 C 程序,也无需运行脚本。而且,由于整个库包含在一个翻译单元中,编译器能够进行更高级的优化,从而将性能提高 5% 到 10%。由于这些原因,合并源文件(“ sqlite3.c") 推荐用于所有应用程序。

建议所有应用都 使用合并。

直接从单个源代码文件构建 SQLite 当然是可能的,但不推荐这样做。对于某些专门的应用程序,可能需要以仅使用从网站下载的预构建合并源文件无法完成的方式修改构建过程。对于这些情况,建议构建并使用自定义合并(如下所述换句话说,即使项目需要从单个源文件开始构建 SQLite,仍然建议使用合并源文件作为中间步骤。

2.编译命令行界面

命令行界面的构建需要三个源文件:

  • sqlite3.c : SQLite 合并源文件
  • sqlite3.h:sqlite3.c 附带的头文件,定义了 SQLite 的 C 语言接口。
  • shell.c:命令行界面程序本身。这是包含main()例程的定义和提示用户输入并将该输入传递到 SQLite 数据库引擎进行处理的循环的 C 源代码文件。

以上所有三个源文件都包含在 下载页面上可用的合并 tarball中。

要构建 CLI,只需将这三个文件放在同一目录中并将它们一起编译即可。使用 MSVC:

cl shell.c sqlite3.c -Fesqlite3.exe

在 unix 系统上(或在使用 cygwin 或 mingw+msys 的 Windows 上),该命令通常如下所示:

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

需要 pthreads 库来使 SQLite 线程安全。但由于 CLI 是单线程的,我们可以指示 SQLite 在非线程安全模式下构建,从而省略 pthreads 库:

gcc -DSQLITE_THREADSAFE=0 shell.c sqlite3.c -ldl -lm -o sqlite3

需要 -ldl 库来支持动态加载、 sqlite3_load_extension()接口和 load_extension() SQL 函数如果不需要这些功能,则可以使用SQLITE_OMIT_LOAD_EXTENSION编译时选项省略它们:

gcc -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION shell.c sqlite3.c -o sqlite3

可能需要提供其他编译时选项,例如 用于全文搜索的 -DSQLITE_ENABLE_FTS4-DSQLITE_ENABLE_FTS5 ,用于R*Tree 搜索引擎扩展的 -DSQLITE_ENABLE_RTREE,用于包含JSON SQL 函数的-DSQLITE_ENABLE_JSON1,或 用于dbstat 虚拟表的 -DSQLITE_ENABLE_DBSTAT_VTAB . 为了在EXPLAIN列表中看到额外的评论,添加 -DSQLITE_ENABLE_EXPLAIN_COMMENTS选项。在 unix 系统上,如果主机支持 usleep() 系统调用,则添加 -DHAVE_USLEEP=1。添加 -DHAVE_READLINE 以及 -lreadline 和 -lncurses 库以获得命令行编辑支持。人们可能还想指定一些编译器优化开关。(可从 SQLite 网站下载的预编译 CLI 使用“-Os”。)这里有无数种可能的变体。编译全功能 shell 的命令可能如下所示:

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 -lm -lreadline -lncurses -o sqlite3

关键点在于:构建 CLI 包括将两个 C 语言文件编译在一起。shell.c文件包含入口点和用户输入循环的定义以及 SQLite 合并sqlite3.c包含SQLite 库的完整实现。

3.编译TCL接口

SQLite 的TCL 接口是一个小模块,添加到常规合并中。结果是一个名为“ tclsqlite3.c ”的新合并源文件。这个单一的源文件是生成共享库所需的全部,共享库可以 使用 TCL 加载命令加载到标准tclshwish中,或者生成内置 SQLite 的独立 tclsh。tcl 合并的副本是作为TEA tarball中的文件包含在下载页面上。

要在 Linux 上为 SQLite 生成 TCL 可加载库,以下命令就足够了:

gcc -o libtclsqlite3.so -shared tclsqlite3.c -lpthread -ldl -ltcl

不幸的是,为 Mac OS X 和 Windows 构建共享库并不是那么简单。对于这些平台,最好使用包含在TEA tarball中的配置脚本和 makefile 。

要生成与 SQLite 静态链接的独立 tclsh,请使用此编译器调用:

gcc -DTCLSH=1 tclsqlite3.c -ltcl -lpthread -ldl -lz -lm

这里的技巧是 -DTCLSH=1 选项。SQLite 的 TCL 接口模块包括一个main()过程,该过程初始化 TCL 解释器并在使用 -DTCLSH=1 编译时进入命令行循环。上面的命令适用于 Linux 和 Mac OS X,但可能需要根据平台和链接的 TCL 版本调整库选项。

4.建立合并

下载页面上提供的 SQLite 合并版本 通常适用于大多数用户。但是,某些项目可能想要或需要构建自己的合并。构建自定义合并的一个常见原因是为了使用某些 编译时选项自定义 SQLite 库。回想一下,SQLite 合并包含大量由辅助程序和脚本生成的 C 代码。许多编译时选项会影响生成的代码,并且必须在合并之前提供给代码生成器。必须传递到代码生成器的编译时选项集可能因 SQLite 的一个版本而异,但在撰写本文时(大约 SQLite 3.6.20,2009-11-04)选项集代码生成器必须知道的信息包括:

要构建自定义合并,首先将原始的单个源文件下载到 unix 或类 unix 开发平台上。确保获取原始源文件而不是“预处理源文件”。可以从下载页面或直接从配置管理系统获取整套原始源文件

假设 SQLite 源代码树存储在名为“sqlite”的目录中。计划在名为(例如)“bld”的并行目录中构建合并。首先通过在 SQLite 源代码树的顶部运行配置脚本,或者通过在源代码树的顶部制作模板 Makefiles 之一的副本来构建适当的 Makefile。然后手动编辑此 Makefile 以包含所需的编译时选项。最后运行:

make sqlite3.c

或者在带有 MSVC 的 Windows 上:

nmake /f Makefile.msc sqlite3.c

“sqlite3.c”make target 会自动构建常规的“ sqlite3.c ”合并源文件,它的头文件“ sqlite3.h ”,以及包含TCL 接口的“ tclsqlite3.c ”合并源文件。之后,可以将所需的文件复制到项目目录中,并根据上述过程进行编译。

5.构建 Windows DLL

要构建用于 Windows 的 SQLite DLL,首先要获取适当的合并源代码文件 sqlite3.c 和 sqlite3.h。这些可以从SQLite 网站下载,也可以从 上面显示的源自定义生成。

使用工作目录中的源代码文件,可以使用 MSVC 通过以下命令生成 DLL:

cl sqlite3.c -link -dll -out:sqlite3.dll

上面的命令应该从 MSVC 本机工具命令提示符运行。如果您的机器上安装了 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 - 在 SQLite 中包含全文搜索引擎代码。

  • -DSQLITE_ENABLE_RTREE - 包括R-Tree 扩展

  • -DSQLITE_ENABLE_COLUMN_METADATA - 这会启用某些常见系统(包括 Ruby-on-Rails)所需的一些额外 API。