sqlite: add build option to build without sqlite

Signed-off-by: Michael Dawson <midawson@redhat.com>
PR-URL: https://github.com/nodejs/node/pull/58122
Reviewed-By: Edy Silva <edigleyssonsilva@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Michael Dawson 2025-04-29 22:38:51 +00:00
parent 1350adeeaf
commit 535c2f7562
33 changed files with 144 additions and 34 deletions

View File

@ -509,16 +509,24 @@ SQLITE_BINDING_SOURCES := \
$(wildcard test/sqlite/*/*.c)
# Implicitly depends on $(NODE_EXE), see the build-sqlite-tests rule for rationale.
ifndef NOSQLITE
test/sqlite/.buildstamp: $(ADDONS_PREREQS) \
$(SQLITE_BINDING_GYPS) $(SQLITE_BINDING_SOURCES)
@$(call run_build_addons,"$$PWD/test/sqlite",$@)
else
test/sqlite/.buildstamp:
endif
.PHONY: build-sqlite-tests
ifndef NOSQLITE
# .buildstamp needs $(NODE_EXE) but cannot depend on it
# directly because it calls make recursively. The parent make cannot know
# if the subprocess touched anything so it pessimistically assumes that
# .buildstamp is out of date and need a rebuild.
build-sqlite-tests: | $(NODE_EXE) test/sqlite/.buildstamp ## Build SQLite tests.
else
build-sqlite-tests:
endif
.PHONY: clear-stalled
clear-stalled: ## Clear any stalled processes.

View File

@ -864,6 +864,12 @@ parser.add_argument('--without-node-options',
default=None,
help='build without NODE_OPTIONS support')
parser.add_argument('--without-sqlite',
action='store_true',
dest='without_sqlite',
default=None,
help='build without SQLite (disables SQLite and Web Stoage API)')
parser.add_argument('--ninja',
action='store_true',
dest='use_ninja',
@ -1816,6 +1822,16 @@ def configure_openssl(o):
configure_library('openssl', o)
def configure_sqlite(o):
o['variables']['node_use_sqlite'] = b(not options.without_sqlite)
if options.without_sqlite:
def without_sqlite_error(option):
error(f'--without-sqlite is incompatible with {option}')
if options.shared_sqlite:
without_sqlite_error('--shared-sqlite')
return
configure_library('sqlite', o, pkgname='sqlite3')
def configure_static(o):
if options.fully_static or options.partly_static:
@ -2259,7 +2275,7 @@ configure_library('cares', output, pkgname='libcares')
configure_library('nghttp2', output, pkgname='libnghttp2')
configure_library('nghttp3', output, pkgname='libnghttp3')
configure_library('ngtcp2', output, pkgname='libngtcp2')
configure_library('sqlite', output, pkgname='sqlite3')
configure_sqlite(output);
configure_library('uvwasi', output, pkgname='libuvwasi')
configure_library('zstd', output, pkgname='libzstd')
configure_v8(output, configurations)

View File

@ -25,6 +25,7 @@
'node_shared_uvwasi%': 'false',
'node_shared_nghttp2%': 'false',
'node_use_openssl%': 'true',
'node_use_sqlite%': 'true',
'node_shared_openssl%': 'false',
'node_v8_options%': '',
'node_enable_v8_vtunejit%': 'false',
@ -140,7 +141,6 @@
'src/node_shadow_realm.cc',
'src/node_snapshotable.cc',
'src/node_sockaddr.cc',
'src/node_sqlite.cc',
'src/node_stat_watcher.cc',
'src/node_symbols.cc',
'src/node_task_queue.cc',
@ -154,7 +154,6 @@
'src/node_wasi.cc',
'src/node_wasm_web_api.cc',
'src/node_watchdog.cc',
'src/node_webstorage.cc',
'src/node_worker.cc',
'src/node_zlib.cc',
'src/path.cc',
@ -275,7 +274,6 @@
'src/node_snapshot_builder.h',
'src/node_sockaddr.h',
'src/node_sockaddr-inl.h',
'src/node_sqlite.h',
'src/node_stat_watcher.h',
'src/node_union_bytes.h',
'src/node_url.h',
@ -285,7 +283,6 @@
'src/node_v8_platform-inl.h',
'src/node_wasi.h',
'src/node_watchdog.h',
'src/node_webstorage.h',
'src/node_worker.h',
'src/path.h',
'src/permission/child_process_permission.h',
@ -418,6 +415,12 @@
'test/cctest/test_inspector_socket.cc',
'test/cctest/test_inspector_socket_server.cc',
],
'node_sqlite_sources': [
'src/node_sqlite.cc',
'src/node_webstorage.cc',
'src/node_sqlite.h',
'src/node_webstorage.h',
],
'node_mksnapshot_exec': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)node_mksnapshot<(EXECUTABLE_SUFFIX)',
'node_js2c_exec': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)node_js2c<(EXECUTABLE_SUFFIX)',
'conditions': [
@ -892,6 +895,12 @@
'src/node_snapshot_stub.cc',
]
}],
[ 'node_use_sqlite=="true"', {
'sources': [
'<@(node_sqlite_sources)',
],
'defines': [ 'HAVE_SQLITE=1' ],
}],
[ 'node_shared=="true" and node_module_version!="" and OS!="win"', {
'product_extension': '<(shlib_suffix)',
'xcode_settings': {
@ -940,6 +949,12 @@
'<@(node_quic_sources)',
],
}],
[ 'node_use_sqlite=="true"', {
'sources': [
'<@(node_sqlite_sources)',
],
'defines': [ 'HAVE_SQLITE=1' ],
}],
[ 'OS in "linux freebsd mac solaris" and '
'target_arch=="x64" and '
'node_target_type=="executable"', {

View File

@ -233,7 +233,7 @@
'dependencies': [ 'deps/brotli/brotli.gyp:brotli' ],
}],
[ 'node_shared_sqlite=="false"', {
[ 'node_use_sqlite=="true" and node_shared_sqlite=="false"', {
'dependencies': [ 'deps/sqlite/sqlite.gyp:sqlite' ],
}],

View File

@ -75,7 +75,6 @@
V(serdes) \
V(signal_wrap) \
V(spawn_sync) \
V(sqlite) \
V(stream_pipe) \
V(stream_wrap) \
V(string_decoder) \
@ -95,7 +94,6 @@
V(wasi) \
V(wasm_web_api) \
V(watchdog) \
V(webstorage) \
V(worker) \
V(zlib)
@ -105,7 +103,8 @@
NODE_BUILTIN_ICU_BINDINGS(V) \
NODE_BUILTIN_PROFILER_BINDINGS(V) \
NODE_BUILTIN_DEBUG_BINDINGS(V) \
NODE_BUILTIN_QUIC_BINDINGS(V)
NODE_BUILTIN_QUIC_BINDINGS(V) \
NODE_BUILTIN_SQLITE_BINDINGS(V)
// This is used to load built-in bindings. Instead of using
// __attribute__((constructor)), we call the _register_<modname>

View File

@ -36,6 +36,14 @@ static_assert(static_cast<int>(NM_F_LINKED) ==
#define NODE_BUILTIN_QUIC_BINDINGS(V)
#endif
#if HAVE_SQLITE
#define NODE_BUILTIN_SQLITE_BINDINGS(V) \
V(sqlite) \
V(webstorage)
#else
#define NODE_BUILTIN_SQLITE_BINDINGS(V)
#endif
#define NODE_BINDINGS_WITH_PER_ISOLATE_INIT(V) \
V(async_wrap) \
V(blob) \

View File

@ -139,6 +139,9 @@ BuiltinLoader::BuiltinCategories BuiltinLoader::GetBuiltinCategories() const {
"sqlite", // Experimental.
"sys", // Deprecated.
"wasi", // Experimental.
#if !HAVE_SQLITE
"internal/webstorage", // Experimental.
#endif
"internal/test/binding", "internal/v8_prof_polyfill",
"internal/v8_prof_processor",
};
@ -686,8 +689,8 @@ void BuiltinLoader::CompileFunction(const FunctionCallbackInfo<Value>& args) {
void BuiltinLoader::HasCachedBuiltins(const FunctionCallbackInfo<Value>& args) {
auto instance = Environment::GetCurrent(args)->builtin_loader();
RwLock::ScopedReadLock lock(instance->code_cache_->mutex);
args.GetReturnValue().Set(Boolean::New(
args.GetIsolate(), instance->code_cache_->has_code_cache));
args.GetReturnValue().Set(
Boolean::New(args.GetIsolate(), instance->code_cache_->has_code_cache));
}
void SetInternalLoaders(const FunctionCallbackInfo<Value>& args) {

View File

@ -11,7 +11,9 @@
#include "node.h"
#include "simdjson.h"
#include "simdutf.h"
#if HAVE_SQLITE
#include "sqlite3.h"
#endif // HAVE_SQLITE
#include "undici_version.h"
#include "util.h"
#include "uv.h"
@ -152,7 +154,9 @@ Metadata::Versions::Versions() {
simdjson = SIMDJSON_VERSION;
simdutf = SIMDUTF_VERSION;
#if HAVE_SQLITE
sqlite = SQLITE_VERSION;
#endif // HAVE_SQLITE
ada = ADA_VERSION;
nbytes = NBYTES_VERSION;
}

View File

@ -55,7 +55,6 @@ namespace node {
V(acorn) \
V(simdjson) \
V(simdutf) \
V(sqlite) \
V(ada) \
V(nbytes) \
NODE_VERSIONS_KEY_AMARO(V) \
@ -86,11 +85,18 @@ namespace node {
#define NODE_VERSIONS_KEY_QUIC(V)
#endif
#if HAVE_SQLITE
#define NODE_VERSIONS_KEY_SQLITE(V) V(sqlite)
#else
#define NODE_VERSIONS_KEY_SQLITE(V)
#endif
#define NODE_VERSIONS_KEYS(V) \
NODE_VERSIONS_KEYS_BASE(V) \
NODE_VERSIONS_KEY_CRYPTO(V) \
NODE_VERSIONS_KEY_INTL(V) \
NODE_VERSIONS_KEY_QUIC(V)
NODE_VERSIONS_KEY_QUIC(V) \
NODE_VERSIONS_KEY_SQLITE(V)
class Metadata {
public:

View File

@ -257,6 +257,12 @@ Indicates if [internationalization][] is supported.
Indicates whether `IPv6` is supported on this platform.
### `hasSQLite`
* [\<boolean>][<boolean>]
Indicates whether SQLite is available.
### `inFreeBSDJail`
* [\<boolean>][<boolean>]
@ -481,6 +487,11 @@ at `tools/eslint/node_modules/eslint`
Skip the rest of the tests in the current file when the Inspector
was disabled at compile time.
### `skipIfSQLiteMissing()`
Skip the rest of the tests in the current file when the SQLite
was disabled at compile time.
### `skipIf32Bits()`
Skip the rest of the tests in the current file when the Node.js executable

10
test/common/index.js Normal file → Executable file
View File

@ -54,6 +54,8 @@ const noop = () => {};
const hasCrypto = Boolean(process.versions.openssl) &&
!process.env.NODE_SKIP_CRYPTO;
const hasSQLite = Boolean(process.versions.sqlite);
const hasQuic = hasCrypto && !!process.config.variables.node_quic;
function parseTestFlags(filename = process.argv[1]) {
@ -682,6 +684,12 @@ function skipIf32Bits() {
}
}
function skipIfSQLiteMissing() {
if (!hasSQLite) {
skip('missing SQLite');
}
}
function getArrayBufferViews(buf) {
const { buffer, byteOffset, byteLength } = buf;
@ -883,6 +891,7 @@ const common = {
hasIntl,
hasCrypto,
hasQuic,
hasSQLite,
invalidArgTypeHelper,
isAlive,
isASan,
@ -912,6 +921,7 @@ const common = {
skipIf32Bits,
skipIfEslintMissing,
skipIfInspectorDisabled,
skipIfSQLiteMissing,
spawnPromisified,
get enoughTestMem() {

View File

@ -16,6 +16,7 @@ const {
getBufferSources,
getTTYfd,
hasCrypto,
hasSQLite,
hasIntl,
hasIPv6,
isAIX,
@ -44,6 +45,7 @@ const {
skipIf32Bits,
skipIfEslintMissing,
skipIfInspectorDisabled,
skipIfSQLiteMissing,
spawnPromisified,
} = common;
@ -64,6 +66,7 @@ export {
getPort,
getTTYfd,
hasCrypto,
hasSQLite,
hasIntl,
hasIPv6,
isAIX,
@ -92,5 +95,6 @@ export {
skipIf32Bits,
skipIfEslintMissing,
skipIfInspectorDisabled,
skipIfSQLiteMissing,
spawnPromisified,
};

0
test/fixtures/rc/non-readable/node.config.json vendored Executable file → Normal file
View File

View File

@ -1,6 +1,7 @@
'use strict';
const { spawnPromisified } = require('../common');
const { spawnPromisified, skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const fixtures = require('../common/fixtures');
const { match, strictEqual } = require('node:assert');
const { test } = require('node:test');

View File

@ -1,5 +1,6 @@
'use strict';
const common = require('../common');
common.skipIfSQLiteMissing();
const assert = require('node:assert');
const code = `const sqlite = require('node:sqlite');

View File

@ -1,4 +1,4 @@
import { hasCrypto, hasIntl } from '../common/index.mjs';
import { hasCrypto, hasIntl, hasSQLite } from '../common/index.mjs';
import assert from 'node:assert';
import { builtinModules } from 'node:module';
import { isMainThread } from 'node:worker_threads';
@ -39,6 +39,10 @@ if (!hasIntl) {
// TODO(@jasnell): Remove this once node:quic graduates from unflagged.
publicBuiltins.delete('node:quic');
if (!hasSQLite) {
publicBuiltins.delete('node:sqlite');
}
for (const id of publicBuiltins) {
assert.strictEqual(process.getBuiltinModule(id), require(id));
}

View File

@ -21,12 +21,12 @@ const expected_keys = [
'acorn',
'simdjson',
'simdutf',
'sqlite',
'ada',
'cjs_module_lexer',
'nbytes',
];
const hasUndici = process.config.variables.node_builtin_shareable_builtins.includes('deps/undici/undici.js');
const hasAmaro = process.config.variables.node_builtin_shareable_builtins.includes('deps/amaro/dist/index.js');
@ -56,6 +56,10 @@ if (common.hasIntl) {
expected_keys.push('unicode');
}
if (common.hasSQLite) {
expected_keys.push('sqlite');
}
expected_keys.sort();
expected_keys.unshift('node');

View File

@ -1,6 +1,7 @@
import '../common/index.mjs';
import { DatabaseSync } from 'node:sqlite';
import { skipIfSQLiteMissing } from '../common/index.mjs';
import { describe, test } from 'node:test';
skipIfSQLiteMissing();
const { DatabaseSync } = await import('node:sqlite');
describe('DatabaseSync.prototype.aggregate()', () => {
describe('input validation', () => {

View File

@ -1,10 +1,11 @@
import '../common/index.mjs';
import { skipIfSQLiteMissing } from '../common/index.mjs';
import tmpdir from '../common/tmpdir.js';
import { join } from 'node:path';
import { backup, DatabaseSync } from 'node:sqlite';
import { describe, test } from 'node:test';
import { writeFileSync } from 'node:fs';
import { pathToFileURL } from 'node:url';
skipIfSQLiteMissing();
const { backup, DatabaseSync } = await import('node:sqlite');
let cnt = 0;

View File

@ -1,5 +1,6 @@
'use strict';
require('../common');
const { skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const assert = require('node:assert');
const { DatabaseSync } = require('node:sqlite');
const { suite, test } = require('node:test');

View File

@ -1,5 +1,6 @@
'use strict';
require('../common');
const { skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const tmpdir = require('../common/tmpdir');
const { join } = require('node:path');
const { DatabaseSync } = require('node:sqlite');

View File

@ -1,5 +1,6 @@
'use strict';
require('../common');
const { skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const tmpdir = require('../common/tmpdir');
const assert = require('node:assert');
const { join } = require('node:path');

View File

@ -1,5 +1,6 @@
'use strict';
require('../common');
const { skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const tmpdir = require('../common/tmpdir');
const { existsSync } = require('node:fs');
const { join } = require('node:path');

View File

@ -1,5 +1,6 @@
'use strict';
require('../common');
const { skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const tmpdir = require('../common/tmpdir');
const { join } = require('node:path');
const { DatabaseSync } = require('node:sqlite');

View File

@ -1,6 +1,7 @@
// Flags: --experimental-sqlite
'use strict';
require('../common');
const { skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const {
DatabaseSync,
constants,

View File

@ -1,5 +1,6 @@
'use strict';
require('../common');
const { skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const assert = require('node:assert');
const { DatabaseSync } = require('node:sqlite');
const { suite, test } = require('node:test');

View File

@ -1,6 +1,7 @@
// Flags: --expose-gc
'use strict';
require('../common');
const { skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const tmpdir = require('../common/tmpdir');
const { join } = require('node:path');
const { DatabaseSync, StatementSync } = require('node:sqlite');

View File

@ -1,5 +1,6 @@
'use strict';
require('../common');
const { skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const tmpdir = require('../common/tmpdir');
const { join } = require('node:path');
const { DatabaseSync } = require('node:sqlite');

View File

@ -1,5 +1,6 @@
'use strict';
require('../common');
const { skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const tmpdir = require('../common/tmpdir');
const { join } = require('node:path');
const { DatabaseSync } = require('node:sqlite');

View File

@ -1,5 +1,6 @@
'use strict';
require('../common');
const { skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const tmpdir = require('../common/tmpdir');
const { join } = require('node:path');
const { DatabaseSync } = require('node:sqlite');

View File

@ -1,5 +1,6 @@
'use strict';
const { spawnPromisified } = require('../common');
const { spawnPromisified, skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const tmpdir = require('../common/tmpdir');
const { join } = require('node:path');
const { DatabaseSync, constants } = require('node:sqlite');

View File

@ -1,11 +1,11 @@
'use strict';
const common = require('../common');
const { skipIfSQLiteMissing, spawnPromisified } = require('../common');
skipIfSQLiteMissing();
const tmpdir = require('../common/tmpdir');
const assert = require('node:assert');
const { join } = require('node:path');
const { readdir } = require('node:fs/promises');
const { test, describe } = require('node:test');
const { spawnPromisified } = common;
let cnt = 0;
tmpdir.refresh();

View File

@ -1,4 +1,6 @@
'use strict';
const { skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const tmpdir = require('../common/tmpdir');
const { WPTRunner } = require('../common/wpt');
const { join } = require('node:path');