Skip to content

LLM-generated hermetic llvm#3045

Open
AlexanderViand wants to merge 16 commits into
google:mainfrom
AlexanderViand:use-hermetic-llvm
Open

LLM-generated hermetic llvm#3045
AlexanderViand wants to merge 16 commits into
google:mainfrom
AlexanderViand:use-hermetic-llvm

Conversation

@AlexanderViand

Copy link
Copy Markdown
Collaborator

No description provided.

The llvm 0.7.8 module defines its cc_toolchain/toolchain() rules under
@llvm//toolchain, not the root package. register_toolchains("@llvm//:all")
therefore matched zero toolchains, so builds silently fell back to the
autodetected host clang. Point the registration at @llvm//toolchain:all.
LLVM's llvm:Support pulls zlib/zstd headers via @llvm-project//third-party
cc_library_wrapper targets that propagate the includes field (-I) but not
system_includes (-isystem). zstd uses strip_include_prefix='lib' (propagating
-I); zlib-ng uses strip_include_prefix='.' (a no-op), so zlib.h only reached
the -iquote path. On a normal host '#include <zlib.h>' resolved via
/usr/include; under the hermetic clang toolchain (no system include dirs) it
failed with: 'zlib.h' file not found with <angled> include.

Add a HEIR-local zlib-ng.BUILD that relocates zlib.h/zconf.h into include/
with strip_include_prefix='include' (mirroring zstd) and point @llvm_zlib at
it so a propagating -I reaches llvm:Support.
fmt 11.1.3's include/fmt/format.h uses the unqualified C functions
malloc/free in detail::allocator but only includes C++ headers. The file
defines _LIBCPP_REMOVE_TRANSITIVE_INCLUDES, so libc++ strips the
transitive includes that would otherwise declare malloc/free. Under
HEIR's hermetic clang+libc++ toolchain this leaves them undeclared and
breaks the build of fmt (pulled in transitively via SCIP/SoPlex).

Pin fmt as a direct bazel_dep and apply a single_version_override patch
that backports the upstream fix (explicit #include <stdlib.h>). Drop the
override once HEIR moves to an fmt release containing the fix.
bison vendors gnulib, whose generated replacement headers (lib/stdio.h /
lib/stdio-safer.h) leave fopen_safer & friends undeclared under HEIR's
hermetic clang+libc++ toolchain (explicit -isystem search), failing with
'expected function body after function declarator'. Pin bison via
single_version_override and apply patches/bison.patch so it builds.
rustc's default link args for x86_64-unknown-linux-gnu unconditionally
inject -lgcc_s for unwinding, but the bootstrapped LLVM toolchain ships
compiler-rt + libunwind and has no libgcc_s, so every Rust link (starting
with rules_rust's process_wrapper) fails with 'unable to find library
-lgcc_s'. Enable the toolchain's documented escape hatch
--@llvm//config:experimental_stub_libgcc_s=True (Linux only) which provides
a stub libgcc_s to satisfy the flag while still linking libunwind statically.
…hain

The bootstrapped clang distribution ships no OpenMP runtime / omp.h, so OpenFHE's
'#include <omp.h>' + -fopenmp -lomp (enabled by @openfhe//:enable_openmp, default
True) could not be satisfied. Build libomp from the pinned LLVM openmp sources
(@openmp//:libomp), expose its omp.h, and patch OpenFHE to link it instead of a
nonexistent system libomp -- so the hermetic build keeps OpenMP enabled.
The Python frontend's OpenFHE backend JIT-compiles the emitted C++ into a
.so at runtime. Under the hermetic LLVM toolchain, @openfhe//:libopenfhe is
built against libc++, so its exported symbols use libc++'s std::__1::...
mangling and the library statically embeds (and weakly re-exports) libc++.
The JIT previously used the host compiler with no -stdlib pin, which on Linux
defaults to libstdc++ (std::...). The mismatched mangling left the OpenFHE
symbols unresolved -> "undefined symbol" ImportError at module load.

Thread a stdlib-matching option through the JIT path:

- config.py (OpenFHEConfig): new optional cxx_compiler / extra_compiler_flags
  / extra_linker_search_paths / extra_link_libs fields, populated from new
  OPENFHE_CXX_* env vars (runfiles-resolved like the existing OPENFHE_* vars).
  Add _discover_hermetic_toolchain_clang(): when handed hermetic libc++
  headers but no explicit compiler, locate the toolchain's clang next to them
  (the host clang/g++ is too old to parse the toolchain's libc++ headers --
  "libc++ only supports Clang 20 and later").
- backend.py: use OpenFHEConfig.cxx_compiler for the JIT compiler and append
  the extra flags / search paths / libs to both compile invocations.
- testing.bzl: depend on the toolchain's libc++ / libc++abi -isystem header
  dirs and pass them plus -stdlib=libc++ -nostdinc++ to the JIT.
- MODULE.bazel: use_repo the llvm_source libcxx / libcxxabi repos so the
  frontend tests can reference their header search dirs.
The libc++/libc++abi -isystem dirs were passed via $(rootpath ...), which for a
cross-repo target yields a ../<repo>/... path; joined onto RUNFILES_DIR in
config.py it escaped the runfiles tree, so clang found no libc++ headers
(manifesting as '<initializer_list> file not found'). Use $(rlocationpath ...)
so it resolves to runfiles/<repo>/... NOTE: the raw-clang JIT still needs the
rest of the toolchain hermetic include set (clang builtins, glibc, kernel,
compiler-rt).
The prebuilt @openfhe//:libopenfhe is built by the hermetic LLVM
toolchain against libc++, so the runtime JIT step must compile the
emitted OpenFHE C++ against the same libc++ to match its std::__1
symbol mangling.

Hand the JIT the toolchain's libc++/libc++abi/glibc/kernel/builtin
include set plus -stdlib=libc++ -nostdinc++ --sysroot=/dev/null
-nostdlibinc so the libc++ headers parse with no host include leakage.
Those flags are compile-only: the link must use the host C runtime
(crt*.o, libc, libm, libgcc_s) and let libopenfhe.so supply the libc++
symbols at load, so --sysroot=/dev/null/-stdlib=libc++/-lc++ must not
reach the linker.

Split compile_to_shared_object into a -c compile (with the libc++
compile-only flags) and a separate -shared link (without them) whenever
compile_only_flags are supplied.
…rule, re-enable sandboxing, and gate hermetic config to linux
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