How to work with external libraries when cross compiling?

48,605

Solution 1

Regarding your general questions:

Why the C library works:

The C library is part of your cross toolchain. That's why the headers are found and the program correctly links and runs. This is also true for some other very basic system libraries like libm and libstdc++ (not in every case, depends on the toolchain configuration).

In general when dealing with cross-development you need some way to get your desired libraries cross-compiled. Using binaries in this case is very rare. That is, especially with ARM hardware, because there are so many different configurations and often everything is stripped down much in different ways. That's why binaries are not very much binary compatible between different devices and Linux configurations.

If you're running Ubuntu on the Raspberry Pi then there is a chance that you may find a suitable ncurses library on the internet or even in some Ubuntu apt repository. The typical way, however, will be to cross compile the library with the specific toolchain you have got.

In cases when a lot and complex libraries need to be cross-compiled there are solutions that make life a bit easier like buildroot or ptxdist. These programs build complete Linux kernels and root file systems for embedded devices.

In your case, however, as long as you only want ncurses you can compile the source code yourself. You just need to download the sources, run configure while specifying your toolchain using the --host option. The --prefix option will choose the installation directory. After running make and make install, considering everything went fine, you will have got a set of headers and the ARM-compiled library for your application to link against.

Regarding cross compilation you will surely find loads of information on the internet and maybe ncurses has got some pointers in its shipped documentation, too.

Solution 2

For the query How the C library works in cross-tools

When compiling and building cross-tool chain during configuration they will provide sysroot.

like --with-sysroot=${CLFS_CROSS_TOOLS}

--with-sysroot --with-sysroot=dir

Tells GCC to consider dir as the root of a tree that contains (a subset of) the root filesystem of the target operating system. Target system headers, libraries and run-time object files will be searched for in there. More specifically, this acts as if --sysroot=dir was added to the default options of the built compiler. The specified directory is not copied into the install tree, unlike the options --with-headers and --with-libs that this option obsoletes. The default value, in case --with-sysroot is not given an argument, is ${gcc_tooldir}/sys-root. If the specified directory is a subdirectory of ${exec_prefix}, then it will be found relative to the GCC binaries if the installation tree is moved.

So instead of looking /lib /usr/include it will look /Toolchain/(libc) and (include files) when its compiling

you can check by

arm-linux-gnueabihf-gcc -print-sysroot

this show where to look for libc .

also

arm-linux-gnueabihf-gcc -print-search-dirs

gives you clear picture

Solution 3

Clearly, you will need an ncurses compiled for the ARM that you are targeting - the one on the host will do you absolutely no good at all [unless your host has an ARM processor - but you said x86, so clearly not the case].

There MAY be some prebuilt libraries available, but I suspect it's more work to find one (that works and matches your specific conditions) than to build the library yourself from sources - it shouldn't be that hard, and I expect ncurses doesn't take that many minutes to build.

Solution 4

As to your first question, if you intend to use ncurses library with your cross-compiler toolchain, you'll have its arm-built binaries prepared.

Your second question is how it works with std libs, well it's really NOT the system libc/libm the toolchain is using to compile/link your program is. Maybe you'll see it from --print-file-name= option of your compiler:

arm-none-linux-gnuabi-gcc --print-file-name=libm.a

...(my working folder)/arm-2011.03(arm-toolchain folder)/bin/../arm-none-linux-gnuabi/libc/usr/lib/libm.a

arm-none-linux-gnuabi-gcc --print-file-name=libpthread.so

...(my working folder)/arm-2011.03(arm-toolchain folder)/bin/../arm-none-linux-gnuabi/libc/usr/lib/libpthread.so

I think your Raspberry toolchain might be the same. You can try this out.

Solution 5

Vinay's answer is pretty solid. Just a correction when compiling the ncurses library for raspberry pi the option to set your rootfs is --sysroot=<dir> and not --with-sysroot . Thats what I found when I was using the following compiler:

arm-linux-gnueabihf-gcc --version
arm-linux-gnueabihf-gcc (crosstool-NG linaro-1.13.1+bzr2650 - Linaro GCC 2014.03) 4.8.3 20140303 (prerelease)
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Share:
48,605
Punit Soni
Author by

Punit Soni

I am a computer engineering grad student at North Carolina State University, USA. My interests are Embedded Systems Software OS and kernel programming Linux Hardware Interfacing Device Drivers

Updated on May 12, 2020

Comments

  • Punit Soni
    Punit Soni almost 4 years

    I am writing some code for raspberry pi ARM target on x86 ubuntu machine. I am using the gcc-linaro-armhf toolchain. I am able to cross compile and run some independent programs on pi. Now, I want to link my code with external library such as ncurses. How can I achieve this.

    Should I just link my program with the existing ncurses lib on host machine and then run on ARM? (I don't think this will work) Do I need to get source or prebuilt version of lib for arm, put it in my lib path and then compile?

    What is the best practice in this kind of situation?

    I also want to know how it works for the c stdlib. In my program I used the stdio functions and it worked after cross compiling without doing anything special. I just provided path for my arm gcc in makefile. So, I want to know, how it got correct std headers and libs?

  • Punit Soni
    Punit Soni over 10 years
    Thanks, I was just trying to confirm, that this is the best way to do it. So, how does the stdlib works in this case. I did not compile or link the stdlib for ARM here.
  • Punit Soni
    Punit Soni over 10 years
    Thanks, that was helpful. One more general question. Regarding the C libraries, I did not specify any path in makefile. I just provided the path to arm-gcc, so how does it know where to find the stdlib. I know that for external lib, I can specify the path using -L.
  • Punit Soni
    Punit Soni over 10 years
    Thanks, that makes sense.
  • cifer
    cifer about 8 years
    @PunitSoni arm-gcc will caculated itself according to relative path, so you can't change the directory structure of your cross compiler
  • Michael
    Michael over 7 years
    might help to give an example of how those options (--host, --prefix) work.
  • pavon
    pavon almost 3 years
    So, if I have an ISO for my embedded system, can I mount that ISO (read-only) and use --with-sysroot to make the cross-compiler use all those system libraries when building new packages?