From efa7851edd34a22e841249b29bd811f4a63f20e4 Mon Sep 17 00:00:00 2001 From: Philippe Pittoli Date: Thu, 23 Oct 2025 00:40:21 +0200 Subject: [PATCH] Cleaner build.zig + pongd draft. --- build.zig | 26 ++++++++++--- src/examples/pongd.zig | 83 ++++++++++++++++++++++++++++++++++++++++++ src/zigroot.zig | 24 ++++++++++++ 3 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 src/examples/pongd.zig create mode 100644 src/zigroot.zig diff --git a/build.zig b/build.zig index cca1496..62597a0 100644 --- a/build.zig +++ b/build.zig @@ -35,10 +35,12 @@ pub fn build(b: *std.Build) void { // intend to expose to consumers that were defined in other files part // of this module, you will have to make sure to re-export them from // the root file. - .root_source_file = b.path("src/root.zig"), + .root_source_file = b.path("src/zigroot.zig"), // Later on we'll use this module as the root module of a test executable // which requires us to specify a target. .target = target, + // libc is required since libipc uses umask. + .link_libc = true, }); // Compile libipc as a static library with C bindings. @@ -49,10 +51,9 @@ pub fn build(b: *std.Build) void { .root_source_file = b.path("src/root.zig"), .target = target, .optimize = optimize, + .link_libc = true, // libc is required since libipc uses umask. }), }); - // Tell the compiler we need libc. - static_lib.root_module.link_libc = true; b.installArtifact(static_lib); // Compile libipc as a dynamic library with C bindings. @@ -64,10 +65,9 @@ pub fn build(b: *std.Build) void { .root_source_file = b.path("src/root.zig"), .target = target, .optimize = optimize, + .link_libc = true, // libc is required since libipc uses umask. }), }); - // Tell the compiler we need libc. - dynamic_lib.root_module.link_libc = true; b.installArtifact(dynamic_lib); // pong client using the c client. @@ -110,6 +110,22 @@ pub fn build(b: *std.Build) void { b.installArtifact(pongd_with_c_bindings); pongd_with_c_bindings.linkLibrary(static_lib); + // pong service using the zig library directly. + const pongd = b.addExecutable(.{ + .name = "pongd", // name of the executable + .root_module = b.createModule(.{ + .root_source_file = b.path("src/examples/pongd.zig"), + .target = target, + .optimize = optimize, + + // No need for external modules to import. + .imports = &.{ + .{ .name = "ipc", .module = mod }, + }, + }), + }); + b.installArtifact(pongd); + // This creates a top level step. Top level steps have a name and can be // invoked by name when running `zig build` (e.g. `zig build run`). // This will evaluate the `run` step rather than the default step. diff --git a/src/examples/pongd.zig b/src/examples/pongd.zig new file mode 100644 index 0000000..4f5b569 --- /dev/null +++ b/src/examples/pongd.zig @@ -0,0 +1,83 @@ +// Example of a `pong` service using the C bindings. +const std = @import("std"); +const ipc = @import("ipc"); + +const hexdump = ipc.hexdump; +const Message = ipc.Message; +const util = ipc.util; + +const builtin = @import("builtin"); +const native_os = builtin.target.os.tag; +const print = std.debug.print; +const testing = std.testing; + +fn create_service() !void { + var gpa = std.heap.DebugAllocator(.{.safety = true}){}; + defer _ = gpa.deinit(); + const allocator = gpa.allocator(); + + var ctx = try ipc.Context.init(allocator); + defer { + std.debug.print("Deinit context.\n", .{}); + ctx.deinit(); // There. Can't leak. Isn't Zig wonderful? + } + + // SERVER SIDE: creating a service. + _ = try ctx.server_init("pong"); + + try ctx.add_external(0); + + var some_event: ipc.Event = undefined; + ctx.timer = 20000; // 2 seconds + var count: u32 = 0; + var should_continue = true; + while(should_continue) { + some_event = try ctx.wait_event(); + switch (some_event.t) { + .EXTERNAL => { + should_continue = false; + }, + .TIMER => { + std.debug.print("\rTimer! ({d})", .{count}); + count += 1; + }, + + .CONNECTION => { + std.debug.print("Connection (fd {d}): {d} so far!\n", .{some_event.newfd, ctx.pollfd.items.len - 1}); + }, + + .DISCONNECTION => { + std.debug.print("User {d} disconnected, {d} remainaing.\n" + , .{some_event.origin, ctx.pollfd.items.len - 1}); + }, + + .MESSAGE_RX => { + if (some_event.m) |m| { + std.debug.print("Message received from {d} ({d} bytes)\n", .{m.fd, m.payload.len}); + util.print_message ("RECEIVED MESSAGE", m); + try ctx.schedule(m); + } + else { + std.debug.print("Error while receiving new message. Ignoring.\n", .{}); + } + }, + + .MESSAGE_TX => { + std.debug.print("Message sent to {d}.\n", .{some_event.origin}); + }, + + else => { + std.debug.print("Error: unexpected event\n", .{}); + std.debug.print("Quitting.\n", .{}); + break; + }, + } + } + + std.debug.print("Goodbye\n", .{}); +} + +pub fn main() !u8 { + try create_service(); + return 0; +} diff --git a/src/zigroot.zig b/src/zigroot.zig new file mode 100644 index 0000000..0860ac5 --- /dev/null +++ b/src/zigroot.zig @@ -0,0 +1,24 @@ +// Provide a convenient access to all `libipc` functions for Zig applications. + +pub const CBEvent = @import("./callback.zig").CBEvent; +pub const Connection = @import("./connection.zig").Connection; +pub const Message = @import("./message.zig").Message; +pub const Event = @import("./event.zig").Event; +pub const Switch = @import("./switch.zig").Switch; +pub const Messages = @import("./message.zig").Messages; +pub const Switches = @import("./switch.zig").Switches; +pub const Connections = @import("./connection.zig").Connections; +pub const Context = @import("./context.zig").Context; +pub const util = @import("./util.zig"); +pub const hexdump = @import("./hexdump.zig"); +pub const exchangefd = @import("./exchange-fd.zig"); + +test { + _ = @import("./callback.zig"); + _ = @import("./connection.zig"); + _ = @import("./context.zig"); + _ = @import("./event.zig"); + _ = @import("./message.zig"); + _ = @import("./switch.zig"); + _ = @import("./util.zig"); +}