From 7389d2600791bbf80633f024da15b90f6a4e8361 Mon Sep 17 00:00:00 2001 From: Dimitris Karakasilis Date: Sat, 15 Aug 2026 21:10:45 +0300 Subject: [PATCH] build: make the tree compile on gcc 16, and add a CI lane that keeps it that way Five files call ::getpid() without including and compiled only because an older libstdc++ pulled the header in transitively. gcc 16 does not, so they fail. One of them is src/vllm/entrypoints/openai/server_main.cpp, i.e. a SHIPPED binary that does not build on a current distro. This is the second time this exact break has landed. The first three files were fixed after a gfx1151 report on #41; the pattern came back in five more, because every Linux CI lane installs the distro g++ (gcc 13 on ubuntu-latest) and no lane uses anything newer. A point fix does not hold, so this adds the missing coverage rather than only the includes: * build-newest-gcc: a COMPILE-ONLY lane in the gcc:16 container, tests configured ON so the test tree is compiled too. It deliberately does not run ctest -- build-test-cpu already owns execution, and this lane exists to catch compile-time portability for roughly one extra build per PR. * cmake/CompilerWarnings.cmake: on gcc >= 16 only, -Warray-bounds is reported but no longer fatal. gcc 16 emits it inside libstdc++ and vendored nlohmann for correct code, and no change to the calling code avoids it: after inlining, _Sp_counted_base::_M_release() is identical for every shared_ptr type, so GCC attributes one instantiation's destructor to another's allocation size. libstdc++ carries its own #pragma suppressions around that destructor; upstream is GCC PR tree-optimization/122197. gcc <= 15 is unchanged and still fails the build on a real out-of-bounds. * docs/USAGE.md: a Host compilers section stating which compilers build the tree and what the gcc 16 warning policy is. Required by check-doc-checkpoint, which classifies src/vllm/entrypoints/ as a user-facing surface and has no bypass by design. Verified on gcc 16.1.1 (Arch): full CPU configure + build with tests ON, no command-line workaround, 0 errors, and build-gcc16/examples/vllm-server runs (`vllm.cpp 0.0.3 c-abi=20`). check-doc-checkpoint, check-public-doc-tables, check-readme-structure and check-env-doc all pass. The workflow file itself is NOT verified -- there is no way to execute a GitHub Actions lane locally, so this PR's own CI is its first run. FOLLOWING_AGENTS_PROTOCOL Assisted-by: Claude Code:claude-opus-5 [ClaudeCode] Signed-off-by: Dimitris Karakasilis --- .github/workflows/ci.yml | 40 +++++++++++++++++++ cmake/CompilerWarnings.cmake | 27 ++++++++++++- docs/USAGE.md | 16 ++++++++ src/vllm/entrypoints/openai/server_main.cpp | 1 + .../models/test_indextts2_s2mel_loader.cpp | 1 + .../models/test_indextts2_talker_loader.cpp | 1 + tests/vllm/models/test_ltx2_text_encoder.cpp | 1 + .../models/test_minimax_music3_loader.cpp | 1 + 8 files changed, 87 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5bfd93f70..23b69b019 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -892,6 +892,46 @@ jobs: echo "Running test_ops_matmul_elem with VT_CPU_MATMUL_TIER=${tier}" VT_CPU_MATMUL_TIER="${tier}" build/tests/test_ops_matmul_elem done + build-newest-gcc: + # COMPILE-ONLY coverage on a compiler NEWER than any other lane's. Every + # other Linux lane installs the distro `g++`, which on ubuntu-latest is + # gcc 13, so a header that only compiles because of a TRANSITIVE include + # goes green here and red on a current distro. That is not hypothetical: + # ::getpid without was fixed once and came back in five more + # files, one of them src/vllm/entrypoints/openai/server_main.cpp — a + # SHIPPED binary that does not build on gcc 16 (reported on issue #41). + # + # Deliberately does NOT run ctest: this lane exists to catch compile-time + # portability, and build-test-cpu already owns execution. Keeping it to a + # build is roughly one extra compile per PR. + concurrency: + group: ci-build-newest-gcc-${{ github.event_name }}-${{ github.ref }}-${{ github.repository }} + cancel-in-progress: ${{ github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' }} + if: github.event.action != 'closed' + runs-on: ubuntu-latest + timeout-minutes: 90 + container: gcc:16 + steps: + - name: Install build tools + # The gcc image ships the toolchain only; git is needed BEFORE checkout + # so actions/checkout uses git rather than the slower tarball path. + run: | + apt-get update + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + ca-certificates cmake git ninja-build python3 + rm -rf /var/lib/apt/lists/* + - uses: actions/checkout@v4 + - name: Report the compiler this lane is actually pinning + run: g++ --version + - name: Configure + run: | + cmake -S . -B build-newest-gcc -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DVLLM_CPP_BUILD_TESTS=ON + - name: Build + # Same bounded parallelism as build-test-cpu: a bare -j OOM-kills the + # runner during the parallel link of the test executables. + run: cmake --build build-newest-gcc -j 2 build-test-cpu-arm64: # Independent Arm execution evidence: the x86 lane cannot prove HWCAP # dispatch, Arm instructions, or the host ABI. The native runner exercises diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake index 6a56933f6..0c7918306 100644 --- a/cmake/CompilerWarnings.cmake +++ b/cmake/CompilerWarnings.cmake @@ -15,12 +15,37 @@ function(vllm_cpp_set_warnings target) if(NOT VLLM_CPP_SANITIZE STREQUAL "OFF") set(_vllm_cpp_werror "") endif() + + # GCC >= 16 reports -Warray-bounds inside LIBSTDC++ and the vendored nlohmann + # json for code that is correct, so the diagnostic stays VISIBLE but stops + # being fatal on those compilers only. Everything <= 15 is unchanged and still + # fails the build on a real out-of-bounds. + # + # It is the same false-positive class this file already documents above for + # the sanitizer lanes, and it is not something the calling code can avoid: + # `_Sp_counted_base::_M_release()` is identical machine code for every + # shared_ptr type, so after inlining GCC attributes ONE instantiation's + # destructor to ANOTHER instantiation's allocation size. On gcc 16.1.1 that + # presents as "array subscript 'std::mutex[0]' is partly outside array bounds + # of 'unsigned char [32]'" pointing at a json.dump() call, in a translation + # unit that contains no shared_ptr at all. + # + # libstdc++ carries its own `#pragma GCC diagnostic` suppressions around that + # very destructor (bits/shared_ptr_base.h), i.e. the standard library treats + # this as a warning to silence rather than a bug to fix in user code. Upstream + # is GCC PR tree-optimization/122197; Eigen, assimp and CMSSW all disable the + # check the same way on the affected releases. + set(_vllm_cpp_array_bounds "") + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND + CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16) + set(_vllm_cpp_array_bounds -Wno-error=array-bounds) + endif() if(MSVC) target_compile_options(${target} PRIVATE $<$:/W4 /WX>) else() target_compile_options(${target} PRIVATE - $<$:-Wall -Wextra ${_vllm_cpp_werror}> + $<$:-Wall -Wextra ${_vllm_cpp_werror} ${_vllm_cpp_array_bounds}> # OBJCXX (.mm — the Metal backend) is a SEPARATE COMPILE_LANGUAGE from CXX, # so the CXX genex above does not reach it. Without this line the Metal TUs # would be the only unwarned code in the tree (BACKEND-METAL-MLX W0). diff --git a/docs/USAGE.md b/docs/USAGE.md index 0772f1eb0..cc5860427 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -22,6 +22,22 @@ example targets are named after the directories they are built from, so an in-source build makes the linker write each executable over its own source directory (issue #85). +### Host compilers + +gcc 13 and 14 and clang are exercised by CI, and **gcc 16 builds the tree, +including the OpenAI server**. Before this it did not: several files, one of +them the server's own `main`, called `getpid()` without including `` +and compiled only because an older libstdc++ happened to pull that header in +for them. A compile-only CI lane on the newest released gcc now guards this, +because every other Linux lane uses the distro compiler and cannot see it. + +On gcc 16 the `array-bounds` warning is reported but is **not** treated as an +error, unlike on every earlier gcc. That release emits it inside libstdc++ and +the vendored JSON library for code that is correct, and no change to the +calling code avoids it (`cmake/CompilerWarnings.cmake` explains the mechanism +and cites the upstream gcc bug). A genuine out-of-bounds still fails the build +on gcc 15 and earlier, which is what the rest of CI enforces. + ### Setting the compiled build identity `vllm-server --version` reports the CMake project version by default. Release diff --git a/src/vllm/entrypoints/openai/server_main.cpp b/src/vllm/entrypoints/openai/server_main.cpp index 552a843fd..d22bb074d 100644 --- a/src/vllm/entrypoints/openai/server_main.cpp +++ b/src/vllm/entrypoints/openai/server_main.cpp @@ -29,6 +29,7 @@ // tests/vllm/entrypoints/openai/test_api_server.cpp). The wiring below is the // same either way. #include +#include #include #include #include diff --git a/tests/vllm/models/test_indextts2_s2mel_loader.cpp b/tests/vllm/models/test_indextts2_s2mel_loader.cpp index 43ec72a4d..0d3901133 100644 --- a/tests/vllm/models/test_indextts2_s2mel_loader.cpp +++ b/tests/vllm/models/test_indextts2_s2mel_loader.cpp @@ -6,6 +6,7 @@ // skipped otherwise -- skipped LOUDLY, so "the real checkpoint was never // checked" cannot read as "the real checkpoint passed". #include +#include #include #include #include diff --git a/tests/vllm/models/test_indextts2_talker_loader.cpp b/tests/vllm/models/test_indextts2_talker_loader.cpp index e8920c124..9d16a382f 100644 --- a/tests/vllm/models/test_indextts2_talker_loader.cpp +++ b/tests/vllm/models/test_indextts2_talker_loader.cpp @@ -3,6 +3,7 @@ // The real-checkpoint cases run when VLLM_CPP_INDEXTTS2_GPT points at the // converted gpt.safetensors, and skip LOUDLY otherwise. #include +#include #include #include #include diff --git a/tests/vllm/models/test_ltx2_text_encoder.cpp b/tests/vllm/models/test_ltx2_text_encoder.cpp index b36f0b0f4..9234f5511 100644 --- a/tests/vllm/models/test_ltx2_text_encoder.cpp +++ b/tests/vllm/models/test_ltx2_text_encoder.cpp @@ -24,6 +24,7 @@ // a 1.19e-5 ABSOLUTE floor under any epsilon, which would let a tight tolerance // silently accept anything (including zero). #include +#include #include #include #include diff --git a/tests/vllm/models/test_minimax_music3_loader.cpp b/tests/vllm/models/test_minimax_music3_loader.cpp index 847ebca41..f033e98f0 100644 --- a/tests/vllm/models/test_minimax_music3_loader.cpp +++ b/tests/vllm/models/test_minimax_music3_loader.cpp @@ -24,6 +24,7 @@ // number against a reference implementation, and nothing below should be read // as having done so. #include +#include #include #include #include