From 21d8afb21a484b19cf87147d400ccd647eff33b5 Mon Sep 17 00:00:00 2001 From: JacobCrabill Date: Tue, 30 Jan 2024 20:20:21 -0800 Subject: [PATCH] Update build system to latest Zig master Builds with Zig 0.12.0-dev.2341 on x86_64-linux Also ran 'mdformat' on README.md --- README.md | 372 +++++++++++++++++++-------------------------- build.zig | 37 ++--- build.zig.zon | 16 +- facil.io/build.zig | 60 ++++---- 4 files changed, 219 insertions(+), 266 deletions(-) diff --git a/README.md b/README.md index 209674c..ce6d60b 100644 --- a/README.md +++ b/README.md @@ -1,224 +1,189 @@ - - # ⚡zap⚡ - blazingly fast backends in zig -![](https://github.com/zigzap/zap/actions/workflows/build-zig-11.yml/badge.svg) [![Discord](https://img.shields.io/discord/1107835896356675706?label=chat&logo=discord&style=plastic)](https://discord.gg/jQAAN6Ubyj) +![](https://github.com/zigzap/zap/actions/workflows/build-zig-11.yml/badge.svg) +[![Discord](https://img.shields.io/discord/1107835896356675706?label=chat&logo=discord&style=plastic)](https://discord.gg/jQAAN6Ubyj) -Zap is the [zig](https://ziglang.org) replacement for the REST APIs I used to -write in [python](https://python.org) with -[Flask](https://flask.palletsprojects.com) and -[mongodb](https://www.mongodb.com), etc. It can be considered to be a -microframework for web applications. +Zap is the [zig](https://ziglang.org) replacement for the REST APIs I used to write in +[python](https://python.org) with [Flask](https://flask.palletsprojects.com) and +[mongodb](https://www.mongodb.com), etc. It can be considered to be a microframework for web +applications. -What I needed as a replacement was a blazingly fast and robust HTTP server that -I could use with Zig, and I chose to wrap the superb evented networking C -library [facil.io](https://facil.io). Zap wraps and patches [facil.io - the C web application -framework](https://facil.io). +What I needed as a replacement was a blazingly fast and robust HTTP server that I could use with +Zig, and I chose to wrap the superb evented networking C library [facil.io](https://facil.io). Zap +wraps and patches [facil.io - the C web application framework](https://facil.io). ## **⚡ZAP⚡ IS FAST, ROBUST, AND STABLE** - -After having used ZAP in production for over 6 months, I can confidently assert -that it proved to be: +After having used ZAP in production for over 6 months, I can confidently assert that it proved to +be: - ⚡ **blazingly fast** ⚡ - 💪 **extremely robust** 💪 Exactly the goals I set out to achieve! - ## Most FAQ: - Q: **Where is the API documentation?** - - A: Docs are a work in progress. You can check them out [here](https://zigzap.org/zap). The docs are based on the `zig-0.12.0` branch but apply to the current release (zig 0.11.0), too. + - A: Docs are a work in progress. You can check them out [here](https://zigzap.org/zap). The docs + are based on the `zig-0.12.0` branch but apply to the current release (zig 0.11.0), too. - Q: **Zap doesn't build with Zig master?** - - A: See the 0.12.0 branch. An example of how to use it is - [here](https://github.com/zigzap/hello-0.12.0). Please note that the 0.12.0 - branch is not the official master branch of ZAP. Yet. Until zig 0.12.0 is - released. + - A: See the 0.12.0 branch. An example of how to use it is + [here](https://github.com/zigzap/hello-0.12.0). Please note that the 0.12.0 branch is not the + official master branch of ZAP. Yet. Until zig 0.12.0 is released. - Q: **Does ZAP work on Windows?** - - A: No. This is due to the underlying facil.io C library. Future versions of - facil.io might support Windows but there is no timeline yet. Your best options - on Windows are WSL2 or a docker container. + - A: No. This is due to the underlying facil.io C library. Future versions of facil.io might + support Windows but there is no timeline yet. Your best options on Windows are WSL2 or a docker + container. - Q: **Does ZAP support TLS / HTTPS?** - - A: Yes, ZAP supports using the system's openssl. See the - [https](./examples/https/https.zig) example and make sure to build with the - `-Dopenssl` flag or the environment variable `ZAP_USE_OPENSSL=true`: - - `.openssl = true,` (in dependent projects' build.zig, `b.dependency("zap" - .{...})`) - - `ZAP_USE_OPENSSL=true zig build https` - - `zig build -Dopenssl=true https` + - A: Yes, ZAP supports using the system's openssl. See the [https](./examples/https/https.zig) + example and make sure to build with the `-Dopenssl` flag or the environment variable + `ZAP_USE_OPENSSL=true`: + - `.openssl = true,` (in dependent projects' build.zig, `b.dependency("zap" .{...})`) + - `ZAP_USE_OPENSSL=true zig build https` + - `zig build -Dopenssl=true https` ## Here's what works -I recommend checking out **Endpoint-based examples for more realistic -use cases**. Most of the examples are super stripped down to only include -what's necessary to show a feature. +I recommend checking out **Endpoint-based examples for more realistic use cases**. Most of the +examples are super stripped down to only include what's necessary to show a feature. -- **Super easy build process**: Zap's `build.zig` now uses the new Zig package - manager for its C-dependencies, no git submodules anymore. +- **Super easy build process**: Zap's `build.zig` now uses the new Zig package manager for its + C-dependencies, no git submodules anymore. - _tested on Linux and macOS (arm, M1)_ - **[hello](examples/hello/hello.zig)**: welcomes you with some static HTML -- **[routes](examples/routes/routes.zig)**: a super easy example dispatching on - the HTTP path. **NOTE**: The dispatch in the example is a super-basic - DIY-style dispatch. See endpoint-based examples for more realistic use cases. -- **[serve](examples/serve/serve.zig)**: the traditional static web server with - optional dynamic request handling -- **[sendfile](examples/sendfile/sendfile.zig)**: simple example of how to send - a file, honoring compression headers, etc. -- **[bindataformpost](examples/bindataformpost/bindataformpost.zig)**: example - to receive binary files via form post. -- **[hello_json](examples/hello_json/hello_json.zig)**: serves you json - dependent on HTTP path -- **[endpoint](examples/endpoint/)**: a simple JSON REST API example featuring a - `/users` endpoint for performing PUT/DELETE/GET/POST operations and listing - users, together with a simple frontend to play with. **It also introduces a - `/stop` endpoint** that shuts down Zap, so **memory leak detection** can be - performed in main(). - - Check out how [main.zig](examples/endpoint/main.zig) uses ZIG's awesome - `GeneralPurposeAllocator` to report memory leaks when ZAP is shut down. - The [StopEndpoint](examples/endpoint/stopendpoint.zig) just stops ZAP when - receiving a request on the `/stop` route. +- **[routes](examples/routes/routes.zig)**: a super easy example dispatching on the HTTP path. + **NOTE**: The dispatch in the example is a super-basic DIY-style dispatch. See endpoint-based + examples for more realistic use cases. +- **[serve](examples/serve/serve.zig)**: the traditional static web server with optional dynamic + request handling +- **[sendfile](examples/sendfile/sendfile.zig)**: simple example of how to send a file, honoring + compression headers, etc. +- **[bindataformpost](examples/bindataformpost/bindataformpost.zig)**: example to receive binary + files via form post. +- **[hello_json](examples/hello_json/hello_json.zig)**: serves you json dependent on HTTP path +- **[endpoint](examples/endpoint/)**: a simple JSON REST API example featuring a `/users` endpoint + for performing PUT/DELETE/GET/POST operations and listing users, together with a simple frontend + to play with. **It also introduces a `/stop` endpoint** that shuts down Zap, so **memory leak + detection** can be performed in main(). + - Check out how [main.zig](examples/endpoint/main.zig) uses ZIG's awesome + `GeneralPurposeAllocator` to report memory leaks when ZAP is shut down. The + [StopEndpoint](examples/endpoint/stopendpoint.zig) just stops ZAP when receiving a request on + the `/stop` route. - **[mustache](examples/mustache/mustache.zig)**: a simple example using [mustache](https://mustache.github.io/) templating. -- **[endpoint authentication](examples/endpoint_auth/endpoint_auth.zig)**: a - simple authenticated endpoint. Read more about authentication - [here](./doc/authentication.md). -- **[http parameters](examples/http_params/http_params.zig)**: a simple example - sending itself query parameters of all supported types. -- **[cookies](examples/cookies/cookies.zig)**: a simple example sending itself a - cookie and responding with a session cookie. -- **[websockets](examples/websockets/)**: a simple websockets chat for the - browser. -- **[Username/Password Session - Authentication](./examples/userpass_session_auth/)**: A convenience - authenticator that redirects un-authenticated requests to a login page and - sends cookies containing session tokens based on username/password pairs - received via POST request. -- **[MIDDLEWARE support](examples/middleware/middleware.zig)**: chain together - request handlers in middleware style. Provide custom context structs, totally - type-safe, using **[ZIG-CEPTION](doc/zig-ception.md)**. If you come from GO - this might appeal to you. -- **[MIDDLEWARE with endpoint - support](examples/middleware_with_endpoint/middleware_with_endpoint.zig)**: - Same as the example above, but this time we use an endpoint at the end of the - chain, by wrapping it via `zap.Middleware.EndpointHandler`. Mixing endpoints - in your middleware chain allows for usage of Zap's authenticated endpoints and - your custom endpoints. Since Endpoints use a simpler API, you have to use - `r.setUserContext()` and `r.getUserContext()` with the request if you want to - access the middleware context from a wrapped endpoint. Since this mechanism - uses an `*anyopaque` pointer underneath (to not break the Endpoint API), it is - less type-safe than `zap.Middleware`'s use of contexts. -- [**Per Request Contexts**](./src/zap.zig#L102) : With the introduction of - `setUserContext()` and `getUserContext()`, you can, of course use those two in - projects that don't use `zap.Endpoint` or `zap.Middleware`, too, if you - really, really, absolutely don't find another way to solve your context - problem. **We recommend using a `zap.Endpoint`** inside of a struct that - can provide all the context you need **instead**. You get access to your - struct in the callbacks via the `@fieldParentPtr()` trick that is used - extensively in Zap's examples, like the [endpoint - example](examples/endpoint/endpoint.zig). -- [**Error Trace Responses**](./examples/senderror/senderror.zig): You can now - call `r.sendError(err, status_code)` when you catch an error and a stack trace - will be returned to the client / browser. -- [**HTTPS**](examples/https/https.zig): Shows how easy it is to use facil.io's - openssl support. Must be compiled with `-Dopenssl=true` or the environment - variable `ZAP_USE_OPENSSL` set to `true` and requires openssl dev dependencies - (headers, lib) to be installed on the system. - - run it like this: `ZAP_USE_OPENSSL=true zig build run-https` - OR like this: `zig build -Dopenssl=true run-https` +- **[endpoint authentication](examples/endpoint_auth/endpoint_auth.zig)**: a simple authenticated + endpoint. Read more about authentication [here](./doc/authentication.md). +- **[http parameters](examples/http_params/http_params.zig)**: a simple example sending itself query + parameters of all supported types. +- **[cookies](examples/cookies/cookies.zig)**: a simple example sending itself a cookie and + responding with a session cookie. +- **[websockets](examples/websockets/)**: a simple websockets chat for the browser. +- **[Username/Password Session Authentication](./examples/userpass_session_auth/)**: A convenience + authenticator that redirects un-authenticated requests to a login page and sends cookies + containing session tokens based on username/password pairs received via POST request. +- **[MIDDLEWARE support](examples/middleware/middleware.zig)**: chain together request handlers in + middleware style. Provide custom context structs, totally type-safe, using + **[ZIG-CEPTION](doc/zig-ception.md)**. If you come from GO this might appeal to you. +- **[MIDDLEWARE with endpoint support](examples/middleware_with_endpoint/middleware_with_endpoint.zig)**: + Same as the example above, but this time we use an endpoint at the end of the chain, by wrapping + it via `zap.Middleware.EndpointHandler`. Mixing endpoints in your middleware chain allows for + usage of Zap's authenticated endpoints and your custom endpoints. Since Endpoints use a simpler + API, you have to use `r.setUserContext()` and `r.getUserContext()` with the request if you want to + access the middleware context from a wrapped endpoint. Since this mechanism uses an `*anyopaque` + pointer underneath (to not break the Endpoint API), it is less type-safe than `zap.Middleware`'s + use of contexts. +- [**Per Request Contexts**](./src/zap.zig#L102) : With the introduction of `setUserContext()` and + `getUserContext()`, you can, of course use those two in projects that don't use `zap.Endpoint` or + `zap.Middleware`, too, if you really, really, absolutely don't find another way to solve your + context problem. **We recommend using a `zap.Endpoint`** inside of a struct that can provide all + the context you need **instead**. You get access to your struct in the callbacks via the + `@fieldParentPtr()` trick that is used extensively in Zap's examples, like the + [endpoint example](examples/endpoint/endpoint.zig). +- [**Error Trace Responses**](./examples/senderror/senderror.zig): You can now call + `r.sendError(err, status_code)` when you catch an error and a stack trace will be returned to the + client / browser. +- [**HTTPS**](examples/https/https.zig): Shows how easy it is to use facil.io's openssl support. + Must be compiled with `-Dopenssl=true` or the environment variable `ZAP_USE_OPENSSL` set to `true` + and requires openssl dev dependencies (headers, lib) to be installed on the system. + - run it like this: `ZAP_USE_OPENSSL=true zig build run-https`\ + OR like this: + `zig build -Dopenssl=true run-https` - it will tell you how to generate certificates -- [**simple_router**](examples/simple_router/simple_router.zig): See how you - can use `zap.Router` to dispatch to handlers by HTTP path. It also features - `zap.RequestHandler` to capture the "self" pointer of the container of the - handler functions. - -I'll continue wrapping more of facil.io's functionality and adding stuff to zap -to a point where I can use it as the JSON REST API backend for real research -projects, serving thousands of concurrent clients. +- [**simple_router**](examples/simple_router/simple_router.zig): See how you can use `zap.Router` to + dispatch to handlers by HTTP path. It also features `zap.RequestHandler` to capture the "self" + pointer of the container of the handler functions. +I'll continue wrapping more of facil.io's functionality and adding stuff to zap to a point where I +can use it as the JSON REST API backend for real research projects, serving thousands of concurrent +clients. ## ⚡blazingly fast⚡ -Claiming to be blazingly fast is the new black. At least, Zap doesn't slow you -down and if your server performs poorly, it's probably not exactly Zap's fault. -Zap relies on the [facil.io](https://facil.io) framework and so it can't really -claim any performance fame for itself. In this initial implementation of Zap, -I didn't care about optimizations at all. +Claiming to be blazingly fast is the new black. At least, Zap doesn't slow you down and if your +server performs poorly, it's probably not exactly Zap's fault. Zap relies on the +[facil.io](https://facil.io) framework and so it can't really claim any performance fame for itself. +In this initial implementation of Zap, I didn't care about optimizations at all. -But, how fast is it? Being blazingly fast is relative. When compared with a -simple GO HTTP server, a simple Zig Zap HTTP server performed really good on my -machine (x86_64-linux): +But, how fast is it? Being blazingly fast is relative. When compared with a simple GO HTTP server, a +simple Zig Zap HTTP server performed really good on my machine (x86_64-linux): - Zig Zap was nearly 30% faster than GO - Zig Zap had over 50% more throughput than GO -**Update**: Thanks to @felipetrz, I got to test against more realistic Python -and Rust examples. Both python `sanic` and rust `axum` were easy enough to -integrate. +**Update**: Thanks to @felipetrz, I got to test against more realistic Python and Rust examples. +Both python `sanic` and rust `axum` were easy enough to integrate. -**Update**: I have automated the benchmarks. See -[blazingly-fast.md](./blazingly-fast.md) for more information. Also, thanks to -@alexpyattaev, the benchmarks are fairer now, pinning server and client to -specific CPU cores. +**Update**: I have automated the benchmarks. See [blazingly-fast.md](./blazingly-fast.md) for more +information. Also, thanks to @alexpyattaev, the benchmarks are fairer now, pinning server and client +to specific CPU cores. -**Update**: I have consolidated the benchmarks to one good representative per -language. See more details in [blazingly-fast.md](./blazingly-fast.md). It -contains rust implementations that come pretty close to Zap's performance in the -simplistic testing scenario. +**Update**: I have consolidated the benchmarks to one good representative per language. See more +details in [blazingly-fast.md](./blazingly-fast.md). It contains rust implementations that come +pretty close to Zap's performance in the simplistic testing scenario. ![](./wrk/samples/README_req_per_sec.png) ![](./wrk/samples/README_xfer_per_sec.png) +So, being somewhere in the ballpark of basic GO performance, zig zap seems to be ... of reasonable +performance 😎. -So, being somewhere in the ballpark of basic GO performance, zig zap seems to be -... of reasonable performance 😎. - -I can rest my case that developing ZAP was a good idea because it's faster than -both alternatives: a) staying with Python, and b) creating a GO + Zig hybrid. +I can rest my case that developing ZAP was a good idea because it's faster than both alternatives: +a) staying with Python, and b) creating a GO + Zig hybrid. See more details in [blazingly-fast.md](blazingly-fast.md). ## 💪 Robust -ZAP is **very robust**. In fact, it is so robust that I was confidently able to -only work with in-memory data (RAM) in all my ZAP projects so far: over 5 large -online research experiments. No database, no file persistence, until I hit -"save" at the end 😊. +ZAP is **very robust**. In fact, it is so robust that I was confidently able to only work with +in-memory data (RAM) in all my ZAP projects so far: over 5 large online research experiments. No +database, no file persistence, until I hit "save" at the end 😊. -So I was able to postpone my cunning data persistence strategy that's similar to -a mark-and-sweep garbage collector and would only persist "dirty" data when -traffic is low, in favor of getting stuff online more quickly. But even if -implemented, such a persistence strategy is risky because when traffic is not -low, it means the system is under (heavy) load. Would you confidently NOT save -data when load is high and the data changes most frequently -> the potential -data loss is maximized? +So I was able to postpone my cunning data persistence strategy that's similar to a mark-and-sweep +garbage collector and would only persist "dirty" data when traffic is low, in favor of getting stuff +online more quickly. But even if implemented, such a persistence strategy is risky because when +traffic is not low, it means the system is under (heavy) load. Would you confidently NOT save data +when load is high and the data changes most frequently -> the potential data loss is maximized? -To answer that question, I just skipped it. I skipped saving any data until -receiving a "save" signal via API. And it worked. ZAP just kept on zapping. When -traffic calmed down or all experiment participants had finished, I hit "save" -and went on analyzing the data. +To answer that question, I just skipped it. I skipped saving any data until receiving a "save" +signal via API. And it worked. ZAP just kept on zapping. When traffic calmed down or all experiment +participants had finished, I hit "save" and went on analyzing the data. -Handling all errors does pay off after all. No hidden control flow, no hidden -errors or exceptions is one of Zig's strengths. - -To be honest: There are still pitfalls. E.g. if you request large stack sizes -for worker threads, Zig won't like that and panic. So make sure you don't have -local variables that require tens of megabytes of stack space. +Handling all errors does pay off after all. No hidden control flow, no hidden errors or exceptions +is one of Zig's strengths. +To be honest: There are still pitfalls. E.g. if you request large stack sizes for worker threads, +Zig won't like that and panic. So make sure you don't have local variables that require tens of +megabytes of stack space. ### 🛡️ Memory-safe -See the [StopEndpoint](examples/endpoint/stopendpoint.zig) in the -[endpoint](examples/endpoint) example. That example uses ZIG's awesome -`GeneralPurposeAllocator` to report memory leaks when ZAP is shut down. The -`StopEndpoint` just stops ZAP when receiving a request on the `/stop` route. - -You can use the same strategy in your debug builds and tests to check if your -code leaks memory. - +See the [StopEndpoint](examples/endpoint/stopendpoint.zig) in the [endpoint](examples/endpoint) +example. That example uses ZIG's awesome `GeneralPurposeAllocator` to report memory leaks when ZAP +is shut down. The `StopEndpoint` just stops ZAP when receiving a request on the `/stop` route. +You can use the same strategy in your debug builds and tests to check if your code leaks memory. ## Getting started @@ -246,20 +211,21 @@ $ mkdir zaptest && cd zaptest $ zig init-exe $ git init ## (optional) ``` -**Note**: Nix/NixOS users are lucky; you can use the existing `flake.nix` and run -`nix develop` to get a development shell providing zig and all -dependencies to build and run the GO, python, and rust examples for the -`wrk` performance tests. For the mere building of zap projects, + +**Note**: Nix/NixOS users are lucky; you can use the existing `flake.nix` and run `nix develop` to +get a development shell providing zig and all dependencies to build and run the GO, python, and rust +examples for the `wrk` performance tests. For the mere building of zap projects, `nix develop .#build` will only fetch zig 0.11.0. With an existing Zig project, adding Zap to it is easy: 1. Add zap to your `build.zig.zon` -2. Add zap to your `build.zig` +1. Add zap to your `build.zig` To add zap to `build.zig.zon`: + ```zig .{ .name = "My example project", @@ -274,10 +240,10 @@ To add zap to `build.zig.zon`: } } ``` + -Then, in your `build.zig`'s `build` function, add the following before -`b.installArtifact(exe)`: +Then, in your `build.zig`'s `build` function, add the following before `b.installArtifact(exe)`: ```zig const zap = b.dependency("zap", .{ @@ -289,8 +255,8 @@ Then, in your `build.zig`'s `build` function, add the following before exe.linkLibrary(zap.artifact("facil.io")); ``` -From then on, you can use the Zap package in your project. Check out the -examples to see how to use Zap. +From then on, you can use the Zap package in your project. Check out the examples to see how to use +Zap. ## Updating your project to the latest version of zap @@ -302,9 +268,8 @@ You can change the URL to Zap in your `build.zig.zon` ### Using a tagged release -Go to the [release page](https://github.com/zigzap/zap/releases). Every release -will state its version number and also provide instructions for changing -`build.zig.zon` and `build.zig`. +Go to the [release page](https://github.com/zigzap/zap/releases). Every release will state its +version number and also provide instructions for changing `build.zig.zon` and `build.zig`. ### Using other versions @@ -312,32 +277,28 @@ See [here](./doc/other-versions.md). ## Contribute to ⚡zap⚡ - blazingly fast -At the current time, I can only add to zap what I need for my personal and -professional projects. While this happens **blazingly fast**, some if not all -nice-to-have additions will have to wait. You are very welcome to help make the -world a blazingly fast place by providing patches or pull requests, add -documentation or examples, or interesting issues and bug reports - you'll know -what to do when you receive your calling 👼. +At the current time, I can only add to zap what I need for my personal and professional projects. +While this happens **blazingly fast**, some if not all nice-to-have additions will have to wait. You +are very welcome to help make the world a blazingly fast place by providing patches or pull +requests, add documentation or examples, or interesting issues and bug reports - you'll know what to +do when you receive your calling 👼. Check out [CONTRIBUTING.md](CONTRIBUTING.md) for more details. -See also [introducing.md](introducing.md) for more on the state and progress of -this project. +See also [introducing.md](introducing.md) for more on the state and progress of this project. **We now have our own [ZAP discord](https://discord.gg/jQAAN6Ubyj) server!!!** -You can also reach me on [the zig showtime discord -server](https://discord.gg/CBzE3VMb) under the handle renerocksai -(renerocksai#1894). +You can also reach me on [the zig showtime discord server](https://discord.gg/CBzE3VMb) under the +handle renerocksai (renerocksai#1894). ## Support ⚡zap⚡ -Being blazingly fast requires a constant feed of caffeine. I usually manage to -provide that to myself for myself. However, to support keeping the juices -flowing and putting a smile on my face and that warm and cozy feeling into my -heart, you can always [buy me a coffee](https://buymeacoffee.com/renerocksai) -☕. All donations are welcomed 🙏 blazingly fast! That being said, just saying -"hi" also works wonders with the smiles, warmth, and coziness 😊. +Being blazingly fast requires a constant feed of caffeine. I usually manage to provide that to +myself for myself. However, to support keeping the juices flowing and putting a smile on my face and +that warm and cozy feeling into my heart, you can always +[buy me a coffee](https://buymeacoffee.com/renerocksai) ☕. All donations are welcomed 🙏 blazingly +fast! That being said, just saying "hi" also works wonders with the smiles, warmth, and coziness 😊. ## Examples @@ -348,8 +309,8 @@ $ zig build [EXAMPLE] $ ./zig-out/bin/[EXAMPLE] ``` -... where `[EXAMPLE]` is one of `hello`, `routes`, `serve`, ... see the [list of -examples above](#heres-what-works). +... where `[EXAMPLE]` is one of `hello`, `routes`, `serve`, ... see the +[list of examples above](#heres-what-works). Example: building and running the hello example: @@ -404,26 +365,3 @@ pub fn main() !void { }); } ``` - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build.zig b/build.zig index 0ccbb6f..8b40bae 100644 --- a/build.zig +++ b/build.zig @@ -1,7 +1,7 @@ const std = @import("std"); const build_facilio = @import("facil.io/build.zig").build_facilio; -pub fn build(b: *std.build.Builder) !void { +pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); // Standard release options allow the person running `zig build` to select // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. @@ -15,16 +15,16 @@ pub fn build(b: *std.build.Builder) !void { break :blk false; }; - // create a module to be used internally. - var zap_module = b.createModule(.{ - .source_file = .{ .path = "src/zap.zig" }, - }); - - // register the module so it can be referenced using the package manager. - try b.modules.put(b.dupe("zap"), zap_module); - + // Build Facil.IO as a static library const facilio = try build_facilio("facil.io", b, target, optimize, use_openssl); + // Create the Zap module and attach the facilio lib to it. + // This will enable all users of Zap to simply import the "zap" module and be on their way. + const zap_module = b.addModule("zap", .{ + .root_source_file = .{ .path = "src/zap.zig" }, + }); + zap_module.linkLibrary(facilio); + const all_step = b.step("all", "build all examples"); inline for ([_]struct { @@ -81,8 +81,7 @@ pub fn build(b: *std.build.Builder) !void { .optimize = optimize, }); - example.linkLibrary(facilio); - example.addModule("zap", zap_module); + example.root_module.addImport("zap", zap_module); // const example_run = example.run(); const example_run = b.addRunArtifact(example); @@ -120,8 +119,7 @@ pub fn build(b: *std.build.Builder) !void { .target = target, .optimize = optimize, }); - auth_tests.linkLibrary(facilio); - auth_tests.addModule("zap", zap_module); + auth_tests.root_module.addImport("zap", zap_module); const run_auth_tests = b.addRunArtifact(auth_tests); const install_auth_tests = b.addInstallArtifact(auth_tests, .{}); @@ -133,8 +131,7 @@ pub fn build(b: *std.build.Builder) !void { .target = target, .optimize = optimize, }); - mustache_tests.linkLibrary(facilio); - mustache_tests.addModule("zap", zap_module); + mustache_tests.root_module.addImport("zap", zap_module); const run_mustache_tests = b.addRunArtifact(mustache_tests); const install_mustache_tests = b.addInstallArtifact(mustache_tests, .{}); @@ -147,8 +144,7 @@ pub fn build(b: *std.build.Builder) !void { .optimize = optimize, }); - httpparams_tests.linkLibrary(facilio); - httpparams_tests.addModule("zap", zap_module); + httpparams_tests.root_module.addImport("zap", zap_module); const run_httpparams_tests = b.addRunArtifact(httpparams_tests); // TODO: for some reason, tests aren't run more than once unless // dependencies have changed. @@ -164,8 +160,7 @@ pub fn build(b: *std.build.Builder) !void { .optimize = optimize, }); - sendfile_tests.linkLibrary(facilio); - sendfile_tests.addModule("zap", zap_module); + sendfile_tests.root_module.addImport("zap", zap_module); const run_sendfile_tests = b.addRunArtifact(sendfile_tests); const install_sendfile_tests = b.addInstallArtifact(sendfile_tests, .{}); @@ -198,7 +193,7 @@ pub fn build(b: *std.build.Builder) !void { // // pkghash // - var pkghash_exe = b.addExecutable(.{ + const pkghash_exe = b.addExecutable(.{ .name = "pkghash", .root_source_file = .{ .path = "./tools/pkghash.zig" }, .target = target, @@ -212,7 +207,7 @@ pub fn build(b: *std.build.Builder) !void { // // announceybot // - var announceybot_exe = b.addExecutable(.{ + const announceybot_exe = b.addExecutable(.{ .name = "announceybot", .root_source_file = .{ .path = "./tools/announceybot.zig" }, .target = target, diff --git a/build.zig.zon b/build.zig.zon index 7770496..0f256ea 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1 +1,15 @@ -.{ .name = "zap", .version = "0.5.0" } +.{ + .name = "zap", + .version = "0.5.0", + .paths = .{ + "doc/", + "examples/", + "facil.io/", + "src/", + "tools/", + "README.md", + "build.zig", + "build.zig.zon", + "targets.txt", + }, +} diff --git a/facil.io/build.zig b/facil.io/build.zig index e072242..2312e36 100644 --- a/facil.io/build.zig +++ b/facil.io/build.zig @@ -2,11 +2,11 @@ const std = @import("std"); pub fn build_facilio( comptime subdir: []const u8, - b: *std.build.Builder, - target: std.zig.CrossTarget, + b: *std.Build, + target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, use_openssl: bool, -) !*std.build.CompileStep { +) !*std.Build.Step.Compile { const lib = b.addStaticLibrary(.{ .name = "facil.io", .target = target, @@ -15,7 +15,7 @@ pub fn build_facilio( // Generate flags var flags = std.ArrayList([]const u8).init(std.heap.page_allocator); - if (lib.optimize != .Debug) try flags.append("-Os"); + // if (lib.optimize != .Debug) try flags.append("-Os"); // TODO try flags.append("-Wno-return-type-c-linkage"); try flags.append("-fno-sanitize=undefined"); @@ -26,7 +26,7 @@ pub fn build_facilio( // try flags.append("-DFIO_HTTP_EXACT_LOGGING"); - if (target.getAbi() == .musl) + if (target.result.abi == .musl) try flags.append("-D_LARGEFILE64_SOURCE"); if (use_openssl) try flags.append("-DHAVE_OPENSSL -DFIO_TLS_FOUND"); @@ -42,30 +42,36 @@ pub fn build_facilio( lib.addIncludePath(.{ .path = subdir ++ "/lib/facil/tls" }); // C source files - lib.addCSourceFiles(&.{ - subdir ++ "/lib/facil/fio.c", - subdir ++ "/lib/facil/fio_zig.c", - subdir ++ "/lib/facil/http/http.c", - subdir ++ "/lib/facil/http/http1.c", - subdir ++ "/lib/facil/http/websockets.c", - subdir ++ "/lib/facil/http/http_internal.c", - subdir ++ "/lib/facil/fiobj/fiobj_numbers.c", - subdir ++ "/lib/facil/fiobj/fio_siphash.c", - subdir ++ "/lib/facil/fiobj/fiobj_str.c", - subdir ++ "/lib/facil/fiobj/fiobj_ary.c", - subdir ++ "/lib/facil/fiobj/fiobj_data.c", - subdir ++ "/lib/facil/fiobj/fiobj_hash.c", - subdir ++ "/lib/facil/fiobj/fiobj_json.c", - subdir ++ "/lib/facil/fiobj/fiobject.c", - subdir ++ "/lib/facil/fiobj/fiobj_mustache.c", - subdir ++ "/lib/facil/cli/fio_cli.c", - }, flags.items); + lib.addCSourceFiles(.{ + .files = &.{ + subdir ++ "/lib/facil/fio.c", + subdir ++ "/lib/facil/fio_zig.c", + subdir ++ "/lib/facil/http/http.c", + subdir ++ "/lib/facil/http/http1.c", + subdir ++ "/lib/facil/http/websockets.c", + subdir ++ "/lib/facil/http/http_internal.c", + subdir ++ "/lib/facil/fiobj/fiobj_numbers.c", + subdir ++ "/lib/facil/fiobj/fio_siphash.c", + subdir ++ "/lib/facil/fiobj/fiobj_str.c", + subdir ++ "/lib/facil/fiobj/fiobj_ary.c", + subdir ++ "/lib/facil/fiobj/fiobj_data.c", + subdir ++ "/lib/facil/fiobj/fiobj_hash.c", + subdir ++ "/lib/facil/fiobj/fiobj_json.c", + subdir ++ "/lib/facil/fiobj/fiobject.c", + subdir ++ "/lib/facil/fiobj/fiobj_mustache.c", + subdir ++ "/lib/facil/cli/fio_cli.c", + }, + .flags = flags.items, + }); if (use_openssl) { - lib.addCSourceFiles(&.{ - subdir ++ "/lib/facil/tls/fio_tls_openssl.c", - subdir ++ "/lib/facil/tls/fio_tls_missing.c", - }, flags.items); + lib.addCSourceFiles(.{ + .files = &.{ + subdir ++ "/lib/facil/tls/fio_tls_openssl.c", + subdir ++ "/lib/facil/tls/fio_tls_missing.c", + }, + .flags = flags.items, + }); } // link against libc