[libcxx] [llvm] [libc++][CI] Add hermetic Linux premerge builder (PR #226358)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 22:54:58 PDT 2026


https://github.com/zeroomega updated https://github.com/llvm/llvm-project/pull/226358

>From 1499a67389ca737651ca7ce71322eda1bc83ea37 Mon Sep 17 00:00:00 2001
From: Haowei Wu <haowei at google.com>
Date: Thu, 24 Sep 2026 22:53:36 -0700
Subject: [PATCH] [libc++][CI] Add hermetic Linux builder container and
 run-buildbot support

Add a hermetic Linux builder container image and run-buildbot flags so
libc++ can be built and tested with CMake, Ninja, and Clang installed
under /opt/hermetic outside of PATH, catching implicit dependencies on
host build tools or compilers in CMake or Lit test scripts (such as
#224192).

- Add libcxx/utils/ci/docker/linux-builder-hermetic.dockerfile based
  on ubuntu:26.04 with CMake, Ninja, and Compiler Explorer Clang
  ((LLVM_HEAD_VERSION - 1).1.0) installed under /opt/hermetic and no
  cmake/ninja/make/gcc/g++/clang in PATH.
- Register libcxx-linux-builder-hermetic in docker-compose.yml and
  .github/workflows/libcxx-build-containers.yml.
- Add --hermetic, --cmake, --ninja, --cc, and --cxx flags to
  libcxx/utils/ci/run-buildbot, unexporting CMAKE/NINJA/CC/CXX when
  --hermetic is set and passing CMAKE_C_COMPILER and CMAKE_CXX_COMPILER
  explicitly to CMake.

Assisted-by: Gemini
---
 .github/workflows/libcxx-build-containers.yml |   2 +-
 libcxx/utils/ci/docker/docker-compose.yml     |  10 ++
 .../docker/linux-builder-hermetic.dockerfile  | 102 ++++++++++++++++++
 libcxx/utils/ci/run-buildbot                  |  44 +++++++-
 4 files changed, 153 insertions(+), 5 deletions(-)
 create mode 100644 libcxx/utils/ci/docker/linux-builder-hermetic.dockerfile

diff --git a/.github/workflows/libcxx-build-containers.yml b/.github/workflows/libcxx-build-containers.yml
index 5f24cc54021ad..6cce2b239dc19 100644
--- a/.github/workflows/libcxx-build-containers.yml
+++ b/.github/workflows/libcxx-build-containers.yml
@@ -28,7 +28,7 @@ jobs:
     if: github.repository_owner == 'llvm'
     strategy:
       matrix:
-        image_name: ['libcxx-linux-builder', 'libcxx-android-builder']
+        image_name: ['libcxx-linux-builder', 'libcxx-linux-builder-hermetic', 'libcxx-android-builder']
     permissions:
       packages: write
 
diff --git a/libcxx/utils/ci/docker/docker-compose.yml b/libcxx/utils/ci/docker/docker-compose.yml
index 2070dcd96274c..e2280af3d6ab8 100644
--- a/libcxx/utils/ci/docker/docker-compose.yml
+++ b/libcxx/utils/ci/docker/docker-compose.yml
@@ -17,6 +17,16 @@ services:
         GCC_HEAD_VERSION: 17
         LLVM_HEAD_VERSION: 23
 
+  libcxx-linux-builder-hermetic:
+    image: ghcr.io/llvm/libcxx-linux-builder-hermetic:${TAG:-latest}
+    build:
+      context: ../../../.. # monorepo root
+      dockerfile: libcxx/utils/ci/docker/linux-builder-hermetic.dockerfile
+      args:
+        LLVM_HEAD_VERSION: 23
+        CMAKE_VERSION: 4.4.3
+        NINJA_VERSION: 1.13.2
+
   libcxx-android-builder:
     image: ghcr.io/llvm/libcxx-android-builder:${TAG:-latest}
     build:
diff --git a/libcxx/utils/ci/docker/linux-builder-hermetic.dockerfile b/libcxx/utils/ci/docker/linux-builder-hermetic.dockerfile
new file mode 100644
index 0000000000000..3cf1c15eb9431
--- /dev/null
+++ b/libcxx/utils/ci/docker/linux-builder-hermetic.dockerfile
@@ -0,0 +1,102 @@
+# ===----------------------------------------------------------------------===##
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+# ===----------------------------------------------------------------------===##
+#
+# This file defines the hermetic Linux builder image used for libc++ CI testing
+# where CMake, Ninja, and Clang/LLVM are placed under /opt/hermetic outside of
+# PATH, catching any implicit dependencies on host build tools or compilers.
+#
+# From the root of the monorepo, this image can be built with:
+#
+#   $ docker compose --file libcxx/utils/ci/docker/docker-compose.yml build libcxx-linux-builder-hermetic
+#
+
+FROM docker.io/library/ubuntu:26.04
+
+# Changing this file causes a rebuild of the image in a GitHub action.
+RUN echo "Last forced update executed on 2026-09-24."
+
+# Make sure apt-get doesn't try to prompt for stuff like our time zone, etc.
+ENV DEBIAN_FRONTEND=noninteractive
+
+# Populated in the docker-compose file
+ARG LLVM_HEAD_VERSION=23
+ENV LLVM_HEAD_VERSION=${LLVM_HEAD_VERSION}
+
+ARG CMAKE_VERSION=4.4.3
+ENV CMAKE_VERSION=${CMAKE_VERSION}
+
+ARG NINJA_VERSION=1.13.2
+ENV NINJA_VERSION=${NINJA_VERSION}
+
+# Install sudo and setup passwordless sudo.
+RUN apt-get update && \
+    apt-get install -y sudo && \
+    echo "ALL ALL = (ALL) NOPASSWD: ALL" | tee /etc/sudoers
+
+# Installing tzdata before other packages avoids the time zone prompts.
+RUN sudo apt-get update \
+    && sudo apt-get install -y \
+        tzdata
+
+# Install runtime/test utilities and the basic host C sysroot (libc6-dev, libgcc-15-dev).
+# Intentionally OMIT: build-essential, gcc, g++, clang, make, cmake, ninja-build.
+RUN sudo apt-get update \
+    && sudo apt-get install -y \
+        bash \
+        binutils \
+        bzip2 \
+        curl \
+        gdb \
+        git \
+        gpg \
+        language-pack-en \
+        language-pack-fr \
+        language-pack-ja \
+        language-pack-ru \
+        language-pack-zh-hans \
+        libc6-dev \
+        libgcc-15-dev \
+        libstdc++-15-dev \
+        lsb-release \
+        python3 \
+        python3-dev \
+        python3-packaging \
+        python3-psutil \
+        python3-setuptools \
+        python3-venv \
+        python3-yaml \
+        rsync \
+        unzip \
+        wget \
+        xz-utils \
+    && sudo rm -rf /var/lib/apt/lists/*
+
+# These two locales are not enabled by default so generate them
+RUN printf "fr_CA ISO-8859-1\ncs_CZ ISO-8859-2\n" | sudo tee -a /etc/locale.gen && \
+    sudo mkdir -p /usr/local/share/i1en/ && \
+    printf "fr_CA ISO-8859-1\ncs_CZ ISO-8859-2\n" | sudo tee -a /usr/local/share/i1en/SUPPORTED && \
+    sudo locale-gen
+
+# Fetch CMake and Ninja from official GitHub releases, and Clang from Compiler Explorer
+# (matching linux-builder.dockerfile's ce_install and LLVM_HEAD_VERSION), into /opt/hermetic
+# outside of PATH.
+RUN sudo mkdir -p /opt/hermetic/cmake /opt/hermetic/ninja && \
+    curl -fsSL "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-linux-x86_64.tar.gz" \
+      | sudo tar xzf - --strip-components=1 -C /opt/hermetic/cmake && \
+    curl -fsSL -o /tmp/ninja-linux.zip \
+      "https://github.com/ninja-build/ninja/releases/download/v${NINJA_VERSION}/ninja-linux.zip" && \
+    sudo unzip -q /tmp/ninja-linux.zip -d /opt/hermetic/ninja && \
+    sudo chmod +x /opt/hermetic/ninja/ninja && \
+    rm -f /tmp/ninja-linux.zip && \
+    sudo apt-get update && sudo apt-get install -y make && \
+    sudo git clone --depth 1 https://github.com/compiler-explorer/infra.git /tmp/ce-infra && \
+    (cd /tmp/ce-infra && sudo make ce) && \
+    sudo /tmp/ce-infra/bin/ce_install --dest /opt/hermetic install compilers/c++/clang $((LLVM_HEAD_VERSION - 1)).1.0 && \
+    sudo ln -sfn /opt/hermetic/clang-$((LLVM_HEAD_VERSION - 1)).1.0 /opt/hermetic/llvm && \
+    sudo rm -rf /tmp/ce-infra && \
+    sudo apt-get purge -y make && sudo apt-get autoremove -y && sudo rm -rf /var/lib/apt/lists/*
diff --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot
index 572f326c4fb0a..c90c2c0d4c393 100755
--- a/libcxx/utils/ci/run-buildbot
+++ b/libcxx/utils/ci/run-buildbot
@@ -28,6 +28,14 @@ ${PROGNAME} [options] <BUILDER>
 --build-dir <DIR>   The directory to use for building the library. By default,
                     this is '<llvm-root>/build/<builder>'.
 
+--cmake <PATH>      Path to the cmake binary to use.
+
+--ninja <PATH>      Path to the ninja binary to use.
+
+--cc <PATH>         Path to the C compiler to use.
+
+--cxx <PATH>        Path to the C++ compiler to use.
+
 Environment variables
 CMAKE               The cmake binary to use. This variable is optional.
 
@@ -89,6 +97,26 @@ while [[ $# -gt 0 ]]; do
             BUILD_DIR="${2}"
             shift; shift
             ;;
+        --cmake)
+            CMAKE="${2}"
+            shift; shift
+            ;;
+        --ninja)
+            NINJA="${2}"
+            shift; shift
+            ;;
+        --cc)
+            CC="${2}"
+            shift; shift
+            ;;
+        --cxx)
+            CXX="${2}"
+            shift; shift
+            ;;
+        --hermetic)
+            HERMETIC=true
+            shift
+            ;;
         *)
             BUILDER="${1}"
             shift
@@ -111,15 +139,19 @@ else
 fi
 
 if [ -z ${CC+x} ]; then
-    error "Environment variable CC must be defined"
+    error "Environment variable CC or --cc must be defined"
     exit 1
 fi
 
 if [ -z ${CXX+x} ]; then
-    error "Environment variable CXX must be defined"
+    error "Environment variable CXX or --cxx must be defined"
     exit 1
 fi
 
+if [ -n "${HERMETIC+x}" ]; then
+    export -n CMAKE NINJA CC CXX
+fi
+
 # Print the version of a few tools to aid diagnostics in some cases
 step "Diagnose tools in use"
 ${CMAKE} --version
@@ -135,8 +167,10 @@ function generate-cmake-base() {
     step "Generating CMake"
 
     # FIXME: This should really be set in the Dockerfile
-    export CMAKE_PREFIX_PATH="/opt/compiler-explorer/clang-trunk/lib/cmake"
-    export PATH="$PATH:/opt/compiler-explorer/clang-trunk/bin"
+    if [ -z "${HERMETIC+x}" ]; then
+        export CMAKE_PREFIX_PATH="/opt/compiler-explorer/clang-trunk/lib/cmake"
+        export PATH="$PATH:/opt/compiler-explorer/clang-trunk/bin"
+    fi
 
     # We can remove -DCMAKE_INSTALL_MESSAGE=NEVER once https://gitlab.kitware.com/cmake/cmake/-/issues/26085 is fixed.
     ${CMAKE} \
@@ -144,6 +178,8 @@ function generate-cmake-base() {
           -B "${BUILD_DIR}" \
           -GNinja \
           ${MAKE_PROGRAM} \
+          -DCMAKE_C_COMPILER="${CC}" \
+          -DCMAKE_CXX_COMPILER="${CXX}" \
           -DCMAKE_BUILD_TYPE=RelWithDebInfo \
           -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \
           -DLIBCXX_ENABLE_WERROR=YES \



More information about the llvm-commits mailing list