Skip to content

Upgrade to Clang 20 and Rust 1.88  #4265

Description

@miladfarca

RHEL llvm-toolset and rust-toolset packages are version‑coupled. For example, installing llvm-toolset-19.1.7 brings in Rust 1.84.1. Currently the ppc64 and s390x platforms are using Rust 1.84, which still ships with libadler. Starting with Rust 1.86, this changes to libadler2.

The Chromium build repository currently has this logic to work around the mismatch, since our toolchain is older than Chromium upstream:

if (rustc_nightly_capability) {
  stdlib_files += [ "adler2" ]
} else {
  stdlib_files += [ "adler" ]
}

The issue now is that AIX is also moving to Rust 1.86, which uses libadler2, but AIX still falls into the else branch because it does not use the Chromium toolchain. That means this logic no longer works for AIX.

To avoid having to maintain libadler for different Rust versions upstream, we need to upgrade our toolchain to Rust 1.86+ and fully remove that if/else block.

On RHEL, upgrading Rust to 1.88 also means upgrading our llvm-toolset (Clang) to version 20, since Rust and LLVM are version‑coupled there.

Furthermore Libc++ now only supports Clang 20 and later: llvm/llvm-project#165684
Chromium upstream is also already using Clang 23, so an upgrade may need to be performed down the road regardless.

Activity

  1. miladfarca commented on Mar 5, 2026

    @miladfarca
    ContributorAuthor

    /cc @nodejs/build

  2. changed the title [-]Upgrading to clang 20 and rustc 1.88[/-] [+]Upgrade to Clang 20 and Rust 1.88 [/+] on Mar 5, 2026
  3. targos commented on Mar 6, 2026

    @targos
    Member

    I guess that's ok if we do it on specific systems when there's a good reason like this, but I'm not sure we can easily bump the official requirement to Clang 20. For example on macOS, stable Xcode is still on Clang 19:

    Image

    https://en.wikipedia.org/wiki/Xcode#Toolchain_versions

  4. miladfarca commented on Mar 28, 2026

    @miladfarca
    ContributorAuthor

    adler is now removed from chromium build and adler2 is being used unconditionally:
    http://crrev.com/c/7704595
    For building V8 rustc >= 1.86 will now be required.

  5. richardlau commented on Apr 24, 2026

    @richardlau
    Member

    We've landed V8 14.6 on main where the V8 CI passed with Clang 19 and Rust 1.88.

    We will need to update Rust for V8 14.8: nodejs/node#62572 (comment)

    Unfortunately https://chromium-review.googlesource.com/c/chromium/src/+/7704595 affects whether Rust 1.82 or 1.88 is usable, and that is in V8's build repo so isn't checked into Node.js. I tried to roll the sha in deps/v8/DEPS on main forward to include that change but that just fails the CI with an undefined identifier: https://ci.nodejs.org/job/node-test-commit-v8-linux/7149/nodes=rhel8-s390x,v8test=v8test/console

    So updating the machines to clang 20 and rust 1.88 will break the V8 CI with V8 14.6 (on main) but is necessary for the 14.8 update. Which is going to mean some coordination/acceptance of broken CI before V8 is updated.

    The "good" news is that the Temporal stuff is off by default in V8 versions earlier than 14.4, so existing Node.js release lines before 26 won't be affected.

  6. richardlau commented on May 1, 2026

    @richardlau
    Member

    Refs nodejs/node#62572 (comment)

    So in addition to adler/adler2 for Rust, we have several compiler options being used by the V8 build that are not supported by clang 19 or 20.

    I think the most practical solution is to patch tools/make-v8.sh to erase options that we know are invalid for the compiler in use.

    For transition, we could also replace adler2->adler and adler->adler2 as necessary at build time based on the version of Rust,

    e.g. rustc 1.92.0 (Fedora 43)

    $  basename $(find $(rustc --print sysroot)/lib/rustlib/ -type f -name "libadler*") | cut -d '-' -f 1
    libadler2
    $
    [root@test-ibm-rhel8-x64-1 ~]#  basename $(find $(rustc --print sysroot)/lib/rustlib/ -type f -name "libadler*") | cut -d '-' -f 1
    libadler
    [root@test-ibm-rhel8-x64-1 ~]#

    and then sed to replace adler/adler2 in build/rust/std/BUILD.gn based on the returned strings.
    e.g.

    sed -i -e 's/"adler2"/"adler"/g' build/rust/std/BUILD.gn
    

    for libadler and

    sed -e 's/"adler"/"adler2"/g' build/rust/std/BUILD.gn
    

    for libadler2.

    That should then allow us to transition the clang and rust versions on the RHEL machines and still be able to build Node.js 26 and main (with later V8).

  7. targos commented on May 2, 2026

    @targos
    Member
  8. targos commented on May 2, 2026

    @targos
    Member

    I looked at Jenkins outputs from https://ci.nodejs.org/job/node-test-pull-request/73065/.
    Here are the systems that have Rust <1.86:

  9. targos commented on May 2, 2026

    @targos
    Member

    I'm quite concerned with this, TBH. I hope we won't have to update almost all of the CI hosts every time there is a V8 update...

  10. targos commented on May 13, 2026

    @targos
    Member

    FYI Here's a PR that tries to update temporal_rs and it's blocked by the too low Rust version installed on some CI hosts: nodejs/node#63281

  11. richardlau commented on May 15, 2026

    @richardlau
    Member

    I'm quite concerned with this, TBH. I hope we won't have to update almost all of the CI hosts every time there is a V8 update...

    I echo this concern. It's still early days but we don't yet know:

    • If we can keep to one version of rust for the duration of a Node.js Long Term Support release line (or under the new release policy, every future release line)?
    • Even if we can, how do we manage multiple versions of rust on platforms (e.g. RHEL) where there is only a rolling package (which means we cannot install two different versions of rust using the RHEL package manager like we can with e.g. gcc)?
    • Or is it "safe" to allow periodic updates of rust (e.g. when RHEL roll rust-toolset to new versions just pick up the latest)? But on RHEL, both rust and clang are dependent on llvm which means updating rust via the package manager would also mean updating clang.

    The Rust community solution is rustup but I'm hesitant to use that in the same way that we have not installed e.g. nvm onto the Jenkins runners. Given supply chain concerns over e.g. npm packages, I'd like some way of controlling what is installed on our machines (especially the critical release ones) at Ansible setup time that is not overridable/changeable on the machines at runtime. As far as I can tell rustup itself is not signed/check-summed and does not check the rust binaries it downloads (it appears to rely entirely on trusting the download server) at least until something like rust-lang/rfcs#3724 is implemented.
    (FWIW I am aware that for expediency we did end up using rustup on a couple of platforms.)

  12. bricss commented on May 16, 2026

    @bricss

    Rewriting temporal_rs in modern C++ will solve all those issues 🧐

  13. 2 remaining items

  14. joyeecheung commented on Jun 3, 2026

    @joyeecheung
    Member

    It could be a bad idea but: if the rustc requirement mostly comes from temporal_rs we can also patch that to work with lower version of rustc, like how we patch V8 to work with lower version of clang/gcc.

  15. richardlau commented on Jun 11, 2026

    @richardlau
    Member

    I looked at Jenkins outputs from https://ci.nodejs.org/job/node-test-pull-request/73065/. Here are the systems that have Rust <1.86:

    Or we could try trixie-backports: https://packages.debian.org/source/trixie-backports/rustc

  16. pinned this issue on Jun 12, 2026
  17. richardlau commented on Jul 3, 2026

    @richardlau
    Member

    I've updated the Ubuntu 24.04 machines, which was the last thing listed in #4265 (comment).

  18. miladfarca commented on Jul 23, 2026

    @miladfarca
    ContributorAuthor

    Seems like everything is done, ok to close this issue?

  19. unpinned this issue on Aug 12, 2026
  20. joyeecheung commented on Sep 2, 2026

    @joyeecheung
    Member

    Looks like we missed github actions nodejs/node#65742 (not sure about the clang 20 part, but rust 1.88 is defintely needed)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions