Skip to content

Commit 1056be2

Browse files
authored
Add SQLite port (sqlite3) (#17297)
The SQLite port adds `-sUSE_SQLITE3`. Internally it uses sqlite amalgamation (single file distribution). The port creates `libsqlite3.a` (non-threaded) or `libsqlite3-mt.a` (multi-threaded).
1 parent 6fecf8c commit 1056be2

File tree

5 files changed

+115
-32
lines changed

5 files changed

+115
-32
lines changed

embuilder.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
'crt1_proxy_main',
6262
'libunwind-except',
6363
'libnoexit',
64+
'sqlite3',
65+
'sqlite3-mt',
6466
]
6567

6668
# Additional tasks on top of MINIMAL_TASKS that are necessary for PIC testing on
@@ -103,6 +105,7 @@
103105
'sdl2_image_png': ('sdl2_image', {'SDL2_IMAGE_FORMATS': ["png"]}),
104106
'sdl2_image_jpg': ('sdl2_image', {'SDL2_IMAGE_FORMATS': ["jpg"]}),
105107
'libpng-mt': ('libpng', {'USE_PTHREADS': 1}),
108+
'sqlite3-mt': ('sqlite3', {'USE_PTHREADS': 1}),
106109
}
107110

108111
PORTS = sorted(list(ports.ports_by_name.keys()) + list(PORT_VARIANTS.keys()))

src/settings.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,10 @@ var SDL2_IMAGE_FORMATS = [];
14981498
// [link]
14991499
var SDL2_MIXER_FORMATS = ["ogg"];
15001500

1501+
// 1 = use sqlite3 from emscripten-ports
1502+
// [link]
1503+
var USE_SQLITE3 = false;
1504+
15011505
// If true, the current build is performed for the Emscripten test harness.
15021506
// [other]
15031507
var IN_TEST_HARNESS = false;

tests/test_core.py

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6665,38 +6665,20 @@ def test_freetype(self):
66656665
@no_asan('local count too large for VMs')
66666666
@no_ubsan('local count too large for VMs')
66676667
@is_slow_test
6668-
def test_sqlite(self):
6669-
self.set_setting('EXPORTED_FUNCTIONS', ['_main', '_sqlite3_open', '_sqlite3_close', '_sqlite3_exec', '_sqlite3_free'])
6670-
if '-g' in self.emcc_args:
6671-
print("disabling inlining") # without registerize (which -g disables), we generate huge amounts of code
6672-
self.set_setting('INLINING_LIMIT')
6673-
6674-
# newer clang has a warning for implicit conversions that lose information,
6675-
# which happens in sqlite (see #9138)
6676-
self.emcc_args += ['-Wno-implicit-int-float-conversion']
6677-
# newer clang warns about "suspicious concatenation of string literals in an
6678-
# array initialization; did you mean to separate the elements with a comma?"
6679-
self.emcc_args += ['-Wno-string-concatenation']
6680-
# ignore unknown flags, which lets the above flags be used on github CI
6681-
# before the LLVM change rolls in (the same LLVM change that adds the
6682-
# warning also starts to warn on it)
6683-
self.emcc_args += ['-Wno-unknown-warning-option']
6684-
self.emcc_args += ['-Wno-pointer-bool-conversion']
6685-
6686-
self.emcc_args += ['-I' + test_file('third_party/sqlite')]
6687-
6688-
src = '''
6689-
#define SQLITE_DISABLE_LFS
6690-
#define LONGDOUBLE_TYPE double
6691-
#define SQLITE_INT64_TYPE long long int
6692-
#define SQLITE_THREADSAFE 0
6693-
'''
6694-
src += read_file(test_file('third_party/sqlite/sqlite3.c'))
6695-
src += read_file(test_file('sqlite/benchmark.c'))
6696-
self.do_run(src,
6697-
read_file(test_file('sqlite/benchmark.txt')),
6698-
includes=[test_file('sqlite')],
6699-
force_c=True)
6668+
@parameterized({
6669+
'': (False,),
6670+
'pthreads': (True,),
6671+
})
6672+
def test_sqlite(self, use_pthreads):
6673+
if use_pthreads:
6674+
self.set_setting('USE_PTHREADS')
6675+
self.setup_node_pthreads()
6676+
self.emcc_args += ['-sUSE_SQLITE3']
6677+
self.do_run_from_file(
6678+
test_file('sqlite/benchmark.c'),
6679+
test_file('sqlite/benchmark.txt'),
6680+
force_c=True
6681+
)
67006682

67016683
@needs_make('mingw32-make')
67026684
@is_slow_test

tools/ports/sqlite3.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Copyright 2022 The Emscripten Authors. All rights reserved.
2+
# Emscripten is available under two separate licenses, the MIT license and the
3+
# University of Illinois/NCSA Open Source License. Both these licenses can be
4+
# found in the LICENSE file.
5+
6+
import os
7+
import shutil
8+
import logging
9+
10+
# sqlite amalgamation download URL uses relase year and tag
11+
# 2022 and (3, 38, 5) -> '/2022/sqlite-amalgamation-3380500.zip'
12+
VERSION = (3, 39, 0)
13+
VERSION_YEAR = 2022
14+
HASH = 'cbaf4adb3e404d9aa403b34f133c5beca5f641ae1e23f84dbb021da1fb9efdc7c56b5922eb533ae5cb6d26410ac60cb3f026085591bc83ebc1c225aed0cf37ca'
15+
16+
deps = []
17+
18+
19+
def needed(settings):
20+
return settings.USE_SQLITE3
21+
22+
23+
def get_lib_name(settings):
24+
return 'libsqlite3' + ('-mt' if settings.USE_PTHREADS else '') + '.a'
25+
26+
27+
def get(ports, settings, shared):
28+
release = f'sqlite-amalgamation-{VERSION[0]}{VERSION[1]:02}{VERSION[2]:02}00'
29+
# TODO: Fetch the file from an emscripten-hosted mirror.
30+
ports.fetch_project('sqlite3', f'https://www.sqlite.org/{VERSION_YEAR}/{release}.zip', release, sha512hash=HASH)
31+
32+
def create(final):
33+
logging.info('building port: libsqlite3')
34+
35+
source_path = os.path.join(ports.get_dir(), 'sqlite3', release)
36+
dest_path = os.path.join(ports.get_build_dir(), 'sqlite3')
37+
38+
shutil.rmtree(dest_path, ignore_errors=True)
39+
shutil.copytree(source_path, dest_path)
40+
41+
ports.install_headers(dest_path)
42+
43+
# flags are based on sqlite-autoconf output.
44+
# SQLITE_HAVE_ZLIB is only used by shell.c
45+
flags = [
46+
'-DSTDC_HEADERS=1',
47+
'-DHAVE_SYS_TYPES_H=1',
48+
'-DHAVE_SYS_STAT_H=1',
49+
'-DHAVE_STDLIB_H=1',
50+
'-DHAVE_STRING_H=1',
51+
'-DHAVE_MEMORY_H=1',
52+
'-DHAVE_STRINGS_H=1',
53+
'-DHAVE_INTTYPES_H=1',
54+
'-DHAVE_STDINT_H=1',
55+
'-DHAVE_UNISTD_H=1',
56+
'-DHAVE_FDATASYNC=1',
57+
'-DHAVE_USLEEP=1',
58+
'-DHAVE_LOCALTIME_R=1',
59+
'-DHAVE_GMTIME_R=1',
60+
'-DHAVE_DECL_STRERROR_R=1',
61+
'-DHAVE_STRERROR_R=1',
62+
'-DHAVE_POSIX_FALLOCATE=1',
63+
'-DSQLITE_OMIT_LOAD_EXTENSION=1',
64+
'-DSQLITE_ENABLE_MATH_FUNCTIONS=1',
65+
'-DSQLITE_ENABLE_FTS4=1',
66+
'-DSQLITE_ENABLE_FTS5=1',
67+
'-DSQLITE_ENABLE_RTREE=1',
68+
'-DSQLITE_ENABLE_GEOPOLY=1',
69+
'-DSQLITE_OMIT_POPEN=1',
70+
]
71+
if settings.USE_PTHREADS:
72+
flags += [
73+
'-sUSE_PTHREADS',
74+
'-DSQLITE_THREADSAFE=1',
75+
]
76+
else:
77+
flags += ['-DSQLITE_THREADSAFE=0']
78+
79+
ports.build_port(dest_path, final, flags=flags, exclude_files=['shell.c'])
80+
81+
return [shared.Cache.get_lib(get_lib_name(settings), create, what='port')]
82+
83+
84+
def clear(ports, settings, shared):
85+
shared.Cache.erase_lib(get_lib_name(settings))
86+
87+
88+
def process_args(ports):
89+
return []
90+
91+
92+
def show():
93+
return 'sqlite (USE_SQLITE3=1); public domain)'

tools/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
'USE_FREETYPE',
4848
'SDL2_MIXER_FORMATS',
4949
'SDL2_IMAGE_FORMATS',
50+
'USE_SQLITE3',
5051
}
5152

5253
# Subset of settings that apply at compile time.

0 commit comments

Comments
 (0)