Small. Fast. Reliable.
Choose any three.
如何编译SQLite
How To Compile SQLite

概述

SQLite是ANSI-C源代码。必须先将其编译为机器代码,然后才能使用。本文是有关各种SQLite编译方法的指南。

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

1.合并与单个源文件

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

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

建议在所有应用程序中 使用合并

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

2.编译命令行界面

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

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

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

cl shell.c sqlite3.c -Fesqlite3.exe

在UNIX系统上(或在使用cygwin或mingw + msys的Windows上),命令通常看起来像这样:

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

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

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

需要-ldl库来支持动态加载, sqlite3_load_extension()接口和 load_extension()SQL函数。如果不需要这些功能,则可以使用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用于dbstat。为了在EXPLAIN列表中查看其他评论,请添加 -DSQLITE_ENABLE_EXPLAIN_COMMENTS选项。在Unix系统上,如果主机支持usleep()系统调用,请添加-DHAVE_USLEEP = 1。添加-DHAVE_READLINE以及-lreadline和-inccurses库以获得命令行编辑支持。可能还需要指定一些编译器优化开关。(可从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 -readline -incurses -o sqlite3

关键是:构建CLI包括将两个C语言文件编译在一起。该shell.c文件包含入口点的定义和用户输入回路和SQLite的融合sqlite3.c包含了SQLite库的完整实现。

3.编译TCL接口

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

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

gcc -o libtclsqlite3.so-共享的tclsqlite3.c -lpthread -ldl -ltcl

不幸的是,为Mac OS X和Windows构建共享库并不是那么简单。对于那些平台,最好使用TEA tarball随附的configure脚本和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源树顶部的configure脚本,或通过在源树顶部复制其中一个模板Makefile来构建适当的Makefile。然后手动编辑此Makefile以包括所需的编译时选项。最后运行:

制作sqlite3.c

或在具有MSVC的Windows上:

nmake / f Makefile.msc sqlite3.c

“ sqlite3.c”生成目标将自动构造常规的“ sqlite3.c ”合并源文件,其头文件“ sqlite3.h ”和包含TCL接口的“ tclsqlite3.c ”合并源文件。然后,可以将所需的文件复制到项目目录中,并根据上述步骤进行编译。

5.构建Windows DLL

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

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

cl sqlite3.c-链接-dll -out:sqlite3.dll

上面的命令应从MSVC本机工具命令提示符处运行。如果您的计算机上安装了MSVC,则可能有此命令提示符的多个版本,用于x86和x64的本机版本,还可能用于交叉编译到ARM。根据所需的DLL使用适当的命令提示符。

如果使用MinGW编译器,则命令行为:

gcc-共享的sqlite3.c -o sqlite3.dll

请注意,MinGW仅生成32位DLL。有一个单独的MinGW64项目,可用于生成64位DLL。大概命令行语法是相似的。还要注意,最新版本的MSVC生成的DLL在WinXP和Windows的早期版本上将无法使用。因此,为最大程度地兼容您生成的DLL,建议使用MinGW。一个好的经验法则是使用MinGW生成32位DLL,并使用MSVC生成64位DLL。

在大多数情况下,您将需要在上面的基本命令中添加 适合您的应用程序的编译时选项。常用的编译时选项包括: