Skip to content

Commit a84984a

Browse files
authored
chore(build): convert from bazel to cmake (#2393)
This converts the project from using bazel to cmake to make it integrate easier on different dev machines.
1 parent 736a815 commit a84984a

File tree

11 files changed

+423
-144
lines changed

11 files changed

+423
-144
lines changed

.github/workflows/CI.yml

Lines changed: 201 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,18 @@ jobs:
3434
cache-hit: ${{ steps.cache-plugin.outputs.cache-hit }}
3535
steps:
3636
- uses: actions/checkout@v4
37-
- name: Cache protoc plugin
37+
- name: Cache protoc and plugin
3838
id: cache-plugin
3939
uses: actions/cache@v4
4040
with:
4141
path: ${{ runner.temp }}/protoc-plugin
42-
# The key changes only when plugin source files change
43-
key: ${{ runner.os }}-protoc-plugin-${{ hashFiles('protoc-gen-rust-grpc/src/**', 'protoc-gen-rust-grpc/.bazelrc', 'protoc-gen-rust-grpc/MODULE.bazel') }}
44-
- name: Install Bazel
42+
# The key changes only when plugin source files or CMake files change
43+
key: ${{ runner.os }}-protoc-plugin-cmake-v4-${{ hashFiles('protoc-gen-rust-grpc/src/**', 'protoc-gen-rust-grpc/CMakeLists.txt', 'protoc-gen-rust-grpc/cmake/**') }}
44+
- name: Install CMake
4545
if: steps.cache-plugin.outputs.cache-hit != 'true'
46-
uses: bazel-contrib/setup-bazel@0.15.0
46+
uses: lukka/get-cmake@latest
4747
with:
48-
# Avoid downloading Bazel every time.
49-
bazelisk-cache: true
50-
# Store build cache per workflow.
51-
disk-cache: ${{ github.workflow }}
52-
# Share repository cache between workflows.
53-
repository-cache: true
54-
module-root: ./protoc-gen-rust-grpc
48+
cmakeVersion: "~3.28.0"
5549
# Building the protoc plugin from scratch takes 6–14 minutes, depending on
5650
# the OS. This delays the execution of workflows that use the plugin in
5751
# build.rs files. We try to avoid rebuilding the plugin if it hasn't
@@ -62,17 +56,100 @@ jobs:
6256
shell: bash
6357
run: |
6458
set -e
65-
# On windows, the "//src" gets converted to "/". Disable this path
66-
# conversion.
67-
export MSYS_NO_PATHCONV=1
68-
export MSYS2_ARG_CONV_EXCL="*"
59+
# Create build directory
60+
mkdir -p build
61+
cd build
6962
70-
bazel build //src:protoc-gen-rust-grpc --enable_platform_specific_config
63+
# Configure with CMake
64+
cmake .. -DCMAKE_BUILD_TYPE=Release -DPROTOBUF_VERSION=32.0
65+
66+
# Build with limited parallelism to avoid OOM
67+
cmake --build . --parallel 2
7168
7269
# The target path needs to match the cache config.
7370
TARGET_PATH="${{ runner.temp }}/protoc-plugin"
7471
mkdir -p "${TARGET_PATH}"
75-
cp bazel-bin/src/protoc-gen-rust-grpc "${TARGET_PATH}"
72+
73+
# Copy both protoc and the plugin
74+
# First, find and copy protoc
75+
PROTOC_FOUND=false
76+
for protoc_path in "bin/protoc" "bin/protoc.exe" "bin/Release/protoc.exe" "bin/Debug/protoc.exe" "_deps/protobuf-build/protoc" "_deps/protobuf-build/protoc.exe" "_deps/protobuf-build/Release/protoc.exe" "_deps/protobuf-build/Debug/protoc.exe"; do
77+
if [ -f "$protoc_path" ]; then
78+
echo "Found protoc at: $protoc_path"
79+
# Copy with explicit name to ensure it's called 'protoc' or 'protoc.exe'
80+
if [[ "$protoc_path" == *.exe ]]; then
81+
cp "$protoc_path" "${TARGET_PATH}/protoc.exe"
82+
echo "Copied to: ${TARGET_PATH}/protoc.exe"
83+
else
84+
cp "$protoc_path" "${TARGET_PATH}/protoc"
85+
chmod +x "${TARGET_PATH}/protoc"
86+
echo "Copied to: ${TARGET_PATH}/protoc"
87+
fi
88+
PROTOC_FOUND=true
89+
break
90+
fi
91+
done
92+
93+
if [ "$PROTOC_FOUND" = "false" ]; then
94+
echo "Error: protoc not found in expected locations"
95+
echo "Searching for protoc in build directory:"
96+
find . -name "protoc" -o -name "protoc.exe" | head -20
97+
exit 1
98+
fi
99+
100+
# Copy protoc with its standard installation structure
101+
echo "Setting up protoc installation..."
102+
103+
# protoc expects to find includes relative to its binary location
104+
# Standard structure: bin/protoc and include/google/protobuf/*.proto
105+
106+
# First check if CMake created an install directory
107+
if [ -d "install" ] && [ -f "install/bin/protoc" -o -f "install/bin/protoc.exe" ]; then
108+
echo "Found CMake install directory"
109+
cp -r install/* "${TARGET_PATH}/"
110+
else
111+
# Manual setup if no install directory
112+
echo "Creating manual protoc installation structure..."
113+
114+
# The protoc binary should already be copied to TARGET_PATH
115+
# Now find and copy the include files to the correct relative location
116+
mkdir -p "${TARGET_PATH}/include"
117+
118+
# Find the protobuf include files
119+
INCLUDE_FOUND=false
120+
for include_path in "_deps/protobuf-src/src" "_deps/protobuf-build/include" "include"; do
121+
if [ -d "$include_path/google/protobuf" ] && [ -f "$include_path/google/protobuf/descriptor.proto" ]; then
122+
echo "Found protobuf includes at: $include_path"
123+
cp -r "$include_path/google" "${TARGET_PATH}/include/"
124+
INCLUDE_FOUND=true
125+
break
126+
fi
127+
done
128+
129+
if [ "$INCLUDE_FOUND" = "false" ]; then
130+
echo "Warning: Could not find protobuf include files"
131+
echo "Searching for descriptor.proto:"
132+
find . -name "descriptor.proto" -type f | grep -v "test" | head -10
133+
fi
134+
fi
135+
136+
# Then copy the plugin (handle different output locations)
137+
if [ -f "bin/protoc-gen-rust-grpc" ]; then
138+
cp bin/protoc-gen-rust-grpc "${TARGET_PATH}/"
139+
elif [ -f "bin/protoc-gen-rust-grpc.exe" ]; then
140+
cp bin/protoc-gen-rust-grpc.exe "${TARGET_PATH}/"
141+
elif [ -f "bin/Release/protoc-gen-rust-grpc.exe" ]; then
142+
# Windows Release build
143+
cp bin/Release/protoc-gen-rust-grpc.exe "${TARGET_PATH}/"
144+
elif [ -f "bin/Debug/protoc-gen-rust-grpc.exe" ]; then
145+
# Windows Debug build (shouldn't happen with Release config, but just in case)
146+
cp bin/Debug/protoc-gen-rust-grpc.exe "${TARGET_PATH}/"
147+
else
148+
echo "Error: protoc-gen-rust-grpc not found"
149+
echo "Looking for binary in common locations..."
150+
find . -name "protoc-gen-rust-grpc*" -type f 2>/dev/null | head -10
151+
exit 1
152+
fi
76153
77154
clippy:
78155
runs-on: ubuntu-latest
@@ -82,19 +159,32 @@ jobs:
82159
- uses: hecrj/setup-rust-action@v2
83160
with:
84161
components: clippy
85-
- uses: taiki-e/install-action@v2
86-
with:
87-
tool: protoc@3.32.0
88-
- name: Restore protoc plugin from cache
162+
- name: Restore protoc and plugin from cache
89163
id: cache-plugin
90164
uses: actions/cache@v4
91165
with:
92166
path: ${{ runner.temp }}/protoc-plugin
93-
key: ${{ runner.os }}-protoc-plugin-${{ hashFiles('protoc-gen-rust-grpc/src/**', 'protoc-gen-rust-grpc/.bazelrc', 'protoc-gen-rust-grpc/MODULE.bazel') }}
94-
- name: Add protoc plugin to PATH
167+
key: ${{ runner.os }}-protoc-plugin-cmake-v4-${{ hashFiles('protoc-gen-rust-grpc/src/**', 'protoc-gen-rust-grpc/CMakeLists.txt', 'protoc-gen-rust-grpc/cmake/**') }}
168+
- name: Add protoc and plugin to PATH
95169
shell: bash
96170
run: |
97-
echo "${{ runner.temp }}/protoc-plugin" >> $GITHUB_PATH
171+
# Use forward slashes for all paths in bash, even on Windows
172+
PROTOC_DIR="${{ runner.temp }}/protoc-plugin"
173+
PROTOC_DIR="${PROTOC_DIR//\\/\/}" # Convert backslashes to forward slashes
174+
175+
echo "${PROTOC_DIR}" >> $GITHUB_PATH
176+
177+
# Also set PROTOC for build scripts
178+
if [ "${{ runner.os }}" = "Windows" ]; then
179+
echo "PROTOC=${PROTOC_DIR}/protoc.exe" >> $GITHUB_ENV
180+
else
181+
echo "PROTOC=${PROTOC_DIR}/protoc" >> $GITHUB_ENV
182+
fi
183+
184+
# Set the protoc include path only if it exists
185+
if [ -d "${PROTOC_DIR}/include" ]; then
186+
echo "PROTOC_INCLUDE=${PROTOC_DIR}/include" >> $GITHUB_ENV
187+
fi
98188
- uses: Swatinem/rust-cache@v2
99189
- run: cargo clippy --workspace --all-features --all-targets
100190

@@ -117,19 +207,32 @@ jobs:
117207
toolchain: nightly-2025-03-27
118208
- uses: taiki-e/install-action@cargo-hack
119209
- uses: taiki-e/install-action@cargo-udeps
120-
- uses: taiki-e/install-action@v2
121-
with:
122-
tool: protoc@3.32.0
123-
- name: Restore protoc plugin from cache
210+
- name: Restore protoc and plugin from cache
124211
id: cache-plugin
125212
uses: actions/cache@v4
126213
with:
127214
path: ${{ runner.temp }}/protoc-plugin
128-
key: ${{ runner.os }}-protoc-plugin-${{ hashFiles('protoc-gen-rust-grpc/src/**', 'protoc-gen-rust-grpc/.bazelrc', 'protoc-gen-rust-grpc/MODULE.bazel') }}
129-
- name: Add protoc plugin to PATH
215+
key: ${{ runner.os }}-protoc-plugin-cmake-v4-${{ hashFiles('protoc-gen-rust-grpc/src/**', 'protoc-gen-rust-grpc/CMakeLists.txt', 'protoc-gen-rust-grpc/cmake/**') }}
216+
- name: Add protoc and plugin to PATH
130217
shell: bash
131218
run: |
132-
echo "${{ runner.temp }}/protoc-plugin" >> $GITHUB_PATH
219+
# Use forward slashes for all paths in bash, even on Windows
220+
PROTOC_DIR="${{ runner.temp }}/protoc-plugin"
221+
PROTOC_DIR="${PROTOC_DIR//\\/\/}" # Convert backslashes to forward slashes
222+
223+
echo "${PROTOC_DIR}" >> $GITHUB_PATH
224+
225+
# Also set PROTOC for build scripts
226+
if [ "${{ runner.os }}" = "Windows" ]; then
227+
echo "PROTOC=${PROTOC_DIR}/protoc.exe" >> $GITHUB_ENV
228+
else
229+
echo "PROTOC=${PROTOC_DIR}/protoc" >> $GITHUB_ENV
230+
fi
231+
232+
# Set the protoc include path only if it exists
233+
if [ -d "${PROTOC_DIR}/include" ]; then
234+
echo "PROTOC_INCLUDE=${PROTOC_DIR}/include" >> $GITHUB_ENV
235+
fi
133236
- uses: Swatinem/rust-cache@v2
134237
- run: cargo hack udeps --workspace --exclude-features=_tls-any,tls,tls-aws-lc,tls-ring --each-feature
135238
- run: cargo udeps --package tonic --features tls-ring,transport
@@ -151,19 +254,32 @@ jobs:
151254
- uses: actions/checkout@v4
152255
- uses: hecrj/setup-rust-action@v2
153256
- uses: taiki-e/install-action@cargo-hack
154-
- uses: taiki-e/install-action@v2
155-
with:
156-
tool: protoc@3.32.0
157-
- name: Restore protoc plugin from cache
257+
- name: Restore protoc and plugin from cache
158258
id: cache-plugin
159259
uses: actions/cache@v4
160260
with:
161261
path: ${{ runner.temp }}/protoc-plugin
162-
key: ${{ runner.os }}-protoc-plugin-${{ hashFiles('protoc-gen-rust-grpc/src/**', 'protoc-gen-rust-grpc/.bazelrc', 'protoc-gen-rust-grpc/MODULE.bazel') }}
163-
- name: Add protoc plugin to PATH
262+
key: ${{ runner.os }}-protoc-plugin-cmake-v4-${{ hashFiles('protoc-gen-rust-grpc/src/**', 'protoc-gen-rust-grpc/CMakeLists.txt', 'protoc-gen-rust-grpc/cmake/**') }}
263+
- name: Add protoc and plugin to PATH
164264
shell: bash
165265
run: |
166-
echo "${{ runner.temp }}/protoc-plugin" >> $GITHUB_PATH
266+
# Use forward slashes for all paths in bash, even on Windows
267+
PROTOC_DIR="${{ runner.temp }}/protoc-plugin"
268+
PROTOC_DIR="${PROTOC_DIR//\\/\/}" # Convert backslashes to forward slashes
269+
270+
echo "${PROTOC_DIR}" >> $GITHUB_PATH
271+
272+
# Also set PROTOC for build scripts
273+
if [ "${{ runner.os }}" = "Windows" ]; then
274+
echo "PROTOC=${PROTOC_DIR}/protoc.exe" >> $GITHUB_ENV
275+
else
276+
echo "PROTOC=${PROTOC_DIR}/protoc" >> $GITHUB_ENV
277+
fi
278+
279+
# Set the protoc include path only if it exists
280+
if [ -d "${PROTOC_DIR}/include" ]; then
281+
echo "PROTOC_INCLUDE=${PROTOC_DIR}/include" >> $GITHUB_ENV
282+
fi
167283
- uses: Swatinem/rust-cache@v2
168284
- name: Check features
169285
run: cargo hack check --workspace --no-private --each-feature --no-dev-deps
@@ -204,19 +320,38 @@ jobs:
204320
steps:
205321
- uses: actions/checkout@v4
206322
- uses: hecrj/setup-rust-action@v2
207-
- uses: taiki-e/install-action@v2
208-
with:
209-
tool: protoc@3.32.0
210-
- name: Restore protoc plugin from cache
323+
- name: Restore protoc and plugin from cache
211324
id: cache-plugin
212325
uses: actions/cache@v4
213326
with:
214327
path: ${{ runner.temp }}/protoc-plugin
215-
key: ${{ runner.os }}-protoc-plugin-${{ hashFiles('protoc-gen-rust-grpc/src/**', 'protoc-gen-rust-grpc/.bazelrc', 'protoc-gen-rust-grpc/MODULE.bazel') }}
216-
- name: Add protoc plugin to PATH
328+
key: ${{ runner.os }}-protoc-plugin-cmake-v4-${{ hashFiles('protoc-gen-rust-grpc/src/**', 'protoc-gen-rust-grpc/CMakeLists.txt', 'protoc-gen-rust-grpc/cmake/**') }}
329+
- name: Check cache status
330+
if: steps.cache-plugin.outputs.cache-hit != 'true'
331+
run: |
332+
echo "ERROR: Cache miss! The protoc plugin was not found in cache."
333+
echo "This means the build-protoc-plugin job either failed or didn't run."
334+
exit 1
335+
- name: Add protoc and plugin to PATH
217336
shell: bash
218337
run: |
219-
echo "${{ runner.temp }}/protoc-plugin" >> $GITHUB_PATH
338+
# Use forward slashes for all paths in bash, even on Windows
339+
PROTOC_DIR="${{ runner.temp }}/protoc-plugin"
340+
PROTOC_DIR="${PROTOC_DIR//\\/\/}" # Convert backslashes to forward slashes
341+
342+
echo "${PROTOC_DIR}" >> $GITHUB_PATH
343+
344+
# Also set PROTOC for build scripts
345+
if [ "${{ runner.os }}" = "Windows" ]; then
346+
echo "PROTOC=${PROTOC_DIR}/protoc.exe" >> $GITHUB_ENV
347+
else
348+
echo "PROTOC=${PROTOC_DIR}/protoc" >> $GITHUB_ENV
349+
fi
350+
351+
# Set the protoc include path only if it exists
352+
if [ -d "${PROTOC_DIR}/include" ]; then
353+
echo "PROTOC_INCLUDE=${PROTOC_DIR}/include" >> $GITHUB_ENV
354+
fi
220355
- uses: taiki-e/install-action@cargo-hack
221356
- uses: taiki-e/install-action@cargo-nextest
222357
- uses: Swatinem/rust-cache@v2
@@ -243,19 +378,32 @@ jobs:
243378
steps:
244379
- uses: actions/checkout@v4
245380
- uses: hecrj/setup-rust-action@v2
246-
- uses: taiki-e/install-action@v2
247-
with:
248-
tool: protoc@3.32.0
249-
- name: Restore protoc plugin from cache
381+
- name: Restore protoc and plugin from cache
250382
id: cache-plugin
251383
uses: actions/cache@v4
252384
with:
253385
path: ${{ runner.temp }}/protoc-plugin
254-
key: ${{ runner.os }}-protoc-plugin-${{ hashFiles('protoc-gen-rust-grpc/src/**', 'protoc-gen-rust-grpc/.bazelrc', 'protoc-gen-rust-grpc/MODULE.bazel') }}
255-
- name: Add protoc plugin to PATH
386+
key: ${{ runner.os }}-protoc-plugin-cmake-v4-${{ hashFiles('protoc-gen-rust-grpc/src/**', 'protoc-gen-rust-grpc/CMakeLists.txt', 'protoc-gen-rust-grpc/cmake/**') }}
387+
- name: Add protoc and plugin to PATH
256388
shell: bash
257389
run: |
258-
echo "${{ runner.temp }}/protoc-plugin" >> $GITHUB_PATH
390+
# Use forward slashes for all paths in bash, even on Windows
391+
PROTOC_DIR="${{ runner.temp }}/protoc-plugin"
392+
PROTOC_DIR="${PROTOC_DIR//\\/\/}" # Convert backslashes to forward slashes
393+
394+
echo "${PROTOC_DIR}" >> $GITHUB_PATH
395+
396+
# Also set PROTOC for build scripts
397+
if [ "${{ runner.os }}" = "Windows" ]; then
398+
echo "PROTOC=${PROTOC_DIR}/protoc.exe" >> $GITHUB_ENV
399+
else
400+
echo "PROTOC=${PROTOC_DIR}/protoc" >> $GITHUB_ENV
401+
fi
402+
403+
# Set the protoc include path only if it exists
404+
if [ -d "${PROTOC_DIR}/include" ]; then
405+
echo "PROTOC_INCLUDE=${PROTOC_DIR}/include" >> $GITHUB_ENV
406+
fi
259407
- uses: Swatinem/rust-cache@v2
260408
- name: Run interop tests
261409
run: ./interop/test.sh

flake.nix

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@
8181
devShells.default = pkgs.mkShell {
8282
packages = with pkgs; [
8383
cargo-nextest
84-
bazel_7
8584
pre-commit
85+
cmake
8686

8787
(rustToolchain.withComponents [
8888
"cargo"
@@ -92,14 +92,11 @@
9292
"rustfmt"
9393
"rust-analyzer"
9494
])
95-
# protobuf
9695
];
9796

9897
hardeningDisable = [ "fortify" ];
9998

10099
shellHook = ''
101-
export PATH="$PWD/protoc-gen-rust-grpc/bazel-bin/src:$HOME/code/install/bin:$PATH"
102-
103100
${config.pre-commit.installationScript}
104101
'';
105102
};

interop/build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
fn main() {
22
let proto = "proto/grpc/testing/test.proto";
33

4+
eprintln!("{}", tonic_protobuf_build::protoc());
5+
let path = std::env::var("PATH").unwrap_or_default();
6+
std::env::set_var("PATH", format!("{}:{}", path, tonic_protobuf_build::bin()));
7+
48
tonic_prost_build::compile_protos(proto).unwrap();
59
tonic_protobuf_build::CodeGen::new()
610
.include("proto/grpc/testing")

protoc-gen-rust-grpc/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ bazel-out
55
bazel-protoc-gen-rust-grpc
66
bazel-testlogs
77
MODULE.bazel.lock
8+
9+
build/*
10+
CMakeFiles/*

0 commit comments

Comments
 (0)