ARM-10-SQLite3 库移植笔记

一、为什么要移植 SQLite3

嵌入式 Linux 开发中经常需要在开发板上存储数据,SQLite3 是首选方案:

特点 说明
轻量 库文件只有几百 KB,嵌入式友好
无需配置 不需要单独的数据库服务进程
无需网络 本地文件即数据库,断网也能用
标准 SQL 语法与 MySQL 基本一致,上手快

移植本质:在 ubuntu 上用交叉编译器把 SQLite3 编译成 ARM 平台的动态库,再拷贝到开发板上。


二、移植前提条件

2.1 检查交叉编译工具链

bash 复制代码
arm-linux-gnueabihf-gcc --version

如果没有安装:

bash 复制代码
sudo apt install gcc-arm-linux-gnueabi

2.2 下载 SQLite3 源码

官网下载地址:https://www.sqlite.org/download.html

下载 sqlite-autoconf-xxxxx.tar.gz(autoconf 版本,带 configure 脚本)


三、完整移植步骤

第一步:解压源码

bash 复制代码
tar -xvf sqlite-autoconf-3530000.tar.gz
cd sqlite-autoconf-3530000

第二步:创建编译目录并配置

bash 复制代码
mkdir build_arm
cd build_arm

CC=arm-linux-gnueabihf-gcc \
../configure \
    --host=arm-linux \
    --prefix=$(pwd)/install

参数说明:

参数 说明
CC=arm-linux-gnueabihf-gcc 指定交叉编译器(不同工具链名称不同,按实际修改)
--host=arm-linux 告诉 configure 目标平台是 ARM Linux
--prefix=$(pwd)/install 编译结果安装到当前目录下的 install 子目录

⚠️ 如果工具链名称不同(如 arm-none-linux-gnueabi-gcc),修改 CC= 后面的值即可。

第三步:编译并安装

bash 复制代码
make
make install

编译完成后,目录结构如下:

复制代码
build_arm/install/
├── include/
│   └── sqlite3.h        ← 头文件(编译应用程序时用)
└── lib/
    ├── libsqlite3.so.0.8.6   ← 动态库(拷贝到开发板)
    ├── libsqlite3.so.0       → 软链接
    └── libsqlite3.so         → 软链接

第四步:将动态库拷贝到开发板

前提:开发板与虚拟机网络正常,NFS 已挂载。

bash 复制代码
# 如果开发板 /lib 下已有旧版本,先删除
rm /lib/libsqlite3.so*

# 拷贝新库到开发板(/lib 或 /usr/lib 都可以)
cp libsqlite3.so.0.8.6 /lib/

关键经验:开发板库目录 /lib/usr/lib 都会被动态链接器找到,任选其一即可。

第五步:交叉编译测试程序

bash 复制代码
arm-linux-gnueabihf-gcc test.c -o sqlite_test \
    -I ./sqlite-autoconf-3530000/build_arm/install/include \
    -L ./sqlite-autoconf-3530000/build_arm/install/lib \
    -lsqlite3

编译参数说明:

参数 说明
-I 路径 指定头文件 sqlite3.h 的位置
-L 路径 指定动态库 libsqlite3.so 的位置
-lsqlite3 链接 sqlite3 库

第六步:拷贝到开发板运行

bash 复制代码
cp sqlite_test /home/linux/nfs/imx6/rootfs/home/root/

在开发板上运行:

bash 复制代码
./sqlite_test

四、测试代码

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>

// 查询结果回调函数(每返回一行数据调用一次)
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()
{
    sqlite3 *db;
    char *errMsg = 0;
    int rc;

    // 1. 打开数据库(文件不存在则自动创建)
    rc = sqlite3_open("test.db", &db);
    if (rc)
    {
        fprintf(stderr, "无法打开数据库: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        return 1;
    }
    printf("数据库打开成功\n");

    // 2. 创建表
    const char *sqlCreate =
        "CREATE TABLE IF NOT EXISTS COMPANY("
        "ID   INT  PRIMARY KEY  NOT NULL,"
        "NAME TEXT              NOT NULL,"
        "AGE  INT               NOT NULL);";

    rc = sqlite3_exec(db, sqlCreate, NULL, 0, &errMsg);
    if (rc != SQLITE_OK)
    {
        fprintf(stderr, "创建表失败: %s\n", errMsg);
        sqlite3_free(errMsg);
        sqlite3_close(db);
        return 1;
    }
    printf("表创建成功\n");

    // 3. 插入数据
    const char *sqlInsert =
        "INSERT INTO COMPANY (ID, NAME, AGE) VALUES "
        "(1, 'Alice',   25), "
        "(2, 'Bob',     30), "
        "(3, 'Charlie', 35);";

    rc = sqlite3_exec(db, sqlInsert, NULL, 0, &errMsg);
    if (rc != SQLITE_OK)
    {
        fprintf(stderr, "插入数据失败: %s\n", errMsg);
        sqlite3_free(errMsg);
    }
    else
    {
        printf("数据插入成功\n");
    }

    // 4. 查询数据(结果通过 callback 打印)
    const char *sqlSelect = "SELECT * FROM COMPANY";
    rc = sqlite3_exec(db, sqlSelect, callback, 0, &errMsg);
    if (rc != SQLITE_OK)
    {
        fprintf(stderr, "查询失败: %s\n", errMsg);
        sqlite3_free(errMsg);
    }

    // 5. 关闭数据库
    sqlite3_close(db);
    printf("数据库已关闭\n");
    return 0;
}

预期输出:

复制代码
数据库打开成功
表创建成功
数据插入成功
ID = 1
NAME = Alice
AGE = 25

ID = 2
NAME = Bob
AGE = 30

ID = 3
NAME = Charlie
AGE = 35

数据库已关闭

五、常用 SQLite3 API 速查

函数 说明
sqlite3_open(文件名, &db) 打开/创建数据库文件
sqlite3_close(db) 关闭数据库
sqlite3_exec(db, sql, callback, 0, &errMsg) 执行 SQL 语句
sqlite3_free(errMsg) 释放错误消息内存
sqlite3_errmsg(db) 获取最后一次错误描述

callback 函数参数说明:

c 复制代码
static int callback(void *NotUsed, int argc, char **argv, char **azColName)
//                  用户数据(可不用)  列数    每列的值    每列的列名

六、完整流程总结

复制代码
ubuntu 主机
    │
    ├── 1. 下载 SQLite3 源码
    ├── 2. mkdir build_arm && cd build_arm
    ├── 3. CC=arm-linux-gnueabihf-gcc ../configure --host=arm-linux --prefix=$(pwd)/install
    ├── 4. make && make install
    ├── 5. 交叉编译测试程序
    │       arm-linux-gnueabihf-gcc test.c -o sqlite_test -I .../include -L .../lib -lsqlite3
    │
    │  通过 NFS
    ▼
ARM 开发板
    ├── 6. cp libsqlite3.so.0.8.6 /lib/
    ├── 7. cp sqlite_test /home/root/
    └── 8. ./sqlite_test  → 看到输出即移植成功

⚠️ 关键经验总结:

  • 交叉编译必须同时指定 -I 头文件路径和 -L 库路径
  • 开发板上若有旧版动态库,必须先删除再拷贝新的
  • 开发板库目录 /lib/usr/lib 均可放置动态库
相关推荐
luck_bor36 分钟前
IO流知识点笔记
java·开发语言·笔记
東雪木2 小时前
泛型、反射、注解(Spring 框架核心底层)专属复习笔记
java·windows·笔记·学习·spring
小熊猫程序猿2 小时前
Datawhale Task04 具身智能零基础入门 打卡笔记
笔记
问心无愧05133 小时前
ctf show web入门71
android·前端·笔记
light blue bird3 小时前
支组汇总主子节点工序路径图表
前端·jvm·.net·桌面端·gdi绘图
小陈phd3 小时前
多模态大模型学习笔记(四十七)——跨模态融合策略:早融合、中融合与晚融合核心解析
笔记·学习
cmes_love4 小时前
美股和港股的量化笔记-从下载逐笔tick到合成分钟
笔记·区块链
A_humble_scholar4 小时前
C++11 学习笔记:统一初始化、右值引用与完美转发
c++·笔记·学习
magic_now4 小时前
Modbus RTU 与 TCP 学习笔记
笔记·学习·tcp/ip
轻闲一号机4 小时前
【语音】笔记
前端·笔记·算法