官方編譯方式
SQLite3 源碼提供了非常便捷的編譯腳本,通過執行以下命令可以編譯得到sqlite3.c
、sqlite3.h
、sqlite3ext.h
、shell.c
以及一個可執行程序 sqlite3。所有的代碼都被合併到了sqlite3.c
文件中,根據官網How To Compile SQLite 一文中提到,這樣做的好處是編譯器能夠進行更進一步的優化,從而提升5%~10%的性能。
mkdir bld ;# Build will occur in a sibling directory
cd bld ;# Change to the build directory
../sqlite/configure ;# Run the configure script
make ;# Run the makefile.
make sqlite3.c ;# Build the "amalgamation" source file
make test ;# Run some tests (requires Tcl)
將所有源碼合併得到一個文件的方式儘管帶來了很多便利的地方,但在實際使用時卻有一些問題。由於合併得到的文件太大,通過Clion
打開後會提示:
The file size (8.56MB) exceeds the configured limit(2.56MB). Code insight features are not available.
並且對其編輯或者調試可以感受到IDE明顯的卡頓。儘管這些是外部工具自身的問題,那麼我們能不能將SQLite
退回多文件的編譯方式緩解由於工具性能不足帶來的問題呢?
改造項目
基於 3.39.4 版本更改
- 新建一個空項目
- 將 sqlite3 源碼底下 src 目錄中所有文件拷貝到新建的項目中
- 將 sqlite3 源碼底下 tool 目錄中的
lemon.c
和lempar.c
拷貝過來 - 執行
gcc -o lemon lemon.c
生成lemon程序 - 運行
./lemon parse.y
生成parse.c
和parse.h
文件 - 在 sqlite3 源碼執行
./configure
和make
命令 - 將編譯得到的
tscr
底下的opencodes.c
、opencodec.h
和sqlite.h
拷貝過來 - 刪除 test* 等一系列測試文件,以及
tclsqlite.c
文件 - 創建CMakeLists.txt如下
cmake_minimum_required(VERSION 3.21)
project(SqliteBuild C)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DSQLITE_CORE=1")
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
file(GLOB sources "*.c")
file(GLOB headers "*.h")
list(REMOVE_ITEM sources ${CMAKE_CURRENT_SOURCE_DIR}/lempar.c)
list(REMOVE_ITEM sources ${CMAKE_CURRENT_SOURCE_DIR}/lemon.c)
add_executable(SqliteBuild ${sources} ${headers} SqliteMain.c)
SqliteMain.c 爲自己調試添加的入口文件,可自行更換
#include <stdio.h>
#include "sqlite3.h"
/* print a record from table outputed by sql statement */
static int callback(void* NotUsed, int argc, char** argv, char** azColName) {
int i;
for (i = 0; i < argc; i++) {
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main(int argc, char** argv) {
sqlite3* db;
char* zErrMsg = 0;
int rc;
if (argc != 3) {
fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);
return(1);
}
rc = sqlite3_open(argv[1], &db); /* open database */
if (rc) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return(1);
}
rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg); /* execute SQL statement */
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
sqlite3_close(db); /* close database */
return 0;
}