fix(build): add SQLite conflict detection and Command Line Tools verification

Prevents iOS build failures caused by pkgx SQLite linking conflicts and
ensures Xcode Command Line Tools are properly installed.

Problem:
- pkgx installs SQLite built for macOS, causing linker errors when building
  for iOS simulator: "linking in dylib built for 'macOS'"
- Missing Command Line Tools cause build failures without clear error messages

Changes:
- Add check_sqlite_conflicts() function
  - Detects pkgx SQLite installations in ~/.pkgx
  - Warns about macOS dylibs that will cause iOS simulator build failures
  - Checks for system SQLite from Command Line Tools
  - Validates library paths (DYLD_LIBRARY_PATH, LD_LIBRARY_PATH)

- Add check_command_line_tools() function
  - Verifies Xcode Command Line Tools are installed and configured
  - Checks for xcodebuild availability
  - Verifies sqlite3 is available (part of Command Line Tools)
  - Provides clear error messages with installation instructions

- Enhance pkgx detection in iOS build functions
  - Specifically searches for pkgx SQLite dylibs
  - Automatically removes pkgx paths from PATH environment variable
  - Provides detailed warnings about detected conflicts
  - Cleans all problematic environment variables before building

- Integrate checks into environment validation
  - Runs automatically when building for iOS
  - Provides early warnings before build starts
  - Fails fast with clear error messages if tools are missing

This fixes the linker error:
  "ld: building for 'iOS-simulator', but linking in dylib
   (/Users/trent/.pkgx/sqlite.org/v3.44.2/lib/libsqlite3.0.dylib)
   built for 'macOS'"

The build script now:
- Detects pkgx SQLite conflicts before building
- Automatically fixes environment variables
- Verifies Command Line Tools are installed
- Provides clear guidance for manual fixes if needed

Files modified:
- scripts/build-native.sh
This commit is contained in:
Jose Olarte III
2026-01-15 18:34:33 +08:00
parent 5247ebeecb
commit 2915fe7438
2 changed files with 137 additions and 76 deletions

View File

@@ -1,76 +1,47 @@
refactor(android): Complete plugin refactoring and safety fixes (Batches 0-7)
fix(build): add SQLite conflict detection and Command Line Tools verification
Comprehensive refactoring to make DailyNotificationPlugin a thin adapter,
eliminate duplicated logic, remove unsafe operations, and harden security.
Prevents iOS build failures caused by pkgx SQLite linking conflicts and
ensures Xcode Command Line Tools are properly installed.
Batch 0 - Constants Centralization:
- Created DailyNotificationConstants.kt to eliminate magic numbers and duplicates
- Centralized: PERMISSION_REQUEST_CODE, channel constants, intent actions/extras,
SharedPreferences keys, WorkManager tags, notification IDs
- Replaced duplicates across Plugin, PermissionManager, ChannelManager, Scheduler
Problem:
- pkgx installs SQLite built for macOS, causing linker errors when building
for iOS simulator: "linking in dylib built for 'macOS'"
- Missing Command Line Tools cause build failures without clear error messages
Batch 1 - Permission Flow Unification:
- Created PermissionStatus.kt data class for unified permission reporting
- Added PermissionManager.getPermissionStatus() as single source of truth
- Implemented PendingPermissionRequest tracking for reliable resume resolution
- Replaced method-name-based resume logic with token-based tracking
- Plugin now delegates all permission checks to PermissionManager
Changes:
- Add check_sqlite_conflicts() function
- Detects pkgx SQLite installations in ~/.pkgx
- Warns about macOS dylibs that will cause iOS simulator build failures
- Checks for system SQLite from Command Line Tools
- Validates library paths (DYLD_LIBRARY_PATH, LD_LIBRARY_PATH)
- Add check_command_line_tools() function
- Verifies Xcode Command Line Tools are installed and configured
- Checks for xcodebuild availability
- Verifies sqlite3 is available (part of Command Line Tools)
- Provides clear error messages with installation instructions
Batch 2 - Notification Status Checker Hardening:
- Modified NotificationStatusChecker to always check OS-level notification
enablement via NotificationManagerCompat.areNotificationsEnabled()
- Added getReadinessReport() method providing comprehensive status with issues
and actionable guidance
- Plugin checkStatus() now uses readiness report
- Enhance pkgx detection in iOS build functions
- Specifically searches for pkgx SQLite dylibs
- Automatically removes pkgx paths from PATH environment variable
- Provides detailed warnings about detected conflicts
- Cleans all problematic environment variables before building
Batch 3 - Cancel Semantics Safety:
- Removed unsafe brute-force cancellation loop (was trying request codes 0-100)
- Cancellation now only targets alarms proven to exist in database
- Prevents accidental cancellation of other alarms and false confidence
- Integrate checks into environment validation
- Runs automatically when building for iOS
- Provides early warnings before build starts
- Fails fast with clear error messages if tools are missing
Batch 4 - Legacy Scheduler Removal:
- Removed unused legacy scheduleExactAlarm() method (48 lines)
- All scheduling now goes through modern paths:
1. exactAlarmManager.scheduleAlarm() (if available)
2. pendingIntentManager.scheduleExactAlarm() (modern path)
3. pendingIntentManager.scheduleWindowedAlarm() (fallback)
This fixes the linker error:
"ld: building for 'iOS-simulator', but linking in dylib
(/Users/trent/.pkgx/sqlite.org/v3.44.2/lib/libsqlite3.0.dylib)
built for 'macOS'"
Batch 5 - Input Contract Tightening:
- Enforced single input shape for updateStarredPlans: { planIds: string[] }
- Added validation: rejects non-array, non-string elements, empty strings
- Legacy support: single string normalized to array (with warning)
- Clear error messages for contract violations
Batch 6 - Token Storage Security:
- Added explicit opt-in for JWT token persistence (persistToken: true)
- Default behavior: tokens NOT persisted (secure default)
- Security warnings logged when persistence is enabled
- Documents unencrypted storage risk
Batch 7 - Plugin Thinning:
- Moved getExactAlarmStatus() to PermissionManager.getExactAlarmStatus()
- Moved canRequestExactAlarmPermission() to PermissionManager
- Removed direct AlarmManager access in cancelAllNotifications()
- Delegated scheduleUserNotification/scheduleDualNotification permission
handling to PermissionManager.requestExactAlarmPermission()
- Removed unused imports: AlarmManager, PendingIntent, PowerManager,
NotificationManagerCompat
Result:
- Plugin is now a thin adapter delegating to services
- No duplicated permission logic
- No unsafe cancellation operations
- No legacy scheduler paths
- Secure token storage defaults
- Clear input contracts
- Comprehensive status reporting
The build script now:
- Detects pkgx SQLite conflicts before building
- Automatically fixes environment variables
- Verifies Command Line Tools are installed
- Provides clear guidance for manual fixes if needed
Files modified:
- DailyNotificationConstants.kt (new)
- PermissionStatus.kt (new)
- DailyNotificationPlugin.kt (thinned, ~500 lines refactored)
- PermissionManager.java (enhanced with status methods)
- NotificationStatusChecker.java (hardened)
- DailyNotificationScheduler.java (legacy removed)
Refs: Cursor directive Batches 0-7
- scripts/build-native.sh

View File

@@ -47,6 +47,75 @@ get_pod_command() {
fi
}
check_sqlite_conflicts() {
local PLATFORM=$1
if [ "$PLATFORM" != "ios" ] && [ "$PLATFORM" != "all" ]; then
return 0
fi
# Check for pkgx SQLite that might interfere with iOS builds
if [ -d "$HOME/.pkgx" ]; then
# Look for pkgx SQLite installations
PKGX_SQLITE=$(find "$HOME/.pkgx" -name "libsqlite3*.dylib" 2>/dev/null | head -1)
if [ -n "$PKGX_SQLITE" ]; then
log_warn "⚠️ pkgx SQLite detected: $PKGX_SQLITE"
log_warn " This may cause iOS build failures (linking macOS dylib for iOS simulator)"
log_warn " The build script will unset problematic environment variables"
# Check if library paths point to pkgx
if [ -n "$DYLD_LIBRARY_PATH" ] && echo "$DYLD_LIBRARY_PATH" | grep -q "\.pkgx"; then
log_warn " DYLD_LIBRARY_PATH contains pkgx paths - will be unset for build"
fi
if [ -n "$LD_LIBRARY_PATH" ] && echo "$LD_LIBRARY_PATH" | grep -q "\.pkgx"; then
log_warn " LD_LIBRARY_PATH contains pkgx paths - will be unset for build"
fi
fi
fi
# Check for system SQLite (from Command Line Tools)
if command -v sqlite3 &> /dev/null; then
SQLITE_PATH=$(which sqlite3)
if [ "$SQLITE_PATH" = "/usr/bin/sqlite3" ]; then
log_info "✅ System SQLite found (from Command Line Tools): $SQLITE_PATH"
else
log_warn "⚠️ SQLite found at non-standard location: $SQLITE_PATH"
log_warn " Ensure this is compatible with iOS builds"
fi
else
log_warn "⚠️ sqlite3 command not found - Command Line Tools may not be installed"
log_warn " Install with: xcode-select --install"
fi
}
check_command_line_tools() {
if [ "$(uname)" != "Darwin" ]; then
return 0
fi
# Check if xcode-select points to a valid developer directory
if ! xcode-select -p &> /dev/null; then
log_error "Xcode Command Line Tools not configured"
log_error " Run: xcode-select --install"
exit 1
fi
# Check if xcodebuild is available
if ! command -v xcodebuild &> /dev/null; then
log_error "xcodebuild not found - Command Line Tools may be incomplete"
log_error " Run: xcode-select --install"
exit 1
fi
# Verify sqlite3 is available (part of Command Line Tools)
if ! command -v sqlite3 &> /dev/null; then
log_warn "⚠️ sqlite3 not found - Command Line Tools may be incomplete"
log_warn " This may cause iOS build issues"
log_warn " Run: xcode-select --install"
fi
}
check_environment() {
local PLATFORM=$1
@@ -86,7 +155,13 @@ check_environment() {
fi
if [ "$PLATFORM" = "ios" ] || [ "$PLATFORM" = "all" ]; then
# iOS checks are done in build_ios() function
# Check Command Line Tools
check_command_line_tools
# Check for SQLite conflicts
check_sqlite_conflicts "$PLATFORM"
# iOS-specific checks are done in build_ios() function
# to avoid failing if iOS tools aren't available when building Android only
:
fi
@@ -188,13 +263,25 @@ build_plugin_for_test_app() {
build_plugin_for_test_app_ios() {
log_info "Building iOS test app..."
# Warn about pkgx interference with SQLite linking
# Fix pkgx interference with SQLite linking
# pkgx installs SQLite built for macOS, which causes linker errors when building for iOS simulator
if [ -n "$PKGX_DIR" ] || [ -d "$HOME/.pkgx" ]; then
log_warn "⚠️ pkgx detected - this may interfere with iOS SQLite linking"
log_warn " Temporarily unsetting PKGX_DIR and DYLD_LIBRARY_PATH for build..."
log_warn "⚠️ pkgx detected - fixing SQLite linking conflicts..."
# Check for pkgx SQLite specifically
PKGX_SQLITE=$(find "$HOME/.pkgx" -name "libsqlite3*.dylib" 2>/dev/null | head -1)
if [ -n "$PKGX_SQLITE" ]; then
log_warn " Found pkgx SQLite: $PKGX_SQLITE"
log_warn " This is built for macOS and will cause iOS simulator build failures"
fi
log_warn " Temporarily unsetting PKGX_DIR and library paths for build..."
unset PKGX_DIR
unset DYLD_LIBRARY_PATH
unset LD_LIBRARY_PATH
# Also unset any pkgx-related paths that might be in PATH
export PATH=$(echo "$PATH" | tr ':' '\n' | grep -v "\.pkgx" | tr '\n' ':' | sed 's/:$//')
fi
# Ensure symlink is in place FIRST (before building)
@@ -431,11 +518,14 @@ build_ios() {
exit 1
fi
# Warn about pkgx interference with SQLite linking
if [ -n "$PKGX_DIR" ] || [ -d "$HOME/.pkgx" ]; then
log_warn "⚠️ pkgx detected - this may interfere with iOS SQLite linking"
log_warn " If you see 'sqlite3' undefined symbol errors, try:"
log_warn " unset PKGX_DIR && unset DYLD_LIBRARY_PATH && ./scripts/build-native.sh --platform ios"
# Check for SQLite conflicts (already done in check_environment, but remind here)
if [ -d "$HOME/.pkgx" ]; then
PKGX_SQLITE=$(find "$HOME/.pkgx" -name "libsqlite3*.dylib" 2>/dev/null | head -1)
if [ -n "$PKGX_SQLITE" ]; then
log_warn "⚠️ pkgx SQLite detected - build script will handle this automatically"
log_warn " If you still see linker errors, manually run:"
log_warn " unset PKGX_DIR DYLD_LIBRARY_PATH LD_LIBRARY_PATH && ./scripts/build-native.sh --platform ios"
fi
fi
# Detect project type