交叉编译 sqlite3 与 SQLiteCpp(RV1126 / armhf)
交叉编译 sqlite3 与 SQLiteCpp(RV1126 / armhf)工具链前缀:arm-rockchip1240-linux-gnueabihf-验证统一使用交叉版工具:arm-rockchip1240-linux-gnueabihf-readelf(不要用主机自带的readelf,虽然多数字段也能读,但统一用交叉版更稳妥、避免混淆)。一、交叉编译 sqlite3sqlite-autoconf 是 autoconf/autosetup 工程,用configuremake。cd~/workspace/3rdparty-keep-32/sqlite-autoconf-3530200mkdir-pbuild-rv1126bcdbuild-rv1126b../configure\--hostarm-rockchip1240-linux-gnueabihf\--prefix/home/guopf/workspace/3rdparty-keep-32/install/sqlite3_clean\CCarm-rockchip1240-linux-gnueabihf-gcc\LDFLAGS-Wl,-soname,libsqlite3.so.0makeLDFLAGS.rpathinstall验证(完整路径,任意目录均可执行):arm-rockchip1240-linux-gnueabihf-readelf-d\/home/guopf/workspace/3rdparty-keep-32/install/sqlite3_clean/lib/libsqlite3.so.0\|grep-ESONAME|RPATH|RUNPATH|NEEDED期望:有SONAME libsqlite3.so.0,没有 RPATH,NEEDED只有libm.so.6、libc.so.6。注意点 / 避坑一定要显式加-Wl,-soname,libsqlite3.so.0。交叉环境下默认可能不会把 SONAME 烧进二进制。库没有 SONAME 会引发连锁问题:依赖它的库会把“链接时的路径”当成依赖名(见 SQLiteCpp 部分)。SONAME 取值规范:lib名.so.主版本号,即libsqlite3.so.0。只到主版本号,不要用裸libsqlite3.so,也不要用完整的libsqlite3.so.3.53.2(否则每次小版本升级都得重链所有使用者)。-Wl,-soname后面必须跟名字,单独写-Wl,-soname无效。去掉写死的主机 RPATH。sqlite 的 configure 会自动往链接命令塞-Wl,-rpath,prefix/lib,它存在生成的Makefile的变量LDFLAGS.rpath里。用命令行覆盖为空即可:make LDFLAGS.rpath install。主机 RPATH 烧进库后,部署到板子上指向一个不存在的主机路径,容易引起加载混乱。--prefix与构建分离。用独立的build-rv1126b目录构建,--prefix指向干净的安装目录,便于管理。二、交叉编译 SQLiteCppSQLiteCpp 是 CMake 工程,依赖 sqlite3。它需要一个自己写的toolchain 文件来指定交叉工具链。先准备 toolchain 文件:rv1126b-toolchain.cmake这个文件不是库自带的,是自己写的,放在 SQLiteCpp 源码目录下。内容如下:set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) set(TOOLCHAIN_PATH /home/guopf/workspace/tool/arm-rockchip1240-linux-gnueabihf/bin) set(CMAKE_C_COMPILER ${TOOLCHAIN_PATH}/arm-rockchip1240-linux-gnueabihf-gcc) set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PATH}/arm-rockchip1240-linux-gnueabihf-g) # 很关键避免找错x86库 set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # 指向 sqlite3 的安装目录供 find_package(SQLite3) 搜索 set(CMAKE_PREFIX_PATH /home/guopf/workspace/3rdparty-keep-32/install/sqlite3_clean )说明:CMAKE_SYSTEM_NAME/PROCESSOR告诉 CMake 这是交叉编译。指定交叉gcc/g。CMAKE_FIND_ROOT_PATH_MODE_*防止find_package误用主机 x86 的库/头。CMAKE_PREFIX_PATH指向 sqlite3 的安装目录,供find_package(SQLite3)查找。配置 编译 安装cd~/workspace/3rdparty-keep-32/SQLiteCppmkdir-pbuild-rv1126bcdbuild-rv1126b cmake\-DCMAKE_TOOLCHAIN_FILE/home/guopf/workspace/3rdparty-keep-32/SQLiteCpp/rv1126b-toolchain.cmake\-DCMAKE_BUILD_TYPERelWithDebInfo\-DBUILD_SHARED_LIBSON\-DSQLITECPP_INTERNAL_SQLITEOFF\-DSQLITECPP_FIND_SQLITEON\-DSQLITECPP_BUILD_TESTSOFF-DSQLITECPP_BUILD_EXAMPLESOFF\-DSQLITECPP_RUN_CPPLINTOFF-DSQLITECPP_USE_ASANOFF\-DSQLite3_INCLUDE_DIR/home/guopf/workspace/3rdparty-keep-32/install/sqlite3_clean/include\-DSQLite3_LIBRARY/home/guopf/workspace/3rdparty-keep-32/install/sqlite3_clean/lib/libsqlite3.so\-DCMAKE_SKIP_BUILD_RPATHON-DCMAKE_SKIP_INSTALL_RPATHON\-DCMAKE_INSTALL_PREFIX/home/guopf/workspace/3rdparty-keep-32/install/SQLiteCpp_clean\..cmake--build.-j4cmake--install.验证(完整路径,任意目录均可执行):arm-rockchip1240-linux-gnueabihf-readelf-d\/home/guopf/workspace/3rdparty-keep-32/install/SQLiteCpp_clean/lib/libSQLiteCpp.so.0\|grep-ESONAME|RPATH|RUNPATH|NEEDED期望:有SONAME libSQLiteCpp.so.0,没有 RPATH,且对 sqlite3 的NEEDED是纯名字libsqlite3.so.0(不是绝对路径)。注意点 / 避坑必须设-DSQLITECPP_INTERNAL_SQLITEOFF。SQLiteCpp 默认ON,会编译它自带的 sqlite3 源码,完全不用你单独编的外部 sqlite3。要用外部 sqlite3 共享库,必须关掉它,并保持-DSQLITECPP_FIND_SQLITEON(走find_package(SQLite3))。前提:被链接的 sqlite3 必须已经有 SONAME。这是最容易踩的坑。如果 sqlite3 没有 SONAME,链接器会把“链接时用到的那条路径”烧进 SQLiteCpp 的NEEDED。由于这里用绝对路径-DSQLite3_LIBRARY.../libsqlite3.so指定,就会变成主机绝对路径,部署到板子上必然找不到库而报cannot open shared object file。→ 所以一定要先按第一部分把 sqlite3 的 SONAME 编对。用-DSQLite3_LIBRARY/-DSQLite3_INCLUDE_DIR显式指定 sqlite3。这两个变量优先级高于CMAKE_PREFIX_PATH,能确保链到你想要的那份 sqlite3,避免被 toolchain 里的旧路径或系统库干扰。配置完看 CMake 输出的Found SQLite3: ...确认路径对不对。关闭 CMake 写 RPATH:-DCMAKE_SKIP_BUILD_RPATHON -DCMAKE_SKIP_INSTALL_RPATHON。否则 CMake 会把构建/安装路径写进 RPATH,同样是主机路径污染。三、通用避坑总结(两库共通)SONAME 一定要有,且只到主版本号(libxxx.so.major)——它是运行时依赖解析的依据,不是文件名软链。不要让主机绝对路径进入库:既不能出现在 RPATH,也不能出现在NEEDED。依赖库要先编好 SONAME,再编上层库,顺序不能反。验证三件套(用交叉readelf -d 完整路径):有正确 SONAME、无主机 RPATH、NEEDED全是纯名字。部署到板子时,把真实.so和版本软链一起拷到板子库目录(或设LD_LIBRARY_PATH)。