Add initial support for building with extensions

This commit is contained in:
2026-05-19 00:26:53 +09:00
parent 72b6cf722a
commit 9cd0e995bd
8 changed files with 281 additions and 29 deletions
+55 -6
View File
@@ -22,7 +22,7 @@
enableDebug = [ true false ];
enableInteractive = [ true false ];
};
in lib.mergeAttrsList (lib.mapCartesianProduct (args@{
in lib.mergeAttrsList (lib.mapCartesianProduct ({
enableMinimal,
enableDebug,
enableInteractive,
@@ -35,11 +35,60 @@
enableInteractive;
};
in {
"sqlite${result.suffix}" = result.sqlite;
"sqlite-amalgamation${result.suffix}" = result.amalgamation;
"sqlite-cli${result.suffix}" = result.sqlite-cli;
"sqlite-static${result.suffix}" = result.sqlite-static;
"sqlite${result._suffix}" = result.sqlite;
"sqlite-amalgamation${result._suffix}" = result.amalgamation;
"sqlite-cli${result._suffix}" = result.sqlite-cli;
"sqlite-static${result._suffix}" = result.sqlite-static;
}) productVars));
checks = forAllSystems (system: pkgs: let
sqlite-example-exts-static = pkgs.stdenv.mkDerivation {
name = "sqlite-example-exts-static";
src = ./sqlite-example-exts;
env.NIX_CFLAGS_COMPILE = "-DSQLITE_CORE";
buildInputs = with pkgs; [ sqlite.dev ];
buildPhase = ''
runHook preBuild
"$CC" -c addext.c
"$AR" rcs libaddext.a addext.o
"$CC" -c subext.c
"$AR" rcs libsubext.a subext.o
runHook postBuild
'';
installPhase = ''
runHook preInstall
install -Dm444 *.a -t "$out/lib"
runHook postInstall
'';
};
sqlite-with-static-exts = self.mkSqlite {
inherit pkgs;
extensions = [
{
library = "${sqlite-example-exts-static}/lib/libaddext.a";
init = "sqlite3_addext_init";
}
{
library = "${sqlite-example-exts-static}/lib/libsubext.a";
init = "sqlite3_subext_init";
}
];
};
in {
inherit sqlite-example-exts-static;
sqlite-with-static-ext = sqlite-with-static-exts.sqlite;
sqlite-cli-with-static-ext = sqlite-with-static-exts.sqlite-cli;
});
};
}
+38
View File
@@ -0,0 +1,38 @@
#include <sqlite3ext.h>
SQLITE_EXTENSION_INIT1
static void add_func(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
) {
if (argc != 2) {
sqlite3_result_null(ctx);
return;
}
int a = sqlite3_value_int(argv[0]);
int b = sqlite3_value_int(argv[1]);
sqlite3_result_int(ctx, a + b);
}
int sqlite3_addext_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
) {
SQLITE_EXTENSION_INIT2(pApi);
return sqlite3_create_function(
db,
"add",
2,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
0,
add_func,
0,
0
);
}
+38
View File
@@ -0,0 +1,38 @@
#include <sqlite3ext.h>
SQLITE_EXTENSION_INIT1
static void sub_func(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
) {
if (argc != 2) {
sqlite3_result_null(ctx);
return;
}
int a = sqlite3_value_int(argv[0]);
int b = sqlite3_value_int(argv[1]);
sqlite3_result_int(ctx, a - b);
}
int sqlite3_subext_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
) {
SQLITE_EXTENSION_INIT2(pApi);
return sqlite3_create_function(
db,
"sub",
2,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
0,
sub_func,
0,
0
);
}
+4 -2
View File
@@ -11,8 +11,10 @@
zlib,
icu,
features,
featureFlags,
extensions ? [ ],
extraLibraries ? [ ],
features ? { },
featureFlags ? [ ],
enableInteractive ? false,
...
+87
View File
@@ -0,0 +1,87 @@
{
lib,
extensions,
nameSuffix,
version,
stdenv,
writeText,
...
}:
assert lib.assertMsg (extensions != [ ]) "This derivation should not be evaluated if there are no extensions to build.";
# TODO: assert no colliding init/shutdown symbols across extensions.
let
initSymbols = builtins.catAttrs "init" extensions;
shutdownSymbols = builtins.catAttrs "shutdown" extensions;
coreInitHeaders = writeText "sqlite-core-init.h" ''
int core_init(const char *dummy);
void core_shutdown(void);
${lib.concatMapStringsSep "\n" (sym: "int ${sym}(const char *dummy);") initSymbols}
${lib.concatMapStringsSep "\n" (sym: "void ${sym}(void);") shutdownSymbols}
'';
coreInitImpl = writeText "sqlite-core-init.c" ''
#include "${coreInitHeaders}"
int core_init(const char *dummy) {
int err = 0;
${lib.concatMapStringsSep "\n" (sym: "err += ${sym}(dummy);") initSymbols}
return err;
}
void core_shutdown(void) {
${lib.concatMapStringsSep "\n" (sym: "${sym}();") shutdownSymbols}
}
'';
in stdenv.mkDerivation (finalAttrs: {
pname = "sqlite-core-init${nameSuffix}";
version = version;
src = null;
dontUnpack = true;
buildPhase = ''
runHook preBuild
"$CC" -c '${coreInitImpl}' -o sqlite-core-init.o
runHook postBuild
'';
installPhase = ''
runHook preInstall
install -Dm644 '${coreInitHeaders}' "$out/include/sqlite-core-init.h"
mkdir -p "$out/lib"
"$AR" rcs "$out/lib/libsqlite-core-init.a" sqlite-core-init.o
runHook postInstall
'';
# TODO: Add a checkphase that runs nm on the provided extensions to ensure the expected symbols are present.
# Also verify that the `sqlite_api` symbol is not present, and give a nice warning about using -DSQLITE_CORE
# if it is.
passthru = {
extraLDFLAGS = [
"-L${finalAttrs.finalPackage}/lib"
"-lsqlite-core-init"
] ++ lib.concatMap (ext: [
"-L${lib.dirOf ext.library}"
"-l${lib.removeSuffix ".so" (lib.removeSuffix ".a" (lib.removePrefix "lib" (lib.baseNameOf ext.library)))}"
]) extensions;
extraMakeFlags = let
opts = [
"-DSQLITE_EXTRA_INIT=core_init"
"-DSQLITE_EXTRA_SHUTDOWN=core_shutdown"
"-DSQLITE_CUSTOM_INCLUDE=${placeholder "out"}/include/sqlite-core-init.h"
];
in map (opt: "OPTIONS+=${lib.escapeShellArg opt}") opts;
};
})
+42 -9
View File
@@ -25,12 +25,21 @@
features ? { },
# Custom SQLite extensions and their entrypoints.
# extensions ? [ ],
#
# extensions :: [{ library :: str, init :: str, shutdown :: nullOr str }]
extensions ? [ ],
# Additional libraries to link against, useful when the extensions
# use external libraries.
# extraLibraries ? [ ],
}: let
extraLibraries ? [ ],
}:
assert lib.assertMsg (extensions == [ ] -> extraLibraries == [ ]) "If no extensions are specified, extraLibraries must be empty.";
# TODO: fix compiling with extensions with amalgamation turned off
assert lib.assertMsg (extensions != [ ] -> amalgamate) "Building with extensions without amalgamation is not currently supported.";
let
config = (lib.evalModules {
modules = [
./build-config.nix
@@ -53,32 +62,56 @@
(lib.concatStringsSep "-")
(x: if x == "" then "" else "-${x}")
];
coreInitExt = if extensions == [ ]
then null
else pkgs.callPackage ./core-init-ext.nix ({
inherit version src;
inherit extensions;
inherit extraLibraries;
nameSuffix = suffix;
} // config);
in {
inherit config;
inherit suffix;
_config = config;
_suffix = suffix;
_coreInitExt = coreInitExt;
sqlite = pkgs.callPackage ./sqlite.nix ({
inherit (pkgs.sqlite) version src;
inherit version src;
inherit amalgamate;
inherit features;
inherit extensions;
inherit extraLibraries;
inherit coreInitExt;
nameSuffix = suffix;
static = false;
} // config);
sqlite-static = pkgs.callPackage ./sqlite.nix ({
inherit (pkgs.sqlite) version src;
inherit version src;
inherit amalgamate;
inherit features;
inherit extensions;
inherit extraLibraries;
inherit coreInitExt;
nameSuffix = suffix;
static = true;
} // config);
sqlite-cli = pkgs.callPackage ./sqlite-cli.nix ({
inherit (pkgs.sqlite) version src;
inherit version src;
inherit amalgamate;
inherit features;
inherit extensions;
inherit extraLibraries;
nameSuffix = suffix;
} // config);
} // lib.optionalAttrs amalgamate {
amalgamation = pkgs.callPackage ./amalgamation.nix ({
inherit (pkgs.sqlite) version src;
inherit version src;
inherit features;
inherit extensions;
inherit extraLibraries;
nameSuffix = suffix;
} // config);
}
+8 -6
View File
@@ -11,9 +11,10 @@
zlib,
icu,
amalgamate,
features,
featureFlags,
amalgamate ? true,
coreInitExt ? null,
features ? { },
featureFlags ? [ ],
enableInteractive ? false,
...
@@ -57,8 +58,9 @@ stdenv.mkDerivation (finalAttrs: {
"--with-icu-config=${lib.getExe' icu.dev "icu-config"}"
];
env.NIX_CFLAGS_COMPILE = lib.concatStringsSep " " featureFlags;
env.NIX_CFLAGS_LINK = lib.optionalString features.ENABLE_FTS5 "-lm";
makeTarget = "sqlite3";
makeFlags = (coreInitExt.passthru.makeFlags or [ ]) ++ map (opt: "OPTIONS+=${lib.escapeShellArg opt}") featureFlags;
env.NIX_CFLAGS_LINK = lib.optionalString features.ENABLE_FTS5 "-lm";
env.NIX_LDFLAGS = lib.concatStringsSep " " (coreInitExt.passthru.extraLDFLAGS or [ ]);
})
+9 -6
View File
@@ -13,9 +13,10 @@
zlib,
icu,
amalgamate,
features,
featureFlags,
amalgamate ? true,
coreInitExt ? null,
features ? { },
featureFlags ? [ ],
enableInteractive ? false,
...
@@ -54,13 +55,15 @@ stdenv.mkDerivation (finalAttrs: {
"--${if static then "disable" else "enable"}-shared"
"--${if static then "enable" else "disable"}-static"
"--${if amalgamate then "enable" else "disable"}-amalgamation"
] ++ lib.optional features.ENABLE_ICU [
"--enable-icu-collations"
"--with-icu-config=${lib.getExe' icu.dev "icu-config"}"
];
env.NIX_CFLAGS_COMPILE = lib.concatStringsSep " " featureFlags;
env.NIX_CFLAGS_LINK = lib.optionalString features.ENABLE_FTS5 "-lm";
makeTarget = if static then "lib" else "so";
makeFlags = (coreInitExt.passthru.makeFlags or [ ]) ++ map (opt: "OPTIONS+=${lib.escapeShellArg opt}") featureFlags;
makeTarget = "sqlite3.la";
env.NIX_CFLAGS_LINK = lib.optionalString features.ENABLE_FTS5 "-lm";
env.NIX_LDFLAGS = lib.concatStringsSep " " (coreInitExt.passthru.extraLDFLAGS or [ ]);
})