[libcxx-commits] [libcxx] Restrategize compiler installation in libc++ builders. (PR #95706)

via libcxx-commits libcxx-commits at lists.llvm.org
Sun Jun 16 06:57:35 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Eric (EricWF)

<details>
<summary>Changes</summary>

This patch changes how we install compilers and tools in the libc++
builders. Instead of using apt, we now use separate tool images
containing one tool per image; copying the tool from the tool image
into the builder image directly.

The tool images are created using compiler-explorer-infra, though
this is largely a convience. The important aspect is that each
tool is installed under a different prefix inside the tool image,
meaning each tool is independent and doesn't conflict or clobber
other installations.

This change has passed a few breathing tests, but I'll canary
new generated images today.


---
Full diff: https://github.com/llvm/llvm-project/pull/95706.diff


2 Files Affected:

- (modified) libcxx/utils/ci/Dockerfile (+53-53) 
- (added) libcxx/utils/ci/Dockerfile.tools (+115) 


``````````diff
diff --git a/libcxx/utils/ci/Dockerfile b/libcxx/utils/ci/Dockerfile
index 54dd0f1186880..0f62026625402 100644
--- a/libcxx/utils/ci/Dockerfile
+++ b/libcxx/utils/ci/Dockerfile
@@ -48,14 +48,6 @@ FROM $BASE_IMAGE AS builder-base
 # 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 GCC_LATEST_VERSION
-ENV GCC_LATEST_VERSION=${GCC_LATEST_VERSION}
-
-# populated in the docker-compose file
-ARG LLVM_HEAD_VERSION
-ENV LLVM_HEAD_VERSION=${LLVM_HEAD_VERSION}
-
 # HACK: The github actions runner image already has sudo and requires its use. The buildkite base image does not.
 # Reconcile this.
 RUN <<EOF
@@ -73,6 +65,7 @@ RUN sudo apt-get update \
 RUN sudo apt-get update \
     && sudo apt-get install -y \
         bash \
+        build-essential \
         ccache \
         curl \
         gdb \
@@ -101,16 +94,6 @@ RUN sudo apt-get update \
     && sudo rm -rf /var/lib/apt/lists/*
 
 
-# Install various tools used by the build or the test suite
-#RUN apt-get update && apt-get install -y ninja-build python3 python3-distutils python3-psutil git gdb ccache
-# TODO add ninja-build once 1.11 is available in Ubuntu, also remove the manual installation.
-RUN <<EOF
-  wget -qO /tmp/ninja.gz https://github.com/ninja-build/ninja/releases/latest/download/ninja-linux.zip
-  gunzip /tmp/ninja.gz
-  chmod a+x /tmp/ninja
-  sudo mv /tmp/ninja /usr/local/bin/ninja
-EOF
-
 
 # These two locales are not enabled by default so generate them
 RUN <<EOF
@@ -120,43 +103,60 @@ RUN <<EOF
   sudo locale-gen
 EOF
 
-# Install Clang <latest>, <latest-1> and ToT, which are the ones we support.
-# We also install <latest-2> because we need to support the "latest-1" of the
-# current LLVM release branch, which is effectively the <latest-2> of the
-# tip-of-trunk LLVM. For example, after branching LLVM 14 but before branching
-# LLVM 15, we still need to have Clang 12 in this Docker image because the LLVM
-# 14 release branch CI uses it. The tip-of-trunk CI will never use Clang 12,
-# though.
-RUN <<EOF
-  sudo apt-get update
-  wget https://apt.llvm.org/llvm.sh -O /tmp/llvm.sh
-  chmod +x /tmp/llvm.sh
-  sudo /tmp/llvm.sh $(($LLVM_HEAD_VERSION - 3)) all  # for CI transitions
-  sudo /tmp/llvm.sh $(($LLVM_HEAD_VERSION - 2)) all  # previous release
-  sudo /tmp/llvm.sh $(($LLVM_HEAD_VERSION - 1)) all  # latest release
-  sudo /tmp/llvm.sh $LLVM_HEAD_VERSION          all  # current ToT
-  sudo apt-get install -y libomp5-$LLVM_HEAD_VERSION
-  sudo rm -rf /var/lib/apt/lists/*
-EOF
+# See Dockerfile.tools for information on how to produce the tool images.
+RUN sudo mkdir /opt/libcxx-infra && sudo chown -R $(whoami):$(whoami) /opt/libcxx-infra
+COPY --from=ghcr.io/libcxx/tools:cmake-3.27.9 /opt/libcxx-infra/cmake-v3.27.9 /opt/libcxx-infra/cmake-3.27.9
+COPY --from=ghcr.io/libcxx/tools:ninja-1.11.1 /opt/libcxx-infra/ninja-v1.11.1 /opt/libcxx-infra/ninja-1.11.1
 
-# Install the most recent GCC, like clang install the previous version as a transition.
-RUN <<EOF
-  sudo add-apt-repository ppa:ubuntu-toolchain-r/test
-  sudo apt-get update
-  sudo apt-get install -y \
-    gcc-$((GCC_LATEST_VERSION - 1)) \
-    g++-$((GCC_LATEST_VERSION - 1)) \
-    gcc-$GCC_LATEST_VERSION \
-    g++-$GCC_LATEST_VERSION
-  sudo rm -rf /var/lib/apt/lists/*
-EOF
+# Install the GCC versions
+COPY --from=ghcr.io/libcxx/tools:gcc-13.3.0 /opt/libcxx-infra/gcc-13.3.0 /opt/libcxx-infra/gcc-13.3.0
+COPY --from=ghcr.io/libcxx/tools:gcc-14.1.0 /opt/libcxx-infra/gcc-14.1.0 /opt/libcxx-infra/gcc-14.1.0
 
-RUN <<EOF
-    # Install a recent CMake
-    wget https://github.com/Kitware/CMake/releases/download/v3.21.1/cmake-3.21.1-linux-x86_64.sh -O /tmp/install-cmake.sh
-    sudo bash /tmp/install-cmake.sh --prefix=/usr --exclude-subdir --skip-license
-    rm /tmp/install-cmake.sh
-EOF
+COPY --from=ghcr.io/libcxx/tools:clang-16.0.0 /opt/libcxx-infra/clang-16.0.0 /opt/libcxx-infra/clang-16.0.0
+COPY --from=ghcr.io/libcxx/tools:clang-17.0.1 /opt/libcxx-infra/clang-17.0.1 /opt/libcxx-infra/clang-17.0.1
+COPY --from=ghcr.io/libcxx/tools:clang-18.1.0 /opt/libcxx-infra/clang-18.1.0 /opt/libcxx-infra/clang-18.1.0
+COPY --from=ghcr.io/libcxx/tools:clang-trunk-20240615 /opt/libcxx-infra/clang-trunk-20240615 /opt/libcxx-infra/clang-trunk
+
+# Create /opt/libcxx-infra/bin/ to store the executables we want to use/test against for both the tools (ninja/cmake)
+# and the compilers (clang/gcc). The compilers are symlinked with a name that includes the major version.
+#
+# The binaries that are symlinked are:
+#  - ninja
+#  - cmake
+#  - clang-<version>
+#  - clang++-<version>
+#  - gcc-<version>
+#  - g++-<version>
+#  - llvm-symbolizer-<version> (likely only the latest clang version)
+RUN mkdir /opt/libcxx-infra/bin/ \
+    && ln -s /opt/libcxx-infra/ninja-1.11.1/ninja /opt/libcxx-infra/bin/ninja \
+    && ln -s /opt/libcxx-infra/cmake-3.27.9/bin/cmake /opt/libcxx-infra/bin/cmake \
+    && ln -s /opt/libcxx-infra/clang-16.0.0/bin/clang /opt/libcxx-infra/bin/clang-16 \
+    && ln -s /opt/libcxx-infra/clang-16.0.0/bin/clang++ /opt/libcxx-infra/bin/clang++-16 \
+    && ln -s /opt/libcxx-infra/clang-17.0.1/bin/clang /opt/libcxx-infra/bin/clang-17 \
+    && ln -s /opt/libcxx-infra/clang-17.0.1/bin/clang++ /opt/libcxx-infra/bin/clang++-17 \
+    && ln -s /opt/libcxx-infra/clang-18.1.0/bin/clang /opt/libcxx-infra/bin/clang-18 \
+    && ln -s /opt/libcxx-infra/clang-18.1.0/bin/clang++ /opt/libcxx-infra/bin/clang++-18 \
+    && ln -s /opt/libcxx-infra/clang-trunk/bin/clang /opt/libcxx-infra/bin/clang-19 \
+    && ln -s /opt/libcxx-infra/clang-trunk/bin/clang++ /opt/libcxx-infra/bin/clang++-19 \
+    && ln -s /opt/libcxx-infra/clang-trunk/bin/llvm-symbolizer /opt/libcxx-infra/bin/llvm-symbolizer-19 \
+    && ln -s /opt/libcxx-infra/gcc-13.3.0/bin/gcc /opt/libcxx-infra/bin/gcc-13 \
+    && ln -s /opt/libcxx-infra/gcc-13.3.0/bin/g++ /opt/libcxx-infra/bin/g++-13 \
+    && ln -s /opt/libcxx-infra/gcc-14.1.0/bin/gcc /opt/libcxx-infra/bin/gcc-14 \
+    && ln -s /opt/libcxx-infra/gcc-14.1.0/bin/g++ /opt/libcxx-infra/bin/g++-14
+
+
+ENV PATH="/opt/libcxx-infra/bin:${PATH}"
+
+RUN echo "testing Ninja" && ninja --version \
+    && echo "testing CMake" && cmake --version \
+    && echo "testing Clang 16" && clang-16 --version \
+    && echo "testing Clang 17" && clang-17 --version \
+    && echo "testing Clang 18" && clang-18 --version \
+    && echo "testing Clang 19" && clang-19 --version \
+    && echo "testing LLVM symbolizer 19" && llvm-symbolizer-19 --version \
+    && echo "testing GCC 13" && gcc-13 --version \
+    && echo "testing GCC 14" && gcc-14 --version
 
 # ===----------------------------------------------------------------------===##
 #                       Android Buildkite Image
diff --git a/libcxx/utils/ci/Dockerfile.tools b/libcxx/utils/ci/Dockerfile.tools
new file mode 100644
index 0000000000000..fc3cf84103f36
--- /dev/null
+++ b/libcxx/utils/ci/Dockerfile.tools
@@ -0,0 +1,115 @@
+#===----------------------------------------------------------------------===##
+#
+# 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 image is used to create the ghcr.io/tools:<tool:version> packages consumed by the libc++ builders.
+# Each image contains a single tool, and is created by installing the tool from Compiler Explorer's infra repository
+# into /opt/libcxx-infra/<tool>-<version>.
+#
+# The image is then copied into the final image libc++ builder image.
+#
+# This allows us to install tools independently of APT, and allows us to version the tools using docker tags, avoiding
+# issues with nightly builds polluting the other packages installed via apt.
+#
+# See https://github.com/compiler-explorer/infra for more information on the tools available.
+#
+# To create a new tool image using this Dockerfile, you need to set the following build arguments:
+# - TOOL_ID: The ID of the tool to install. This is the name of the tool as it appears in the list of tools available
+#            in the infra repository.
+#            Some examples of tool id's are:
+#            - compilers/c++/clang 16.0.0
+#            - compilers/c++/clang trunk (the nightly)
+#            - compilers/c++/x86/gcc 13.0.0
+#            - tools/ninja 1.11.1
+#            - tools/cmake 3.22.0
+# - NIGHTLY: Whether to install the nightly version of the tool. This is a boolean value, and must be either 'true' or
+#            'false'. Must be set to 'true' to install the nightly version of the tool.
+#
+# Example usage:
+#   docker build \
+#       --build-arg 'TOOL_ID=compilers/c++/clang trunk' \
+#       --build-arg NIGHTLY=true \
+#       -t ghcr.io/libcxx/tools:clang-trunk-YYYYMMDD \
+#       -f Dockerfile.tools .
+
+# Images built from nightly tools should be tagged with the suffix -YYYYMMDD, where YYYYMMDD is the date of the nightly
+# See the build-tool-image.yaml workflow in github.com/libcxx/builders
+FROM ubuntu:jammy-20240530 AS tool-installer
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+    bash \
+    curl \
+    git \
+    make \
+    python3 \
+    python3-venv \
+    python3-pip \
+    uuid-dev \
+    wget \
+    unzip \
+    xz-utils \
+    && rm -rf /var/lib/apt/lists/*
+
+RUN git clone --depth=1 https://github.com/compiler-explorer/infra.git infra \
+    && cd infra/ \
+    && rm -rf .git \
+    && python3 -m venv .venv \
+    && . ./.venv/bin/activate \
+    && make ce \
+    && ./bin/ce_install list
+
+
+COPY <<EOF /usr/bin/installer
+#!/usr/bin/env bash
+set -ex
+set -o pipefail
+
+
+ARGS=()
+
+. /infra/.venv/bin/activate
+
+mkdir /tmp/staging
+mkdir /opt/libcxx-infra
+
+if [[ "\$NIGHTLY" == "true" ]]; then
+    ARGS+=("--enable" "nightly")
+elif [[ "\$NIGHTLY" == "false" ]]; then
+    echo "Not nightly"
+else
+    echo "NIGHTLY must be either 'true' or 'false'"
+    exit 1
+fi
+
+if [[ -z "\$TOOL_ID" ]]; then
+    echo "TOOL_ID must be set"
+    exit 1
+fi
+
+/infra/bin/ce_install --staging-dir /tmp/staging --dest /opt/libcxx-infra "\${ARGS[@]}" install "\$TOOL_ID"
+
+rm -rf /tmp/staging
+EOF
+
+RUN chmod +x /usr/bin/installer
+
+FROM tool-installer AS install-tool
+
+ARG TOOL_ID
+ENV TOOL_ID=${TOOL_ID}
+
+ARG NIGHTLY=false
+ENV NIGHTLY=${NIGHTLY}
+
+
+RUN /usr/bin/installer
+
+# Use alpine as the base for the minimal final image. The image should only contain the tool, and will be copied into
+# other images that will eventually use it.
+FROM alpine AS installed-tool
+
+COPY --from=install-tool /opt/libcxx-infra /opt/libcxx-infra

``````````

</details>


https://github.com/llvm/llvm-project/pull/95706


More information about the libcxx-commits mailing list