mirror of
https://github.com/zigzap/zap.git
synced 2025-10-20 23:24:09 +00:00
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
This commit is contained in:
parent
9ce4b4438d
commit
21d8afb21a
4 changed files with 219 additions and 266 deletions
372
README.md
372
README.md
|
@ -1,224 +1,189 @@
|
|||
|
||||
|
||||
# ⚡zap⚡ - blazingly fast backends in zig
|
||||
|
||||
 [](https://discord.gg/jQAAN6Ubyj)
|
||||

|
||||
[](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.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
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`:
|
||||
|
||||
<!-- INSERT_DEP_BEGIN -->
|
||||
|
||||
```zig
|
||||
.{
|
||||
.name = "My example project",
|
||||
|
@ -274,10 +240,10 @@ To add zap to `build.zig.zon`:
|
|||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- INSERT_DEP_END -->
|
||||
|
||||
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 {
|
|||
});
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
37
build.zig
37
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,
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue