|
| 1 | +import 'dart:io'; |
| 2 | + |
| 3 | +import 'package:path/path.dart' as p; |
| 4 | + |
| 5 | +typedef SqliteVersion = ({String version, String year}); |
| 6 | + |
| 7 | +const SqliteVersion latest = (version: '3500200', year: '2025'); |
| 8 | +const SqliteVersion minimum = (version: '3440000', year: '2023'); |
| 9 | + |
| 10 | +Future<void> main(List<String> args) async { |
| 11 | + if (args.contains('version')) { |
| 12 | + print(latest.version); |
| 13 | + exit(0); |
| 14 | + } |
| 15 | + |
| 16 | + await _downloadAndCompile('latest', latest, force: args.contains('--force')); |
| 17 | + await _downloadAndCompile('minimum', minimum, |
| 18 | + force: args.contains('--force')); |
| 19 | +} |
| 20 | + |
| 21 | +extension on SqliteVersion { |
| 22 | + String get autoconfUrl => |
| 23 | + 'https://sqlite.org/$year/sqlite-autoconf-$version.tar.gz'; |
| 24 | +} |
| 25 | + |
| 26 | +Future<void> _downloadAndCompile(String name, SqliteVersion version, |
| 27 | + {bool force = false}) async { |
| 28 | + final dartDirectory = p.dirname(p.dirname(Platform.script.toFilePath())); |
| 29 | + final target = p.join(dartDirectory, '.dart_tool', 'sqlite3', name); |
| 30 | + final versionFile = File(p.join(target, 'version')); |
| 31 | + |
| 32 | + final needsDownload = force || |
| 33 | + !versionFile.existsSync() || |
| 34 | + versionFile.readAsStringSync() != version.version; |
| 35 | + |
| 36 | + if (!needsDownload) { |
| 37 | + print( |
| 38 | + 'Not downloading sqlite3 $name as it has already been downloaded. Use ' |
| 39 | + '--force to re-compile it.', |
| 40 | + ); |
| 41 | + return; |
| 42 | + } |
| 43 | + |
| 44 | + print('Downloading and compiling sqlite3 $name (${version.version})'); |
| 45 | + final targetDirectory = Directory(target); |
| 46 | + |
| 47 | + if (!targetDirectory.existsSync()) { |
| 48 | + targetDirectory.createSync(recursive: true); |
| 49 | + } |
| 50 | + |
| 51 | + final temporaryDir = |
| 52 | + await Directory.systemTemp.createTemp('powersync-core-compile-sqlite3'); |
| 53 | + final temporaryDirPath = temporaryDir.path; |
| 54 | + |
| 55 | + await _run('curl -L ${version.autoconfUrl} --output sqlite.tar.gz', |
| 56 | + workingDirectory: temporaryDirPath); |
| 57 | + await _run('tar zxvf sqlite.tar.gz', workingDirectory: temporaryDirPath); |
| 58 | + |
| 59 | + final sqlitePath = |
| 60 | + p.join(temporaryDirPath, 'sqlite-autoconf-${version.version}'); |
| 61 | + |
| 62 | + await _run('./configure', workingDirectory: sqlitePath); |
| 63 | + await _run('make -j', workingDirectory: sqlitePath); |
| 64 | + |
| 65 | + await File(p.join(sqlitePath, 'sqlite3')).copy(p.join(target, 'sqlite3')); |
| 66 | + final libsPath = name == 'latest' ? sqlitePath : p.join(sqlitePath, '.libs'); |
| 67 | + |
| 68 | + if (Platform.isLinux) { |
| 69 | + await File(p.join(libsPath, 'libsqlite3.so')) |
| 70 | + .copy(p.join(target, 'libsqlite3.so')); |
| 71 | + } else if (Platform.isMacOS) { |
| 72 | + await File(p.join(libsPath, 'libsqlite3.dylib')) |
| 73 | + .copy(p.join(target, 'libsqlite3.dylib')); |
| 74 | + } |
| 75 | + |
| 76 | + await File(p.join(target, 'version')).writeAsString(version.version); |
| 77 | +} |
| 78 | + |
| 79 | +Future<void> _run(String command, {String? workingDirectory}) async { |
| 80 | + print('Running $command'); |
| 81 | + |
| 82 | + final proc = await Process.start( |
| 83 | + 'sh', |
| 84 | + ['-c', command], |
| 85 | + mode: ProcessStartMode.inheritStdio, |
| 86 | + workingDirectory: workingDirectory, |
| 87 | + ); |
| 88 | + final exitCode = await proc.exitCode; |
| 89 | + |
| 90 | + if (exitCode != 0) { |
| 91 | + exit(exitCode); |
| 92 | + } |
| 93 | +} |
0 commit comments