From e723717d53b5d86f7869d40a6e9b85470608b84a Mon Sep 17 00:00:00 2001 From: Philippe Pittoli Date: Thu, 9 Feb 2023 17:21:54 +0100 Subject: [PATCH] First commit: zig library build + C link without sugar. --- .gitignore | 3 +++ mk/makefile.valgrind | 17 +++++++++++++ zig-lib_no-sugar/joke.c | 21 ++++++++++++++++ zig-lib_no-sugar/libipc.h | 9 +++++++ zig-lib_no-sugar/makefile | 17 +++++++++++++ zig-lib_no-sugar/test-gpa.zig | 45 ++++++++++++++++++++++++++++++++++ zig-lib_no-sugar/test-gpa2.zig | 39 +++++++++++++++++++++++++++++ 7 files changed, 151 insertions(+) create mode 100644 .gitignore create mode 100644 mk/makefile.valgrind create mode 100644 zig-lib_no-sugar/joke.c create mode 100644 zig-lib_no-sugar/libipc.h create mode 100644 zig-lib_no-sugar/makefile create mode 100644 zig-lib_no-sugar/test-gpa.zig create mode 100644 zig-lib_no-sugar/test-gpa2.zig diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4efd822 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +joke +*.o +*.a diff --git a/mk/makefile.valgrind b/mk/makefile.valgrind new file mode 100644 index 0000000..812dde3 --- /dev/null +++ b/mk/makefile.valgrind @@ -0,0 +1,17 @@ +# Debug with valgrind. +ifdef VG_SUPPRESS_WARNINGS +VALGRIND_SUPPRESS_WARNINGS ?= --suppressions=./valgrind.suppr +endif +ifdef VG_GENERATE_SUPPRESSION +VALGRIND_GEN_SUPPRESSION ?= --gen-suppressions=all +endif +VALGRIND_OPTS=-v --leak-check=full --track-origins=yes +ifdef USE_VALGRIND +VALGRIND ?= valgrind $(VALGRIND_SUPPRESS_WARNINGS) \ + $(VALGRIND_GEN_SUPPRESSION) \ + $(VALGRIND_OPTS) +endif +# Optional parameters (copied here to help with autocompletion). +VG_SUPPRESS_WARNINGS ?= +VG_GENERATE_SUPPRESSION ?= +USE_VALGRIND ?= diff --git a/zig-lib_no-sugar/joke.c b/zig-lib_no-sugar/joke.c new file mode 100644 index 0000000..0e80e9d --- /dev/null +++ b/zig-lib_no-sugar/joke.c @@ -0,0 +1,21 @@ +#include +#include +#include + +#include "./libipc.h" + +int main(void) { + printf ("Init context.\n"); + void *ctx = ipc_context_init (); + + if (ctx == NULL) { + printf ("Cannot init context.\n"); + return 1; + } + + printf ("Deinit context\n"); + ipc_context_deinit (ctx); + + printf ("Context freed.\n"); + return 0; +} diff --git a/zig-lib_no-sugar/libipc.h b/zig-lib_no-sugar/libipc.h new file mode 100644 index 0000000..b580181 --- /dev/null +++ b/zig-lib_no-sugar/libipc.h @@ -0,0 +1,9 @@ +#ifndef LIBIPC +#define LIBIPC + +#include + +void* ipc_context_init (void); +void ipc_context_deinit (void* ctx); + +#endif diff --git a/zig-lib_no-sugar/makefile b/zig-lib_no-sugar/makefile new file mode 100644 index 0000000..c2e20f8 --- /dev/null +++ b/zig-lib_no-sugar/makefile @@ -0,0 +1,17 @@ +# No sugar for you! + +build: lib + gcc -Os -I. -static -o joke joke.c libtest-gpa.a + +lib: + zig build-lib test-gpa.zig -OReleaseSmall + +run: + $(VALGRIND) ./joke + + +include ../mk/makefile.valgrind + +# Another library. +lib-alt: + zig build-lib test-gpa2.zig -OReleaseSmall diff --git a/zig-lib_no-sugar/test-gpa.zig b/zig-lib_no-sugar/test-gpa.zig new file mode 100644 index 0000000..5615d31 --- /dev/null +++ b/zig-lib_no-sugar/test-gpa.zig @@ -0,0 +1,45 @@ +const std = @import("std"); +const fmt = std.fmt; +const testing = std.testing; + +const print = std.debug.print; +const GPA = std.heap.GeneralPurposeAllocator(.{ .safety = true }); + +pub const Context = struct { + const Self = @This(); + rundir: [:0]u8, + gpa: GPA, + + pub fn init(gpa: *GPA) !Self { + var rundir = try gpa.allocator().dupeZ(u8, "/tmp/libipc-run/"); + return Self{ .rundir = rundir, .gpa = gpa.* }; + } + + pub fn deinit(self: *Self) void { + self.gpa.allocator().free(self.rundir); + } +}; + +export fn ipc_context_init() callconv(.C) ?*anyopaque { + std.log.err("Let's use GPA!", .{}); + var gpa = GPA{}; + var new_context = gpa.allocator().create(Context) catch return null; + new_context.* = Context.init(&gpa) catch return null; + return new_context; +} + +export fn ipc_context_deinit(opaque_ctx: *anyopaque) callconv(.C) void { + var ctx = @ptrCast(*Context, @alignCast(@alignOf(Context), opaque_ctx)); + ctx.deinit(); + var gpa = ctx.gpa; // save the gpa before destroying ctx + std.log.err("Let's destroy Context!", .{}); + gpa.allocator().destroy(ctx); + _ = gpa.deinit(); // now deinit the gpa +} + +test "context_init_deinit" { + const ctx = ipc_context_init(); + try std.testing.expect(ctx != null); + + ipc_context_deinit(ctx.?); +} diff --git a/zig-lib_no-sugar/test-gpa2.zig b/zig-lib_no-sugar/test-gpa2.zig new file mode 100644 index 0000000..d00581c --- /dev/null +++ b/zig-lib_no-sugar/test-gpa2.zig @@ -0,0 +1,39 @@ +const std = @import("std"); +const fmt = std.fmt; +const testing = std.testing; + +const print = std.debug.print; +var gpa = std.heap.GeneralPurposeAllocator(.{ .safety = true }){}; + +pub const Context = struct { + const Self = @This(); + rundir: [:0]u8, + + pub fn init() !Self { + var rundir = try gpa.allocator().dupeZ(u8, "/tmp/libipc-run/"); + return Self{ .rundir = rundir }; + } + + pub fn deinit(self: *Self) void { + gpa.allocator().free(self.rundir); + } +}; + +export fn ipc_context_init() callconv(.C) ?*anyopaque { + var new_context = gpa.allocator().create(Context) catch return null; + new_context.* = Context.init() catch return null; + return new_context; +} + +export fn ipc_context_deinit(opaque_ctx: *anyopaque) callconv(.C) void { + var ctx = @ptrCast(*Context, @alignCast(@alignOf(Context), opaque_ctx)); + ctx.deinit(); + gpa.allocator().destroy(ctx); +} + +test "context_init_deinit" { + const ctx = ipc_context_init(); + try std.testing.expect(ctx != null); + + ipc_context_deinit(ctx.?); +}