How to you compile glibc (32-bit and 64-bit)? - linux

Right now, I have a modified version of a open-source dependency library (mylib.a file) in my project and thus I have it statically linked via gcc command(s). I am getting the error that...
"statically linked applications require at runtime the shared libraries from the glibc version used for linking"
My translation: my static dependency library cannot dynamically use glibc; it must also be compiled and dynamically linked. Thus, I'm trying to compile and statically link glibc.
I've gather that they would need to be compiled, the *.a library placed in a folder within the project, the "-I//location//" added in for the include headers, and the "-L//location//" added in for the libraries themselves.
But, for the question itself...
How to you compile glibc (32-bit and 64-bit)?
Through open-source research, I've found this link and I have cloned the repo but I cannot find any documentation on how to actually compile it.
git clone git://sourceware.org/git/glibc.git
Any thoughts or suggestions are welcomed.

My translation: my static dependency library cannot dynamically use glibc; it must also be compiled and dynamically linked. Thus, I'm trying to compile and statically link glibc.
As n.m. pointed out, your translation is wrong.
You are trying to link a fully static executable, and GLIBC is warning you that such executable will not run correctly on any machine with a different version of GLIBC installed.
Instead of trying to build a fully-static executable, build it such that it uses libc.so.6 (you can still link mylib.a into such executable).
IF the reason you added -static to your link is that you have both libmylib.a and libmylib.so, and would like to link in the former instead of the latter, read this answer.

Related

Build static executable on RHEL 7?

I have a C++ project that I'm currently building using dynamic linking to various system libraries. It's on a RHEL 7 system. I've been using devtoolset-9 to get a more modern version of g++ (the system one is 4.8.5, I think). It all works fine, but I'd like to now build a static executable that I will be able to run on a non-RHEL linux system. I've tried specifying -static-libstdc++, but it appears to still be dynamically linked, looking at the ldd output. I've read that devtoolset compilers use some link-time trickery to link in both the system libstdc++ dynamically and any new C++ functionality statically. Is this true? It doesn't work for me; if I copy the executable over to the non-RHEL system and try to run it, I get a bunch of things like this (from memory, so hopefully correct):
/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found
Is there any way to build a fully static executable using g++ from devtoolset-9? Thank you.

"undefined reference to `__stat_time64'" when cross-compiling rust project on musl 1.2.0

I'm trying to cross-compile a rust project for arm-linux-musleabihf and am hitting a linker error when using musl-cross-make. The rust project has a dependency on libgit2 and this is the dependency that seems to be causing the problem.
Using:
the latest rust (1.43.1 via rustup)
the arm-unknown-linux-musleabihf target
the latest musl-cross-make with TARGET=arm-linux-musleabihf
pointing TARGET_CC_linux_arm-unknown-linux-musleabihf and CARGO_TARGET_ARM_UNKNOWN_LINUX_MUSLEABIHF_LINKER at /opt/musl-cross-make/output/bin/arm-linux-musleabihf-gcc
I get an error when building:
error: linking with `/opt/musl-cross-make/output/bin/arm-linux-musleabihf-gcc` failed: exit code: 1
...
= note: /opt/musl-cross-make/output/bin/../lib/gcc/arm-linux-musleabihf/9.2.0/../../../../arm-linux-musleabihf/bin/ld: /tmp/rustcvSvGAJ/liblibgit2_sys-e56c2f9bd024a0a9.rlib(odb.o): in function `git_odb__add_default_backends':
odb.c:(.text.git_odb__add_default_backends+0x24): undefined reference to `__stat_time64'
/opt/musl-cross-make/output/bin/../lib/gcc/arm-linux-musleabihf/9.2.0/../../../../arm-linux-musleabihf/bin/ld: /tmp/rustcvSvGAJ/liblibgit2_sys-e56c2f9bd024a0a9.rlib(config.o): in function `git_config_add_file_ondisk':
config.c:(.text.git_config_add_file_ondisk+0x34): undefined reference to `__stat_time64'
/opt/musl-cross-make/output/bin/../lib/gcc/arm-linux-musleabihf/9.2.0/../../../../arm-linux-musleabihf/bin/ld: /tmp/rustcvSvGAJ/liblibgit2_sys-e56c2f9bd024a0a9.rlib(config_file.o): in function `config_file_read':
config_file.c:(.text.config_file_read+0x48): undefined reference to `__stat_time64'
...etc...
It looks like the linker is having difficulty resolving the musl-specific time64 symbols, and it's not clear why.
This works fine if:
I use the x86_64-linux-musl target on both rust and musl-cross-make
I build musl-cross-make with MUSL_VER=1.1.24
I also wrote a little C program that uses both time and stat, and this builds on musl 1.2.0 on the cross compiler without any issue.
What's going on here? What's special about libgit2 which means that it can't find the right __time64 symbols?
The problem is that the MUSL libc that ships with Rust versions up to and including 1.44 is MUSL libc 1.1.X based, not 1.2.0.
When Rust builds libgit2 is also needs to build libgit2-sys, which is C code. When building libgit2-sys it uses the MUSL libc version that you've built and installed yourself with musl-cross-make. This is 1.2.0 by default, which has reworked time_t 32/64 bit support, having a dependency on __stat_time64 and various other similarly named methods (such as __time64).
However, when Rust is linking your final application it is using the version of MUSL libc shipped with Rust for the x86_64-linux-musl target, which doesn't include that new time_t support, and doesn't have __stat_time64, __time64, etc. So the link fails.
Right now you have 2 options:
Use musl-cross-make to build 1.1.24 of MUSL lib. I'm not 100% what version is included with Rust 1.44. It may be 1.1.22, although from my own testing I found 1.1.24 works just fine (as have you).
Build your own version of Rust and/or the target liblibc.rlib with your own version of MUSL libc. I've never managed to successfully achieve this myself, although this might be a good place to start if you want to try this.
The general issue of using libc shipped with Rust, instead of a locally provided version, is being worked on, e.g. here.
You could try the instructions listed in https://github.com/richfelker/libcompat_time32:
Add -Wl,--whole-archive -lcompat_time32 -Wl,--no-whole-archive to the link command line. Special hacks (like prepending -Wl, to -lcompat_time32) may be needed if libtool is intercepting and mangling the command line.
I would recommend trying out https://github.com/rust-embedded/cross : it sets up the environment for cross-compilation in docker and seamlessly works, even for the case highlighted here.
AFAICT, they recompile musl with the correct version.

How to see which static libraries were used for gcc/g++ compilation from the generated binary?

Context: I'm using a linux toolchain (includes g++, other build tools, libs, headers, etc) to build my code with statically linked libraries. I want to ensure that I'm using ONLY libraries/headers from my toolchain, not the default ones on the build machine. I can use strace to see what g++ is doing (which libraries it is using) while it is compiling which would be helpful in a normal scenario - but my build system has many wrappers around g++ that hide all of the output.
Question: is there a way to obtain from a statically-linked binary any useful information regarding the library and header files which were used to create the binary? I've taken a look at the objdump tool but I'm not sure if it will help much.
Just pass -v to g++ or gcc at link time. It will show all the linked libraries. Perhaps try make CC='gcc -v' CXX='g++ -v'
More generally, -v passed g++ or gcc shows you the underlying command with its arguments because gcc or g++ is just a driver program (starting cc1, ld or collect2, as, ...)
By passing the -H flag to GCC (i.e. g++ or gcc) you can see every included header. So you can check that only the heanders you expect are included.
You cannot see what static library has been linked, because linking a static library just means linking the relevant object file members in it, so a static library can (and usually is) linked in only partly.
You could use the nm command to find names from such libraries.
If you can simply recompile, then there are ways (using some of the techniques that Basile explained) to get the headers and libraries (static or dynamic) but, unfortunately, there is no way to know which libraries were used after the compilation is complete.

Autoconf, Libtool shared and static library

I am using autoconf gnu tools to build my product.
It generates both the shared as well as static library for any library where *.la is mentioned.
The issue is if you use .la to link your binary in Makefile.am.
It links with the dynamic library but when you use ldd to the binary, it says
"not a dynamic executable" although it links with shared library. I proved it by removing the shared library after the binary is built and then tried to run the binary. It didn't find the shared library and couldn't run.
Another question is how to put library in a specified location using Makefile.am direction ?
Looks like you run ldd on the wrapper scripts created by libtool. They are used to link uninstalled libraries with uninstalled executables. Real binaries are placed in .libs directory.
You can install a lib to some specific place in this way
mylibrary_LTLIBRARIES = libmylibrary.la
mylibrarydir = ${libdir}/my_plugins/

Linking against a specific shared library version in linux

My build process consists of Qt's qmake Makefile generator and the typical make utility bundled with linux.
My application consists of a few shared libraries and the main application is linked against them.
How can I apply the typical linux versioning scheme on my libraries? (Use version 2 -> link against foo.so.2 that points to foo.so.2.y.z with an ldconfig generated link).
The answer doesn't have to be specific for my build process.
Your library should be named libfoo.so.2.y.z, with symlinks of libfoo.so.2 and libfoo.so both pointing to that. The library should be created using -soname libfoo.so.2 in the linker command line (or -Wl,-soname,libfoo.so.2 on the gcc command line).
Hope that helps!

Resources