There are much simpler ways to downgrade the glibc as well. For example, yum will calculate all of the needed dependencies for you with a

yum downgrade glibc\* 

command. But beware: downgrading glibc is always a really dangerous trick, and it is so on every system.

Glibc on version 2.4 and 2.9 had already very good compatibility between them, I suggest for you the best option were is your 2.9 left.

Answer from peterh on Stack Exchange
Discussions

Change target GLIBC version
Also, I've found in many forums that upgrading/downgrading your system's GLIBC version is not recommended, as it is highly likely that you'll break something systemwide · So the question is: Is there any way to change the target GLIBC version to an older one, so that my module can run in older ... More on github.com
🌐 github.com
2
January 27, 2021
How do i get a newer version of glibc? (2.38 or above?)
Not on Debian stable. But you could run another distro's userspace (one that has a sufficiently new glibc) in a container or chroot. More on reddit.com
🌐 r/debian
11
11
June 9, 2024
How to change rust glibc version?
hello people,i was able to build a cross compile toolchain for RISCV using rustup command,am able to get execulatble but problem is when i execute the binary on RISCV machine its showing as **" GLIBC_2.33 " not found ** The machine (x86) which i had built toolchain on has "ldd (glibc version ... More on users.rust-lang.org
🌐 users.rust-lang.org
6
0
February 1, 2022
How to switch to a certain version of glibc?
Hello, I currently have glibc 2.13. I was wondering if you could teach me how to switch to : glibc2.3.2 I would really appreciate it if you tell me how to do it step by step since I am a beginner . thanks. More on unix.com
🌐 unix.com
0
0
June 11, 2012
🌐
Reddit
reddit.com › r/ubuntu › how do i update glibc?
r/Ubuntu on Reddit: How do I update GLIBC?
July 24, 2025 -

I’m currently using GLIBC 2.35 on Ubuntu 22.04, and I want to update it (for gaming purposes).

I’m also aware that updating it isn’t as simple as typing:

“sudo apt update GLIBC yada yada”

or whatever, so I’m not entirely sure how to update it properly without bricking my install.

Any ideas on what to do?

🌐
NXP
community.nxp.com › t5 › T-Series › How-to-update-Glibc-version-in-yocto-sdk-v2-0 › td-p › 1300101
How to update Glibc version in yocto sdk v2.0 - NXP Community
November 3, 2021 - Please modify GLIBCVERSION_qoriq-ppc to 2.28 in sources/meta-freescale/conf/distro/fsl-qoriq.conf. ... Then rebuild glibc and rootfs filesystem. ... WARNING: Host distribution "Ubuntu-16.04" has not been validated with this version of the build system; you may possibly experience unexpected ...
🌐
Devtuts
devtuts.net › en › linux › how-to-update-glibc.html
How to update glibc
June 15, 2024 - # Debian / Ubuntu / Kali sudo apt-get update && sudo apt-get install --reinstall libc6 # RHEL / CentOS / Rocky / AlmaLinux sudo yum reinstall glibc # or: sudo dnf reinstall glibc # openSUSE / SLES sudo zypper in --force glibc · If a newer release is only available in a newer distribution version, ...
🌐
GitHub
github.com › nodejs › node-gyp › issues › 2317
Change target GLIBC version · Issue #2317 · nodejs/node-gyp
January 27, 2021 - COLLECT_GCC=cc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none:hsa OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.3.0-17ubuntu1~20.04' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib -
Author   nodejs
🌐
Reddit
reddit.com › r/debian › how do i get a newer version of glibc? (2.38 or above?)
r/debian on Reddit: How do i get a newer version of glibc? (2.38 or above?)
June 9, 2024 -

Basically im trying to run a game but it requires at least glibc 2.38 but it seems debian only offers 2.36 at the moment. Any way i can get a newer vesion of it?

EDIT: ended up just downloading the windows version of the game and running it with wine, im an idiot and thought i was having a problem with the sound when i first downloaded, that's why i tried the linux binary, but when i ran it with wine again i found out that the game came muted by default and that i had to press + to get the volume up

Find elsewhere
🌐
Rust Programming Language
users.rust-lang.org › help
How to change rust glibc version? - help - The Rust Programming Language Forum
February 1, 2022 - hello people,i was able to build a cross compile toolchain for RISCV using rustup command,am able to get execulatble but problem is when i execute the binary on RISCV machine its showing as **" GLIBC_2.33 " not found ** The machine (x86) which i had built toolchain on has "ldd (glibc version ...
🌐
Unix.com
unix.com › unix for beginners q & a › unix for dummies questions & answers
How to switch to a certain version of glibc? - UNIX for Dummies Questions & Answers - Unix Linux Community
June 11, 2012 - Hello, I currently have glibc 2.13. I was wondering if you could teach me how to switch to : glibc2.3.2 I would really appreciate it if you tell me how to do it step by step since I am a beginner . thanks.
🌐
Baeldung
baeldung.com › home › installation › multiple glibc on a single linux machine
Multiple glibc on a Single Linux Machine | Baeldung on Linux
March 18, 2024 - So, in a way, we can have multiple versions of glibc on our machine and have a libglib-2.0.so link to a specific version. The linker will look for the soname field in the shared object and embed it in the resulting binary. The soname field specifies the filename for our target shared library.
🌐
Jertype
jertype.com › upgrading-glibc
Using newer libc on old Linux distributions - Jertype
April 21, 2018 - You might find advice that suggests using LD_LIBRARY_PATH (ex: LD_LIBRARY_PATH=/opt/glibc-2.14/lib), but this can cause problems. When you specify the LD_LIBRARY_PATH you are giving your system an additional path to look for libraries to dynamically load. However, the lib folder contains many other libraries that could be loaded. This can cause things like unexpected segfaults. Our application only needed to load libc.so.6. If you use LD_PRELOAD, you can tell your application to load functions from a specific file instead of the locations it would normally load from.
🌐
Arch Linux Forums
bbs.archlinux.org › viewtopic.php
How to build against a specific version of glibc, what options? / GNU/Linux Discussion / Arch Linux Forums
January 31, 2024 - What I've done that sort of worked is a Docker image of a Debian version that uses an older version of glibc. This worked and got me the build environment. So in reality "compile [retroarch] under glibc 2.37 or lower" means to compile it and all its dependencies under glibc 2.37
🌐
OpenGenus
iq.opengenus.org › install-specific-version-of-glibc
Install specific version of Glibc
October 17, 2022 - This will install the required version of Glibc. ... wget http://ftp.gnu.org/gnu/libc/glibc-2.36.tar.gz tar -xvf glibc-2.36.tar.gz cd glibc-2.36 mkdir build mkdir glibc-2.36-install cd build ~/glibc/glibc-2.36/configure --prefix=$HOME/glibc/glibc-2.36-install make -j make install · With this article at OpenGenus, you must be able to install any version of Glibc.
🌐
Puppy Linux Discussion Forum
forum.puppylinux.com › board index › puppy linux main › house training › users help
How exactly do you update glibc? - Puppy Linux Discussion Forum
This table, that was provided by wiak, seems to indicate it may not actually cause any big issues, changing to a newer version of glibc.
Top answer
1 of 13
352

It is very possible to have multiple versions of GLIBC on the same system (we do that every day).

However, you need to know that GLIBC consists of many pieces (200+ shared libraries) which all must match. One of the pieces is ld-linux.so.2 (ld-linux-x86-64.so.2 on x86_64 systems), and it must match libc.so.6, or you'll see the errors you are seeing.

The absolute path to ld-linux.so.2 is hard-coded into the executable at link time, and can not be easily changed after the link is done (Update: can be done with patchelf; see this answer below).

To build an executable that will work with the new GLIBC, do this:

g++ main.o -o myapp ... \
   -Wl,--rpath=/path/to/newglibc \
   -Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2

The -rpath linker option will make the runtime loader search for libraries in /path/to/newglibc (so you wouldn't have to set LD_LIBRARY_PATH before running it), and the -dynamic-linker option will "bake" path to correct ld-linux.so.2 into the application.

If you can't relink the myapp application (e.g. because it is a third-party binary), not all is lost, but it gets trickier. One solution is to set a proper chroot environment for it. Another possibility is to use rtldi and a binary editor.

Update: or you can use patchelf on existing binaries to redirect them to the alternate libc.

2 of 13
167

This question is old, the other answers are old. Employed Russian's answer is very good and informative, but it only works if you have the source code. If you don't, the alternatives back then were very tricky. Fortunately nowadays we have a simple solution to this problem (as commented in one of his replies), using patchelf. All you have to do is:

$ ./patchelf --set-interpreter /path/to/newglibc/ld-linux.so.2 --set-rpath /path/to/newglibc/ myapp

This changes the non-working executable to use a different path for its linker. And after that, you can just execute your file:

$ ./myapp

No need to chroot or manually edit binaries, thankfully. But remember to backup your binary before patching it, if you're not sure what you're doing, because it modifies your binary file. After you patch it, you can't restore the old path to interpreter/rpath. If it doesn't work, you'll have to keep patching it until you find the path that will actually work... Well, it doesn't have to be a trial-and-error process. For example, in OP's example, he needed GLIBC_2.3, so you can easily find which lib provides that version using strings:

$ strings /lib/i686/libc.so.6 | grep GLIBC_2.3
$ strings /path/to/newglib/libc.so.6 | grep GLIBC_2.3

In theory, the first grep would come empty because the system libc doesn't have the version he wants, and the 2nd one should output GLIBC_2.3 because it has the version myapp is using, so we know we can patchelf our binary using that path. If you get a segmentation fault, read the note at the end.

When you try to run a binary in linux, the binary tries to load the linker (aka loader, aka interpreter), then the libraries, and they should all be in the path and/or in the right place. If your problem is with the linker and you want to find out which path your binary is looking for, you can find out with this command:

$ readelf -l myapp | grep interpreter
  [Requesting program interpreter: /lib/ld-linux.so.2]                                                                                                                                                                                   

If your problem is with the libs, commands that will give you the libs being used are:

$ readelf -d myapp | grep Shared
$ ldd myapp 

This will list the libs that your binary needs, but you probably already know the problematic ones, since they are already yielding errors as in OP's case. After you do patchelf, it might happen that myapp is still not working, and when you run ldd myapp it lists the libs with mixed paths, some to the path you set, others to the original system path. That's because your path doesn't have those libs. rpath will search for the lib in the path you set, but if it's not there, it still looks for it in the other system locations. In this case, if you have the missing lib somewhere, just copy it to the rpath that you chose and it should work.

"patchelf" works for many different problems that you may encounter while trying to run a program, related to these 2 problems. For example, if you get: ELF file OS ABI invalid, it may be fixed by setting a new loader (the --set-interpreter part of the command) as I explain here. Another example is for the problem of getting No such file or directory when you run a file that is there and executable, as exemplified here. In that particular case, OP was missing a link to the loader, but maybe in your case you don't have root access and can't create the link. Setting a new interpreter would solve your problem.

Thanks Employed Russian and Michael Pankov for the insight and solution!


Note for segmentation fault: you might be in the case where myapp uses several libs, and most of them are ok but some are not; then you patchelf it to a new dir, and you get segmentation fault. When you patchelf your binary, you change the path of several libs, even if some were originally in a different path. Take a look at my example below:

$ ldd myapp
./myapp: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by ./myapp)
./myapp: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./myapp)
        linux-vdso.so.1 =>  (0x00007fffb167c000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9a9aad2000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9a9a8ce000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f9a9a6af000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f9a9a3ab000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9a99fe6000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f9a9adeb000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9a99dcf000)

Note that most libs are in /lib/x86_64-linux-gnu/ but the problematic one (libstdc++.so.6) is on /usr/lib/x86_64-linux-gnu. After I patchelf'ed myapp to point to /path/to/mylibs, I got segmentation fault. For some reason, the libs are not totally compatible with the binary. Since myapp didn't complain about the original libs, I copied them from /lib/x86_64-linux-gnu/ to /path/to/mylibs2, and I also copied libstdc++.so.6 from /path/to/mylibs there. Then I patchelf'ed it to /path/to/mylibs2, and myapp works now. If your binary uses different libs, and you have different versions, it might happen that you can't fix your situation. :( But if it's possible, mixing libs might be the way. It's not ideal, but maybe it will work. Good luck!

🌐
Substack
blogsystem5.substack.com › blog system/5 › picking glibc versions at runtime
Picking glibc versions at runtime - by Julio Merino
September 24, 2024 - And before containers existed, they surely weren’t testing glibc changes by installing modified versions of the library over the system-wide one and YOLOing it. So. What options do we really have? To answer this question, we need to look at how dynamic binaries work and what glibc is.
Top answer
1 of 7
109

You are correct in that glibc uses symbol versioning. If you are curious, the symbol versioning implementation introduced in glibc 2.1 is described here and is an extension of Sun's symbol versioning scheme described here.

One option is to statically link your binary. This is probably the easiest option.

You could also build your binary in a chroot build environment, or using a glibc-new => glibc-old cross-compiler.

According to the http://www.trevorpounds.com blog post Linking to Older Versioned Symbols (glibc), it is possible to to force any symbol to be linked against an older one so long as it is valid by using the same .symver pseudo-op that is used for defining versioned symbols in the first place. The following example is excerpted from the blog post.

The following example makes use of glibc’s realpath, but makes sure it is linked against an older 2.2.5 version.

#include <limits.h>
#include <stdlib.h>
#include <stdio.h>

__asm__(".symver realpath,realpath@GLIBC_2.2.5");
int main()
{
    const char* unresolved = "/lib64";
    char resolved[PATH_MAX+1];

    if(!realpath(unresolved, resolved))
        { return 1; }

    printf("%s\n", resolved);

    return 0;
}
2 of 7
44

Setup 1: compile your own glibc without dedicated GCC and use it

Since it seems impossible to do just with symbol versioning hacks, let's go one step further and compile glibc ourselves.

This setup might work and is quick as it does not recompile the whole GCC toolchain, just glibc.

But it is not reliable as it uses host C runtime objects such as crt1.o, crti.o, and crtn.o provided by glibc. This is mentioned at: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location Those objects do early setup that glibc relies on, so I wouldn't be surprised if things crashed in wonderful and awesomely subtle ways.

For a more reliable setup, see Setup 2 below.

Build glibc and install locally:

export glibc_install="$(pwd)/glibc/build/install"

git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28
mkdir build
cd build
../configure --prefix "$glibc_install"
make -j `nproc`
make install -j `nproc`

Setup 1: verify the build

test_glibc.c

#define _GNU_SOURCE
#include <assert.h>
#include <gnu/libc-version.h>
#include <stdatomic.h>
#include <stdio.h>
#include <threads.h>

atomic_int acnt;
int cnt;

int f(void* thr_data) {
    for(int n = 0; n < 1000; ++n) {
        ++cnt;
        ++acnt;
    }
    return 0;
}

int main(int argc, char **argv) {
    /* Basic library version check. */
    printf("gnu_get_libc_version() = %s\n", gnu_get_libc_version());

    /* Exercise thrd_create from -pthread,
     * which is not present in glibc 2.27 in Ubuntu 18.04.
     * https://stackoverflow.com/questions/56810/how-do-i-start-threads-in-plain-c/52453291#52453291 */
    thrd_t thr[10];
    for(int n = 0; n < 10; ++n)
        thrd_create(&thr[n], f, NULL);
    for(int n = 0; n < 10; ++n)
        thrd_join(thr[n], NULL);
    printf("The atomic counter is %u\n", acnt);
    printf("The non-atomic counter is %u\n", cnt);
}

Compile and run with test_glibc.sh:

#!/usr/bin/env bash
set -eux
gcc \
  -L "${glibc_install}/lib" \
  -I "${glibc_install}/include" \
  -Wl,--rpath="${glibc_install}/lib" \
  -Wl,--dynamic-linker="${glibc_install}/lib/ld-linux-x86-64.so.2" \
  -std=c11 \
  -o test_glibc.out \
  -v \
  test_glibc.c \
  -pthread \
;
ldd ./test_glibc.out
./test_glibc.out

The program outputs the expected:

gnu_get_libc_version() = 2.28
The atomic counter is 10000
The non-atomic counter is 8674

Command adapted from https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location but --sysroot made it fail with:

cannot find /home/ciro/glibc/build/install/lib/libc.so.6 inside /home/ciro/glibc/build/install

so I removed it.

ldd output confirms that the ldd and libraries that we've just built are actually being used as expected:

+ ldd test_glibc.out
        linux-vdso.so.1 (0x00007ffe4bfd3000)
        libpthread.so.0 => /home/ciro/glibc/build/install/lib/libpthread.so.0 (0x00007fc12ed92000)
        libc.so.6 => /home/ciro/glibc/build/install/lib/libc.so.6 (0x00007fc12e9dc000)
        /home/ciro/glibc/build/install/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fc12f1b3000)

The gcc compilation debug output shows that my host runtime objects were used, which is bad as mentioned previously, but I don't know how to work around it, e.g. it contains:

COLLECT_GCC_OPTIONS=/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o

Setup 1: modify glibc

Now let's modify glibc with:

diff --git a/nptl/thrd_create.c b/nptl/thrd_create.c
index 113ba0d93e..b00f088abb 100644
--- a/nptl/thrd_create.c
+++ b/nptl/thrd_create.c
@@ -16,11 +16,14 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */

+#include <stdio.h>
+
 #include "thrd_priv.h"

 int
 thrd_create (thrd_t *thr, thrd_start_t func, void *arg)
 {
+  puts("hacked");
   _Static_assert (sizeof (thr) == sizeof (pthread_t),
                   "sizeof (thr) != sizeof (pthread_t)");

Then recompile and re-install glibc, and recompile and re-run our program:

cd glibc/build
make -j `nproc`
make -j `nproc` install
./test_glibc.sh

and we see hacked printed a few times as expected.

This further confirms that we actually used the glibc that we compiled and not the host one.

Tested on Ubuntu 18.04.

Setup 2: crosstool-NG pristine setup

This is an alternative to setup 1, and it is the most correct setup I've achieved far: everything is correct as far as I can observe, including the C runtime objects such as crt1.o, crti.o, and crtn.o.

In this setup, we will compile a full dedicated GCC toolchain that uses the glibc that we want.

The only downside to this method is that the build will take longer. But I wouldn't risk a production setup with anything less.

crosstool-NG is a set of scripts that downloads and compiles everything from source for us, including GCC, glibc and binutils.

Yes the GCC build system is so bad that we need a separate project for that.

This setup is only not perfect because crosstool-NG does not support building the executables without extra -Wl flags, which feels weird since we've built GCC itself. But everything seems to work, so this is only an inconvenience.

Get crosstool-NG and configure it:

git clone https://github.com/crosstool-ng/crosstool-ng
cd crosstool-ng
git checkout a6580b8e8b55345a5a342b5bd96e42c83e640ac5
export CT_PREFIX="$(pwd)/.build/install"
export PATH="/usr/lib/ccache:${PATH}"
./bootstrap
./configure --enable-local
make -j `nproc`
./ct-ng x86_64-unknown-linux-gnu
./ct-ng menuconfig

The only mandatory option that I can see, is making it match your host kernel version to use the correct kernel headers. Find your host kernel version with:

uname -a

which shows me:

4.15.0-34-generic

so in menuconfig I do:

  • Operating System
    • Version of linux

so I select:

4.14.71

which is the first equal or older version. It has to be older since the kernel is backwards compatible.

Now you can build with:

env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`

and now wait for about thirty minutes to two hours for compilation.

Setup 2: optional configurations

The .config that we generated with ./ct-ng x86_64-unknown-linux-gnu has:

CT_GLIBC_V_2_27=y

To change that, in menuconfig do:

  • C-library
  • Version of glibc

save the .config, and continue with the build.

Or, if you want to use your own glibc source, e.g. to use glibc from the latest git, proceed like this:

  • Paths and misc options
    • Try features marked as EXPERIMENTAL: set to true
  • C-library
    • Source of glibc
      • Custom location: say yes
      • Custom location
        • Custom source location: point to a directory containing your glibc source

where glibc was cloned as:

git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28

Setup 2: test it out

Once you have built he toolchain that you want, test it out with:

#!/usr/bin/env bash
set -eux
install_dir="${CT_PREFIX}/x86_64-unknown-linux-gnu"
PATH="${PATH}:${install_dir}/bin" \
  x86_64-unknown-linux-gnu-gcc \
  -Wl,--dynamic-linker="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib/ld-linux-x86-64.so.2" \
  -Wl,--rpath="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib" \
  -v \
  -o test_glibc.out \
  test_glibc.c \
  -pthread \
;
ldd test_glibc.out
./test_glibc.out

Everything seems to work as in Setup 1, except that now the correct runtime objects were used:

COLLECT_GCC_OPTIONS=/home/ciro/crosstool-ng/.build/install/x86_64-unknown-linux-gnu/bin/../x86_64-unknown-linux-gnu/sysroot/usr/lib/../lib64/crt1.o

Setup 2: failed efficient glibc recompilation attempt

It does not seem possible with crosstool-NG, as explained below.

If you just re-build;

env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`

then your changes to the custom glibc source location are taken into account, but it builds everything from scratch, making it unusable for iterative development.

If we do:

./ct-ng list-steps

it gives a nice overview of the build steps:

Available build steps, in order:
  - companion_tools_for_build
  - companion_libs_for_build
  - binutils_for_build
  - companion_tools_for_host
  - companion_libs_for_host
  - binutils_for_host
  - cc_core_pass_1
  - kernel_headers
  - libc_start_files
  - cc_core_pass_2
  - libc
  - cc_for_build
  - cc_for_host
  - libc_post_cc
  - companion_libs_for_target
  - binutils_for_target
  - debug
  - test_suite
  - finish
Use "<step>" as action to execute only that step.
Use "+<step>" as action to execute up to that step.
Use "<step>+" as action to execute from that step onward.

therefore, we see that there are glibc steps intertwined with several GCC steps, most notably libc_start_files comes before cc_core_pass_2, which is likely the most expensive step together with cc_core_pass_1.

In order to build just one step, you must first set the "Save intermediate steps" in .config option for the intial build:

  • Paths and misc options
    • Debug crosstool-NG
      • Save intermediate steps

and then you can try:

env -u LD_LIBRARY_PATH time ./ct-ng libc+ -j`nproc`

but unfortunately, the + required as mentioned at: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536

Note however that restarting at an intermediate step resets the installation directory to the state it had during that step. I.e., you will have a rebuilt libc - but no final compiler built with this libc (and hence, no compiler libraries like libstdc++ either).

and basically still makes the rebuild too slow to be feasible for development, and I don't see how to overcome this without patching crosstool-NG.

Furthermore, starting from the libc step didn't seem to copy over the source again from Custom source location, further making this method unusable.

Bonus: stdlibc++

A bonus if you're also interested in the C++ standard library: How to edit and re-build the GCC libstdc++ C++ standard library source?