Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: CI

on:
push:
branches:
- master
pull_request:
branches:
- "**"

jobs:
examples:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.23"

- name: Regenerate examples
run: make -C _examples generate

- name: Git diff of regenerated files
run: make -C _examples diff

tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.23"

- name: Install native dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential pkg-config libcurl4-openssl-dev libcjson-dev

- name: Run generator tests
run: go test ./...
144 changes: 144 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# gen-c

This repo contains the templates used by the `webrpc-gen` CLI to code-generate
webrpc C client code.

This generator, from a webrpc schema/design file, will code-generate:

1. Header output
Public C enums, structs, support types, `init` / `free` helpers, client declarations,
and lower-level request / response helpers.

2. Implementation output
C JSON encode/decode helpers, generated method request / response handling,
and an optional `libcurl`-based client runtime.

The generated client is intended to speak to any webrpc server language
(Go, nodejs, etc.) as long as the schema features used are supported by this target.

## Dependencies

Generated `header` output only depends on the C standard library headers included by
the generated file.

Generated `impl` output currently depends on:

- `cJSON`
- `libcurl`

The generated code targets C99.

Typical compile / link flags look like:

```bash
cc -std=c99 \
$(pkg-config --cflags libcurl libcjson) \
-c example.gen.c

cc -std=c99 \
app.c example.gen.c \
$(pkg-config --cflags --libs libcurl libcjson) \
-o app
```

Dependency names can vary slightly by platform or package manager. The important part
is that the generated implementation can include `<cjson/cJSON.h>` and link against
`libcurl` and `cJSON`.

Because the generated implementation uses `cJSON`, exact large 64-bit integer handling
follows `cJSON`'s numeric behavior. If your API needs exact integer round-tripping beyond
normal JSON number precision expectations, prefer `bigint` in the schema instead of
`int64` / `uint64`.

## Features

The current generator supports:

- client code generation
- separate `header` and `impl` emission
- generated DTO structs and enums
- generated `init` / `free` helpers for schema and method wrapper types
- `bigint` values encoded as JSON strings
- `timestamp` values encoded as JSON strings
- `any`, `null`, nested lists, nested maps, and nested structs
- map keys of type `string` and `enum`
- succinct method wire format
- generated lower-level helpers to:
- prepare request bytes without sending them
- send a prepared request with the generated transport
- parse a raw HTTP response into generated response types
- generated `libcurl` client configuration for bearer auth, custom headers, and timeouts

## Limitations

The current generator does not support:

- server generation
- streaming methods
- map keys other than `string` or `enum`
- a shared external transport abstraction; the generated runtime is currently self-contained

Implementation generation also assumes a companion generated header include via
`-header=<file>`.

## Usage

Generate the header:

```bash
webrpc-gen \
-schema=example.ridl \
-target=./local-gen-c \
-emit=header \
-out=./example.gen.h
```

Generate the implementation:

```bash
webrpc-gen \
-schema=example.ridl \
-target=./local-gen-c \
-emit=impl \
-header=example.gen.h \
-out=./example.gen.c
```

When published as a `gen-*` module, this can also be used via:

```bash
webrpc-gen \
-schema=example.ridl \
-target=github.com/webrpc/gen-c@<version> \
-emit=header \
-out=./example.gen.h
```

or:

```bash
webrpc-gen \
-schema=example.ridl \
-target=github.com/webrpc/gen-c@<version> \
-emit=impl \
-header=example.gen.h \
-out=./example.gen.c
```

## Set Custom Template Variables

Change any of the following values by passing `-option="Value"` CLI flag to `webrpc-gen`.

| webrpc-gen -option | Description | Default value | Version |
| --- | --- | --- | --- |
| `-prefix=<name>` | symbol and type prefix | schema name in `snake_case` | v0.0.1 |
| `-client` | generate client declarations and runtime | `true` | v0.0.1 |
| `-emit=<mode>` | emit either `header` or `impl` | `header` | v0.0.1 |
| `-header=<file>` | header include used by `impl` output | `<prefix>.h` | v0.0.1 |

## Notes

- `-target` can be a local template directory or a git module path.
- `bigint` support is string-based by design to avoid precision loss in C JSON handling.
- for precision-sensitive large integer values, prefer `bigint` over `int64` / `uint64` in the schema when targeting this generator
- The generated implementation is tested with smoke, codec, succinct, and reference interop coverage in this repo.
12 changes: 12 additions & 0 deletions _examples/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
WEBRPC_GEN_VERSION := v0.37.1
ROOT := ..
GEN := go run -ldflags="-X github.com/webrpc/webrpc.VERSION=$(WEBRPC_GEN_VERSION)" github.com/webrpc/webrpc/cmd/webrpc-gen@$(WEBRPC_GEN_VERSION)

.PHONY: generate diff

generate:
$(GEN) -schema=smoke/example.ridl -target=$(ROOT) -emit=header -out=smoke/example.gen.h
$(GEN) -schema=smoke/example.ridl -target=$(ROOT) -emit=impl -header=example.gen.h -out=smoke/example.gen.c

diff:
git diff --exit-code -- smoke/example.gen.h smoke/example.gen.c
Loading
Loading