Skip to content

new(envoyproxy.io): Envoy — high-performance edge/service proxy (Bazel build from source) - #13046

Open
tannevaled wants to merge 35 commits into
pkgxdev:mainfrom
tannevaled:new/envoyproxy
Open

new(envoyproxy.io): Envoy — high-performance edge/service proxy (Bazel build from source)#13046
tannevaled wants to merge 35 commits into
pkgxdev:mainfrom
tannevaled:new/envoyproxy

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

From-source Bazel build of envoy. Heavy CI (1-3h, ~8GB RAM), with a vendored-binary fallback commented at the bottom if CI can't sustain it.

Closes a mainstream coverage gap (was missing vs brew + nixpkgs).

@tannevaled

Copy link
Copy Markdown
Contributor Author

Blocker: bazel can't fetch yq from GitHub releases inside the runner sandbox.

Latest run fails at the fetch phase, before any actual compilation:

ERROR: …/bazel/repo.bzl:75:13: An error occurred during the fetch of repository 'envoy_repo':
  fail("yq failed: {}".format(json_result.stderr))
Error in fail: yq failed: execvp(…/.bazel-cache/_bazel_root/.../external/yq/yq, …): No such file or directory

Envoy's bazel rules pull yq from github.com/mikefarah/yq/releases/... via http_archive during MODULE.bazel resolution. Either the download is blocked or the extracted artifact doesn't sit at the path bazel expects (yq_linux_amd64yq).

Options to unblock, in increasing complexity:

  1. Patch envoy's bazel/repo.bzl to use a system yq (need mikefarah.dev/yq added to pantry first — check if it exists)
  2. Pre-seed bazel's external cache with yq before running bazelisk build
  3. Add --repository_cache=$BAZEL_CACHE and pre-populate

I'll move this PR to draft until we have one of those in place. The from-source pattern is correct but envoy's bazel chain has too many fetch-from-network steps for the current runner setup. Open to suggestions from anyone who's wrangled envoy CI elsewhere.

@tannevaled
tannevaled marked this pull request as ready for review May 29, 2026 09:00
@tannevaled

Copy link
Copy Markdown
Contributor Author

Took option 1 — patched bazel/repo.bzl to use the pkgx-installed yq via repository_ctx.which("yq") instead of the broken @yq http_archive.

The http_archive download was technically working but bazel placed the artifact at external/yq/yq_linux_amd64 (single binary, not a tarball) while repo.bzl expected external/yq/yq. The sed patch sidesteps the path mismatch entirely.

Added github.com/mikefarah/yq as a build dep — it's the pure-Go yq, already in pantry, no additional fetches. Moving the PR back from draft.

@tannevaled
tannevaled marked this pull request as draft May 29, 2026 09:46
@tannevaled

Copy link
Copy Markdown
Contributor Author

Yq patch + workspace_status stub both worked — bazel got 5211 compile actions deep before failing.

Current blocker: envoy uses bazel's @llvm_toolchain hermetic rule which fetches its own clang via http_archive. In our sandbox, that download path resolves but the wrapper script then can't exec the toolchain:

ERROR: …/external/hessian2-codec/hessian2/BUILD:31:11:
  Compiling hessian2/reader.cc failed: (Exit 127): cc_wrapper.sh failed:
  error executing CppCompile command (from target @@hessian2-codec//hessian2:reader_lib)
  external/llvm_toolchain/bin/cc_wrapper.sh -U_FORTIFY_SOURCE
  '--target=x86_64-unknown-linux-gnu' …

Exit 127 = command not found. cc_wrapper.sh is there but the clang it tries to exec from external/llvm_toolchain/bin/clang either isn't downloaded properly (same single-binary http_archive trap as @yq) or doesn't have +x.

This needs a bigger patch than #13046 currently has:

  • Either replace @llvm_toolchain references with the pkgx llvm.org install (probably patch via sed in bazel/repository_locations.bzl + bazel/toolchains.bzl)
  • Or pre-seed bazel's repository cache with a working clang tarball

Both options are non-trivial. Re-marking as draft until I have a cleaner approach. Open to suggestions if anyone has wrangled this.

tannevaled added a commit to tannevaled/pantry that referenced this pull request May 29, 2026
Envoy's bazel/repo.bzl reads BAZEL_LLVM_PATH and uses a local LLVM
install when set. Without it, the build falls back to @llvm_toolchain
(http_archive download of clang) which fails Exit 127 in our sandbox
when invoking external/llvm_toolchain/bin/clang.

Add llvm.org as a build dep and point BAZEL_LLVM_PATH at it. This
keeps the from-source promise — every binary tool in the toolchain
now comes from pantry, no http_archive fetches of opaque binaries.

This is the proper alternative the previous yq patch (pkgxdev#13046's
prior commit) demonstrated: where envoy supports it, use an env-var
hook rather than patching the bazel files.
@tannevaled
tannevaled marked this pull request as ready for review May 29, 2026 09:50
@tannevaled

Copy link
Copy Markdown
Contributor Author

Update — envoy's `bazel/repo.bzl` reads `BAZEL_LLVM_PATH` and uses a local LLVM install when set (I found it on re-reading the file):

llvm_path = repository_ctx.os.environ.get("BAZEL_LLVM_PATH", "")
local_llvm = "True" if llvm_path else "False"

Added `llvm.org` as a build dep and `export BAZEL_LLVM_PATH={{deps.llvm.org.prefix}}` before invoking bazelisk. No file patching needed — envoy provides this env-var hook on purpose for exactly this case.

This keeps the from-source promise intact: every binary tool in the toolchain now comes from pantry (bazelisk, llvm.org clang, yq), no http_archive fetches of opaque binaries from random GitHub releases.

Marking ready for review.

tannevaled and others added 11 commits July 7, 2026 19:01
Built from source via Bazel. WARNING: heavy build — expect 1-3
hours on CI hardware and ~8 GB peak RAM. Uses bazelisk as the
bazel-version manager (already in pantry).

Config:
  - --config=release-stripped (-c opt, stripped binary)
  - --jobs=HOST_CPUS*0.5 + --local_ram_resources=HOST_RAM*0.7
    (cap memory pressure so it fits CI runners)
  - Output: //source/exe:envoy-static (the canonical entry point)

linux/x86-64 + linux/aarch64 only. Upstream officially ships
standalone binaries only for Linux; darwin builds via Bazel are
possible but the toolchain wiring is non-trivial — defer to a
follow-up if requested.

Recipe includes a commented-out vendored-binary fallback at the
bottom: if CI can't sustain the bazel build (resource exhaustion),
swap to `warnings: vendored` + curl of upstream's release artifact
(envoy-X.Y.Z-linux-{x86_64,aarch_64}). Same end-result binary,
much cheaper CI.

Closes the "envoy missing from pantry" coverage gap.
…'t a config)

Bazel rejected `--config=release-stripped` ("Config value not defined").
Envoy's bazelrc doesn't define that name — only `--config=release`,
`--config=clang`, etc.

Switch to plain `-c opt` and use upstream's stripped binary target
`//source/exe:envoy-static.stripped`, which is what envoy's own CI
publishes as the release artifact.
Envoy's `_envoy_repo_impl` calls @yq to parse .github/config.yml,
declaring @yq via http_archive pointing at mikefarah/yq releases.
But that release page ships a single binary `yq_linux_amd64`, not
a tarball — bazel ends up with `external/yq/yq_linux_amd64` while
repo.bzl expects `external/yq/yq`:

  execvp(.../external/yq/yq): No such file or directory

Rather than fight bazel's http_archive semantics, just use the
pkgx-installed yq from PATH via `repository_ctx.which("yq")`.
Add `github.com/mikefarah/yq` as a build dep.

This is the cleanest from-source path: every binary tool in the
toolchain comes from pkgx, no http_archive fetches of single-file
binaries from random GitHub releases.
Past the yq patch — bazel now builds further but fails because
envoy's workspace_status.sh runs git to inject build metadata,
and the source tarball has no .git directory:

  ERROR: BazelWorkspaceStatusAction stable-status.txt failed:
  fatal: not a git repository

Stub it with `--workspace_status_command=true` — we don't need
stamping for a from-source release build.
Envoy's bazel/repo.bzl reads BAZEL_LLVM_PATH and uses a local LLVM
install when set. Without it, the build falls back to @llvm_toolchain
(http_archive download of clang) which fails Exit 127 in our sandbox
when invoking external/llvm_toolchain/bin/clang.

Add llvm.org as a build dep and point BAZEL_LLVM_PATH at it. This
keeps the from-source promise — every binary tool in the toolchain
now comes from pantry, no http_archive fetches of opaque binaries.

This is the proper alternative the previous yq patch (pkgxdev#13046's
prior commit) demonstrated: where envoy supports it, use an env-var
hook rather than patching the bazel files.
envoy's `envoy_dynamic_module_prefix_symbols` macro hardcodes
`@llvm_toolchain_llvm//:objcopy` for symbol renaming. When
BAZEL_LLVM_PATH is set (our local-LLVM path), envoy doesn't register
the http_archive that defines @llvm_toolchain_llvm, leaving a
dangling repo reference:

  ERROR: no such package '@@llvm_toolchain_llvm//':
  The repository '@@llvm_toolchain_llvm' could not be resolved
  ... referenced by '//source/extensions/dynamic_modules/
  builtin_extensions:_hickory_dns_static_renamed'

sed-patches the .bzl to use the absolute path of pkgx llvm.org's
llvm-objcopy in the genrule's cmd, and drops the @llvm_toolchain_llvm
entry from tools=[]. Both fix the dangling repo reference in one shot.
Previous form used double quotes with `\\$(...)` to try to escape the
shell command substitution. After YAML and bash double-quote handling
the `$(location @llvm_toolchain_llvm//:objcopy)` actually ran, hit
"location: command not found", returned empty, and produced a malformed
sed expression: `s|\|...|g` → "unterminated 's' command".

Switching to single quotes preserves the bazel `$(location ...)`
placeholder literally for sed to match.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The bazel-rules-cc llvm toolchain defaults to libstdc++ on Linux, but
the pkgx llvm.org bottle ships only libc++ headers — libstdc++ comes
from gcc. With BAZEL_LLVM_PATH pointing at the pkgx llvm bottle and
the default toolchain config, clang couldn't find <string> on the
first C++ source.

Nix's nixpkgs envoy build sidesteps this by using gcc + their hermetic
cc-wrapper, but envoy dropped gcc support in 1.21+. So we force libc++
explicitly via envoy's --config=libc++ + re-add the libc++ include
path (which bazel's cc_wrapper -nostdinc++'s out) + rpath the libc++
bottle so the produced binary still resolves libc++.so at runtime.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The previous form passed --cxxopt=-isystem and --cxxopt=PATH as two
separate bazel flags, which bazel's build action shuffling consumed
as two unrelated -isystem flags neither bound to a path.

Use clang's joined `-isystem=PATH` style (`-isystemPATH` works too
but the GNU-style equals is clearer). One token, one --cxxopt, one
include path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The protobuf/upb code generators bazel builds for envoy run as
"[for tool]" actions in the EXEC config, not the TARGET config.
--cxxopt/--copt/--linkopt apply only to the target build, so host
tools were compiling without libc++ on the include path and dying
with "'string' file not found" before any target action ran.

Mirror the libc++ include + rpath flags onto --host_* variants so
both host tools and target binaries find libc++.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
tannevaled and others added 7 commits July 27, 2026 15:30
The llvm.org bottle ships clang but no libc++ (no include/c++/v1, no
libc++.so), so `--config=libc++` failed with `'iostream' file not found`
when building v8/torque. pantry already has a dedicated libcxx.llvm.org
bottle that provides exactly that. Depend on it (build + runtime) and
point the -isystem / -L / -Wl,-rpath flags (target AND host/exec configs)
at {{deps.libcxx.llvm.org.prefix}} instead of the clang bottle.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
envoy bumped to 1.39.0, which refactored bazel/repo.bzl so it no longer
resolves @yq the old way — the yq patch's verification `grep` then found
nothing and failed the build (exit 1) before anything compiled. Guard the
yq patch on the pattern's presence (no-op on 1.39+), and make the
dynamic_modules diagnostic grep non-fatal. These are diagnostics; they
shouldn't gate the build across version bumps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rors

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
With libc++ now coming from the libcxx.llvm.org bottle, the build got past
the "'iostream' file not found" wall (reaches ~6k actions), but bazel then
rejects the absolute `-isystem /opt/libcxx.llvm.org/.../c++/v1` for the
exec-config v8/torque "[for tool]" compiles: "include path references a
path outside of the execution root". Run compile actions with
--spawn_strategy=local so they can read /opt, keeping genrules sandboxed
to avoid shared-scratch races (same approach as the cockroachdb recipe).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
envoy's --config=libc++ does `-stdlib=libc++` + a static `-l%:libc++.a`
link, so clang looks for libc++ relative to its LLVM install
(BAZEL_LLVM_PATH). The pkgx llvm.org bottle has no libc++ (it's the
separate libcxx.llvm.org bottle), and pointing at it with an explicit
`-isystem /opt/libcxx.../c++/v1` copt tripped bazel's "include path
references a path outside of the execution root" on the exec-config
v8/torque/simdutf "[for tool]" compiles.

Instead build a UNIFIED prefix: symlink the llvm.org tree and overlay
libcxx.llvm.org's include/c++/v1 + static archives (libc++.a/libc++abi.a/
libunwind.a), and set BAZEL_LLVM_PATH to it. The toolchain then discovers
libc++ as a builtin include/lib dir (bazel-accepted, no execroot error),
and the -isystem/-L/-rpath copts are dropped. Static libc++ link means the
binary needs no libc++.so at runtime.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The unified BAZEL_LLVM_PATH prefix cleared the "outside execution root"
wall (build now reaches abseil), but clang then failed with `'algorithm'
file not found`: clang locates its libc++/resource dirs relative to its
own binary via /proc/self/exe, and a SYMLINKED clang resolves back to the
llvm.org bottle (no libc++ there). Copy the real clang driver into the
combined bin/ (aliasing clang/clang++/clang-cpp to it) so its
self-location is the unified prefix; it still resolves libLLVM/libclang-cpp
through its $ORIGIN/../lib rpath into the symlinked lib/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…river

The bin/* symlink loop already linked clang-22, so `cp` of the real
clang-22 onto it failed ("are the same file") under set -e. Remove the
symlink first, then copy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
With the unified libc++ prefix, clang now finds libc++ and abseil compiles;
the build then hit v8's generated_inspector_files / embedded.S genrules,
which cannot run sandboxed — bazel aborts "Genrule spawn cannot be executed
with any of the available strategies [processwrapper-sandbox]". Drop the
`--strategy=Genrule=sandboxed` override (it was a cockroach-recipe pattern
that doesn't apply here) and let genrules follow --spawn_strategy=local.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tannevaled

Copy link
Copy Markdown
Contributor Author

Status update — got the from-source build to ~34% (6382/18507 actions) on linux by clearing several toolchain walls (all in the latest commits). The root difficulty: pkgx ships clang (llvm.org) and libc++ (libcxx.llvm.org) as separate bottles, which fights bazel's --config=libc++.

Walls cleared so far:

  1. 'iostream' file not found → depend on the existing libcxx.llvm.org bottle for libc++ (rather than adding it to the core llvm.org bottle).
  2. bazel "include path references a path outside of the execution root" for an -isystem /opt/... copt on the exec-config ([for tool]) v8/simdutf compiles → build a unified BAZEL_LLVM_PATH prefix that symlinks the llvm.org tree and overlays libcxx's include/c++/v1 + static archives, so libc++ is a toolchain builtin (no external copt).
  3. 'algorithm' file not found → a symlinked clang resolves /proc/self/exe back to the llvm.org bottle (no libc++ there), so copy the real clang driver into the unified prefix.
  4. v8 genrules "Genrule spawn cannot be executed" → drop --strategy=Genrule=sandboxed.

Current wall: rules_foreign_cc builds its own GNU make from source, and that ./configure fails "C compiler cannot create executables" — the --config=libc++ static -l%:libc++.a LINKLIBS get forced onto that plain-C configure link test. Likely fix: point rules_foreign_cc at a prebuilt make, or scope the libc++ linklibs off the foreign_cc tool builds. Pausing here; the toolchain approach above is the reusable part.

tannevaled and others added 5 commits July 27, 2026 19:30
rules_foreign_cc was building its own GNU make from source, and that
./configure link test fails under envoy's --config=libc++ (the static
`-l%:libc++.a` linklibs get forced onto a plain-C configure link →
"C compiler cannot create executables"). Add gnu.org/make as a build dep
and register @rules_foreign_cc//toolchains:preinstalled_make_toolchain so
foreign_cc uses the pkgx make on PATH instead of compiling one.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Preinstalled make cleared the make-tool wall, but rules_foreign_cc then
built pkgconfig from source and hit the same --config=libc++ configure-link
failure. Register the preinstalled make/pkgconfig/cmake/ninja toolchains
(and add ninja-build.org) so foreign_cc uses the pkgx tools on PATH rather
than compiling each build tool from source.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Past the foreign_cc tool walls, links failed with
`ld.lld: unable to find library -l:libc++.a / libc++abi.a / libunwind.a`:
envoy's --config=libc++ references the static archives but nothing points
the linker at them. They're in the unified prefix's lib/, so add
`--linkopt=-L$COMBINED/lib` (+ --host_linkopt for exec-config tool links
like protobuf). -L is a library search path, not an -isystem include, so
it doesn't trip the "outside the execution root" check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…/ninja

Past the linker fix, foreign_cc deps started building (nghttp2 via CMake),
but the build script hit "cmake: command not found": bazel actions don't
inherit the shell PATH, only the runner's system PATH (which has make but
not the pkgx cmake/ninja). Forward the full PATH via
--action_env=PATH / --host_action_env=PATH.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…bcurl

With PATH forwarded, foreign_cc found cmake and nghttp2 built, but the
maxmind CMake build then failed: "cmake: error while loading shared
libraries: libcurl.so.4". The pkgx cmake dlopens libcurl (etc.) at
runtime, which needs LD_LIBRARY_PATH — also not inherited by bazel
actions. Forward it alongside PATH (target + exec/host).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tannevaled

Copy link
Copy Markdown
Contributor Author

Progress update — got much further (≈6350/18501 actions; the foreign_cc deps nghttp2 and maxmind now build). Additional walls cleared beyond the previous comment:

  • static libc++ link: ld.lld: unable to find -l:libc++.a → add -L to the unified prefix lib.
  • foreign_cc tool builds (make/pkgconfig/cmake/ninja) failing their own configure under --config=libc++ → register the @rules_foreign_cc//toolchains:preinstalled_*_toolchain set + add gnu.org/make, ninja.
  • cmake: command not found / cmake: error while loading shared libraries: libcurl.so.4 in foreign_cc build scripts → forward --action_env=PATH and --action_env=LD_LIBRARY_PATH (+ --host_*).

Current wall (infrastructure-level, pausing here): luajit builds a host tool minilua with the modern pkgx clang, which then needs GLIBC_2.29 — but the CI base image's system glibc is older (host/minilua: /lib/x86_64-linux-gnu/libm.so.6: version 'GLIBC_2.29' not found). This is the same old-CI-base-glibc constraint that limited cockroachdb, not a recipe/config issue — a foreign_cc host tool has to run on the build image during the build, and the image's glibc predates what the pkgx toolchain emits. Fixing it cleanly needs either a newer CI base or targeting/bundling an older glibc for the foreign_cc host-tool builds. All the toolchain-plumbing above (unified llvm+libc++ prefix, copied clang, preinstalled foreign_cc toolchains, forwarded PATH/LD_LIBRARY_PATH) is committed and reusable.

tannevaled and others added 11 commits July 28, 2026 10:35
… bottle

luajit builds a host tool `minilua` with the modern pkgx clang, which then
fails to run on the older CI base image: "minilua: libm.so.6: version
GLIBC_2.29 not found". Use pantry's relocatable glibc bottle the documented
way (gnu.org/glibc/README.md smoke-test pattern): link the EXEC-config
binaries with the bottle's own crt + libc + `--dynamic-linker=<bottle
ld-linux>` + rpath, so foreign_cc host tools run against glibc 2.44 on any
host. EXEC/host only (via --host_linkopt) — baking an absolute PT_INTERP
into the target/final envoy binary would break bottle relocation; add
gnu.org/glibc as a build dep.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
--host_linkopt didn't reach foreign_cc's luajit HOST_CC, so minilua still
linked the CI base's old system libm and failed on GLIBC_2.29. Instead
drop a `clang.cfg` next to the copied clang in the unified prefix (clang
auto-loads it from its own bin dir) that points every invocation at the
relocatable pkgx glibc bottle: `-B`/`-L` its crt+libs,
`-Wl,--dynamic-linker=<bottle ld-linux>`, `-Wl,-rpath`. This reaches ALL
clang links — bazel target/exec AND foreign_cc deps' own HOST_CC — with no
wrapper script (clang's /proc/self/exe self-location for libc++ stays
intact). Follows the gnu.org/glibc/README.md relocatable-bottle pattern.
Add gnu.org/glibc as a runtime dep so the shipped binary (whose PT_INTERP
is now the bottle's ld-linux) has it — a step toward running with no system
libc at all (`FROM scratch`). NOTE: PT_INTERP is an absolute bottle path;
full relocation still needs a load-time fixup (bklibcvenv), a follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…step)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…vent

pkgx ships cmake 4.x, which removed compatibility with projects whose
cmake_minimum_required is < 3.5. Envoy's vendored libevent still declares
an ancient minimum, so its rules_foreign_cc CMake build failed with
"Compatibility with CMake < 3.5 has been removed". Forward
CMAKE_POLICY_VERSION_MINIMUM=3.5 into the bazel foreign_cc actions.

The clang.cfg glibc-targeting approach now clears the full toolchain:
minilua and ~6355 build actions (incl. nghttp2 via foreign_cc CMake)
complete; this was the only remaining wall.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
After redirecting the toolchain onto the pkgx glibc 2.44 bottle, the Go
host tools (protoc-gen-validate, protoc plugins) failed to link:

  ld.lld: error: undefined symbol: __res_search
  >>> did you mean: __res_search@GLIBC_2.17

Go's cgo net resolver references the unversioned __res_search, but glibc
2.34+ demoted it to a non-default compat symbol (the public default is now
res_search@@GLIBC_2.34), so lld cannot bind the unversioned reference.
These codegen tools need no cgo; --@io_bazel_rules_go//go/config:pure
drops the glibc resolver dependency entirely.

Follows the CMAKE_POLICY_VERSION_MINIMUM=3.5 fix (libevent) and the
clang.cfg glibc targeting; minilua, libevent and nghttp2 now build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Once clang.cfg points host tools at the pkgx glibc bottle, the pkgx
ld-linux becomes their PT_INTERP and it does not fall back to the system
/lib. A freshly built host tool (rules_rust's process_wrapper) then died:

  process_wrapper: error while loading shared libraries:
    libgcc_s.so.1: cannot open shared object file

The whole libc closure must come from pkgx. gnu.org/gcc/libstdcxx ships
libgcc_s.so.1 and gnu.org/gcc ships libatomic.so.1, both in lib/, which
pkgx adds to the build LD_LIBRARY_PATH forwarded into the bazel actions.

Follows the pure-Go (__res_search) and CMAKE_POLICY_VERSION_MINIMUM=3.5
(libevent) fixes; minilua, libevent, nghttp2 and the Go tools now build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The rules_rust proc-macro build failed with E0463 (can't find crate for
thiserror_impl): rustc loads the proc-macro dylib, whose NEEDED libc.so.6 was
resolving to the pkgx glibc 2.44 on our forwarded LD_LIBRARY_PATH instead of
the libc the rust toolchain expects, so the dylib failed to load.

Keep forwarding LD_LIBRARY_PATH for the pkgx tool libs (cmake→libcurl,
process_wrapper→libgcc_s) but filter out the gnu.org/glibc lib dir: the pkgx
loader still finds libc next to itself by default, so host tools are
unaffected, while rust proc-macro dylibs get the correct libc.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
rules_rust proc-macro dylibs failed to load (E0463) because our forwarded
LD_LIBRARY_PATH (needed for process_wrapper's pkgx libgcc_s) shadows the rust
libstd path. rules_rust already computes RPATHs; --@rules_rust//rust/settings:
experimental_use_cc_common_link=1 routes rust binary linking through bazel's
cc_common (our clang toolchain), baking RPATHs into process_wrapper and the
proc-macro dylibs so libstd/libgcc_s resolve by rpath regardless of
LD_LIBRARY_PATH.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Root fix for the rust proc-macro E0463 (and it avoids the cc_common_link
allocator-ABI wall): envoy pins rust 1.88.0 and rules_rust downloads it, but
that toolchain's libstd lives under bazel-out — unreachable from the
LD_LIBRARY_PATH we must forward for process_wrapper's libgcc_s — so rustc can't
load proc-macro dylibs. pkgx has rust 1.88.0 exactly; use its bottle as the
toolchain (register a rust_toolchain over it in the WORKSPACE, prefer it via
--extra_toolchains) and add its lib/rustlib/<triple>/lib to the forwarded
LD_LIBRARY_PATH. Then one path satisfies both proc-macro libstd and
process_wrapper libgcc_s, with no version drift (1.88.0 == envoy's pin) and no
cc_common_link. Reverts the cc_common_link flag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Forward BOTH pkgx rust lib dirs to bazel's env-cleared actions instead of
assuming the dep seeds rust/lib onto LD_LIBRARY_PATH:
  lib/                -> librustc_driver-*.so (rustc NEEDED, no RUNPATH)
  lib/rustlib/<t>/lib -> libstd-*.so (rustc + the proc-macro dylibs it loads)

Validated end-to-end on real x86_64 hardware (cfarm) with rules_rust: a
proc_macro crate + consumer compiles and runs under this exact rust_toolchain
+ --extra_toolchains + --action_env=LD_LIBRARY_PATH config, reproducing and
clearing the E0463 'can't find crate for proc_macro' wall outside CI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…roc-macro E0463)

Root cause of the remaining rules_rust E0463 (confirmed from the nix64 CI log):
a glibc-version SKEW. envoy's clang.cfg links every exec-config output —
including the proc-macro dylibs rustc dlopens at compile time — against the
pkgx glibc 2.44 bottle (needed so foreign_cc host tools get GLIBC_2.29+ on the
old CI base). But the pkgx rustc ran on its standard PT_INTERP = the old base
glibc, so dlopen'ing a proc-macro that references GLIBC_2.29+ symbols failed
against the loaded old libc -> E0463 'can't find crate for <proc-macro>'.

Fix: drive rustc through a wrapper that re-execs the real rustc via the pkgx
glibc 2.44 loader (ld-linux --library-path). glibc is backward-compatible, so
rustc (needs only old symbols) runs fine on 2.44, and it now shares one modern
libc with the proc-macros it loads -> dlopen succeeds. rustc comes from a tiny
second new_local_repository holding the wrapper (pkgx_rust stays read-only over
the bottle; the wrapper filegroup is named distinctly from its rustc.sh source
to avoid a self-edge cycle).

Validated end-to-end on real x86_64 hardware (cfarm13): rules_rust drives a
wrapper rustc that re-execs via an explicit loader, and a proc_macro crate +
consumer then compile and run.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant