Home > OS >  ld.exe cannot find /lib/libc.so.6 even after sysroot set
ld.exe cannot find /lib/libc.so.6 even after sysroot set

Time:07-31

I am trying to cross-compile a simple C program with GTK for arm-linux-gnueabi on Windows 10 x86_64, using toolchains and sysroots provided by Linaro.

The tools I use in compilation:

  • Build suite: Cmake 3.23.2
  • Make tool: Ninja 1.10.2
  • Build toolchain: Linaro GCC 5.5, as above
  • IDE: CLion 2022.2

My cross compile configuration .cmake file:

# User's variables
set(USER_CROSS_TOOLCHAIN_ROOT "D:/gcc")
set(USER_CROSS_SYSROOT "D:/sysroot")

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(CMAKE_C_COMPILER "${USER_CROSS_TOOLCHAIN_ROOT}/bin/arm-linux-gnueabi-gcc.exe")
set(CMAKE_CXX_COMPILER "${USER_CROSS_TOOLCHAIN_ROOT}/bin/arm-linux-gnueabi-g  .exe")

set(CMAKE_FIND_ROOT_PATH "${USER_CROSS_TOOLCHAIN_ROOT}"
        "${USER_CROSS_TOOLCHAIN_ROOT}/arm-linux-gnueabi"
        )
set(CMAKE_SYSROOT "${USER_CROSS_SYSROOT}")


set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

As you see, CMAKE_SYSROOT is defined in the file above.

My CMakeLists.txt:

cmake_minimum_required(VERSION 3.23)
project(gtkHelloWorld C)

set(CMAKE_C_STANDARD 99)

link_directories(lib)

add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME} PRIVATE libgtk-x11-2.0.so libgdk-x11-2.0.so libXrender.so libgdk_pixbuf-2.0.so libpangocairo-1.0.so libXdamage.so libXfixes.so libatk-1.0.so libpng16.so libxcb-shm.so libxcb-render.so libX11.so libgio-2.0.so libpangoft2-1.0.so libfontconfig.so libfreetype.so libz.so libexpat.so libffi.so libgmodule-2.0.so libgthread-2.0.so libglib-2.0.so)

path/to/arm-linux-gnueabi-gcc.exe -{PARAMETERS BELOW...} -print-search-dirs prints (formatted):

...
Library:
d:/gcc/lib/gcc/arm-linux-gnueabi/5.5.0/
d:/gcc/lib/gcc/arm-linux-gnueabi/
d:/gcc/lib/gcc/
d:/gcc/arm-linux-gnueabi/lib/arm-linux-gnueabi/5.5.0/
d:/gcc/arm-linux-gnueabi/lib/arm-linux-gnueabi/
d:/gcc/arm-linux-gnueabi/lib/
D:/sysroot/lib/arm-linux-gnueabi/5.5.0/
D:/sysroot/lib/arm-linux-gnueabi/
D:/sysroot/lib/
D:/sysroot/usr/lib/arm-linux-gnueabi/5.5.0/
D:/sysroot/usr/lib/arm-linux-gnueabi/
D:/sysroot/usr/lib/

Problem

Everything had been fine until I tried to compile the binary.

I got errors like:

arm-linux-gnueabi/bin/ld.exe: cannot find /lib/libc.so.6
arm-linux-gnueabi/bin/ld.exe: cannot find /usr/lib/libc_nonshared.a
arm-linux-gnueabi/bin/ld.exe: cannot find /lib/ld-linux.so.3
collect2.exe: error: ld returned 1 exit status

The minimal command to reproduce the error:

path/to/arm-linux-gnueabi-gcc.exe \

--sysroot=D:/sysroot \
-g CMakeFiles/gtkHelloWorld.dir/main.c.o \
-LD:/Code/gtkHelloWorld/lib \
-lgtk-x11-2.0  -lgdk-x11-2.0  -lXrender  -lgdk_pixbuf-2.0  -lpangocairo-1.0  -lXdamage  -lXfixes  -latk-1.0 -lpng16  -lxcb-shm  -lxcb-render  -lX11  -lgio-2.0  -lpangoft2-1.0  -lfontconfig  -lfreetype  -lz  -lexpat  -lffi  -lgmodule-2.0  -lgthread-2.0  -lglib-2.0 

-v option prints (formatted):

Using built-in specs.
COLLECT_GCC=D:\gcc\bin\arm-linux-gnueabi-gcc.exe
COLLECT_LTO_WRAPPER=d:/gcc/libexec/gcc/arm-linux-gnueabi/5.5.0/lto-wrapper.exe
Target: arm-linux-gnueabi
Configured with: ...

Thread model: posix
gcc version 5.5.0 (Linaro GCC 5.5-2017.10)
COMPILER_PATH=
d:/gcc/libexec/gcc/arm-linux-gnueabi/5.5.0/;
d:/gcc/libexec/gcc/arm-linux-gnueabi/;
d:/gcc/libexec/gcc/;
d:/gcc/arm-linux-gnueabi/bin/

LIBRARY_PATH=
d:/gcc/lib/gcc/arm-linux-gnueabi/5.5.0/;
d:/gcc/lib/gcc/arm-linux-gnueabi/;
d:/gcc/lib/gcc/;
d:/gcc/arm-linux-gnueabi/lib/;
D:/sysroot/lib/;
D:/sysroot/usr/lib/

COLLECT_GCC_OPTIONS='-g' '-LD:/Code/gtkHelloWorld/lib' '-v' '-march=armv7-a' '-mtune=cortex-a9' '-mfloat-abi=soft' '-mthumb' '-mtls-dialect=gnu'

d:/gcc/libexec/gcc/arm-linux-gnueabi/5.5.0/collect2.exe \
-plugin d:/gcc/libexec/gcc/arm-linux-gnueabi/5.5.0/liblto_plugin-0.dll \
-plugin-opt=d:/gcc/libexec/gcc/arm-linux-gnueabi/5.5.0/lto-wrapper.exe \
-plugin-opt=-fresolution=C:\Users\w568w\AppData\Local\Temp\ccWU1Lgv.res \
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s \
--sysroot=D:/sysroot \
--build-id --eh-frame-hdr \
-dynamic-linker /lib/ld-linux.so.3 \
-X -m armelf_linux_eabi D:/sysroot/usr/lib/crt1.o D:/sysroot/usr/lib/crti.o d:/gcc/lib/gcc/arm-linux-gnueabi/5.5.0/crtbegin.o \
-LD:/Code/gtkHelloWorld/lib \
-Ld:/gcc/lib/gcc/arm-linux-gnueabi/5.5.0 \
-Ld:/gcc/lib/gcc/arm-linux-gnueabi \
-Ld:/gcc/lib/gcc \
-Ld:/gcc/arm-linux-gnueabi/lib \
-LD:/sysroot/lib \
-LD:/sysroot/usr/lib \
CMakeFiles/gtkHelloWorld.dir/main.c.o \
-rpath D:/Code/gtkHelloWorld/lib \
-lgtk-x11-2.0 -lgdk-x11-2.0 -lXrender -lgdk_pixbuf-2.0 -lpangocairo-1.0 -lXdamage -lXfixes -latk-1.0 -lpng16 -lxcb-shm -lxcb-render -lX11 -lgio-2.0 -lpangoft2-1.0 -lfontconfig -lfreetype -lz -lexpat -lffi -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_ \
--no-as-needed d:/gcc/lib/gcc/arm-linux-gnueabi/5.5.0/crtend.o D:/sysroot/usr/lib/crtn.o

(...A lot of "attempt to open" and "succeeded"...)

opened script file D:/Code/gtkHelloWorld/lib/libc.so
attempt to open /lib/libc.so.6 failed
attempt to open /usr/lib/libc_nonshared.a failed
attempt to open /lib/ld-linux.so.3 failed

d:/gcc/arm-linux-gnueabi/bin/ld.exe: cannot find /lib/libc.so.6
d:/gcc/arm-linux-gnueabi/bin/ld.exe: cannot find /usr/lib/libc_nonshared.a
d:/gcc/arm-linux-gnueabi/bin/ld.exe: cannot find /lib/ld-linux.so.3

collect2.exe: error: ld returned 1 exit status

The file appeared in the output above, D:/Code/gtkHelloWorld/lib/libc.so is:

/* GNU ld script
   Use the shared library, but some functions are only in
   the static library, so try that secondarily.  */
OUTPUT_FORMAT(elf32-littlearm)
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a  AS_NEEDED ( /lib/ld-linux.so.3 ) )

What confuses me is that, all answers I could find tell me to add --sysroot= (or -Wl,--sysroot=), which I have done from the beginning.

Also, I can confirm that the three .so files exactly exist at {SYS_ROOT}/lib and {SYS_ROOT}/usr/lib.

I suppose that the linker does notice the sysroot, because removing --sysroot= from the command will produce another error saying cannot find crt1.o.

The answers I have tried but failed

  1. cannot find /lib/libc.so.6 even after setting sysroot : Add -Wl before --sysroot
  2. Cannot find /lib/libc.so.6 : Add --sysroot
  3. cannot find /lib64/libc.so.6 : Same situation, still no answer

CodePudding user response:

Thanks @n-1-8e9-wheres-my-share-m and @infinitezero for giving advice on how to debug this problem. Now I can answer it by myself.

The crucial point is that ld.exe does not always follow SYS_ROOT or see it as a virtual filesystem root.

It services as a shortcut for including a complete set of headers and libraries (usually useful when doing cross compilation). The documentation says:

--sysroot=dir

Use dir as the logical root directory for headers and libraries. For example, if the compiler normally searches for headers in /usr/include and libraries in /usr/lib, it instead searches dir/usr/include and dir/usr/lib.

But the document omits some special rules. As was discussed here,

You misunderstand GNU ld's --sysroot rule, which is applicable in these two cases:

  • when a path begins with = or $SYSROOT
  • (Only) in case a sysroot prefix is configured, and the filename starts with the ‘/’ character, and the script being processed was located inside the sysroot prefix, the filename will be looked for in the sysroot prefix.

Otherwise, ld will only look at the absolute path defined in the script (/lib/xxx), instead of {SYS_ROOT}/lib/xxx.

So a quick fix for my problem is to change the ld script gtkHelloWorld/lib/libc.so in my project to

/* GNU ld script
   Use the shared library, but some functions are only in
   the static library, so try that secondarily.  */
OUTPUT_FORMAT(elf32-littlearm)
GROUP ( =/lib/libc.so.6 =/usr/lib/libc_nonshared.a  AS_NEEDED ( =/lib/ld-linux.so.3 ) )

Then it compiles normally.

Ref: for those who'd like to explore more about ld script, this is a comprehensive doc.

CodePudding user response:

You can try to add this to your cmake file

find_library(LIB_C "libc" HINTS ${USER_SYSROOT}/lib)
message(STATUS "LIB: ${LIB_C}")

To get an idea if cmake can find it. Then just add ${LIB_C} to target_link_libraries

  • Related