How to compile my own glibc C standard library from source and use it?

Asked
Active3 hr before
Viewed126 times

6 Answers

librarycompile
90%

Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers ,How to compile my own glibc C standard library from source and use it?,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?,crosstool-NG is a set of scripts that downloads and compiles everything from source for us, including GCC, glibc and binutils.

Build glibc and install locally:

git clone git: //sourceware.org/git/glibc.git
   cd glibc
git checkout glibc - 2.32
mkdir build
cd build
export glibc_install = "$(pwd)/install".. / configure--prefix "$glibc_install"
make - j `nproc`
make install - j `nproc`

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.32
The atomic counter is 10000
The non - atomic counter is 8674

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

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

At https://stackoverflow.com/a/66634184/895245 ZeZNiQ provides a workaround that is likely correct, by passing:

-nostartfiles

Get crosstool-NG, configure and build 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
env - u LD_LIBRARY_PATH time. / ct - ng build CT_JOBS = `nproc`

The only mandatory configuration 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 I select:

4.14 .71

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

CT_GLIBC_V_2_27 = y

where glibc was cloned as:

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

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

If you just re-build;

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

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.

and then you can try:

env - u LD_LIBRARY_PATH time. / ct - ng libc + -j`nproc`
load more v
88%

Please note that even though you’re building in a separate build directory, the compilation may need to create or modify files and directories in the source directory. ,This is the default if no option is passed to configure. This enables tunables and selects the default frontend (currently ‘valstring’). ,At present only AArch64 platforms with MTE provide this functionality, although the library will still operate (without memory tagging) on older versions of the architecture. ,Install the library and other machine-dependent files in subdirectories of directory. The default is to the ‘--prefix’ directory if that option is specified, or /usr/local otherwise.

$.. / glibc - version / configure args…
load more v
72%

No, you can't access static libraries directly from C#. You have to use a DLL.,If everything seems to have gone smoothly during configure and still no Makefile, then you probably missed an idiosyncrasy:,The nice thing is that you don't have to upload your library. Behind the scenes JitPack will check out the code from GitHub and compile it. As you publish a new release on GitHub it becomes available for others to use.,If you've pushed your code to GitHub then sharing the library (aar) is easy with JitPack.

You're running into one surprising difference between i386 and x86_64: they don't use the same system call mechanism. The correct code is:

movq $60, % rax
movq $2, % rdi;
not % rbx!
   syscall
load more v
65%

To build glibc without installing you can do the standard configure and make e.g. , Building glibc without installing, Building glibc with intent to install,Use this method if you want to easily debug your application but haven't installed glibc.

To build glibc without installing you can do the standard configure and make e.g.

$ mkdir $HOME / src
$ cd $HOME / src
$ git clone git: //sourceware.org/git/glibc.git
   $ mkdir - p $HOME / build / glibc
$ cd $HOME / build / glibc
$ $HOME / src / glibc / configure--prefix = /usr
$ make
load more v
75%

libc++ is available as both a static and shared library.,If you're using clang directly in your own build system, clang++ will use c++_shared by default. To use the static variant, add -static-libstdc++ to your linker flags. Note that although the option uses the name "libstdc++" for historical reasons, this is correct for libc++ as well.,The system runtime refers to /system/lib/libstdc++.so. This library should not be confused with GNU's full-featured libstdc++. On Android, libstdc++ is just new and delete. Use libc++ for a full-featured C++ standard library.,If your application includes multiple shared libraries, you should use libc++_shared.so.

You can specify c++_shared, c++static, none, or system using the APP_STL variable in your Application.mk file. For example:

APP_STL: = c++_shared
load more v
40%

Embedded Artistry's libc is a stripped-down C standard library implementation targeted for microcontroller-based embedded systems.,Embedded Artistry's libc is intended to provide a portable set of useful C standard library functions that allows quick bring-up of new bare-metal and RTOS-based embedded systems.,This project uses Embedded Artistry's standard Meson build system, and dependencies are described in detail on our website.,In addition, this library provides implementations for __stack_chk_guard and __stack_chk_fail.

sudo apt install git - lfs
load more v

Other "library-compile" queries related to "How to compile my own glibc C standard library from source and use it?"