Add initial support for building with extensions
This commit is contained in:
@@ -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;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
@@ -11,8 +11,10 @@
|
||||
zlib,
|
||||
icu,
|
||||
|
||||
features,
|
||||
featureFlags,
|
||||
extensions ? [ ],
|
||||
extraLibraries ? [ ],
|
||||
features ? { },
|
||||
featureFlags ? [ ],
|
||||
enableInteractive ? false,
|
||||
|
||||
...
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 [ ]);
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user