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
35 changes: 15 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,11 @@ jobs:
strategy:
fail-fast: false
matrix:
# macOS is pinned, not -latest: the wheel's deployment target and
# the runner's Homebrew bottles must agree. See MACOSX_DEPLOYMENT_TARGET
# below. The test matrix above stays on macos-latest — it installs
# editable and never runs delocate, so it is unaffected.
os: [ubuntu-latest, macos-15, windows-latest]
# macos-latest on purpose: its macOS is newer than the wheel's
# deployment target below, which is the case that broke in #18.
# A green leg here shows the target is set independently of the
# runner image.
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v7

Expand All @@ -152,26 +152,21 @@ jobs:
# container; host paths don't resolve. Override there.
CIBW_ENVIRONMENT_LINUX: PROTOWIRE_CPP_DIR=/project/protowire-cpp-checkout
PROTOWIRE_CPP_DIR: ${{ github.workspace }}/protowire-cpp-checkout
# Linux uses manylinux containers — base image protobuf is
# too old (3.5 / 3.14) for our annotations, so build 25.3
# from source. See scripts/cibw_install_protobuf_linux.sh
# for the why.
CIBW_BEFORE_ALL_LINUX: bash {project}/scripts/cibw_install_protobuf_linux.sh
CIBW_BEFORE_ALL_MACOS: brew install protobuf
# Linux and macOS build protobuf 25.3 from source, as publish.yml
# does. See scripts/cibw_install_protobuf.sh for the why.
CIBW_BEFORE_ALL_LINUX: bash {project}/scripts/cibw_install_protobuf.sh
CIBW_BEFORE_ALL_MACOS: PROTOBUF_PREFIX=/tmp/protobuf-install bash {project}/scripts/cibw_install_protobuf.sh
CIBW_ENVIRONMENT_MACOS: CMAKE_PREFIX_PATH=/tmp/protobuf-install
CIBW_BEFORE_ALL_WINDOWS: vcpkg install protobuf:x64-windows
# delvewheel is only auto-installed when cibuildwheel uses
# its default Windows repair command — once we override
# CIBW_REPAIR_WHEEL_COMMAND_WINDOWS we have to install it.
CIBW_BEFORE_BUILD_WINDOWS: pip install delvewheel
# macOS: Homebrew's bottled dylibs are built for the runner's OS,
# and delocate refuses to bundle dylibs whose min target is newer
# than the wheel's. So this value and the runner image are ONE
# decision: keep it equal to the pinned macos-15 in the matrix
# above. Do not switch that runner to macos-latest — GitHub rolled
# macos-latest to macOS 26 in July 2026, whose bottles target 26.0,
# which broke this job for six weeks (#18). Raising both together
# is a support-floor change: it drops every macOS user below the
# new value, so it is a release decision, not a CI tweak.
# The wheel's macOS support floor. protobuf is built from source
# at this target and linked statically, so the value does not
# depend on the runner image (#20). Changing it drops or adds
# macOS users, so it is a release decision, not a CI tweak; keep
# it equal to publish.yml's macosx_deployment_target.
MACOSX_DEPLOYMENT_TARGET: "15.0"
CIBW_ENVIRONMENT_WINDOWS: >-
CMAKE_TOOLCHAIN_FILE="$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"
Expand Down
37 changes: 19 additions & 18 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,14 @@ jobs:
# macOS users fall back to a source build via the published
# sdist for now; we'll add the x86_64 wheel back via
# universal2 (or a self-hosted runner) in a follow-up.
# The runner image and macosx_deployment_target below are ONE
# decision, not two: Homebrew's bottled protobuf/abseil dylibs are
# built for the runner's macOS version, and delocate refuses to
# bundle dylibs whose min target is newer than the wheel's. So the
# runner is pinned rather than -latest. GitHub rolled macos-latest
# to macOS 26 in July 2026, whose bottles target 26.0, silently
# breaking the macOS wheel against the 15.0 target here (#18).
# Raising this pair sets the published wheel's macOS support floor
# — it drops every macOS user below the new value — so it is a
# release decision. Keep the two values equal.
- os: macos-15
# macosx_deployment_target is the published wheel's macOS support
# floor, and it no longer depends on the runner image: protobuf and
# abseil are built from source at this target and linked statically
# (scripts/cibw_install_protobuf.sh), so delocate has no Homebrew
# dylib to compare against it (#18, #20). The runner can move
# freely. Changing this value drops or adds macOS users, so it is a
# release decision.
- os: macos-latest
archs: "arm64"
macosx_deployment_target: "15.0"
- os: windows-latest
Expand Down Expand Up @@ -99,11 +96,15 @@ jobs:
# macOS + Windows: cibuildwheel runs natively, so the host
# path passed via the action-level env block works directly.
PROTOWIRE_CPP_DIR: ${{ github.workspace }}/protowire-cpp-checkout
# The manylinux base image's protobuf-devel rpm is too old
# (3.5 / 3.14) and generates broken C++ for fields named
# `default`. Build 25.3 from source instead.
CIBW_BEFORE_ALL_LINUX: bash {project}/scripts/cibw_install_protobuf_linux.sh
CIBW_BEFORE_ALL_MACOS: brew install protobuf
# Build protobuf 25.3 from source on Linux and macOS. Linux: the
# manylinux base image's protobuf-devel rpm is too old (3.5 / 3.14)
# and generates broken C++ for fields named `default`. macOS: built
# at MACOSX_DEPLOYMENT_TARGET so the wheel's floor is not the
# runner's (#20). See scripts/cibw_install_protobuf.sh.
CIBW_BEFORE_ALL_LINUX: bash {project}/scripts/cibw_install_protobuf.sh
CIBW_BEFORE_ALL_MACOS: PROTOBUF_PREFIX=/tmp/protobuf-install bash {project}/scripts/cibw_install_protobuf.sh
# The build finds that install before anything Homebrew has.
CIBW_ENVIRONMENT_MACOS: CMAKE_PREFIX_PATH=/tmp/protobuf-install
# Use the default dynamic triplet — vcpkg integrates with
# CMake's find_package via the toolchain file, and delvewheel
# bundles the resulting libprotobuf.dll / libabsl_*.dll into
Expand All @@ -117,8 +118,8 @@ jobs:
# CIBW_REPAIR_WHEEL_COMMAND_WINDOWS we have to install it
# ourselves.
CIBW_BEFORE_BUILD_WINDOWS: pip install delvewheel
# See matrix comment: align wheel target with runner OS so
# delocate accepts brew's dylibs.
# The wheel's macOS floor; see the matrix comment. It is set
# independently of the runner image.
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
CIBW_ENVIRONMENT_WINDOWS: >-
CMAKE_TOOLCHAIN_FILE="$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@ format changes.
the corpus's 101-level rows never reached the encoder. A read that fails
still exits 2.

- **The macOS wheel's support floor no longer depends on the CI runner's
macOS** (#20). protobuf and abseil are now built from source at
`MACOSX_DEPLOYMENT_TARGET` and linked statically
(`scripts/cibw_install_protobuf.sh`, which replaces
`cibw_install_protobuf_linux.sh`), instead of taken from Homebrew bottles
built for the runner. The wheel-building runners are back on
`macos-latest`. The floor is unchanged at macOS 15.0. macOS builds
protobuf v36.2; Linux stays on v25.3.

## [1.1.0] — 2026-10-31

### Added
Expand Down
83 changes: 83 additions & 0 deletions scripts/cibw_install_protobuf.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: MIT
# Copyright (c) 2026 TrendVidia, LLC.
#
# Build protobuf (and its bundled abseil) from source for a cibuildwheel
# leg, as static PIC libraries that the native module absorbs.
#
# Linux: runs inside the manylinux container. The base image's
# protobuf-devel rpm is too old (AlmaLinux 8 → 3.5, AlmaLinux 9 → 3.14).
# Protoc only started escaping C++ reserved-word field names (e.g.
# `default` in pxf/annotations.proto) in 3.21, so 3.x rpms generate
# broken `.pb.cc` for our annotations.
#
# macOS: runs on the runner itself. Homebrew's bottles are built for the
# runner's macOS version, and delocate refuses to bundle a dylib whose
# minimum target is newer than the wheel's, so with bottles the wheel's
# support floor was tied to the runner image (#18, #20). Built here at
# MACOSX_DEPLOYMENT_TARGET and linked statically, there is no dylib for
# delocate to check, and the floor is whatever MACOSX_DEPLOYMENT_TARGET
# says. The libraries are built for the runner's architecture.
#
# Versions differ by OS:
# - Linux: v25.3, last stable in the v25 line, before v26's abseil API
# churn. Its bundled abseil is a git submodule.
# - macOS: v36.2, the version Homebrew ships, which the macOS test legs
# already build against. v25.3 cannot build here: its bundled abseil
# (LTS 20230802) passes `-Xarch_x86_64 -msse4.1` as two separate
# options, CMake drops the repeated `-Xarch_x86_64`, and clang refuses
# the bare `-msse4.1` on arm64. Abseil 20240722 fixed it; protobuf v30+
# fetches a fixed abseil (20250512.1 for v36.2) instead of bundling one.
# It is always fetched, never taken from Homebrew, whose abseil is a
# dylib built for the runner's macOS.
#
# Installs into PROTOBUF_PREFIX (default /usr/local). A prefix other than
# a system one must also be on the build's CMAKE_PREFIX_PATH.

set -euxo pipefail

PROTOBUF_VERSION=25.3
PREFIX="${PROTOBUF_PREFIX:-/usr/local}"
WORKDIR="${TMPDIR:-/tmp}/protobuf-build"

cmake_args=()
if [[ "$(uname -s)" == Darwin ]]; then
PROTOBUF_VERSION=36.2
cmake_args+=("-Dprotobuf_FORCE_FETCH_DEPENDENCIES=ON")
# Abseil pins absl::string_view to std::string_view at install time only
# if a test compile at the default standard is C++17 or later. Apple
# clang's default is older, so without this the installed abseil uses
# its own string_view and protowire-cpp fails to compile against it.
# Homebrew builds abseil at 17 too.
cmake_args+=("-DCMAKE_CXX_STANDARD=17")
# The deployment target is the wheel's support floor; building without
# one would quietly target the runner's own macOS again.
: "${MACOSX_DEPLOYMENT_TARGET:?set MACOSX_DEPLOYMENT_TARGET to the macOS floor of the wheel}"
cmake_args+=("-DCMAKE_OSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET}")
fi

# The release-page tarball excludes git submodules (abseil-cpp,
# utf8_range), so a curl|tar pipeline gives an empty third_party/.
# Use a shallow clone with --recurse-submodules instead.
rm -rf "$WORKDIR"
git clone --depth 1 --branch "v${PROTOBUF_VERSION}" \
--recurse-submodules --shallow-submodules \
https://github.com/protocolbuffers/protobuf.git "$WORKDIR"
cd "$WORKDIR"

cmake -B build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-Dprotobuf_BUILD_TESTS=OFF \
-Dprotobuf_BUILD_SHARED_LIBS=OFF \
-Dprotobuf_ABSL_PROVIDER=module \
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
${cmake_args[@]+"${cmake_args[@]}"}
cmake --build build -j"$(getconf _NPROCESSORS_ONLN)"
cmake --install build
if [[ "$(uname -s)" == Linux ]]; then
ldconfig 2>/dev/null || true
fi

# Sanity check: the installed protoc must be 3.21+.
"$PREFIX/bin/protoc" --version
42 changes: 0 additions & 42 deletions scripts/cibw_install_protobuf_linux.sh

This file was deleted.

Loading