diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 3ecfa06..68db8e4 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -10,9 +10,9 @@ jobs: uses: actions/checkout@v2 - name: setup-zig - uses: mlugg/setup-zig@v1 + uses: mlugg/setup-zig@v2 with: - version: 0.14.0 + version: 0.14.1 - name: lint run: | @@ -31,9 +31,9 @@ jobs: submodules: recursive - name: setup-zig - uses: mlugg/setup-zig@v1 + uses: mlugg/setup-zig@v2 with: - version: 0.14.0 + version: 0.14.1 - name: test run: | diff --git a/README.md b/README.md index 04c3784..f975350 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Build and use RocksDB in zig. # Build Dependencies -`rocksdb-zig` is pinned to [Zig `0.13`](https://ziglang.org/download/), so you will need to have it installed. +`rocksdb-zig` is pinned to [Zig `0.14.1`](https://ziglang.org/download/), so you will need to have it installed. # Usage diff --git a/build.zig b/build.zig index 8122297..9c4a044 100644 --- a/build.zig +++ b/build.zig @@ -3,12 +3,18 @@ const Build = std.Build; const ResolvedTarget = Build.ResolvedTarget; const OptimizeMode = std.builtin.OptimizeMode; -pub fn build(b: *Build) void { +pub fn build(b: *Build) !void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); + const enable_snappy = b.option( + bool, + "enable_snappy", + "Enables and builds with the Snappy compressor", + ) orelse false; + // RocksDB's translate-c module - const rocksdb_mod = addRocksDB(b, target, optimize); + const rocksdb_mod = try addRocksDB(b, target, optimize, enable_snappy); const bindings_mod = b.addModule("bindings", .{ .target = target, .optimize = optimize, @@ -32,7 +38,8 @@ fn addRocksDB( b: *Build, target: ResolvedTarget, optimize: OptimizeMode, -) *Build.Module { + enable_snappy: bool, +) !*Build.Module { const rocks_dep = b.dependency("rocksdb", .{}); const translate_c = b.addTranslateC(.{ @@ -68,8 +75,18 @@ fn addRocksDB( }), }); - try buildRocksDB(b, static_rocksdb, target); - try buildRocksDB(b, dynamic_rocksdb, target); + const maybe_libsnappy = if (enable_snappy) b.addLibrary(.{ + .name = "snappy", + .linkage = .static, + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + .pic = if (force_pic == true) true else null, + }), + }) else null; + + try buildRocksDB(b, static_rocksdb, maybe_libsnappy, target); + try buildRocksDB(b, dynamic_rocksdb, maybe_libsnappy, target); mod.addIncludePath(rocks_dep.path("include")); mod.linkLibrary(static_rocksdb); @@ -81,6 +98,7 @@ fn addRocksDB( fn buildRocksDB( b: *Build, librocksdb: *std.Build.Step.Compile, + maybe_libsnappy: ?*std.Build.Step.Compile, target: std.Build.ResolvedTarget, ) !void { const t = target.result; @@ -89,6 +107,16 @@ fn buildRocksDB( librocksdb.linkLibC(); librocksdb.linkLibCpp(); + var rocksdb_flags: std.ArrayListUnmanaged([]const u8) = .empty; + defer rocksdb_flags.deinit(b.allocator); + try rocksdb_flags.appendSlice(b.allocator, &.{ + "-std=c++17", + "-faligned-new", + "-DHAVE_ALIGNED_NEW", + "-DROCKSDB_UBSAN_RUN", + }); + if (maybe_libsnappy != null) try rocksdb_flags.append(b.allocator, "-DSNAPPY=1"); + librocksdb.addIncludePath(rocks_dep.path("include")); librocksdb.addIncludePath(rocks_dep.path(".")); librocksdb.addCSourceFiles(.{ @@ -431,24 +459,55 @@ fn buildRocksDB( "utilities/transactions/lock/range/range_tree/lib/util/dbt.cc", "utilities/transactions/lock/range/range_tree/lib/util/memarena.cc", }, - .flags = &.{ - "-std=c++17", - "-faligned-new", - "-DHAVE_ALIGNED_NEW", - "-DROCKSDB_UBSAN_RUN", - }, + .flags = rocksdb_flags.items, }); + if (maybe_libsnappy) |libsnappy| not_yet_fetched: { + const snappy_dep = b.lazyDependency("snappy", .{}) orelse + break :not_yet_fetched; + + librocksdb.linkLibrary(libsnappy); + librocksdb.addIncludePath(snappy_dep.path(".")); + + libsnappy.linkLibCpp(); + + const flags = .{ + "-std=c++11", + "-fno-exceptions", + "-fno-rtti", + "-Wno-sign-compare", + }; + + libsnappy.addCSourceFiles(.{ + .root = snappy_dep.path("."), + .files = &.{ + "snappy-c.cc", + "snappy-sinksource.cc", + "snappy-stubs-internal.cc", + "snappy.cc", + }, + .flags = &flags, + }); + + const build_version = b.addConfigHeader(.{ + .style = .{ .cmake = snappy_dep.path("snappy-stubs-public.h.in") }, + .include_path = "snappy-stubs-public.h", + }, .{ + .PROJECT_VERSION_MAJOR = 1, + .PROJECT_VERSION_MINOR = 2, + .PROJECT_VERSION_PATCH = 2, + .HAVE_SYS_UIO_H_01 = 1, + }); + + libsnappy.addIncludePath(build_version.getOutput().dirname()); + librocksdb.addIncludePath(build_version.getOutput().dirname()); + } + // platform dependent stuff if (t.cpu.arch == .aarch64) { librocksdb.addCSourceFile(.{ .file = rocks_dep.path("util/crc32c_arm64.cc"), - .flags = &.{ - "-std=c++17", - "-faligned-new", - "-DHAVE_ALIGNED_NEW", - "-DROCKSDB_UBSAN_RUN", - }, + .flags = rocksdb_flags.items, }); } @@ -463,11 +522,7 @@ fn buildRocksDB( "env/fs_posix.cc", "env/io_posix.cc", }, - .flags = &.{ - "-std=c++17", - "-faligned-new", - "-DHAVE_ALIGNED_NEW", - }, + .flags = rocksdb_flags.items, }); } else { @panic("TODO: support windows!"); diff --git a/build.zig.zon b/build.zig.zon index c46aebe..64336a2 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -2,11 +2,17 @@ .name = .rocksdb, .fingerprint = 0xd916a6b24e94f0cf, .version = "9.7.4", + .minimum_zig_version = "0.14.1", .dependencies = .{ .rocksdb = .{ .url = "git+https://github.com/Syndica/rocksdb#3793e721c7795b338d9d7808544b75db6bde3548", .hash = "N-V-__8AAAKhcQL5PtDzqfPNCjk1LJCK8svO8KtC-f_3bj6z", }, + .snappy = .{ + .url = "git+https://github.com/google/snappy#25e52c58fbf83ee40f4c9284f757f777f691f76f", + .hash = "N-V-__8AADcwMwCa__yeHfNDwYl4KEDbkj-VwAqY844Nblr8", + .lazy = true, + }, }, .paths = .{ "build.zig", diff --git a/src/database.zig b/src/database.zig index 6e7c253..84d3279 100644 --- a/src/database.zig +++ b/src/database.zig @@ -26,6 +26,7 @@ pub const DB = struct { dir: []const u8, db_options: DBOptions, maybe_column_families: ?[]const ColumnFamilyDescription, + for_read_only: bool, err_str: *?Data, ) (Allocator.Error || error{RocksDBOpen})!struct { Self, []const ColumnFamily } { const column_families = if (maybe_column_families) |cfs| @@ -47,15 +48,30 @@ pub const DB = struct { cf_options[i] = cf.options.convert(); } var ch = CallHandler.init(err_str); - break :db try ch.handle(rdb.rocksdb_open_column_families( - db_options.convert(), - dir.ptr, - @intCast(cf_names.len), - @ptrCast(cf_names.ptr), - @ptrCast(cf_options.ptr), - @ptrCast(cf_handles.ptr), - @ptrCast(&ch.err_str_in), - ), error.RocksDBOpen); + + const ret = if (for_read_only) + rdb.rocksdb_open_for_read_only_column_families( + db_options.convert(), + dir.ptr, + @intCast(cf_names.len), + @ptrCast(cf_names.ptr), + @ptrCast(cf_options.ptr), + @ptrCast(cf_handles.ptr), + 0, + @ptrCast(&ch.err_str_in), + ) + else + rdb.rocksdb_open_column_families( + db_options.convert(), + dir.ptr, + @intCast(cf_names.len), + @ptrCast(cf_names.ptr), + @ptrCast(cf_options.ptr), + @ptrCast(cf_handles.ptr), + @ptrCast(&ch.err_str_in), + ); + + break :db try ch.handle(ret, error.RocksDBOpen); }; // organize column family metadata @@ -370,6 +386,7 @@ test "DB clean init and deinit" { .create_missing_column_families = true, }, null, + false, &data, ); @@ -554,6 +571,7 @@ fn runTest(err_str: *?Data) !void { .{ .name = "default" }, .{ .name = "another" }, }, + false, err_str, ); defer db.deinit(); @@ -593,6 +611,7 @@ fn runTest(err_str: *?Data) !void { .{ .name = "default" }, .{ .name = "another" }, }, + false, err_str, ); defer db.deinit();