Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to work with external libraries when cross compiling?

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?

like image 418
Punit Soni Avatar asked Sep 19 '13 17:09

Punit Soni


People also ask

Why is cross-compiling so hard?

"building a cross-compiler is significantly harder than building a compiler that targets the platform it runs on." The problem exists due to the way libraries are built and accessed. In the normal situation all the libraries are located in a specific spot, and are used by all apps on that system.

How does cross-compiling work?

A cross compiler is a compiler capable of creating executable code for a platform other than the one on which the compiler is running. For example, a compiler that runs on a PC but generates code that runs on an Android smartphone is a cross compiler.

Can GCC cross compile?

For instance when installing GCC, the GNU Compiler Collection, we can use --target= target to specify that we want to build GCC as a cross-compiler for target . Mixing --build and --target , we can cross-compile a cross-compiler; such a three-way cross-compilation is known as a Canadian cross.


4 Answers

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.

like image 136
gerrit zijlstra Avatar answered Oct 17 '22 06:10

gerrit zijlstra


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

like image 27
vinay hunachyal Avatar answered Oct 17 '22 04:10

vinay hunachyal


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.

like image 2
Mats Petersson Avatar answered Oct 17 '22 05:10

Mats Petersson


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.

like image 1
TwoCode Avatar answered Oct 17 '22 06:10

TwoCode