summaryrefslogtreecommitdiff
path: root/build.zig
diff options
context:
space:
mode:
authorGravatar Vincent Rischmann2025-02-16 01:08:39 +0100
committerGravatar GitHub2025-02-16 01:08:39 +0100
commitcbc803e89ffdd033529ee06f869baa52e9f07672 (patch)
treeb27357993e6a0d25e662455f1abc41cd8408876b /build.zig
parentMerge pull request #180 from nektro/patch-1 (diff)
parentbuild: fix zigcrypto dependencies (diff)
downloadzig-sqlite-cbc803e89ffdd033529ee06f869baa52e9f07672.tar.gz
zig-sqlite-cbc803e89ffdd033529ee06f869baa52e9f07672.tar.xz
zig-sqlite-cbc803e89ffdd033529ee06f869baa52e9f07672.zip
Merge pull request #179 from vrischmann/use-upstream
Use upstream sqlite
Diffstat (limited to 'build.zig')
-rw-r--r--build.zig231
1 files changed, 156 insertions, 75 deletions
diff --git a/build.zig b/build.zig
index 7833a54..328679c 100644
--- a/build.zig
+++ b/build.zig
@@ -1,8 +1,12 @@
1const std = @import("std"); 1const std = @import("std");
2const builtin = @import("builtin"); 2const debug = std.debug;
3const Step = std.Build.Step; 3const heap = std.heap;
4const mem = std.mem;
4const ResolvedTarget = std.Build.ResolvedTarget; 5const ResolvedTarget = std.Build.ResolvedTarget;
5const Query = std.Target.Query; 6const Query = std.Target.Query;
7const builtin = @import("builtin");
8
9const Preprocessor = @import("build/Preprocessor.zig");
6 10
7fn getTarget(original_target: ResolvedTarget) ResolvedTarget { 11fn getTarget(original_target: ResolvedTarget) ResolvedTarget {
8 var tmp = original_target; 12 var tmp = original_target;
@@ -104,6 +108,31 @@ fn computeTestTargets(isNative: bool, ci: ?bool) ?[]const TestTarget {
104 return null; 108 return null;
105} 109}
106 110
111// This creates a SQLite static library from the SQLite dependency code.
112fn 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 {
113 const lib = b.addStaticLibrary(.{
114 .name = "sqlite",
115 .target = target,
116 .optimize = optimize,
117 });
118
119 lib.addIncludePath(dep.path("."));
120 lib.addIncludePath(b.path("c"));
121 if (sqlite_c == .with) {
122 lib.addCSourceFile(.{
123 .file = dep.path("sqlite3.c"),
124 .flags = c_flags,
125 });
126 }
127 lib.addCSourceFile(.{
128 .file = b.path("c/workaround.c"),
129 .flags = c_flags,
130 });
131 lib.linkLibC();
132
133 return lib;
134}
135
107pub fn build(b: *std.Build) !void { 136pub fn build(b: *std.Build) !void {
108 const in_memory = b.option(bool, "in_memory", "Should the tests run with sqlite in memory (default true)") orelse true; 137 const in_memory = b.option(bool, "in_memory", "Should the tests run with sqlite in memory (default true)") orelse true;
109 const dbfile = b.option([]const u8, "dbfile", "Always use this database file instead of a temporary one"); 138 const dbfile = b.option([]const u8, "dbfile", "Always use this database file instead of a temporary one");
@@ -113,6 +142,14 @@ pub fn build(b: *std.Build) !void {
113 const target = b.resolveTargetQuery(query); 142 const target = b.resolveTargetQuery(query);
114 const optimize = b.standardOptimizeOption(.{}); 143 const optimize = b.standardOptimizeOption(.{});
115 144
145 // Upstream dependency
146 const sqlite_dep = b.dependency("sqlite", .{
147 .target = target,
148 .optimize = optimize,
149 });
150
151 // Define C flags to use
152
116 var flags = std.ArrayList([]const u8).init(b.allocator); 153 var flags = std.ArrayList([]const u8).init(b.allocator);
117 defer flags.deinit(); 154 defer flags.deinit();
118 try flags.append("-std=c99"); 155 try flags.append("-std=c99");
@@ -131,50 +168,41 @@ pub fn build(b: *std.Build) !void {
131 168
132 const c_flags = flags.items; 169 const c_flags = flags.items;
133 170
134 const sqlite_lib = b.addStaticLibrary(.{ 171 //
135 .name = "sqlite", 172 // Main library and module
136 .target = target, 173 //
137 .optimize = optimize,
138 });
139 174
140 sqlite_lib.addIncludePath(b.path("c/")); 175 const sqlite_lib, const sqlite_mod = blk: {
141 sqlite_lib.addCSourceFiles(.{ 176 const lib = makeSQLiteLib(b, sqlite_dep, c_flags, target, optimize, .with);
142 .files = &[_][]const u8{
143 "c/sqlite3.c",
144 "c/workaround.c",
145 },
146 .flags = c_flags,
147 });
148 sqlite_lib.linkLibC();
149 sqlite_lib.installHeader(b.path("c/sqlite3.h"), "sqlite3.h");
150 177
151 b.installArtifact(sqlite_lib); 178 const mod = b.addModule("sqlite", .{
179 .root_source_file = b.path("sqlite.zig"),
180 .link_libc = true,
181 });
182 mod.addIncludePath(b.path("c"));
183 mod.addIncludePath(sqlite_dep.path("."));
184 mod.linkLibrary(lib);
152 185
153 // Create the public 'sqlite' module to be exported 186 break :blk .{ lib, mod };
154 const sqlite_mod = b.addModule("sqlite", .{ 187 };
155 .root_source_file = b.path("sqlite.zig"), 188 b.installArtifact(sqlite_lib);
156 .link_libc = true,
157 });
158 sqlite_mod.addIncludePath(b.path("c/"));
159 sqlite_mod.linkLibrary(sqlite_lib);
160 189
161 // Tool to preprocess the sqlite header files. 190 const sqliteext_mod = blk: {
162 // 191 const lib = makeSQLiteLib(b, sqlite_dep, c_flags, target, optimize, .without);
163 // Due to limitations of translate-c the standard header files can't be used for building loadable extensions
164 // so we have this tool which creates usable header files.
165 192
166 const preprocess_files_tool = b.addExecutable(.{ 193 const mod = b.addModule("sqliteext", .{
167 .name = "preprocess-files", 194 .root_source_file = b.path("sqlite.zig"),
168 .root_source_file = b.path("tools/preprocess_files.zig"), 195 .link_libc = true,
169 .target = getTarget(target), 196 });
170 .optimize = optimize, 197 mod.addIncludePath(b.path("c"));
171 }); 198 mod.linkLibrary(lib);
172 199
173 // Add a top-level step to run the preprocess-files tool 200 break :blk mod;
174 const preprocess_files_run = b.step("preprocess-files", "Run the preprocess-files tool"); 201 };
175 202
176 const preprocess_files_tool_run = b.addRunArtifact(preprocess_files_tool); 203 //
177 preprocess_files_run.dependOn(&preprocess_files_tool_run.step); 204 // Tests
205 //
178 206
179 const test_targets = computeTestTargets(query.isNative(), ci) orelse &[_]TestTarget{.{ 207 const test_targets = computeTestTargets(query.isNative(), ci) orelse &[_]TestTarget{.{
180 .query = query, 208 .query = query,
@@ -195,19 +223,7 @@ pub fn build(b: *std.Build) !void {
195 single_threaded_txt, 223 single_threaded_txt,
196 }); 224 });
197 225
198 const test_sqlite_lib = b.addStaticLibrary(.{ 226 const test_sqlite_lib = makeSQLiteLib(b, sqlite_dep, c_flags, cross_target, optimize, .with);
199 .name = "sqlite",
200 .target = cross_target,
201 .optimize = optimize,
202 });
203 test_sqlite_lib.addCSourceFiles(.{
204 .files = &[_][]const u8{
205 "c/sqlite3.c",
206 "c/workaround.c",
207 },
208 .flags = c_flags,
209 });
210 test_sqlite_lib.linkLibC();
211 227
212 const tests = b.addTest(.{ 228 const tests = b.addTest(.{
213 .name = test_name, 229 .name = test_name,
@@ -217,6 +233,7 @@ pub fn build(b: *std.Build) !void {
217 .single_threaded = test_target.single_threaded, 233 .single_threaded = test_target.single_threaded,
218 }); 234 });
219 tests.addIncludePath(b.path("c")); 235 tests.addIncludePath(b.path("c"));
236 tests.addIncludePath(sqlite_dep.path("."));
220 tests.linkLibrary(test_sqlite_lib); 237 tests.linkLibrary(test_sqlite_lib);
221 238
222 const tests_options = b.addOptions(); 239 const tests_options = b.addOptions();
@@ -229,51 +246,73 @@ pub fn build(b: *std.Build) !void {
229 test_step.dependOn(&run_tests.step); 246 test_step.dependOn(&run_tests.step);
230 } 247 }
231 248
232 const lib = b.addStaticLibrary(.{ 249 // This builds an example shared library with the extension and a binary that tests it.
233 .name = "sqlite", 250
234 .target = getTarget(target), 251 const zigcrypto_install_artifact = addZigcrypto(b, sqliteext_mod, target, optimize);
235 .optimize = optimize, 252 test_step.dependOn(&zigcrypto_install_artifact.step);
236 }); 253
237 lib.addCSourceFile(.{ .file = b.path("c/sqlite3.c"), .flags = c_flags }); 254 const zigcrypto_test_run = addZigcryptoTestRun(b, sqlite_mod, target, optimize);
238 lib.addIncludePath(b.path("c")); 255 zigcrypto_test_run.step.dependOn(&zigcrypto_install_artifact.step);
239 lib.linkLibC(); 256 test_step.dependOn(&zigcrypto_test_run.step);
240 257
241 // 258 //
242 // Examples 259 // Tools
243 // 260 //
244 261
245 // Loadable extension 262 addPreprocessStep(b, sqlite_dep);
246 // 263}
247 // This builds an example shared library with the extension and a binary that tests it. 264
265fn addPreprocessStep(b: *std.Build, sqlite_dep: *std.Build.Dependency) void {
266 var wf = b.addWriteFiles();
267
268 // Preprocessing step
269 const preprocess = PreprocessStep.create(b, .{
270 .source = sqlite_dep.path("."),
271 .target = wf.getDirectory(),
272 });
273 preprocess.step.dependOn(&wf.step);
274
275 const w = b.addUpdateSourceFiles();
276 w.addCopyFileToSource(preprocess.target.join(b.allocator, "loadable-ext-sqlite3.h") catch @panic("OOM"), "c/loadable-ext-sqlite3.h");
277 w.addCopyFileToSource(preprocess.target.join(b.allocator, "loadable-ext-sqlite3ext.h") catch @panic("OOM"), "c/loadable-ext-sqlite3ext.h");
278 w.step.dependOn(&preprocess.step);
248 279
249 const zigcrypto_loadable_ext = b.addSharedLibrary(.{ 280 const preprocess_headers = b.step("preprocess-headers", "Preprocess the headers for the loadable extensions");
281 preprocess_headers.dependOn(&w.step);
282}
283
284fn addZigcrypto(b: *std.Build, sqlite_mod: *std.Build.Module, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.InstallArtifact {
285 const exe = b.addSharedLibrary(.{
250 .name = "zigcrypto", 286 .name = "zigcrypto",
251 .root_source_file = b.path("examples/zigcrypto.zig"), 287 .root_source_file = b.path("examples/zigcrypto.zig"),
252 .version = null, 288 .version = null,
253 .target = getTarget(target), 289 .target = getTarget(target),
254 .optimize = optimize, 290 .optimize = optimize,
255 }); 291 });
256 zigcrypto_loadable_ext.addIncludePath(b.path("c")); 292 exe.root_module.addImport("sqlite", sqlite_mod);
257 zigcrypto_loadable_ext.root_module.addImport("sqlite", sqlite_mod);
258 zigcrypto_loadable_ext.linkLibrary(lib);
259 293
260 const install_zigcrypto_loadable_ext = b.addInstallArtifact(zigcrypto_loadable_ext, .{}); 294 const install_artifact = b.addInstallArtifact(exe, .{});
295 install_artifact.step.dependOn(&exe.step);
261 296
297 return install_artifact;
298}
299
300fn addZigcryptoTestRun(b: *std.Build, sqlite_mod: *std.Build.Module, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Run {
262 const zigcrypto_test = b.addExecutable(.{ 301 const zigcrypto_test = b.addExecutable(.{
263 .name = "zigcrypto-test", 302 .name = "zigcrypto-test",
264 .root_source_file = b.path("examples/zigcrypto_test.zig"), 303 .root_source_file = b.path("examples/zigcrypto_test.zig"),
265 .target = getTarget(target), 304 .target = getTarget(target),
266 .optimize = optimize, 305 .optimize = optimize,
267 }); 306 });
268 zigcrypto_test.addIncludePath(b.path("c"));
269 zigcrypto_test.root_module.addImport("sqlite", sqlite_mod); 307 zigcrypto_test.root_module.addImport("sqlite", sqlite_mod);
270 zigcrypto_test.linkLibrary(lib);
271 308
272 const install_zigcrypto_test = b.addInstallArtifact(zigcrypto_test, .{}); 309 const install = b.addInstallArtifact(zigcrypto_test, .{});
310 install.step.dependOn(&zigcrypto_test.step);
311
312 const run = b.addRunArtifact(zigcrypto_test);
313 run.step.dependOn(&zigcrypto_test.step);
273 314
274 const zigcrypto_compile_run = b.step("zigcrypto", "Build the 'zigcrypto' SQLite loadable extension"); 315 return run;
275 zigcrypto_compile_run.dependOn(&install_zigcrypto_loadable_ext.step);
276 zigcrypto_compile_run.dependOn(&install_zigcrypto_test.step);
277} 316}
278 317
279// See https://www.sqlite.org/compile.html for flags 318// See https://www.sqlite.org/compile.html for flags
@@ -281,3 +320,45 @@ const EnableOptions = struct {
281 // https://www.sqlite.org/fts5.html 320 // https://www.sqlite.org/fts5.html
282 fts5: bool = false, 321 fts5: bool = false,
283}; 322};
323
324const PreprocessStep = struct {
325 const Config = struct {
326 source: std.Build.LazyPath,
327 target: std.Build.LazyPath,
328 };
329
330 step: std.Build.Step,
331
332 source: std.Build.LazyPath,
333 target: std.Build.LazyPath,
334
335 fn create(owner: *std.Build, config: Config) *PreprocessStep {
336 const step = owner.allocator.create(PreprocessStep) catch @panic("OOM");
337 step.* = .{
338 .step = std.Build.Step.init(.{
339 .id = std.Build.Step.Id.custom,
340 .name = "preprocess",
341 .owner = owner,
342 .makeFn = make,
343 }),
344 .source = config.source,
345 .target = config.target,
346 };
347
348 return step;
349 }
350
351 fn make(step: *std.Build.Step, _: std.Build.Step.MakeOptions) !void {
352 const ps: *PreprocessStep = @fieldParentPtr("step", step);
353 const owner = step.owner;
354
355 const sqlite3_h = try ps.source.path(owner, "sqlite3.h").getPath3(owner, step).toString(owner.allocator);
356 const sqlite3ext_h = try ps.source.path(owner, "sqlite3ext.h").getPath3(owner, step).toString(owner.allocator);
357
358 const loadable_sqlite3_h = try ps.target.path(owner, "loadable-ext-sqlite3.h").getPath3(owner, step).toString(owner.allocator);
359 const loadable_sqlite3ext_h = try ps.target.path(owner, "loadable-ext-sqlite3ext.h").getPath3(owner, step).toString(owner.allocator);
360
361 try Preprocessor.sqlite3(owner.allocator, sqlite3_h, loadable_sqlite3_h);
362 try Preprocessor.sqlite3ext(owner.allocator, sqlite3ext_h, loadable_sqlite3ext_h);
363 }
364};