223 lines
7.6 KiB
Zig
223 lines
7.6 KiB
Zig
const std = @import("std");
|
|
|
|
pub fn build(b: *std.Build) void {
|
|
const target = b.standardTargetOptions(.{});
|
|
const optimize = b.standardOptimizeOption(.{});
|
|
const static_build = b.option(bool, "static_build", "builds backlog dependencies for static linking") orelse false;
|
|
|
|
// am i good to always have enet as static?
|
|
const enet = if (static_build and false) b.addStaticLibrary(.{
|
|
.name = "enet_c",
|
|
.target = target,
|
|
.optimize = optimize,
|
|
}) else b.addSharedLibrary(.{
|
|
.name = "enet_c",
|
|
.target = target,
|
|
.optimize = optimize,
|
|
});
|
|
|
|
enet.linkLibC();
|
|
|
|
enet.addCSourceFiles(.{
|
|
.root = b.path("enet-1.3.18"),
|
|
.files = &.{
|
|
"callbacks.c",
|
|
"compress.c",
|
|
"host.c",
|
|
"list.c",
|
|
"packet.c",
|
|
"peer.c",
|
|
"protocol.c",
|
|
"unix.c",
|
|
"win32.c",
|
|
},
|
|
.flags = &.{"-DHAS_OFFSETOF=1"},
|
|
});
|
|
|
|
enet.addIncludePath(b.path("enet-1.3.18/include"));
|
|
|
|
// Platform-specific configuration
|
|
switch (target.result.os.tag) {
|
|
.windows => {
|
|
enet.linkSystemLibrary("ws2_32");
|
|
enet.linkSystemLibrary("winmm");
|
|
},
|
|
.linux, .macos => {
|
|
// Unix platforms - no additional libraries needed
|
|
},
|
|
else => {},
|
|
}
|
|
|
|
b.installArtifact(enet);
|
|
|
|
const mod = b.addModule("enet", .{
|
|
.target = target,
|
|
.optimize = optimize,
|
|
.root_source_file = b.path("src/enet.zig"),
|
|
.link_libc = true,
|
|
});
|
|
|
|
mod.linkLibrary(enet);
|
|
mod.addIncludePath(b.path("enet-1.3.18/include/"));
|
|
|
|
const test_step = b.step("test", "run unit tests for enet");
|
|
const tests = b.addTest(.{
|
|
.target = target,
|
|
.optimize = optimize,
|
|
.root_source_file = b.path("src/tests.zig"),
|
|
.link_libc = true,
|
|
});
|
|
tests.root_module.addImport("enet", mod);
|
|
tests.root_module.addIncludePath(b.path("enet-1.3.18/include/"));
|
|
const runArtifact = b.addRunArtifact(tests);
|
|
test_step.dependOn(&runArtifact.step);
|
|
|
|
// Test server executable
|
|
const test_server = b.addExecutable(.{
|
|
.name = "test-server",
|
|
.root_source_file = b.path("src/test_server.zig"),
|
|
.target = target,
|
|
.optimize = optimize,
|
|
});
|
|
test_server.root_module.addImport("enet", mod);
|
|
test_server.linkLibC();
|
|
|
|
// Test client executable
|
|
const test_client = b.addExecutable(.{
|
|
.name = "test-client",
|
|
.root_source_file = b.path("src/test_client.zig"),
|
|
.target = target,
|
|
.optimize = optimize,
|
|
});
|
|
test_client.root_module.addImport("enet", mod);
|
|
test_client.linkLibC();
|
|
|
|
// Install test programs
|
|
const install_test_server = b.addInstallArtifact(test_server, .{});
|
|
const install_test_client = b.addInstallArtifact(test_client, .{});
|
|
|
|
// Steps to run test programs individually
|
|
const run_test_server = b.addRunArtifact(test_server);
|
|
const run_test_client = b.addRunArtifact(test_client);
|
|
|
|
const run_server_step = b.step("run-test-server", "Run the ENet test server");
|
|
run_server_step.dependOn(&run_test_server.step);
|
|
|
|
const run_client_step = b.step("run-test-client", "Run the ENet test client");
|
|
run_client_step.dependOn(&run_test_client.step);
|
|
|
|
// Loopback test that runs both server and client
|
|
const run_loopback_step = b.step("run-test-loopback", "Run ENet loopback test (server + client)");
|
|
|
|
// Create a custom step for the loopback test
|
|
const loopback_test = LoopbackTestStep.create(b, test_server, test_client);
|
|
run_loopback_step.dependOn(&loopback_test.step);
|
|
|
|
// Build step for test programs
|
|
const build_tests_step = b.step("build-tests", "Build test server and client programs");
|
|
build_tests_step.dependOn(&install_test_server.step);
|
|
build_tests_step.dependOn(&install_test_client.step);
|
|
}
|
|
|
|
// Custom step to run server and client concurrently for loopback testing
|
|
const LoopbackTestStep = struct {
|
|
step: std.Build.Step,
|
|
builder: *std.Build,
|
|
server_exe: *std.Build.Step.Compile,
|
|
client_exe: *std.Build.Step.Compile,
|
|
|
|
const Self = @This();
|
|
|
|
pub fn create(builder: *std.Build, server_exe: *std.Build.Step.Compile, client_exe: *std.Build.Step.Compile) *Self {
|
|
const self = builder.allocator.create(Self) catch @panic("OOM");
|
|
self.* = Self{
|
|
.step = std.Build.Step.init(.{
|
|
.id = .custom,
|
|
.name = "loopback-test",
|
|
.owner = builder,
|
|
.makeFn = make,
|
|
}),
|
|
.builder = builder,
|
|
.server_exe = server_exe,
|
|
.client_exe = client_exe,
|
|
};
|
|
|
|
self.step.dependOn(&server_exe.step);
|
|
self.step.dependOn(&client_exe.step);
|
|
|
|
return self;
|
|
}
|
|
|
|
fn make(step: *std.Build.Step, _: std.Build.Step.MakeOptions) !void {
|
|
const self: *Self = @fieldParentPtr("step", step);
|
|
const allocator = self.builder.allocator;
|
|
|
|
std.debug.print("Running ENet loopback test...\n", .{});
|
|
|
|
// Get the executable paths
|
|
const server_path = self.server_exe.getEmittedBin().getPath(self.builder);
|
|
const client_path = self.client_exe.getEmittedBin().getPath(self.builder);
|
|
|
|
// Start the server process
|
|
std.debug.print("Starting test server...\n", .{});
|
|
var server_process = std.process.Child.init(&[_][]const u8{server_path}, allocator);
|
|
server_process.stdout_behavior = .Pipe;
|
|
server_process.stderr_behavior = .Pipe;
|
|
|
|
try server_process.spawn();
|
|
defer {
|
|
_ = server_process.kill() catch {};
|
|
}
|
|
|
|
// Give server time to start
|
|
std.time.sleep(1 * std.time.ns_per_s);
|
|
|
|
// Start the client process
|
|
std.debug.print("Starting test client...\n", .{});
|
|
var client_process = std.process.Child.init(&[_][]const u8{client_path}, allocator);
|
|
client_process.stdout_behavior = .Pipe;
|
|
client_process.stderr_behavior = .Pipe;
|
|
|
|
try client_process.spawn();
|
|
|
|
// Wait for client to complete
|
|
const client_result = try client_process.wait();
|
|
|
|
// Give server a moment to process the quit message and shut down naturally
|
|
std.time.sleep(2 * std.time.ns_per_s);
|
|
|
|
// Check if server is still running and terminate if needed
|
|
const server_result = server_process.wait() catch {
|
|
std.debug.print("Server still running, terminating...\n", .{});
|
|
_ = server_process.kill() catch {};
|
|
return;
|
|
};
|
|
|
|
// Read and display output
|
|
if (client_process.stdout) |stdout| {
|
|
const client_output = try stdout.reader().readAllAlloc(allocator, 8192);
|
|
defer allocator.free(client_output);
|
|
std.debug.print("\n=== CLIENT OUTPUT ===\n{s}\n", .{client_output});
|
|
}
|
|
|
|
if (server_process.stdout) |stdout| {
|
|
const server_output = try stdout.reader().readAllAlloc(allocator, 8192);
|
|
defer allocator.free(server_output);
|
|
std.debug.print("\n=== SERVER OUTPUT ===\n{s}\n", .{server_output});
|
|
}
|
|
|
|
std.debug.print("\n=== LOOPBACK TEST RESULTS ===\n", .{});
|
|
std.debug.print("Client exit code: {}\n", .{client_result});
|
|
std.debug.print("Server exit code: {}\n", .{server_result});
|
|
|
|
if (client_result == .Exited and client_result.Exited == 0 and
|
|
server_result == .Exited and server_result.Exited == 0)
|
|
{
|
|
std.debug.print("Loopback test PASSED!\n", .{});
|
|
} else {
|
|
std.debug.print("Loopback test FAILED!\n", .{});
|
|
return error.TestFailed;
|
|
}
|
|
}
|
|
};
|