- 問題
- 嘗試 xcodebuild
- 查看 WCDB 是怎麼編譯
- 嘗試自動靜態庫
- 嘗試手動靜態庫
- 總結
因爲項目需求,須要使用一款數據庫,直接使用 sqlite 會手動寫不少 sql 代碼,也容易出錯。使用蘋果官方的 core data,core data 不是線程安全的,須要嚴格區分在不一樣的線程使用不一樣的 manage context,使用上也增長了代碼複雜度,也會更容易出現 bug。因而考慮下基於 sqlite 的開源方案。ios
FMDB: 其實就是 sqlite 的語法糖,多線程訪問須要使用專門的 queue,不支持 ORM。
Realm: 是爲速度而生的數據庫,不少配套設施並不齊全。
WCDB: 性能高,支持線程安全,支持 ORM。缺點:1. 基於objective c++,因此只要使用到了 WCDB 的地方,都須要以 mm 爲文件後綴。2. 增大包體積。
想找到一款易使用有安全的數據庫,最後仍是考慮使用了 WCDB, 雖然它也有本身的不足,可是仍是能夠接受的。c++
因而經過 pod 在項目中使用了 WCDB,並寫了小 demo 熟悉下了使用方式。git
pod 'WCDB'
在熟悉了使用方式以後,就能夠在項目裏使用了,在開發階段都是經過模擬器或者真機測試,覺得都很好。可是在搭建 Bamboo 的 CICD 就會報如下錯。github
fts5_storage.c:305:9: error: 'sqlite3_api_routines' has no member named '__builtin___snprintf_chk' The following build commands failed: CompileC /Users/karosli/Library/Developer/Xcode/DerivedData/xxx-dleyffpkgrddqzfvrhnoakpqgdvz/Build/Intermediates.noindex/ArchiveIntermediates/LefitCoach/IntermediateBuildFilesPath/Pods.build/Debug-iphoneos/WCDB.build/Objects-normal/armv7/fts5.o WCDB/sqlcipher/fts5.c normal armv7 c com.apple.compilers.llvm.clang.1_0.compiler (1 failure)
<!--more-->sql
因爲 CICD 使用的是基於 flastlane gym 的 shell 腳本,於是懷疑是否是 fastlane 的緣由呢,由於我在 Xcode 上直接運行是好的。因此就嘗試使用 xcodebuild 去編譯打包。shell
# 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} # 把上面替換成下面的命令 # archive xcodebuild archive -sdk iphoneos -workspace ${app_workspace} -scheme ${app_schema} -configuration Debug -archivePath ${outputDir} GCC_PREPROCESSOR_DEFINITIONS="$GCC_PREPROCESSOR_DEFINITIONS DEBUG=1 COCOAPODS=1" # export ipa xcodebuild -exportArchive -exportFormat IPA -archivePath ${outputDir} -exportPath ${app_ipa_file} -exportOptionsPlist exportOptions_dev.plist
因爲 WCDB 經過 pod 的方式是能夠再 Xcode 上運行的,猜測下是否是 WCDB.podspec 裏面作了額外的事情。數據庫
能夠看到文件裏面多了一個預處理命令 wcdb.prepare_command
。macos
# pod lib lint --verbose --skip-import-validation WCDB.podspec # pod trunk push WCDB.podspec --verbose --skip-import-validation Pod::Spec.new do |wcdb| wcdb.name = "WCDB" wcdb.version = "1.0.6" wcdb.summary = "WCDB is a cross-platform database framework developed by WeChat." wcdb.description = <<-DESC The WeChat Database, for Objective-C. (If you want to use WCDB from Objective-C, see the "WCDBSwift" pod.) WCDB is an efficient, complete, easy-to-use mobile database framework used in the WeChat application. It can be a replacement for Core Data, SQLite & FMDB. DESC wcdb.homepage = "https://github.com/Tencent/wcdb" wcdb.license = { :type => "BSD", :file => "LICENSE"} wcdb.author = { "sanhuazhang" => "sanhuazhang@tencent.com" } wcdb.ios.deployment_target = "7.0" wcdb.osx.deployment_target = "10.9" wcdb.watchos.deployment_target = "2.0" wcdb.tvos.deployment_target = "9.0" wcdb.source = { :git => "https://github.com/Tencent/wcdb.git", :tag => "v#{wcdb.version}" } wcdb.public_header_files = "objc/WCDB/WCDB.h", "objc/WCDB/**/*.{h,hpp}" wcdb.source_files = "objc/WCDB/WCDB.h", "objc/WCDB/**/*.{h,m,hpp,cpp,mm}", "repair" wcdb.frameworks = "CoreFoundation", "Security", "Foundation" wcdb.ios.frameworks = "UIKit" wcdb.libraries = "z", "c++" wcdb.requires_arc = true wcdb.prepare_command = "git submodule update --init sqlcipher; \ cd tools/templates; sh install.sh; cd ../..; \ cd sqlcipher; make -f Makefile.preprocessed; cd ..; \ cp sqlcipher/ext/fts3/fts3_tokenizer.h sqlcipher/" wcdb.xcconfig = { "GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) WCDB_BUILTIN_COLUMN_CODING WCDB_COCOAPODS", "HEADER_SEARCH_PATHS" => "$(inherited) ${PODS_ROOT}/WCDB", "LIBRARY_SEARCH_PATHS[sdk=macosx*]" => "$(inherited) $(SDKROOT)/usr/lib/system", "CLANG_CXX_LANGUAGE_STANDARD" => "gnu++0x", "CLANG_CXX_LIBRARY" => "libc++", } wcdb.subspec 'sqlcipher' do |sqlcipher| sqlcipher.public_header_files = "sqlcipher/sqlite3.h", "sqlcipher/fts3_tokenizer.h" sqlcipher.source_files = "sqlcipher/src/callback.c", "sqlcipher/src/loadext.c", "sqlcipher/src/rowset.c", "sqlcipher/src/treeview.c", "sqlcipher/ext/userauth.c", "sqlcipher/src/vtab.c", "sqlcipher/src/btmutex.c", "sqlcipher/src/btree.c", "sqlcipher/src/btreeInt.h", "sqlcipher/src/btree.h", "sqlcipher/fts5.c", "sqlcipher/fts5.h", "sqlcipher/ext/fts3/fts3_aux.c", "sqlcipher/ext/fts3/fts3_expr.c", "sqlcipher/ext/fts3/fts3_hash.c", "sqlcipher/ext/fts3/fts3_hash.h", "sqlcipher/ext/fts3/fts3_icu.c", "sqlcipher/ext/fts3/fts3_porter.c", "sqlcipher/ext/fts3/fts3_snippet.c", "sqlcipher/ext/fts3/fts3_tokenize_vtab.c", "sqlcipher/ext/fts3/fts3_tokenizer.c", "sqlcipher/ext/fts3/fts3_tokenizer1.c", "sqlcipher/ext/fts3/fts3_unicode.c", "sqlcipher/ext/fts3/fts3_unicode2.c", "sqlcipher/ext/fts3/fts3_write.c", "sqlcipher/ext/fts3/fts3.c", "sqlcipher/ext/fts3/fts3.h", "sqlcipher/ext/fts3/fts3Int.h", "sqlcipher/src/backup.c", "sqlcipher/src/legacy.c", "sqlcipher/src/main.c", "sqlcipher/src/notify.c", "sqlcipher/src/vdbeapi.c", "sqlcipher/src/table.c", "sqlcipher/src/wal.c", "sqlcipher/src/wal.h", "sqlcipher/src/status.c", "sqlcipher/src/prepare.c", "sqlcipher/src/malloc.c", "sqlcipher/src/mem0.c", "sqlcipher/src/mem1.c", "sqlcipher/src/mem2.c", "sqlcipher/src/mem3.c", "sqlcipher/src/mem5.c", "sqlcipher/src/memjournal.c", "sqlcipher/src/mutex_unix.c", "sqlcipher/src/mutex_noop.c", "sqlcipher/src/mutex.c", "sqlcipher/src/mutex.h", "sqlcipher/src/os_common.h", "sqlcipher/src/os_setup.h", "sqlcipher/src/os_unix.c", "sqlcipher/src/queue.c", "sqlcipher/src/queue.h", "sqlcipher/src/os_wcdb.c", "sqlcipher/src/os_wcdb.h", "sqlcipher/src/mutex_wcdb.c", "sqlcipher/src/mutex_wcdb.h", "sqlcipher/src/os.c", "sqlcipher/src/os.h", "sqlcipher/src/threads.c", "sqlcipher/src/bitvec.c", "sqlcipher/src/pager.c", "sqlcipher/src/pager.h", "sqlcipher/src/pcache.c", "sqlcipher/src/pcache.h", "sqlcipher/src/pcache1.c", "sqlcipher/ext/rtree/rtree.c", "sqlcipher/ext/rtree/rtree.h", "sqlcipher/ext/rtree/sqlite3rtree.h", "sqlcipher/src/complete.c", "sqlcipher/src/tokenize.c", "sqlcipher/src/resolve.c", "sqlcipher/parse.c", "sqlcipher/parse.h", "sqlcipher/src/analyze.c", "sqlcipher/src/func.c", "sqlcipher/src/wherecode.c", "sqlcipher/src/whereexpr.c", "sqlcipher/src/whereInt.h", "sqlcipher/src/alter.c", "sqlcipher/src/attach.c", "sqlcipher/src/auth.c", "sqlcipher/src/build.c", "sqlcipher/src/delete.c", "sqlcipher/src/expr.c", "sqlcipher/src/insert.c", "sqlcipher/src/pragma.c", "sqlcipher/src/pragma.h", "sqlcipher/src/select.c", "sqlcipher/src/trigger.c", "sqlcipher/src/update.c", "sqlcipher/src/vacuum.c", "sqlcipher/src/walker.c", "sqlcipher/src/where.c", "sqlcipher/opcodes.c", "sqlcipher/opcodes.h", "sqlcipher/src/sqlcipher.h", "sqlcipher/sqlite3.h", "sqlcipher/ext/rbu/sqlite3rbu.c", "sqlcipher/ext/rbu/sqlite3rbu.h", "sqlcipher/ext/userauth/sqlite3userauth.h", "sqlcipher/ext/misu/json1.c", "sqlcipher/ext/icu/icu.c", "sqlcipher/ext/icu/sqliteicu.h", "sqlcipher/src/global.c", "sqlcipher/src/ctime.c", "sqlcipher/src/hwtime.h", "sqlcipher/src/date.c", "sqlcipher/src/dbstat.c", "sqlcipher/src/fault.c", "sqlcipher/src/fkey.c", "sqlcipher/src/sqliteInt.h", "sqlcipher/src/sqliteLimit.h", "sqlcipher/src/sqlite3ext.h", "sqlcipher/src/hash.c", "sqlcipher/src/hash.h", "sqlcipher/src/printf.c", "sqlcipher/src/random.c", "sqlcipher/src/utf.c", "sqlcipher/src/util.c", "sqlcipher/src/crypto_cc.c", "sqlcipher/src/crypto_impl.c", "sqlcipher/src/crypto_libtomcrypt.c", "sqlcipher/src/crypto.c", "sqlcipher/src/crypto.h", "sqlcipher/src/vdbe.c", "sqlcipher/src/vdbe.h", "sqlcipher/src/vdbeaux.c", "sqlcipher/src/vdbeblob.c", "sqlcipher/src/vdbeInt.h", "sqlcipher/src/vdbemem.c", "sqlcipher/src/vdbesort.c", "sqlcipher/src/vdbetrace.c", "sqlcipher/src/msvc.h", "sqlcipher/src/vxworks.h", "sqlcipher/fts3_tokenizer.h", "sqlcipher/keywordhash.h" sqlcipher.ios.deployment_target = "8.0" sqlcipher.osx.deployment_target = "10.9" sqlcipher.watchos.deployment_target = "2.0" sqlcipher.tvos.deployment_target = "9.0" sqlcipher.xcconfig = { "GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) SQLITE_ENABLE_FTS3 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_API_ARMOR SQLITE_OMIT_BUILTIN_TEST SQLITE_OMIT_AUTORESET SQLITE_ENABLE_UPDATE_DELETE_LIMIT SQLITE_ENABLE_RTREE SQLITE_ENABLE_LOCKING_STYLE=1 SQLITE_SYSTEM_MALLOC SQLITE_OMIT_LOAD_EXTENSION SQLITE_CORE SQLITE_THREADSAFE=2 SQLITE_DEFAULT_CACHE_SIZE=250 SQLITE_DEFAULT_CKPTFULLFSYNC=1 SQLITE_DEFAULT_PAGE_SIZE=4096 SQLITE_OMIT_SHARED_CACHE SQLITE_HAS_CODEC SQLCIPHER_CRYPTO_CC USE_PREAD=1 SQLITE_TEMP_STORE=2 SQLCIPHER_PREPROCESSED HAVE_USLEEP SQLITE_MALLOC_SOFT_LIMIT=0 SQLITE_WCDB_SIGNAL_RETRY=1 SQLITE_DEFAULT_MEMSTATUS=0 SQLITE_ENABLE_COLUMN_METADATA SQLITE_DEFAULT_WAL_SYNCHRONOUS=1 SQLITE_LIKE_DOESNT_MATCH_BLOBS SQLITE_MAX_EXPR_DEPTH=0 SQLITE_OMIT_DEPRECATED SQLITE_OMIT_PROGRESS_CALLBACK SQLITE_OMIT_SHARED_CACHE OMIT_CONSTTIME_MEM OMIT_MEMLOCK SQLITE_ENABLE_FTS3_TOKENIZER", "CLANG_WARN_CONSTANT_CONVERSION" => "YES", "GCC_WARN_64_TO_32_BIT_CONVERSION" => "NO", "CLANG_WARN_UNREACHABLE_CODE" => "NO", "GCC_WARN_UNUSED_FUNCTION" => "NO", "GCC_WARN_UNUSED_VARIABLE" => "NO", } end end
Makefile.preprocessedjson
./configure --enable-tempstore=yes --with-crypto-lib=commoncrypto CFLAGS="-DSQLITE_HAS_CODEC -DSQLITE_TEMP_STORE=2 -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT" --disable-amalgamation make opcodes.h opcodes.c keywordhash.h fts5.c fts5.h sqlite3.h parse.h parse.c
這裏裏面作了預編譯處理。因而就想怎麼在命令行裏面加入這樣的命令,嘗試了不少了方式,發現沒有那麼簡單,因此就擱淺在這裏了,不要打我,還請大神能幫我解答下。api
因而就另闢蹊徑,想到了靜態庫,把 WCDB 作成靜態庫的形式,那麼再命令行打包的時候,不會再次編譯了。
因而想到了 cocoapod package,去自動打成靜態庫,須要創建一個殼工程,裏面用 pod 安裝 WCDB,而後用命令行打靜態庫。教程在這裏
sudo gem install cocoapods-packager
pod package XXDatabase.podspec --force
成功後,會生成一個帶版本號的庫目錄,而後把裏面的 framework 放到單獨的測試工程師測試,最後發現編譯是經過的,可是找不到 WCDB 的頭文件(即便 podspec 文件配置了 s.public_header_files = 'Pods/**/*.h'
),此路不通。
因而嘗試用手動的方式去打靜態庫,手動方式就有兩種方案了。
方案一: 使用 WCDB 官方的教程是打靜態庫。
方案二: 經過 lipo 命令合併模擬器和真機靜態庫。
使用方案一打出來的靜態庫,若是在主工程裏使用沒有問題,一旦放入到單獨的 pod 裏,檢測的時候,就會上傳失敗。因此放棄了。
而後嘗試方案二,打出的包能夠引入工程,代碼編譯沒有錯,可是一運行就報錯了。
真是懵逼,百思不得解,後來想一想,我如今打開的工程是 WCDB 的 master 分支,而 pod repo 裏面的是 1.0.6 的 tag,因此就切換到 1.0.6 上從新進行方案二。
果真經過這個 tag 打出來的靜態庫是沒有問題的,放入到測試工程(須要加上 other linker flags: $(inherited) -ObjC -all_load
),模擬器和真機測試皆可經過。靜態庫製做教程
剩下就是用一個單獨的 pod 基礎組件去包含這個靜態庫,而後
讓其餘業務組件引入這個 pod 基礎組件就能夠避免這個靜態庫存在多份。
雖然最後是問題是解決了,但也說明本身在編譯原理上的欠缺,因此後面仍是要補充這塊的姿式啊。
https://github.com/Tencent/wc...
http://www.sqlite.org/src/inf...
https://www.jianshu.com/p/815...
https://www.jianshu.com/p/50e...
https://www.jianshu.com/p/283...
https://www.jianshu.com/p/7f6...