Skip to content
Open
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
940003a
new(envoyproxy.io): Envoy — high-performance edge/service proxy
tannevaled May 29, 2026
bd03ebb
fix(envoyproxy.io): use freedesktop.org/pkg-config (pkgconf.org isn't…
tannevaled May 29, 2026
b20f1dd
fix(envoy): bazel '-c opt' + .stripped target ('release-stripped' isn…
tannevaled May 29, 2026
edb3ff7
fix(envoy): patch bazel/repo.bzl to use pkgx-installed yq
tannevaled May 29, 2026
9938284
fix(envoy): stub workspace_status_command (tarball has no .git)
tannevaled May 29, 2026
511c73e
fix(envoy): use pkgx llvm.org via BAZEL_LLVM_PATH
tannevaled May 29, 2026
f99a830
fix(envoy): patch dynamic_modules.bzl to use pkgx llvm-objcopy
tannevaled May 29, 2026
6c4edc7
fix(envoy): single-quote the dynamic_modules sed expression
tannevaled May 29, 2026
b030348
fix(envoy): force --config=libc++ (Nix-inspired)
tannevaled May 29, 2026
b11b478
fix(envoy): joined -isystemPATH so bazel doesn't split it
tannevaled May 29, 2026
eec90e2
fix(envoy): add --host_cxxopt/--host_copt/--host_linkopt for libc++
tannevaled May 29, 2026
29e7fb7
fix(envoyproxy.io): get libc++ from libcxx.llvm.org, not llvm.org
tannevaled Jul 27, 2026
9b5ba91
fix(envoyproxy.io): make version-specific patches robust to 1.39+
tannevaled Jul 27, 2026
f57177f
chore(envoyproxy.io): --verbose_failures to diagnose layered build er…
tannevaled Jul 27, 2026
a9fb645
fix(envoyproxy.io): run compiles locally so libc++ -isystem is reachable
tannevaled Jul 27, 2026
f94483a
fix(envoyproxy.io): unified llvm+libc++ prefix instead of -isystem copts
tannevaled Jul 27, 2026
5b9381c
fix(envoyproxy.io): copy clang into unified prefix so it finds libc++
tannevaled Jul 27, 2026
cd34589
fix(envoyproxy.io): rm the clang-22 symlink before copying the real d…
tannevaled Jul 27, 2026
3e936b6
fix(envoyproxy.io): drop Genrule=sandboxed so v8's genrules can run
tannevaled Jul 27, 2026
90a06d7
fix(envoyproxy.io): use preinstalled make for rules_foreign_cc
tannevaled Jul 27, 2026
f76741a
fix(envoyproxy.io): register all preinstalled foreign_cc tool toolchains
tannevaled Jul 27, 2026
57ea3dd
fix(envoyproxy.io): add -L to the unified prefix lib for static libc++
tannevaled Jul 27, 2026
de5616c
fix(envoyproxy.io): forward PATH to actions so foreign_cc finds cmake…
tannevaled Jul 27, 2026
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
223 changes: 223 additions & 0 deletions projects/envoyproxy.io/package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
# Envoy — high-performance edge/middle/service proxy.
#
# Built from source via Bazel. WARNING: this is a heavy build —
# expect 1-3 hours on CI hardware and ~8 GB peak RAM. If pantry's
# CI runners can't sustain it, we'll need to tune the build (drop
# extensions, reduce parallelism, split into stages, etc.); pantry
# policy is from-source over vendored binaries.

distributable:
url: https://github.com/envoyproxy/envoy/archive/refs/tags/v{{ version }}.tar.gz
strip-components: 1

versions:
github: envoyproxy/envoy

# Upstream officially ships standalone binaries only for Linux.
# darwin builds via Bazel are possible but require a darwin-host
# Bazel setup that's beyond Phase 1 of this recipe.
platforms:
- linux/x86-64
- linux/aarch64

# The shipped envoy binary is linked against libc++ (see --config=libc++
# in the build) with an rpath into the libcxx.llvm.org bottle, so it needs
# that bottle present at runtime.
dependencies:
libcxx.llvm.org: '*'

build:
dependencies:
github.com/bazelbuild/bazelisk: '*' # bazel wrapper / version manager
github.com/mikefarah/yq: '*' # envoy's @yq external repo replacement
llvm.org: '*' # local clang for BAZEL_LLVM_PATH
libcxx.llvm.org: '*' # libc++ (llvm.org ships clang only)
gnu.org/coreutils: '*' # install(1)
gnu.org/make: '*' # rules_foreign_cc make toolchain (else it builds make from source)
ninja-build.org: '*' # rules_foreign_cc ninja toolchain
cmake.org: '*' # some bazel rules use cmake
python.org: '~3.11' # bazel build rules use python
gnu.org/m4: '*'
gnu.org/automake: '*'
gnu.org/autoconf: '*'
gnu.org/libtool: '*'
gnu.org/patch: '*'
freedesktop.org/pkg-config: '*'
curl.se: '*'

script:
# Envoy's `bazel/repo.bzl:_envoy_repo_impl` calls `@yq` to parse
# `.github/config.yml`. It declares @yq via http_archive on the
# mikefarah/yq release page — but that release ships a single
# binary `yq_linux_amd64`, not a tarball, so bazel ends up with
# `external/yq/yq_linux_amd64` while repo.bzl expects `external/yq/yq`.
# Result: "execvp(.../external/yq/yq): No such file or directory".
#
# Patch repo.bzl to use the yq from PATH (pkgx-installed via the
# build dep above) instead of the http_archive. Only needed on envoy
# releases whose repo.bzl still resolves @yq this way (<=1.38.x);
# 1.39+ refactored it out, so guard on the pattern's presence.
- run: |
if grep -q 'repository_ctx.attr.yq' bazel/repo.bzl; then
sed -i 's|repository_ctx.path(repository_ctx.attr.yq)|repository_ctx.which("yq")|' \
bazel/repo.bzl
grep -A1 'which("yq")' bazel/repo.bzl | head -5
fi

# envoy's `dynamic_modules.bzl:envoy_dynamic_module_prefix_symbols`
# hardcodes `@llvm_toolchain_llvm//:objcopy` in the genrule that
# renames dynamic-module symbols. When BAZEL_LLVM_PATH is set,
# envoy doesn't register the @llvm_toolchain_llvm http_archive,
# so the genrule fails analysis:
#
# no such package '@@llvm_toolchain_llvm//': not defined and
# referenced by 'source/extensions/dynamic_modules/builtin_extensions:_hickory_dns_static_renamed'
#
# Patch the .bzl to use the llvm-objcopy from pkgx's llvm.org
# (full path so bazel's action sandbox can find it without PATH
# access).
- run: |
sed -i \
-e 's|$(location @llvm_toolchain_llvm//:objcopy)|{{deps.llvm.org.prefix}}/bin/llvm-objcopy|g' \
-e 's|tools = \["@llvm_toolchain_llvm//:objcopy"\],|tools = [],|g' \
source/extensions/dynamic_modules/dynamic_modules.bzl
grep -A 3 "llvm-objcopy" source/extensions/dynamic_modules/dynamic_modules.bzl | head -6 || true

# Use the release config: -c opt + stripped + minimal symbols.
# `bazelisk` here is the canonical entry point — it reads
# `.bazelversion` from the source tree and downloads the right
# bazel for us.
#
# Bazel's user output goes under $HOME by default; redirect to
# our build dir so the cellar stays clean.
- run: |
export USER=$(id -un)
export TEST_TMPDIR=$PWD/.bazel-cache
mkdir -p $TEST_TMPDIR

# Envoy's repo.bzl checks BAZEL_LLVM_PATH and uses a local
# LLVM install when set. Without this, it falls back to the
# @llvm_toolchain http_archive which fails in our sandbox
# (Exit 127 when invoking external/llvm_toolchain/bin/clang).
#
# The pkgx llvm.org bottle ships clang but NOT libc++ (no
# include/c++/v1, no libc++.a) — that lives in the dedicated
# libcxx.llvm.org bottle. envoy builds with --config=libc++, i.e.
# `-stdlib=libc++` + a static `-l%:libc++.a` link, which makes clang
# look for libc++ RELATIVE to its LLVM install (BAZEL_LLVM_PATH).
# So present a UNIFIED prefix: symlink the llvm.org tree and overlay
# libcxx.llvm.org's headers (include/c++/v1) + static archives
# (libc++.a / libc++abi.a / libunwind.a) into it. The toolchain
# (toolchains_llvm, driven by BAZEL_LLVM_PATH) then discovers libc++
# as a BUILTIN include/lib dir — so bazel accepts it (an explicit
# `-isystem /opt/...` copt instead trips "the include path references
# a path outside of the execution root" on the exec-config
# v8/torque/simdutf "[for tool]" compiles) and clang resolves
# <string>/<vector>/<iostream> with no extra flags.
LLVM="{{deps.llvm.org.prefix}}"
LIBCXX="{{deps.libcxx.llvm.org.prefix}}"
COMBINED="$PWD/.llvm-libcxx"
rm -rf "$COMBINED"; mkdir -p "$COMBINED/include/c++" "$COMBINED/lib" "$COMBINED/bin"
for d in "$LLVM"/*; do
b=$(basename "$d")
case "$b" in bin|include|lib) ;; *) ln -sf "$d" "$COMBINED/$b" ;; esac
done
for d in "$LLVM"/include/*; do ln -sf "$d" "$COMBINED/include/$(basename "$d")"; done
ln -sf "$LIBCXX/include/c++/v1" "$COMBINED/include/c++/v1"
for d in "$LLVM"/lib/*; do ln -sf "$d" "$COMBINED/lib/$(basename "$d")"; done
for d in "$LIBCXX"/lib/libc++* "$LIBCXX"/lib/libunwind*; do ln -sf "$d" "$COMBINED/lib/$(basename "$d")"; done
# bin: symlink the tools, BUT clang locates its libc++/resource dirs
# relative to its own binary via /proc/self/exe — a symlink resolves
# back to the llvm.org bottle (which has no libc++), so `<algorithm>`
# isn't found. COPY the real clang driver into the combined bin so
# its self-location is the unified prefix; it still finds libLLVM/
# libclang-cpp via its $ORIGIN/../lib rpath (our symlinked lib/).
for f in "$LLVM"/bin/*; do ln -sf "$f" "$COMBINED/bin/$(basename "$f")"; done
realclang=$(readlink -f "$LLVM/bin/clang")
rc=$(basename "$realclang")
rm -f "$COMBINED/bin/$rc" # drop the symlink we just made (else cp = same file)
cp "$realclang" "$COMBINED/bin/$rc"
for a in clang clang++ clang-cpp; do ln -sf "$rc" "$COMBINED/bin/$a"; done
export BAZEL_LLVM_PATH="$COMBINED"
echo "BAZEL_LLVM_PATH=$BAZEL_LLVM_PATH"

# The bazel-rules-cc llvm toolchain uses libstdc++ by default
# on Linux, but the pkgx llvm bottle ships only libc++ (no
# libstdc++ — that comes from gcc). Without an override, clang
# fails with "'string' file not found" on the first C++ source.
#
# Nix's nixpkgs envoy build sidesteps this by using gcc with
# its hermetic cc-wrapper, but envoy dropped gcc support in
# 1.21+. So we force libc++ explicitly via envoy's --config:
BAZEL_OPTS="--config=libc++"
# This is a huge, layered build; surface the failing compile
# command on error instead of just the target label.
BAZEL_OPTS="$BAZEL_OPTS --verbose_failures"
# Run actions locally (unsandboxed) so the compiler can reach the
# clang/libc++ toolchain under /opt (via the unified prefix above).
# NB: do NOT force `--strategy=Genrule=sandboxed` — v8's genrules
# (generated_inspector_files, embedded.S) can't run sandboxed and
# bazel aborts with "Genrule spawn cannot be executed with any of
# the available strategies". Let genrules follow --spawn_strategy=local.
BAZEL_OPTS="$BAZEL_OPTS --spawn_strategy=local"

# Memory-constrain bazel to fit on standard CI runners.
# `--local_resources` units: cpu=count, ram=MB.
BAZEL_OPTS="$BAZEL_OPTS -c opt"
BAZEL_OPTS="$BAZEL_OPTS --jobs=HOST_CPUS*0.5"
BAZEL_OPTS="$BAZEL_OPTS --local_ram_resources=HOST_RAM*0.7"
# Tarball install has no .git, so envoy's workspace_status.sh
# fails at `git rev-parse`. Stub workspace status with `true`
# — we don't need stamping for a from-source release build.
BAZEL_OPTS="$BAZEL_OPTS --workspace_status_command=true"
# rules_foreign_cc otherwise builds its OWN build tools (make,
# pkgconfig, cmake, ninja) from source, and each ./configure link
# test fails under envoy's --config=libc++ (static -l%:libc++.a
# linklibs forced onto a plain-C configure: "C compiler cannot
# create executables"). Register the preinstalled toolchains so
# foreign_cc uses the pkgx tools on PATH instead of compiling them.
for tc in make pkgconfig cmake ninja; do
BAZEL_OPTS="$BAZEL_OPTS --extra_toolchains=@rules_foreign_cc//toolchains:preinstalled_${tc}_toolchain"
done
# envoy's --config=libc++ links the static `-l:libc++.a`/`libc++abi.a`/
# `libunwind.a`, but nothing tells the linker WHERE they are — they're
# in our unified prefix's lib/. Add the -L (target AND exec/host
# configs). This is a library search path, not an -isystem include, so
# it does NOT trip bazel's "outside the execution root" check.
BAZEL_OPTS="$BAZEL_OPTS --linkopt=-L$COMBINED/lib --host_linkopt=-L$COMBINED/lib"
# foreign_cc build scripts (nghttp2 etc.) invoke the preinstalled
# cmake/ninja/pkg-config by bare name, but bazel actions don't
# inherit the shell PATH — only the runner's system PATH, which has
# `make` but not the pkgx cmake/ninja → "cmake: command not found".
# Forward the full PATH into target and exec/host actions.
BAZEL_OPTS="$BAZEL_OPTS --action_env=PATH=$PATH --host_action_env=PATH=$PATH"

# NOTE: no explicit -isystem/-L for libc++ — the unified
# BAZEL_LLVM_PATH prefix built above lets the toolchain find it as a
# builtin. envoy's --config=libc++ links libc++/libc++abi STATICALLY
# (BAZEL_LINKLIBS=-l%:libc++.a), so the binary needs no libc++.so at
# runtime either.

# `envoy-static.stripped` is upstream's stripped release target.
bazelisk build $BAZEL_OPTS //source/exe:envoy-static.stripped

- install -Dm755 bazel-bin/source/exe/envoy-static.stripped "{{prefix}}/bin/envoy"

# Bazel leaves a multi-GB output_base under .bazel-cache that we
# don't want in the bottle.
- run: rm -rf .bazel-cache

test:
# `envoy --version` returns "envoy version: <commit>/<ver>/<type>/<status>/<...>".
# We pin against the marketing version to confirm the binary loads.
script:
- run: |
out=$(envoy --version 2>&1 | head -1)
echo "envoy --version: $out"
case "$out" in
*"version: "*"/{{version}}/"*) echo PASS ;;
*) echo "FAIL: expected version {{version}} in output, got: $out"; exit 1 ;;
esac

provides:
- bin/envoy
Loading