Search code examples
craspberry-picentoscross-compiling

Cross compile from CentOS 7 to Raspberry Pi 2B - can't get LIBC and system include headers to work together


I am trying to cross compile a hello world C program on a CentOS 7 64-bit machine to the Raspberry Pi 2B 32-bit target machine.

I downloaded the buster cross compiler cross-gcc-8.3.0-pi_2-3.tar.gz

My hello world C file is the standard hello world program that we all use.

When I inch up on my compile first just trying to compile

arm-linux-gnueabihf-gcc -o helloworld.exe helloworld.c

gives me:

/home/<redacted>/repos/pi-2-compiler/cross-pi-gcc-8.3.0-1/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: /lib64/libc.so.6: version `GLIBC_2.27' not found (required by /home/<redacted>/repos/pi-2-compiler/cross-pi-gcc-8.3.0-1/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld)
collect2: error: ld returned 1 exit status

The libc version is different on my CentOS machine from the target. The libc.so.6 file is in the cross compile path, so when I use the --sysroot option, I get over the libc problem, but get an inability to find the stdio.h file.

arm-linux-gnueabihf-gcc -o helloworld.exe helloworld.c --sysroot=/home/<redacted>/repos/pi-2-compiler/cross-pi-gcc-8.3.0-1/arm-linux-gnueabihf/libc/lib
helloworld.c:1:10: fatal error: stdio.h: No such file or directory
 #include <stdio.h>
          ^~~~~~~~~
compilation terminated.

The stdio.h file is in the cross compile path, but I can't determine way to add that path to the gcc command without destroying my link to the libc world. I tried -I, -isystem, .... but when I do that, I get the original GLIBC error

I am not inventing the wheel here, so there must be something I am missing. I am just getting into this cross compiling thing, and need help to build up my knowledge. I read may sites, but haven't quite found the answer.

Thanks for your help.


Solution

  • Not a total solution, but some explanation ...

    The TL;DR: Unfortunately, we don't have all the files we need.


    I downloaded and extracted the tar file from the link you provided.

    It creates a subdirectory: cross-pi-gcc-8.3.0-1

    Under that directory, we have subdirectories. Of note [some] are:

    arm-linux-gnueabihf
    bin
    lib
    

    To use a given cross-development utility (e.g. ld but similar for gcc, ar, etc.) they are located:

    ./bin/arm-linux-gnueabihf-ld
    ./arm-linux-gnueabihf/bin/ld
    

    These files are identical. Also, [again] they are x86_64 binaries that cross build for arm.

    So, to be able to use the cross build there are two methods:

    1. Set the PATH variable: export PATH=/home/redacted/cross-pi-gcc-8.3.0-1/arm-linux-gnueabihf. Then, if we type the command ld <something>, we are not using the native x86_64 version but the x86_64 to arm cross version.
    2. Instead of using ld, we can use arm-linux-gnueabihf-ld. Here, in our Makefile, we'd do something like: LD = arm-linux-gnueabihf-ld at the top. This works if we install the cross compiler so that the package bin is extracted into a standard bin directory (such as /usr/local/bin
    3. Otherwise, we'd need to do: export PATH=/home/redacted/cross-pi-gcc-8.3.0-1/bin and setting LD as above.

    Either way, we can now cross-build for arm ... Sort of ...

    Under the lib directory, we have libcc1* files. These are build for x86_64.


    The problem is that we do not have an aarch64/arm version of a library. So, if we do:

    arm-linux-gnueabihf-gcc -o hello hello.c
    

    There is no aarch64 (arm) version of (e.g.) libc.

    In other words, the package you downloaded has [just] the cross-compiler but no target system libraries.

    In other words, we'd need to add --sysroot=/path_to_sysroot to the gcc command.

    But, we do not have the sysroot files.

    With --sysroot, we'd expect to find:

    /path_to_sysroot/bin/ls
    /path_to_sysroot/lib/libc*
    

    And, the ls would be the aarch64/arm binary and the libc would have the library code compiled for aarch64/arm


    So, to remedy this, we have to find and download suitable packages that do have pre-built aarch64/arm binaries and have --sysroot= point to the top directory for these.

    Just to recap ... The sysroot directory should have the exact file hierarchy that the target system (e.g. the RPi) will have starting from its root / directory.


    Again, what you have is just the cross-compiler. But, no target libraries or binaries (e.g. ls, vim, etc.)

    You may want to consider a more full featured, one stop approach, such as linaro: