Search code examples
c++compiler-errorsg++cross-compilingld

g++ failing to link statically when compiling to binary format: "skipping incompatible libm.a when searching for -lm"


While attempting to write a kernel in C++, I've run into a peculiar issue. When prompting g++ to compile even a very basic C++ file statically and to binary, it simply keeps skipping over the static math library (libm.a), ultimately failing to compile.

Attempting to compile a simple C++ file:

test.cpp

int main() {
  return 0;
}

using this g++ command:

g++ -static test.cpp -Wl,--oformat=binary

I receive the following error output:

/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: cannot find -lm: No such file or directory

I am running Linux Mint Cinnamon V. 21 (Vanessa) on a VirtualBox VM.

In my attempt to narrow down the issue, I have also attempted to exclude the -static flag:

g++ test.cpp -Wl,--oformat=binary

Which results in a different error entirely:

/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/libstdc++.so: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status

After thorough research, I was made aware that this could be caused by an incompatibility between 32-bit libraries and 64-bit files. Everything is supposed to be in 64 bit. I did attempt to determine bitness of libm.a using file.

When using the file command on /usr/lib/x86_64-linux-gnu/libm.a, I receive the following output:

libm.a: ASCII text

indicating neither bitness. This led me to conclude that perhaps the library is damaged and needs updating. After running sudo apt-get install libc6-dev, the issue persists, however.

I'm not sure what to do at this point.

Update: I've opened libm.a in a text editor and the entire contents of the file are:

/* GNU ld script
*/
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /usr/lib/x86_64-linux-gnu/libm-2.35.a /usr/lib/x86_64-linux-gnu/libmvec.a )

Update 2: apparently this is a linker script. Both referenced files libm-2.35.a and libmvec.a are present in my directory and are, according to objdump, 64-bit-versions.

Based on the compiler's error output, it seems that in my case, for whatever reason, g++ (or more specifically, ld) fails to use this linker script. What could possibly cause this?


Solution

  • I have come to the conclusion that it is not normally possible to statically link C++ code involving object oriented features into a fully functional binary file, as libm.a can apparently be linked to ELF only.

    besides: even the static version of glibc, which is also required, references other dynamic libraries, making it useless for kernel code.

    there might be some sort of workaround, but it seems that g++ does not support this functionality by default.