Skip to content
Merged
66 changes: 55 additions & 11 deletions .github/workflows/build-cli-release.reusable.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
type: boolean
default: true
required: false

push:
branches:
- protoc-fix
env:
MACOSX_DEPLOYMENT_TARGET: "10.13"

Expand Down Expand Up @@ -69,18 +71,47 @@
# shell: bash
# run: |
# ci/ubuntu-install-packages

- uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
target: ${{ matrix._.target }}

- uses: Swatinem/rust-cache@v2

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'BAML Release - Build BAML CLI' step
Uses Step
uses 'Swatinem/rust-cache' with ref 'v2', not a pinned commit hash
with:
workspaces: engine
prefix-key: "v5-rust-${{ matrix._.target }}"
- uses: actions/setup-go@v5
with:
go-version: '1.21'

- name: Install protoc-gen-go
run: go install github.com/golang/protobuf/protoc-gen-go@latest
- name: Install protoc-gen-go into .cargo/bin
shell: bash
run: |
# The cross-compile environment sanitizes the PATH, so we install the plugin
# directly into a directory that is guaranteed to be in the PATH for cargo.
# We also create a symlink from the go/bin to the cargo/bin for consistency.
mkdir -p .cargo/bin
go install github.com/golang/protobuf/protoc-gen-go@latest
cp "$HOME/go/bin/protoc-gen-go" ".cargo/bin/"
echo "Installed protoc-gen-go into .cargo/bin:"
ls -la .cargo/bin

- name: Test protoc-gen-go availability
id: protoc_gen_go_setup
shell: bash
run: |
echo "Current PATH: $PATH"
echo "Go bin directory contents:"
ls -la $HOME/go/bin/
echo "Which protoc-gen-go:"
PROTOC_GEN_GO_PATH=$(which protoc-gen-go)
echo "Found protoc-gen-go at: $PROTOC_GEN_GO_PATH"
echo "protoc_gen_go_path=$PROTOC_GEN_GO_PATH" >> $GITHUB_OUTPUT
echo "Testing protoc can find protoc-gen-go plugin..."
# Test that protoc can find the go plugin (this will show an error about missing .proto file, but that's expected)
protoc --go_out=/tmp --help | grep -q "go_out" && echo "✅ protoc recognizes --go_out flag" || echo "❌ protoc does not recognize --go_out flag"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider failing the step if '--go_out' isn’t recognized instead of only echoing a message.

Suggested change
protoc --go_out=/tmp --help | grep -q "go_out" && echo "✅ protoc recognizes --go_out flag" || echo "❌ protoc does not recognize --go_out flag"
protoc --go_out=/tmp --help | grep -q "go_out" && echo "✅ protoc recognizes --go_out flag" || (echo "❌ protoc does not recognize --go_out flag"; exit 1)




- name: Use Cross
if: contains(matrix._.os, 'ubuntu')
Expand All @@ -106,11 +137,7 @@
echo "target flag is: ${{ env.TARGET_FLAGS }}"
echo "target dir is: ${{ env.TARGET_DIR }}"

- uses: Swatinem/rust-cache@v2
with:
workspaces: engine
prefix-key: "v5-rust-${{ matrix._.target }}"


# Build the CLI - Always use static-ssl features
- name: Build CLI Binary
# This single step now handles all builds
Expand All @@ -121,7 +148,24 @@
working-directory: engine

- name: Build CFFI Library
run: >
shell: bash
run: |
# Set the correct protoc-gen-go path based on whether we're using cross (Linux) or native build
if [[ "${{ env.CARGO }}" == "cross" ]]; then
# For cross builds (Linux), protoc-gen-go will be installed in the container at /usr/local/bin
export PROTOC_GEN_GO_PATH="/usr/local/bin/protoc-gen-go"
else
# For native builds (macOS), use the host path
export PROTOC_GEN_GO_PATH="${{ steps.protoc_gen_go_setup.outputs.protoc_gen_go_path }}"
fi
echo "Using PROTOC_GEN_GO_PATH: $PROTOC_GEN_GO_PATH"

# We must use PROTOC_GEN_GO_PATH to explicitly tell the build script
# where to find the plugin, as the cross-compile environment is isolated.
export GOPATH=$HOME/go
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOROOT:$GOPATH:$GOBIN

${{ env.CARGO }} build --release -p baml_cffi ${{ env.TARGET_FLAGS }}
working-directory: engine
# Skip this step on Windows runners
Expand Down
44 changes: 44 additions & 0 deletions engine/Cross.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Cross.toml - Configuration for cross-compilation

# Install Go and protoc-gen-go for Linux targets
[target.x86_64-unknown-linux-gnu]
pre-build = [
"apt-get update",
"apt-get install -y wget",
"wget -q https://go.dev/dl/go1.21.13.linux-amd64.tar.gz",
"tar -xzf go1.21.13.linux-amd64.tar.gz -C /usr/local",
"export PATH=$PATH:/usr/local/go/bin",
"/usr/local/go/bin/go install github.com/golang/protobuf/protoc-gen-go@latest",
"cp /root/go/bin/protoc-gen-go /usr/local/bin/",
]

[target.x86_64-unknown-linux-musl]
pre-build = [
"if command -v apk >/dev/null 2>&1; then apk update && apk add wget; elif command -v apt-get >/dev/null 2>&1; then apt-get update && apt-get install -y wget; elif command -v yum >/dev/null 2>&1; then yum install -y wget; fi",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider handling the case when none of the expected package managers are found. Also, note that the yum branch doesn’t update packages while others do.

"wget -q https://go.dev/dl/go1.21.13.linux-amd64.tar.gz",
"tar -xzf go1.21.13.linux-amd64.tar.gz -C /usr/local",
"export PATH=$PATH:/usr/local/go/bin",
"/usr/local/go/bin/go install github.com/golang/protobuf/protoc-gen-go@latest",
"cp /root/go/bin/protoc-gen-go /usr/local/bin/",
]

[target.aarch64-unknown-linux-gnu]
pre-build = [
"apt-get update",
"apt-get install -y wget",
"wget -q https://go.dev/dl/go1.21.13.linux-amd64.tar.gz",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the aarch64 targets, the pre-build script downloads a Go tarball for linux-amd64. Using an AMD64 binary for an ARM target may lead to toolchain issues. Consider switching to the ARM64 tarball (e.g. go1.21.13.linux-arm64.tar.gz).

"tar -xzf go1.21.13.linux-amd64.tar.gz -C /usr/local",
"export PATH=$PATH:/usr/local/go/bin",
"/usr/local/go/bin/go install github.com/golang/protobuf/protoc-gen-go@latest",
"cp /root/go/bin/protoc-gen-go /usr/local/bin/",
]

[target.aarch64-unknown-linux-musl]
pre-build = [
"if command -v apk >/dev/null 2>&1; then apk update && apk add wget; elif command -v apt-get >/dev/null 2>&1; then apt-get update && apt-get install -y wget; elif command -v yum >/dev/null 2>&1; then yum install -y wget; fi",
"wget -q https://go.dev/dl/go1.21.13.linux-amd64.tar.gz",
"tar -xzf go1.21.13.linux-amd64.tar.gz -C /usr/local",
"export PATH=$PATH:/usr/local/go/bin",
"/usr/local/go/bin/go install github.com/golang/protobuf/protoc-gen-go@latest",
"cp /root/go/bin/protoc-gen-go /usr/local/bin/",
]
19 changes: 17 additions & 2 deletions engine/language_client_cffi/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,13 @@ mod protoc_lang_out {
}

fn main() -> std::io::Result<()> {
#[cfg(target_os = "windows")]
println!("cargo:rustc-link-lib=dylib=ntdll");

// The last component of the target triple
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
let is_windows = target_os == "windows";

// Re-run build.rs if these files change.
println!("cargo:rerun-if-changed=types/cffi.fbs");
println!("cargo:rerun-if-changed=types/cffi.proto");
Expand All @@ -348,10 +355,18 @@ fn main() -> std::io::Result<()> {
// ..Default::default()
// };

protoc_lang_out::ProtocLangOut::new()
let mut protoc = protoc_lang_out::ProtocLangOut::new();
protoc
.lang(lang)
.input("types/cffi.proto")
.out_dir(lang_dir)
.out_dir(lang_dir);

// Allow overriding the protoc-gen-go plugin path
if let Ok(path) = std::env::var("PROTOC_GEN_GO_PATH") {
protoc.plugin(&path);
}

protoc
.run()
.unwrap_or_else(|_| panic!("Failed to generate {lang} bindings"));
}
Expand Down
Loading