From 36a02c7ecea9616e5aacff7c508b02ec55f55711 Mon Sep 17 00:00:00 2001 From: Matheus Catarino Date: Wed, 4 Sep 2024 10:48:32 -0300 Subject: [PATCH] refactoring and new example test added --- README.md | 5 +- build.zig | 222 +++++++------------------------------------ tests/build.zig | 9 +- tests/http_server.cc | 73 ++++++++++++++ 4 files changed, 114 insertions(+), 195 deletions(-) create mode 100644 tests/http_server.cc diff --git a/README.md b/README.md index 7004bbb..c7ac5cc 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Build libraries ```bash # Build no-header-only libraries -$ zig build -Doptimize= -Dtarget= --summary -Dcontext -Djson -Dsystem -Dcontainer -Dcobalt -Dfilesystem -Dheaders-only=false +$ zig build -Doptimize= -Dtarget= --summary -Dcontext -Djson -Dsystem -Dcontainer -Dcobalt -Dfilesystem ``` #### Helper @@ -30,7 +30,6 @@ Project-Specific Options: ReleaseSafe ReleaseFast ReleaseSmall - -Dheaders-only=[bool] Use headers-only libraries (default: true) -Dcobalt=[bool] Build cobalt library (default: false) -Dcontext=[bool] Build context library (default: false) -Djson=[bool] Build json library (default: false) @@ -61,8 +60,6 @@ pub fn build(b: *std.Build) !void { const boost_dep = b.dependency("boost", .{ .target = target, .optimize = optimize, - // default is true (recommended) - // .@"headers-only" = false, }); const boost_artifact = boost_dep.artifact("boost"); diff --git a/build.zig b/build.zig index 82af3dd..b693c19 100644 --- a/build.zig +++ b/build.zig @@ -117,7 +117,6 @@ pub fn build(b: *std.Build) !void { const boost = boostLibraries(b, .{ .target = target, .optimize = optimize, - .headers_only = b.option(bool, "headers-only", "Use headers-only libraries (default: true)") orelse true, .module = .{ .cobalt = b.option(bool, "cobalt", "Build cobalt library (default: false)") orelse false, .context = b.option(bool, "context", "Build context library (default: false)") orelse false, @@ -160,73 +159,34 @@ pub fn boostLibraries(b: *std.Build, config: Config) *std.Build.Step.Compile { lib.addIncludePath(boostLib); } - if (config.headers_only) { - // zig-pkg bypass (artifact need source file) - const empty = b.addWriteFile("empty.cc", - \\ #include - ); - lib.step.dependOn(&empty.step); - lib.addCSourceFiles(.{ - .root = empty.getDirectory(), - .files = &.{"empty.cc"}, - .flags = cxxFlags, - }); - } else { - if (config.module) |module| { - if (module.cobalt) { - const boostCobalt = buildCobalt(b, .{ - .headers_only = config.headers_only, - .target = config.target, - .optimize = config.optimize, - .include_dirs = lib.root_module.include_dirs, - }); - lib.addObject(boostCobalt); - } - if (module.container) { - const boostContainer = buildContainer(b, .{ - .headers_only = config.headers_only, - .target = config.target, - .optimize = config.optimize, - .include_dirs = lib.root_module.include_dirs, - }); - lib.addObject(boostContainer); - } - if (module.context) { - const boostContext = buildContext(b, .{ - .headers_only = config.headers_only, - .target = config.target, - .optimize = config.optimize, - .include_dirs = lib.root_module.include_dirs, - }); - lib.addObject(boostContext); - } - if (module.json) { - const boostJson = buildJson(b, .{ - .headers_only = config.headers_only, - .target = config.target, - .optimize = config.optimize, - .include_dirs = lib.root_module.include_dirs, - }); - lib.addObject(boostJson); - } - if (module.filesystem) { - const boostFileSystem = buildFileSystem(b, .{ - .headers_only = config.headers_only, - .target = config.target, - .optimize = config.optimize, - .include_dirs = lib.root_module.include_dirs, - }); - lib.addObject(boostFileSystem); - } - if (module.system) { - const boostSystem = buildSystem(b, .{ - .headers_only = config.headers_only, - .target = config.target, - .optimize = config.optimize, - .include_dirs = lib.root_module.include_dirs, - }); - lib.addObject(boostSystem); - } + // zig-pkg bypass (artifact need source file to generate object file) + const empty = b.addWriteFile("empty.cc", + \\ #include + ); + lib.step.dependOn(&empty.step); + lib.addCSourceFiles(.{ + .root = empty.getDirectory(), + .files = &.{"empty.cc"}, + .flags = cxxFlags, + }); + if (config.module) |module| { + if (module.cobalt) { + buildCobalt(b, lib); + } + if (module.container) { + buildContainer(b, lib); + } + if (module.context) { + buildContext(b, lib); + } + if (module.json) { + buildJson(b, lib); + } + if (module.filesystem) { + buildFileSystem(b, lib); + } + if (module.system) { + buildSystem(b, lib); } } if (lib.rootModuleTarget().abi == .msvc) @@ -239,11 +199,9 @@ pub fn boostLibraries(b: *std.Build, config: Config) *std.Build.Step.Compile { } pub const Config = struct { - headers_only: bool = false, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, module: ?boostLibrariesModules = null, - include_dirs: ?std.ArrayListUnmanaged(std.Build.Module.IncludeDir) = null, }; // No header-only libraries @@ -257,21 +215,10 @@ const boostLibrariesModules = struct { system: bool = false, }; -fn buildCobalt(b: *std.Build, config: Config) *std.Build.Step.Compile { +fn buildCobalt(b: *std.Build, obj: *std.Build.Step.Compile) void { const cobaltPath = b.dependency("cobalt", .{}).path("src"); - const obj = b.addObject(.{ - .name = "cobalt", - .target = config.target, - .optimize = config.optimize, - }); - - if (config.include_dirs) |include_dirs| { - for (include_dirs.items) |include| { - obj.root_module.include_dirs.append(b.allocator, include) catch unreachable; - } - } obj.defineCMacro("BOOST_COBALT_SOURCE", null); - obj.defineCMacro("BOOST_COBALT_USE_BOOST_CONTAINER_PMR", null); + // obj.defineCMacro("BOOST_COBALT_USE_BOOST_CONTAINER_PMR", null); obj.addCSourceFiles(.{ .root = cobaltPath, .files = &.{ @@ -285,29 +232,10 @@ fn buildCobalt(b: *std.Build, config: Config) *std.Build.Step.Compile { }, .flags = cxxFlags ++ &[_][]const u8{"-std=c++20"}, }); - if (obj.rootModuleTarget().abi == .msvc) - obj.linkLibC() - else { - obj.defineCMacro("_GNU_SOURCE", null); - obj.linkLibCpp(); - } - - return obj; } -fn buildContainer(b: *std.Build, config: Config) *std.Build.Step.Compile { +fn buildContainer(b: *std.Build, obj: *std.Build.Step.Compile) void { const containerPath = b.dependency("container", .{}).path("src"); - const obj = b.addObject(.{ - .name = "container", - .target = config.target, - .optimize = config.optimize, - }); - - if (config.include_dirs) |include_dirs| { - for (include_dirs.items) |include| { - obj.root_module.include_dirs.append(b.allocator, include) catch unreachable; - } - } obj.addCSourceFiles(.{ .root = containerPath, .files = &.{ @@ -319,29 +247,11 @@ fn buildContainer(b: *std.Build, config: Config) *std.Build.Step.Compile { }, .flags = cxxFlags, }); - if (obj.rootModuleTarget().abi == .msvc) - obj.linkLibC() - else { - obj.defineCMacro("_GNU_SOURCE", null); - obj.linkLibCpp(); - } - - return obj; } -fn buildJson(b: *std.Build, config: Config) *std.Build.Step.Compile { +fn buildJson(b: *std.Build, obj: *std.Build.Step.Compile) void { const jsonPath = b.dependency("json", .{}).path("src"); - const obj = b.addObject(.{ - .name = "json", - .target = config.target, - .optimize = config.optimize, - }); - if (config.include_dirs) |include_dirs| { - for (include_dirs.items) |include| { - obj.root_module.include_dirs.append(b.allocator, include) catch unreachable; - } - } obj.addCSourceFiles(.{ .root = jsonPath, .files = &.{ @@ -349,29 +259,11 @@ fn buildJson(b: *std.Build, config: Config) *std.Build.Step.Compile { }, .flags = cxxFlags, }); - if (obj.rootModuleTarget().abi == .msvc) - obj.linkLibC() - else { - obj.defineCMacro("_GNU_SOURCE", null); - obj.linkLibCpp(); - } - - return obj; } -fn buildSystem(b: *std.Build, config: Config) *std.Build.Step.Compile { +fn buildSystem(b: *std.Build, obj: *std.Build.Step.Compile) void { const systemPath = b.dependency("system", .{}).path("src"); - const obj = b.addObject(.{ - .name = "system", - .target = config.target, - .optimize = config.optimize, - }); - if (config.include_dirs) |include_dirs| { - for (include_dirs.items) |include| { - obj.root_module.include_dirs.append(b.allocator, include) catch unreachable; - } - } obj.addCSourceFiles(.{ .root = systemPath, .files = &.{ @@ -379,29 +271,11 @@ fn buildSystem(b: *std.Build, config: Config) *std.Build.Step.Compile { }, .flags = cxxFlags, }); - if (obj.rootModuleTarget().abi == .msvc) - obj.linkLibC() - else { - obj.defineCMacro("_GNU_SOURCE", null); - obj.linkLibCpp(); - } - - return obj; } -fn buildFileSystem(b: *std.Build, config: Config) *std.Build.Step.Compile { +fn buildFileSystem(b: *std.Build, obj: *std.Build.Step.Compile) void { const fsPath = b.dependency("filesystem", .{}).path("src"); - const obj = b.addObject(.{ - .name = "filesystem", - .target = config.target, - .optimize = config.optimize, - }); - if (config.include_dirs) |include_dirs| { - for (include_dirs.items) |include| { - obj.root_module.include_dirs.append(b.allocator, include) catch unreachable; - } - } if (obj.rootModuleTarget().os.tag == .windows) { obj.addCSourceFiles(.{ .root = fsPath, @@ -429,32 +303,15 @@ fn buildFileSystem(b: *std.Build, config: Config) *std.Build.Step.Compile { .flags = cxxFlags, }); if (obj.rootModuleTarget().abi == .msvc) { - obj.linkLibC(); obj.defineCMacro("_SCL_SECURE_NO_WARNINGS", null); obj.defineCMacro("_SCL_SECURE_NO_DEPRECATE", null); obj.defineCMacro("_CRT_SECURE_NO_WARNINGS", null); obj.defineCMacro("_CRT_SECURE_NO_DEPRECATE", null); - } else { - obj.defineCMacro("_GNU_SOURCE", null); - obj.linkLibCpp(); } - - return obj; } -fn buildContext(b: *std.Build, config: Config) *std.Build.Step.Compile { +fn buildContext(b: *std.Build, obj: *std.Build.Step.Compile) void { const contextPath = b.dependency("context", .{}).path("src"); - const obj = b.addObject(.{ - .name = "context", - .target = config.target, - .optimize = config.optimize, - }); - - if (config.include_dirs) |include_dirs| { - for (include_dirs.items) |include| { - obj.root_module.include_dirs.append(b.allocator, include) catch unreachable; - } - } const ctxPath = contextPath.getPath(b); obj.addIncludePath(.{ .cwd_relative = b.pathJoin(&.{ ctxPath, "asm" }), @@ -609,13 +466,4 @@ fn buildContext(b: *std.Build, config: Config) *std.Build.Step.Compile { }, else => @panic("Invalid arch"), } - - if (obj.rootModuleTarget().abi == .msvc) - obj.linkLibC() - else { - obj.defineCMacro("_GNU_SOURCE", null); - obj.linkLibCpp(); - } - - return obj; } diff --git a/tests/build.zig b/tests/build.zig index 5db2543..4c3a65c 100644 --- a/tests/build.zig +++ b/tests/build.zig @@ -7,9 +7,7 @@ pub fn build(b: *std.Build) void { const boost_dep = b.dependency("boost", .{ .target = target, .optimize = optimize, - // .@"headers-only" = false, // need link-library artifact - // need disable header-only .cobalt = true, .container = true, .context = false, @@ -19,6 +17,7 @@ pub fn build(b: *std.Build) void { }); inline for (&.{ + "http_server.cc", "include_all.cc", }) |file| { buildTests(b, .{ @@ -71,9 +70,11 @@ fn buildTests(b: *std.Build, options: struct { exe.linkLibC(); } - // for boost::asio/boost::beast - if (exe.rootModuleTarget().os.tag == .windows) + // for boost::asio/boost::beast/boost::cobalt + if (exe.rootModuleTarget().os.tag == .windows) { exe.linkSystemLibrary("ws2_32"); + exe.linkSystemLibrary("mswsock"); + } b.installArtifact(exe); const run_cmd = b.addRunArtifact(exe); diff --git a/tests/http_server.cc b/tests/http_server.cc new file mode 100644 index 0000000..ef126d3 --- /dev/null +++ b/tests/http_server.cc @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace async = boost::cobalt; +using boost::asio::ip::tcp; +using tcp_acceptor = async::use_op_t::as_default_on_t; +using tcp_socket = async::use_op_t::as_default_on_t; +namespace this_coro = boost::cobalt::this_coro; +namespace beast = boost::beast; +namespace http = beast::http; + +async::promise handle_request(tcp_socket socket) { + try { + beast::flat_buffer buffer; + http::request request; + + co_await http::async_read(socket, buffer, request, + boost::asio::as_tuple(async::use_op)); + + http::response response(http::status::ok, + request.version()); + response.set(http::field::server, "Boost/AsyncHTTPServer"); + + // Extract the requested path from the HTTP request. + std::string_view path = request.target(); + + // Define different routes and their corresponding responses. + if (path == "/") { + response.body() = "Welcome to the root route!"; + } else if (path == "/hello") { + response.body() = "Hello, World!"; + } else { + response = http::response(http::status::not_found, + request.version()); + response.body() = "404 Not Found"; + } + + response.prepare_payload(); + co_await http::async_write(socket, response, + boost::asio::as_tuple(async::use_op)); + } catch (std::exception &e) { + std::cerr << "HTTP Request Handling Exception: " << e.what() << std::endl; + } +} + +async::generator listen() { + tcp_acceptor acceptor({co_await this_coro::executor}, {tcp::v4(), 8080}); + + for (;;) { + co_yield co_await acceptor.async_accept(); + } +} + +async::promise run_server(async::wait_group &workers) { + auto l = listen(); + + while (true) { + if (workers.size() < 10u) + workers.push_back(handle_request(co_await l)); + else + co_await workers.wait_one(); + } +} + +async::main co_main(int argc, char **argv) { + co_await async::with(async::wait_group(), &run_server); + co_return 0u; +} \ No newline at end of file