Skip to content

Commit

Permalink
Initial commit of go-protoc-gen-java
Browse files Browse the repository at this point in the history
  • Loading branch information
anuraaga committed Jan 26, 2024
0 parents commit 52e0c5b
Show file tree
Hide file tree
Showing 27 changed files with 757 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto eol=lf
34 changes: 34 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: CI
on:
push:
branches:
- main
tags:
- "*"
pull_request:
workflow_dispatch:

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- macos-12
- ubuntu-22.04
- windows-2022
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: actions/setup-go@v5
with:
go-version-file: go.work

- name: run checks
run: go run mage check

- name: build snapshot
run: go run mage snapshot
23 changes: 23 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: "Release"

on:
push:
tags:
- v*

jobs:
build:
name: Release
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: actions/setup-go@v5
with:
go-version-file: go.work

- run: go run mage release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.idea
.vscode
build
dist
testdata/buf.gen.yaml
go.work.sum
24 changes: 24 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
builds:
- main: ./cmd/protoc-gen-grpc-java
id: es
binary: protoc-gen-grpc-java
env:
- CGO_ENABLED=0
targets:
- linux_amd64
- linux_arm64
- darwin_amd64
- darwin_arm64
- windows_amd64
archives:
- format_overrides:
- goos: windows
format: zip
release:
mode: append
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ incpatch .Version }}-next"
changelog:
skip: true
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# go-protoc-gen-grpc-java

go-protoc-gen-grpc-java is a distribution of [protoc-gen-grpc-java][1].
It does not actually reimplement any functionality of grpc-java in Go, instead compiling it
to WebAssembly, and executing with the pure Go Wasm runtime [wazero][2].
This means that `go install` or `go run` can be used to execute it, with no need to rely on external
package managers such as Homebrew, on any platform that Go supports.

## Installation

Precompiled binaries are available in the [releases](https://github.com/wasilibs/go-protoc-gen-grpc-java/releases).
Alternatively, install the plugin using `go install`.

```bash
$ go install github.com/wasilibs/go-protoc-gen-grpc-java/cmd/protoc-gen-grpc-java@latest
```

As long as `$GOPATH/bin`, e.g. `~/go/bin` is on the `PATH`, you can use it with protoc as normal.

```bash
$ protoc --grpc-java_out=out/grpc-java -Iprotos protos/helloworld.proto
```

For [buf][3] users, to avoid installation entirely, it can be convenient to use `go run` in `buf.gen.yaml`.

```yaml
version: v1
plugins:
- plugin: grpc-java
out: out/grpc-java
path: ["go", "run", "github.com/wasilibs/go-protoc-gen-grpc-java/cmd/protoc-gen-grpc-java@latest"]
```
This makes it possible to have full protobuf/gRPC generation with no installation of tools,
besides Go itself, on any platform that Go supports. The above examples use `@latest`, but it is
recommended to specify a version, in which case all of the developers on your codebase will use the
same version of the tool with no special steps.

See a full [example][5] in `go-protoc-gen-builtins`. To generate protos, enter the directory and run
`go run github.com/bufbuild/buf/cmd/[email protected] generate`. As long as your machine has Go installed,
you will be able to generate protos. The first time using `go run` for a command, Go automatically builds
it making it slower, but subsequent invocations should be quite fast.

[1]: https://github.com/grpc/grpc-java
[2]: https://wazero.io/
[3]: https://buf.build/
[4]: https://github.com/wasilibs/go-protoc-gen-builtins
[5]: https://github.com/wasilibs/go-protoc-gen-builtins/tree/main/example
26 changes: 26 additions & 0 deletions buildtools/wasm/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
FROM ghcr.io/wasilibs/wasix-sdk:sha-fc94d60

RUN apt-get update && apt-get install -y binaryen git patch

# Easiest way to build grpc-java plugin is add it to the protoc build
ADD buildtools/wasm/version.txt /version.txt
RUN git clone --recursive https://github.com/grpc/grpc-java.git --branch $(cat /version.txt | awk '{$1=$1};1') /grpcjava
RUN git clone --recursive https://github.com/protocolbuffers/protobuf.git --branch v25.2 /workspace
RUN cp -R /grpcjava/compiler/src/java_plugin/cpp /workspace/src/grpcjava
RUN echo "set(protoc-gen-grpc-java_files \${protobuf_SOURCE_DIR}/src/grpcjava/java_plugin.cpp \${protobuf_SOURCE_DIR}/src/grpcjava/java_generator.cpp) \n\
add_executable(protoc-gen-grpc-java \${protoc-gen-grpc-java_files} \${protobuf_version_rc_file}) \n\
target_link_libraries(protoc-gen-grpc-java libprotoc libprotobuf \${protobuf_ABSL_USED_TARGETS}) \n\
set_target_properties(protoc-gen-grpc-java PROPERTIES VERSION 1.60.0) \n\
" >> /workspace/CMakeLists.txt

WORKDIR /workspace

ENV CXXFLAGS "${CXXFLAGS} -O3 -pthread -D_WASI_EMULATED_MMAN -D_WASI_EMULATED_PROCESS_CLOCKS"
ENV LDFLAGS $LDFLAGS -lwasi-emulated-mman -lwasi-emulated-process-clocks -Wl,--max-memory=4294967296

RUN cmake -S . -B build
RUN cmake --build build --target protoc-gen-grpc-java

RUN wasm-opt -o build/protoc-gen-grpc-java.wasm --low-memory-unused --flatten --rereloop --converge -O3 build/protoc-gen-grpc-java

CMD ["cp", "build/protoc-gen-grpc-java.wasm", "/out/"]
78 changes: 78 additions & 0 deletions buildtools/wasm/create_plugin_entrypoints.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
plugins = [
{
"name": "cpp",
"include": "google/protobuf/compiler/cpp/generator.h",
"generator": "::google::protobuf::compiler::cpp::CppGenerator",
},
{
"name": "csharp",
"include": "google/protobuf/compiler/csharp/csharp_generator.h",
"generator": "::google::protobuf::compiler::csharp::Generator",
},
{
"name": "java",
"include": "google/protobuf/compiler/java/generator.h",
"generator": "::google::protobuf::compiler::java::JavaGenerator",
},
{
"name": "kotlin",
"include": "google/protobuf/compiler/java/kotlin_generator.h",
"generator": "::google::protobuf::compiler::java::KotlinGenerator",
},
{
"name": "objc",
"include": "google/protobuf/compiler/objectivec/generator.h",
"generator": "::google::protobuf::compiler::objectivec::ObjectiveCGenerator",
},
{
"name": "php",
"include": "google/protobuf/compiler/php/php_generator.h",
"generator": "::google::protobuf::compiler::php::Generator",
},
{
"name": "python",
"include": "google/protobuf/compiler/python/generator.h",
"generator": "::google::protobuf::compiler::python::Generator",
},
{
"name": "pyi",
"include": "google/protobuf/compiler/python/pyi_generator.h",
"generator": "::google::protobuf::compiler::python::PyiGenerator",
},
{
"name": "ruby",
"include": "google/protobuf/compiler/ruby/ruby_generator.h",
"generator": "::google::protobuf::compiler::ruby::Generator",
},
{
"name": "rust",
"include": "google/protobuf/compiler/rust/generator.h",
"generator": "::google::protobuf::compiler::rust::RustGenerator",
},
]

with open('main.cc', 'r') as maincc:
main_template = maincc.read()

cmake_addition = """
add_custom_target(plugins)
"""

for plugin in plugins:
main = main_template.replace('{{INCLUDE_PATH}}', plugin["include"]).replace("{{GENERATOR_TYPE}}", plugin["generator"])
with open(f'src/main_{plugin["name"]}.cc', 'w') as maincc:
maincc.write(main)
cmake_addition += f"""
set(protoc-gen-{plugin['name']}_files ${{protobuf_SOURCE_DIR}}/src/java_plugin.cc )
add_executable(protoc-gen-{plugin['name']} ${{protoc-gen-{plugin['name']}_files}} ${{protobuf_version_rc_file}})
target_link_libraries(protoc-gen-{plugin['name']} libprotoc libprotobuf ${{protobuf_ABSL_USED_TARGETS}})
set_target_properties(protoc-gen-{plugin['name']} PROPERTIES VERSION ${{protobuf_VERSION}})
add_dependencies(plugins protoc-gen-{plugin['name']})
"""

print(cmake_addition)

with open('CMakeLists.txt', 'a') as cmakelists:
cmakelists.write(cmake_addition)
18 changes: 18 additions & 0 deletions buildtools/wasm/main.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd

#include "{{INCLUDE_PATH}}"
#include "google/protobuf/compiler/plugin.h"

int main(int argc, char *argv[]) {
{{GENERATOR_TYPE}} generator;
#ifdef GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE
generator.set_opensource_runtime(true);
generator.set_runtime_include_base(GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE);
#endif
return ::google::protobuf::compiler::PluginMain(argc, argv, &generator);
}
1 change: 1 addition & 0 deletions buildtools/wasm/version.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v1.61.0
12 changes: 12 additions & 0 deletions cmd/protoc-gen-grpc-java/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import (
"os"

"github.com/wasilibs/go-protoc-gen-grpc-java/internal/runner"
"github.com/wasilibs/go-protoc-gen-grpc-java/internal/wasm"
)

func main() {
os.Exit(runner.Run("protoc-gen-swift", os.Args[1:], wasm.ProtocGenGRPCJava, os.Stdin, os.Stdout, os.Stderr, "."))
}
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module github.com/wasilibs/go-protoc-gen-grpc-java
go 1.21

require github.com/tetratelabs/wazero v1.6.1-0.20240124004658-4185e533bb18
7 changes: 7 additions & 0 deletions go.work
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
go 1.21

use (
.
./mage
./magefiles
)
56 changes: 56 additions & 0 deletions internal/runner/runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package runner

import (
"context"
"crypto/rand"
"io"
"log"
"os"
"strings"

"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/experimental"
"github.com/tetratelabs/wazero/experimental/sysfs"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
"github.com/tetratelabs/wazero/sys"

"github.com/wasilibs/go-protoc-gen-grpc-java/internal/wasix_32v1"
)

func Run(name string, args []string, wasm []byte, stdin io.Reader, stdout io.Writer, stderr io.Writer, cwd string) int {
ctx := context.Background()

rt := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfig().WithCoreFeatures(api.CoreFeaturesV2|experimental.CoreFeaturesThreads))

wasi_snapshot_preview1.MustInstantiate(ctx, rt)
wasix_32v1.MustInstantiate(ctx, rt)

args = append([]string{name}, args...)

root := sysfs.DirFS(cwd)

cfg := wazero.NewModuleConfig().
WithSysNanosleep().
WithSysNanotime().
WithSysWalltime().
WithStderr(stderr).
WithStdout(stdout).
WithStdin(stdin).
WithRandSource(rand.Reader).
WithArgs(args...).
WithFSConfig(wazero.NewFSConfig().(sysfs.FSConfig).WithSysFSMount(root, "/"))
for _, env := range os.Environ() {
k, v, _ := strings.Cut(env, "=")
cfg = cfg.WithEnv(k, v)
}

_, err := rt.InstantiateWithConfig(ctx, wasm, cfg)
if err != nil {
if sErr, ok := err.(*sys.ExitError); ok {
return int(sErr.ExitCode())
}
log.Fatal(err)
}
return 0
}
Loading

0 comments on commit 52e0c5b

Please sign in to comment.