Skip to content

release-0.7: switch C++ toolchain to gcc-14#321

Open
vporoshok wants to merge 5 commits intorelease-0.7from
chore/release-0.7-gcc-14
Open

release-0.7: switch C++ toolchain to gcc-14#321
vporoshok wants to merge 5 commits intorelease-0.7from
chore/release-0.7-gcc-14

Conversation

@vporoshok
Copy link
Copy Markdown
Collaborator

Summary

The shared CI image ${DEV_REGISTRY}/prompp/ci-gcc-image:gcc-tools-${arch} is built only from the pp branch (see .github/workflows/build-ci-image.yaml) and now ships gcc-14 (debian-trixie). On release-0.7 the Bazel build still registered the g++-13 toolchain, whose builtin_include_directories pointed at /usr/lib/gcc/{x86_64,aarch64}-linux-gnu/13 — these no longer exist in the image. Linker flags also pulled libstdc++_libbacktrace.a, which gcc-14 has folded into libstdc++exp.a.

This brings release-0.7 in line with the new CI image by cherry-picking the toolchain-relevant pieces from pp:

  • b4f95e7af — full cherry-pick of e207bf7bc (PR Fix Bazel c++ toolchain #282 "fix toolchain"): replace -l:libstdc++.a with -lstdc++ (the explicit static-name flag is redundant under -static-libstdc++ and breaks on libstdc++-14 in some setups).
  • c29408fab — partial cherry-pick of 3df13958d (PR Gcc 14 clang tidy 21 #271 "Gcc 14 clang tidy 21"), restricted to the gcc-14 toolchain switch:
    • pp/MODULE.bazel: register cc_toolchain_for_g++-14_toolchain_{aarch64,x86_64} instead of the g++-13 ones.
    • pp/bazel/toolchain/BUILD: drop the now-unused g++-13 cc_toolchain_suite / cc_toolchain / toolchain / cc_toolchain_config entries (the g++-14 definitions were already present on this branch).
    • pp/bazel/toolchain/cc_toolchain_config.bzl: replace -lstdc++_libbacktrace with -lstdc++exp.
    • pp/scripts/test_coredump.sh: --config=g++-13--config=g++-14.

What is intentionally NOT picked from PR #271

PR #271 in pp is layered on top of PR #270 "GOST compile flags", which was never back-ported to release-0.7. The following parts of #271 are therefore left out:

  • Dockerfile.ci, all .github/workflows/* and the new cleanup_pr_images.yamlrelease-0.7 consumes the CI image built from pp, so no workflow changes are needed.
  • pp/.clang-tidy and the bulk of test/source updates that come with the clang-tidy 19 → 21 upgrade and the bugprone-* diagnostics — those depend on the GOST flags and stricter warnings introduced by GOST compile flags #270.
  • The gost_flags / clang_tidy plumbing in cc_toolchain_config.bzl and BUILD — same reason.

The 3-way merge on pp/bazel/toolchain/BUILD correctly dropped the clang_tidy = \":clang_tidy\" attribute that #271 added, because the cc_toolchain_config rule on release-0.7 does not declare it.

Test plan

  • cpp-tests workflow (matrix: OPT={dbg,opt}, SANITIZERS={no_sanitizers,with_sanitizers}, arch={amd64,arm64}) — confirms the C++ unit tests build and pass under gcc-14 with the new toolchain config.
  • build-go-bindings workflow (matrix: COMPILATION_MODE={dbg,opt}, ASAN={false,true}, arch={amd64,arm64}) — confirms cgo links cleanly with -lstdc++exp and without -l:libstdc++.a.
  • go-tests workflow — confirms downstream Go tests still pass with the relinked C++ artifact.
  • build_dev job (triggered automatically on PR) — confirms werf cpp-artifact (which uses the same toolkit image) still builds.

If any step fails with new -Werror warnings or a missing symbol that traces back to gost_flags / libstdc++exp, that is the signal to either back-port the relevant slice of #270 or revert a specific flag here.

Made with Cursor

vporoshok and others added 5 commits May 7, 2026 17:40
Cherry-picked from pp branch (e207bf7).

Required for the migration to gcc-14: -static-libstdc++ already drives
static linking of libstdc++, so the explicit -l:libstdc++.a is redundant
and breaks on debian-trixie / libstdc++-14 in some configurations.

Co-authored-by: Cursor <cursoragent@cursor.com>
Cherry-picked from PR #271 on the pp branch (3df1395,
"Gcc 14 clang tidy 21"), restricted to the toolchain registration parts.

The shared CI image (registry/prompp/ci-gcc-image:gcc-tools-${arch}) is built
only from the pp branch and now ships gcc-14 (debian-trixie). The release-0.7
build was still registering the g++-13 Bazel toolchain, whose
builtin_include_directories pointed at /usr/lib/gcc/{x86_64,aarch64}-linux-gnu/13
which no longer exist in the image; on top of that the linker was pulling
libstdc++_libbacktrace, which gcc-14 has folded into libstdc++exp.

This commit:
- registers cc_toolchain_for_g++-14_toolchain_{aarch64,x86_64} in
  pp/MODULE.bazel,
- drops the now-unused g++-13 cc_toolchain_suite / cc_toolchain / toolchain /
  cc_toolchain_config entries in pp/bazel/toolchain/BUILD,
- replaces -lstdc++_libbacktrace with -lstdc++exp in the default linker flags
  in pp/bazel/toolchain/cc_toolchain_config.bzl.

The clang-tidy / GOST-flag changes from PR #271 (which depend on PR #270
"GOST compile flags") are intentionally excluded because they were never
back-ported to release-0.7 and would pull in additional warnings that the
release branch has not been audited against.

Co-authored-by: Cursor <cursoragent@cursor.com>
Cherry-picked from PR #271 on the pp branch (file pp/third_party/patches/
quasis_crypto/0001-md5.hh.patch from 3df1395).

gcc-14 rejects the use of the built-in __is_trivially_copyable trait inside
a requires-clause ("error: use of built-in trait '__is_trivially_copyable'
in function signature; use library traits instead"). The updated patch:

- replaces __is_trivially_copyable(T) with std::is_trivially_copyable_v<T>
  in the requires-clauses of MD5::update overloads,
- adds the missing #pragma once and <bit>/<type_traits> includes,
- silences a -Wmaybe-uninitialized false positive around hasher.update().

Required to make pp/prometheus tests build under gcc-14.

Co-authored-by: Cursor <cursoragent@cursor.com>
Cherry-picked from PR #287 on the pp branch (c80d137)
for the production-code parts only.

GCC 14's libstdc++ uses sized-range fast paths in std::ranges::equal, which
breaks BareBones::GenericBitset because GenericBitset::size() returns the
allocated bit width, not ranges::distance(begin, end) (the set-bit count).
This caused runtime failures in pp/bare_bones/tests/bitset_tests.cpp
(BitsetFixture.random_access, BitsetConstructorsFixture.MoveConstructor /
MoveAssignment / MoveAssignmentNonEmpty) and in
pp/series_data/tests/querier/{instant_querier,querier}_tests.cpp where the
querier returns a Bitset that is then compared against an initializer_list.

Specialise std::ranges::disable_sized_range<GenericBitset<R>> = true to
restore element-wise comparison.

Also update pp/go/cppbridge/entrypoint.go cgo LDFLAGS:
  -lstdc++_libbacktrace      -> -lstdc++exp
  -l:libstdc++_libbacktrace.a -> -l:libstdc++exp.a
GCC 14 has folded libstdc++_libbacktrace into libstdc++exp; without this the
go-tests / build-go-bindings step fails to link.

Co-authored-by: Cursor <cursoragent@cursor.com>
set_const_labels was sorting label pointers with
  return a->name < b->name;
where a->name and b->name are const String*. This compares stack
addresses, not strings, so the resulting iteration order — and therefore
MetricDescriptor::id / dim_hash — depended on whatever order the local
String objects ended up at on the stack.

Under gcc-13 (and under gcc-14 on the pp branch with -fstack-protector-
strong from PR #270 GOST flags) the layout happened to match the
alphabetical order, so primitives_test/MetricDescriptorFixture.TestWithLabels
produced the expected 9433770049495071547 / 1413792954011449091. On
release-0.7 under plain gcc-14 the layout reverses, the labels are
hashed in the opposite order and the test fails with
8942707084255367343 / 18042764105132557107.

Compare the dereferenced strings instead. This matches what the Go
prometheus/client_golang side does (sort labels lexicographically by
name) and makes id/dim_hash deterministic across compilers / build
flags. The expected values in the test correspond to this alphabetical
order, so the test goes green.

MetricDescriptor::id is computed in the constructor and not persisted,
so the only effect of this change at runtime is that two metrics with
the same labels but constructed in different process invocations now
get the same id (which they already did on pp, just not on release-0.7
under the new compiler).

Co-authored-by: Cursor <cursoragent@cursor.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