Skip to content

Commit 02c03a5

Browse files
Initial implementation (#1)
* Initial implementation * Remove temporary planning docs * Add CI workflows * Document cJSON integer precision limits * Avoid duplicate CI runs
1 parent 2018683 commit 02c03a5

27 files changed

Lines changed: 4681 additions & 0 deletions

.github/workflows/ci.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
branches:
9+
- "**"
10+
11+
jobs:
12+
examples:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Set up Go
18+
uses: actions/setup-go@v5
19+
with:
20+
go-version: "1.23"
21+
22+
- name: Regenerate examples
23+
run: make -C _examples generate
24+
25+
- name: Git diff of regenerated files
26+
run: make -C _examples diff
27+
28+
tests:
29+
runs-on: ubuntu-latest
30+
steps:
31+
- uses: actions/checkout@v4
32+
33+
- name: Set up Go
34+
uses: actions/setup-go@v5
35+
with:
36+
go-version: "1.23"
37+
38+
- name: Install native dependencies
39+
run: |
40+
sudo apt-get update
41+
sudo apt-get install -y build-essential pkg-config libcurl4-openssl-dev libcjson-dev
42+
43+
- name: Run generator tests
44+
run: go test ./...

README.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# gen-c
2+
3+
This repo contains the templates used by the `webrpc-gen` CLI to code-generate
4+
webrpc C client code.
5+
6+
This generator, from a webrpc schema/design file, will code-generate:
7+
8+
1. Header output
9+
Public C enums, structs, support types, `init` / `free` helpers, client declarations,
10+
and lower-level request / response helpers.
11+
12+
2. Implementation output
13+
C JSON encode/decode helpers, generated method request / response handling,
14+
and an optional `libcurl`-based client runtime.
15+
16+
The generated client is intended to speak to any webrpc server language
17+
(Go, nodejs, etc.) as long as the schema features used are supported by this target.
18+
19+
## Dependencies
20+
21+
Generated `header` output only depends on the C standard library headers included by
22+
the generated file.
23+
24+
Generated `impl` output currently depends on:
25+
26+
- `cJSON`
27+
- `libcurl`
28+
29+
The generated code targets C99.
30+
31+
Typical compile / link flags look like:
32+
33+
```bash
34+
cc -std=c99 \
35+
$(pkg-config --cflags libcurl libcjson) \
36+
-c example.gen.c
37+
38+
cc -std=c99 \
39+
app.c example.gen.c \
40+
$(pkg-config --cflags --libs libcurl libcjson) \
41+
-o app
42+
```
43+
44+
Dependency names can vary slightly by platform or package manager. The important part
45+
is that the generated implementation can include `<cjson/cJSON.h>` and link against
46+
`libcurl` and `cJSON`.
47+
48+
Because the generated implementation uses `cJSON`, exact large 64-bit integer handling
49+
follows `cJSON`'s numeric behavior. If your API needs exact integer round-tripping beyond
50+
normal JSON number precision expectations, prefer `bigint` in the schema instead of
51+
`int64` / `uint64`.
52+
53+
## Features
54+
55+
The current generator supports:
56+
57+
- client code generation
58+
- separate `header` and `impl` emission
59+
- generated DTO structs and enums
60+
- generated `init` / `free` helpers for schema and method wrapper types
61+
- `bigint` values encoded as JSON strings
62+
- `timestamp` values encoded as JSON strings
63+
- `any`, `null`, nested lists, nested maps, and nested structs
64+
- map keys of type `string` and `enum`
65+
- succinct method wire format
66+
- generated lower-level helpers to:
67+
- prepare request bytes without sending them
68+
- send a prepared request with the generated transport
69+
- parse a raw HTTP response into generated response types
70+
- generated `libcurl` client configuration for bearer auth, custom headers, and timeouts
71+
72+
## Limitations
73+
74+
The current generator does not support:
75+
76+
- server generation
77+
- streaming methods
78+
- map keys other than `string` or `enum`
79+
- a shared external transport abstraction; the generated runtime is currently self-contained
80+
81+
Implementation generation also assumes a companion generated header include via
82+
`-header=<file>`.
83+
84+
## Usage
85+
86+
Generate the header:
87+
88+
```bash
89+
webrpc-gen \
90+
-schema=example.ridl \
91+
-target=./local-gen-c \
92+
-emit=header \
93+
-out=./example.gen.h
94+
```
95+
96+
Generate the implementation:
97+
98+
```bash
99+
webrpc-gen \
100+
-schema=example.ridl \
101+
-target=./local-gen-c \
102+
-emit=impl \
103+
-header=example.gen.h \
104+
-out=./example.gen.c
105+
```
106+
107+
When published as a `gen-*` module, this can also be used via:
108+
109+
```bash
110+
webrpc-gen \
111+
-schema=example.ridl \
112+
-target=github.com/webrpc/gen-c@<version> \
113+
-emit=header \
114+
-out=./example.gen.h
115+
```
116+
117+
or:
118+
119+
```bash
120+
webrpc-gen \
121+
-schema=example.ridl \
122+
-target=github.com/webrpc/gen-c@<version> \
123+
-emit=impl \
124+
-header=example.gen.h \
125+
-out=./example.gen.c
126+
```
127+
128+
## Set Custom Template Variables
129+
130+
Change any of the following values by passing `-option="Value"` CLI flag to `webrpc-gen`.
131+
132+
| webrpc-gen -option | Description | Default value | Version |
133+
| --- | --- | --- | --- |
134+
| `-prefix=<name>` | symbol and type prefix | schema name in `snake_case` | v0.0.1 |
135+
| `-client` | generate client declarations and runtime | `true` | v0.0.1 |
136+
| `-emit=<mode>` | emit either `header` or `impl` | `header` | v0.0.1 |
137+
| `-header=<file>` | header include used by `impl` output | `<prefix>.h` | v0.0.1 |
138+
139+
## Notes
140+
141+
- `-target` can be a local template directory or a git module path.
142+
- `bigint` support is string-based by design to avoid precision loss in C JSON handling.
143+
- for precision-sensitive large integer values, prefer `bigint` over `int64` / `uint64` in the schema when targeting this generator
144+
- The generated implementation is tested with smoke, codec, succinct, and reference interop coverage in this repo.

_examples/Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
WEBRPC_GEN_VERSION := v0.37.1
2+
ROOT := ..
3+
GEN := go run -ldflags="-X github.com/webrpc/webrpc.VERSION=$(WEBRPC_GEN_VERSION)" github.com/webrpc/webrpc/cmd/webrpc-gen@$(WEBRPC_GEN_VERSION)
4+
5+
.PHONY: generate diff
6+
7+
generate:
8+
$(GEN) -schema=smoke/example.ridl -target=$(ROOT) -emit=header -out=smoke/example.gen.h
9+
$(GEN) -schema=smoke/example.ridl -target=$(ROOT) -emit=impl -header=example.gen.h -out=smoke/example.gen.c
10+
11+
diff:
12+
git diff --exit-code -- smoke/example.gen.h smoke/example.gen.c

0 commit comments

Comments
 (0)