目录
- 问题
- 尝试 xcodebuild
- 查看 WCDB 是怎么编译
- 尝试自动静态库
- 尝试手动静态库
- 总结
1. 问题
由于项目需求,需要使用一款数据库,直接使用 sqlite 会手动写很多 sql 代码,也容易出错。使用苹果官方的 core data,core data 不是线程安全的,需要严格区分在不同的线程使用不同的 manage context,使用上也增加了代码复杂度,也会更容易出现 bug。于是考虑下基于 sqlite 的开源方案。
FMDB: 其实就是 sqlite 的语法糖,多线程访问需要使用专门的 queue,不支持 ORM。
Realm: 是为速度而生的数据库,很多配套设施并不齐全。
WCDB: 性能高,支持线程安全,支持 ORM。缺点:1. 基于objective c++,所以只要使用到了 WCDB 的地方,都需要以 mm 为文件后缀。2. 增大包体积。
想找到一款易使用有安全的数据库,最后还是考虑使用了 WCDB, 虽然它也有自己的不足,但是还是可以接受的。
于是通过 pod 在项目中使用了 WCDB,并写了小 demo 熟悉下了使用方式。
pod 'WCDB' |
在熟悉了使用方式之后,就可以在项目里使用了,在开发阶段都是通过模拟器或者真机测试,以为都很好。但是在搭建 Bamboo 的 CICD 就会报以下错。
fts5_storage.c:305:9: error: 'sqlite3_api_routines' has no member named '__builtin___snprintf_chk' |
2. 尝试 xcodebuild
由于 CICD 使用的是基于 flastlane gym 的 shell 脚本,因而怀疑是不是 fastlane 的原因呢,因为我在 Xcode 上直接运行是好的。所以就尝试使用 xcodebuild 去编译打包。
# fastlane gym --silent --workspace ${app_workspace} --scheme ${app_schema} --clean --xcargs 'GCC_PREPROCESSOR_DEFINITIONS="$GCC_PREPROCESSOR_DEFINITIONS DEBUG=1 COCOAPODS=1"' --export_method development --output_directory ${outputDir} --output_name ${app_ipa_file} |
3. 查看 WCDB 是怎么编译
由于 WCDB 通过 pod 的方式是可以再 Xcode 上运行的,猜想下是不是 WCDB.podspec 里面做了额外的事情。
可以看到文件里面多了一个预处理命令 wcdb.prepare_command
。
# pod lib lint --verbose --skip-import-validation WCDB.podspec |
Makefile.preprocessed
./configure --enable-tempstore=yes --with-crypto-lib=commoncrypto CFLAGS="-DSQLITE_HAS_CODEC -DSQLITE_TEMP_STORE=2 -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT" --disable-amalgamation |
这里里面做了预编译处理。于是就想怎么在命令行里面加入这样的命令,尝试了很多了方式,发现没有那么简单,所以就搁浅在这里了,不要打我,还请大神能帮我解答下。
4. 尝试自动静态库
于是就另辟蹊径,想到了静态库,把 WCDB 做成静态库的形式,那么再命令行打包的时候,不会再次编译了。
于是想到了 cocoapod package,去自动打成静态库,需要建立一个壳工程,里面用 pod 安装 WCDB,然后用命令行打静态库。教程在这里
sudo gem install cocoapods-packager |
pod package XXDatabase.podspec --force |
成功后,会生成一个带版本号的库目录,然后把里面的 framework 放到单独的测试工程师测试,最后发现编译是通过的,但是找不到 WCDB 的头文件(即使 podspec 文件配置了 s.public_header_files = 'Pods/**/*.h'
),此路不通。
5. 尝试手动静态库
于是尝试用手动的方式去打静态库,手动方式就有两种方案了。
方案一: 使用 WCDB 官方的教程是打静态库。
方案二: 通过 lipo 命令合并模拟器和真机静态库。
使用方案一打出来的静态库,如果在主工程里使用没有问题,一旦放入到单独的 pod 里,检测的时候,就会上传失败。所以放弃了。
xcodebuild: error: The workspace named "App" does not contain a scheme named "xxxDatabase". The "-list" option can be used to find the names of the schemes in the workspace. |
然后尝试方案二,打出的包可以引入工程,代码编译没有错,但是一运行就报错了。
真是懵逼,百思不得解,后来想想,我现在打开的工程是 WCDB 的 master 分支,而 pod repo 里面的是 1.0.6 的 tag,所以就切换到 1.0.6 上重新进行方案二。
果然通过这个 tag 打出来的静态库是没有问题的,放入到测试工程(需要加上 other linker flags: $(inherited) -ObjC -all_load
),模拟器和真机测试皆可通过。静态库制作教程
剩下就是用一个单独的 pod 基础组件去包含这个静态库,然后
让其他业务组件引入这个 pod 基础组件就可以避免这个静态库存在多份。
Pod::Spec.new do |s| |
6. 总结
虽然最后是问题是解决了,但也说明自己在编译原理上的欠缺,所以后面还是要补充这块的姿势啊。
参考
https://github.com/Tencent/wcdb/wiki
http://www.sqlite.org/src/info/cd0471ca9f75e7c8
https://www.jianshu.com/p/815fc21b9d0d
https://www.jianshu.com/p/50e0efb66bdf
https://www.jianshu.com/p/283e67ba12a3
https://www.jianshu.com/p/7f6a7e1b3235