fix(android): allow user sqliteFlags to override performanceMode defaults#402
Merged
ospfranco merged 1 commit intoMay 14, 2026
Conversation
be91294 to
16ffb0c
Compare
Contributor
|
Not a cmake expert, so this is really useful to have debugged. Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On Android, user-supplied
sqliteFlagsfrompackage.jsoncannot override flags thatperformanceMode: trueadds. Witha query that relies on DQS string literals (
SELECT 1 FROM t WHERE col = "some-string") succeeds on iOS but fails on Android withno such column: "some-string". iOS works because the podspec buildsOTHER_CFLAGSasoptimizedCflags + sqliteFlags, so user flags arrive after the defaults and win under clang's last-define-wins rule. Android does not have that property today.Root cause
Two-part ordering bug on the clang command line:
android/build.gradleputs theperformanceModeflags on gradle's external-native-buildcFlags, which the Android Gradle Plugin appends toCMAKE_C_FLAGS. They arrive late on the clang command line.android/CMakeLists.txtadds usersqliteFlagsviaadd_definitions(${SQLITE_FLAGS_LIST}). These land inCOMPILE_DEFINITIONS, which CMake emits early on the command line — and, importantly, sorts alphabetically before emission.Net effect: user
-DSQLITE_DQS=3is sorted into earlyCOMPILE_DEFINITIONS, the performanceMode-DSQLITE_DQS=0lands later inCMAKE_C_FLAGS, and clang takes the late one. The library default silently beats the user override.The documented intent of
sqliteFlags(https://op-engineering.github.io/op-sqlite/docs/installation/) is that user flags customize the build. Today on Android they can only add flags, not overrideperformanceModeones.Fix
Route both library defaults (
performanceMode,fts5,rtree) and usersqliteFlagsthrough the same CMake channel —add_compile_options— with defaults declared first and user flags last:android/build.gradlenow collects all default flags into adefaultSqliteFlagslist at config time and passes them to CMake as-DDEFAULT_SQLITE_FLAGS=.... The oldcFlags += [...]blocks forperformanceMode,enableFTS5andenableRtreeare removed.android/CMakeLists.txtcallsadd_compile_options(${DEFAULT_SQLITE_FLAGS_LIST})and thenadd_compile_options(${SQLITE_FLAGS_LIST}).add_compile_optionspreserves declaration order;add_definitionsdoes not (CMake sortsCOMPILE_DEFINITIONSalphabetically, soadd_definitionscannot reliably encode override intent — e.g. a default=1would beat a user=0due to character order).Defaults remain unchanged when no user flags are set. When user flags are set, they land after the defaults on the clang command line and win under clang's last-define-wins rule. This matches the iOS behavior.
Verification
Built the example app's native target twice on
arm64-v8aand inspectedandroid/.cxx/Debug/*/arm64-v8a/compile_commands.jsonforsqlite3.c.Default (no
sqliteFlags,performanceMode: true, fts5: true, rtree: true):All existing defaults still applied.
-DSQLITE_DQS=0present.Override (
"sqliteFlags": "-DSQLITE_DQS=3 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=0"):Both override flags appear after their defaults. Notably,
-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=0overrides=1— this is the caseadd_definitionswould have broken (since'0' < '1'alphabetically), confirming the need foradd_compile_options.Scope notes
sqliteFlags— all existing defaults remain.docs/docs/installation.mdto mention override semantics on both platforms.