Skip to content

Commit

Permalink
Merge pull request #179 from vrischmann/use-upstream
Browse files Browse the repository at this point in the history
Use upstream sqlite
  • Loading branch information
vrischmann authored Feb 16, 2025
2 parents cd7d1c3 + 2ae20ae commit cbc803e
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 274,927 deletions.
16 changes: 0 additions & 16 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,3 @@ jobs:
- name: Run Tests in memory
if: ${{ matrix.os != 'ubuntu-24.04' }}
run: zig build test -Dci=true -Din_memory=true --summary all

test-loadable-extension:
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup zig
uses: goto-bus-stop/setup-zig@v2
with:
version: master

- name: Build the example zigcrypto loadable extension
run: zig build zigcrypto
- name: Test the zigcrypto loadable extension
run: ./zig-out/bin/zigcrypto-test
231 changes: 156 additions & 75 deletions build.zig
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
const std = @import("std");
const builtin = @import("builtin");
const Step = std.Build.Step;
const debug = std.debug;
const heap = std.heap;
const mem = std.mem;
const ResolvedTarget = std.Build.ResolvedTarget;
const Query = std.Target.Query;
const builtin = @import("builtin");

const Preprocessor = @import("build/Preprocessor.zig");

fn getTarget(original_target: ResolvedTarget) ResolvedTarget {
var tmp = original_target;
Expand Down Expand Up @@ -104,6 +108,31 @@ fn computeTestTargets(isNative: bool, ci: ?bool) ?[]const TestTarget {
return null;
}

// This creates a SQLite static library from the SQLite dependency code.
fn makeSQLiteLib(b: *std.Build, dep: *std.Build.Dependency, c_flags: []const []const u8, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, sqlite_c: enum { with, without }) *std.Build.Step.Compile {
const lib = b.addStaticLibrary(.{
.name = "sqlite",
.target = target,
.optimize = optimize,
});

lib.addIncludePath(dep.path("."));
lib.addIncludePath(b.path("c"));
if (sqlite_c == .with) {
lib.addCSourceFile(.{
.file = dep.path("sqlite3.c"),
.flags = c_flags,
});
}
lib.addCSourceFile(.{
.file = b.path("c/workaround.c"),
.flags = c_flags,
});
lib.linkLibC();

return lib;
}

pub fn build(b: *std.Build) !void {
const in_memory = b.option(bool, "in_memory", "Should the tests run with sqlite in memory (default true)") orelse true;
const dbfile = b.option([]const u8, "dbfile", "Always use this database file instead of a temporary one");
Expand All @@ -113,6 +142,14 @@ pub fn build(b: *std.Build) !void {
const target = b.resolveTargetQuery(query);
const optimize = b.standardOptimizeOption(.{});

// Upstream dependency
const sqlite_dep = b.dependency("sqlite", .{
.target = target,
.optimize = optimize,
});

// Define C flags to use

var flags = std.ArrayList([]const u8).init(b.allocator);
defer flags.deinit();
try flags.append("-std=c99");
Expand All @@ -131,50 +168,41 @@ pub fn build(b: *std.Build) !void {

const c_flags = flags.items;

const sqlite_lib = b.addStaticLibrary(.{
.name = "sqlite",
.target = target,
.optimize = optimize,
});
//
// Main library and module
//

sqlite_lib.addIncludePath(b.path("c/"));
sqlite_lib.addCSourceFiles(.{
.files = &[_][]const u8{
"c/sqlite3.c",
"c/workaround.c",
},
.flags = c_flags,
});
sqlite_lib.linkLibC();
sqlite_lib.installHeader(b.path("c/sqlite3.h"), "sqlite3.h");
const sqlite_lib, const sqlite_mod = blk: {
const lib = makeSQLiteLib(b, sqlite_dep, c_flags, target, optimize, .with);

b.installArtifact(sqlite_lib);
const mod = b.addModule("sqlite", .{
.root_source_file = b.path("sqlite.zig"),
.link_libc = true,
});
mod.addIncludePath(b.path("c"));
mod.addIncludePath(sqlite_dep.path("."));
mod.linkLibrary(lib);

// Create the public 'sqlite' module to be exported
const sqlite_mod = b.addModule("sqlite", .{
.root_source_file = b.path("sqlite.zig"),
.link_libc = true,
});
sqlite_mod.addIncludePath(b.path("c/"));
sqlite_mod.linkLibrary(sqlite_lib);
break :blk .{ lib, mod };
};
b.installArtifact(sqlite_lib);

// Tool to preprocess the sqlite header files.
//
// Due to limitations of translate-c the standard header files can't be used for building loadable extensions
// so we have this tool which creates usable header files.
const sqliteext_mod = blk: {
const lib = makeSQLiteLib(b, sqlite_dep, c_flags, target, optimize, .without);

const preprocess_files_tool = b.addExecutable(.{
.name = "preprocess-files",
.root_source_file = b.path("tools/preprocess_files.zig"),
.target = getTarget(target),
.optimize = optimize,
});
const mod = b.addModule("sqliteext", .{
.root_source_file = b.path("sqlite.zig"),
.link_libc = true,
});
mod.addIncludePath(b.path("c"));
mod.linkLibrary(lib);

// Add a top-level step to run the preprocess-files tool
const preprocess_files_run = b.step("preprocess-files", "Run the preprocess-files tool");
break :blk mod;
};

const preprocess_files_tool_run = b.addRunArtifact(preprocess_files_tool);
preprocess_files_run.dependOn(&preprocess_files_tool_run.step);
//
// Tests
//

const test_targets = computeTestTargets(query.isNative(), ci) orelse &[_]TestTarget{.{
.query = query,
Expand All @@ -195,19 +223,7 @@ pub fn build(b: *std.Build) !void {
single_threaded_txt,
});

const test_sqlite_lib = b.addStaticLibrary(.{
.name = "sqlite",
.target = cross_target,
.optimize = optimize,
});
test_sqlite_lib.addCSourceFiles(.{
.files = &[_][]const u8{
"c/sqlite3.c",
"c/workaround.c",
},
.flags = c_flags,
});
test_sqlite_lib.linkLibC();
const test_sqlite_lib = makeSQLiteLib(b, sqlite_dep, c_flags, cross_target, optimize, .with);

const tests = b.addTest(.{
.name = test_name,
Expand All @@ -217,6 +233,7 @@ pub fn build(b: *std.Build) !void {
.single_threaded = test_target.single_threaded,
});
tests.addIncludePath(b.path("c"));
tests.addIncludePath(sqlite_dep.path("."));
tests.linkLibrary(test_sqlite_lib);

const tests_options = b.addOptions();
Expand All @@ -229,55 +246,119 @@ pub fn build(b: *std.Build) !void {
test_step.dependOn(&run_tests.step);
}

const lib = b.addStaticLibrary(.{
.name = "sqlite",
.target = getTarget(target),
.optimize = optimize,
});
lib.addCSourceFile(.{ .file = b.path("c/sqlite3.c"), .flags = c_flags });
lib.addIncludePath(b.path("c"));
lib.linkLibC();
// This builds an example shared library with the extension and a binary that tests it.

const zigcrypto_install_artifact = addZigcrypto(b, sqliteext_mod, target, optimize);
test_step.dependOn(&zigcrypto_install_artifact.step);

const zigcrypto_test_run = addZigcryptoTestRun(b, sqlite_mod, target, optimize);
zigcrypto_test_run.step.dependOn(&zigcrypto_install_artifact.step);
test_step.dependOn(&zigcrypto_test_run.step);

//
// Examples
// Tools
//

// Loadable extension
//
// This builds an example shared library with the extension and a binary that tests it.
addPreprocessStep(b, sqlite_dep);
}

fn addPreprocessStep(b: *std.Build, sqlite_dep: *std.Build.Dependency) void {
var wf = b.addWriteFiles();

// Preprocessing step
const preprocess = PreprocessStep.create(b, .{
.source = sqlite_dep.path("."),
.target = wf.getDirectory(),
});
preprocess.step.dependOn(&wf.step);

const w = b.addUpdateSourceFiles();
w.addCopyFileToSource(preprocess.target.join(b.allocator, "loadable-ext-sqlite3.h") catch @panic("OOM"), "c/loadable-ext-sqlite3.h");
w.addCopyFileToSource(preprocess.target.join(b.allocator, "loadable-ext-sqlite3ext.h") catch @panic("OOM"), "c/loadable-ext-sqlite3ext.h");
w.step.dependOn(&preprocess.step);

const zigcrypto_loadable_ext = b.addSharedLibrary(.{
const preprocess_headers = b.step("preprocess-headers", "Preprocess the headers for the loadable extensions");
preprocess_headers.dependOn(&w.step);
}

fn addZigcrypto(b: *std.Build, sqlite_mod: *std.Build.Module, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.InstallArtifact {
const exe = b.addSharedLibrary(.{
.name = "zigcrypto",
.root_source_file = b.path("examples/zigcrypto.zig"),
.version = null,
.target = getTarget(target),
.optimize = optimize,
});
zigcrypto_loadable_ext.addIncludePath(b.path("c"));
zigcrypto_loadable_ext.root_module.addImport("sqlite", sqlite_mod);
zigcrypto_loadable_ext.linkLibrary(lib);
exe.root_module.addImport("sqlite", sqlite_mod);

const install_zigcrypto_loadable_ext = b.addInstallArtifact(zigcrypto_loadable_ext, .{});
const install_artifact = b.addInstallArtifact(exe, .{});
install_artifact.step.dependOn(&exe.step);

return install_artifact;
}

fn addZigcryptoTestRun(b: *std.Build, sqlite_mod: *std.Build.Module, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Run {
const zigcrypto_test = b.addExecutable(.{
.name = "zigcrypto-test",
.root_source_file = b.path("examples/zigcrypto_test.zig"),
.target = getTarget(target),
.optimize = optimize,
});
zigcrypto_test.addIncludePath(b.path("c"));
zigcrypto_test.root_module.addImport("sqlite", sqlite_mod);
zigcrypto_test.linkLibrary(lib);

const install_zigcrypto_test = b.addInstallArtifact(zigcrypto_test, .{});
const install = b.addInstallArtifact(zigcrypto_test, .{});
install.step.dependOn(&zigcrypto_test.step);

const run = b.addRunArtifact(zigcrypto_test);
run.step.dependOn(&zigcrypto_test.step);

const zigcrypto_compile_run = b.step("zigcrypto", "Build the 'zigcrypto' SQLite loadable extension");
zigcrypto_compile_run.dependOn(&install_zigcrypto_loadable_ext.step);
zigcrypto_compile_run.dependOn(&install_zigcrypto_test.step);
return run;
}

// See https://www.sqlite.org/compile.html for flags
const EnableOptions = struct {
// https://www.sqlite.org/fts5.html
fts5: bool = false,
};

const PreprocessStep = struct {
const Config = struct {
source: std.Build.LazyPath,
target: std.Build.LazyPath,
};

step: std.Build.Step,

source: std.Build.LazyPath,
target: std.Build.LazyPath,

fn create(owner: *std.Build, config: Config) *PreprocessStep {
const step = owner.allocator.create(PreprocessStep) catch @panic("OOM");
step.* = .{
.step = std.Build.Step.init(.{
.id = std.Build.Step.Id.custom,
.name = "preprocess",
.owner = owner,
.makeFn = make,
}),
.source = config.source,
.target = config.target,
};

return step;
}

fn make(step: *std.Build.Step, _: std.Build.Step.MakeOptions) !void {
const ps: *PreprocessStep = @fieldParentPtr("step", step);
const owner = step.owner;

const sqlite3_h = try ps.source.path(owner, "sqlite3.h").getPath3(owner, step).toString(owner.allocator);
const sqlite3ext_h = try ps.source.path(owner, "sqlite3ext.h").getPath3(owner, step).toString(owner.allocator);

const loadable_sqlite3_h = try ps.target.path(owner, "loadable-ext-sqlite3.h").getPath3(owner, step).toString(owner.allocator);
const loadable_sqlite3ext_h = try ps.target.path(owner, "loadable-ext-sqlite3ext.h").getPath3(owner, step).toString(owner.allocator);

try Preprocessor.sqlite3(owner.allocator, sqlite3_h, loadable_sqlite3_h);
try Preprocessor.sqlite3ext(owner.allocator, sqlite3ext_h, loadable_sqlite3ext_h);
}
};
8 changes: 7 additions & 1 deletion build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
.{
.name = "sqlite",
.version = "3.47.2",
.version = "3.48.0",
.dependencies = .{
.sqlite = .{
.url = "https://sqlite.org/2025/sqlite-amalgamation-3480000.zip",
.hash = "1220972595d70da33d69d519392742482cb9762935cecb99924e31f3898d2a330861",
},
},
.paths = .{"."},
}
Loading

0 comments on commit cbc803e

Please sign in to comment.