I am pretty new to cross compilation and I am not sure whether the executable which is getting created through cross compilation is correct or not.
Basically I am working on project which needs the libs to be compiled from different toolchains.
So I have compiled a library on ubuntu system using a arm toolchain and the library is compiled successfully. But now on ubuntu when I try to perform ldd on its arm executable, it shows a message "not a dynamic executable".
However this same library which is compiled from another qnap x86_64 toolchain works fine on performing ldd on its executable. I mean it shows proper dependecies as expected by ldd.
Now I am confused which one is the expected behavior. The one which is showing dependecies from ldd or the one which is showing "not a dynamic executable".
Could someone please clarify this concept to me?
Thanks
Related
Host system: x86-64 Linux, Ubuntu 20.04
Target system: aarch64 Linux, Debian 11, arm architecture: Cortex A53
I develop for an aarch64 based Linux system on matlab/simulink. This toolchain is currently worked out for Linux and Windows hosts. However due to additional IIO devices on the system it has become clear that the current approach of just hardcoding the IIO device numbers is not gonna work anymore.
Now I found libiio which works great when I compile simple programs on the target itself. However I have not managed to cross compile applications using the library.
I have been trying to cross compile the libiio library itself by making a cross compilation file:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_STAGING_PREFIX /home/maud/development/stage)
set(tools /usr/aarch64-none-linux-gnu)
set(CMAKE_C_COMPILER ${tools}/bin/aarch64-none-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/aarch64-none-linux-gnu-g++)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
when I run cmake ../ -DCMAKE_TOOLCHAIN_FILE=~/development/crosscomp.cmake
from the build folder that I made in the libiio folder it seems to work fine. But when I run make the issue starts.
[ 28%] Building C object CMakeFiles/iio.dir/dns_sd_avahi.c.o
Reaping winning child 0x55c895073d40 PID 36856
Live child 0x55c895073d40 (CMakeFiles/iio.dir/dns_sd_avahi.c.o) PID 36858
/home/maud/Downloads/libiio-master/dns_sd_avahi.c:24:10: fatal error: avahi-common/address.h: No such file or directory
24 | #include <avahi-common/address.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~
I get this error, I do have libavahi-common-dev and libavahi-client-dev installed.
But I think it wants aarch64 compiled versions of the dependencies.
And it makes me question whether this is even a feasible goal, whether what I'm doing is even going to get me to where I want to be.
Is it even possible to add a library like this to such a cross compiling toolchain?
I tried taking the .so file from the target, but it will complain about missing a bunch of other dependencies. And even then I will only have managed to build from a Linux host, building from a Windows host feels like it would require way more trouble but I could be wrong. I'm still learning a lot about how all this works.
I got it mostly working, I compiled the library localy on my ARM system, but I tore out a bunch of features that I didnt need anyway. this left me with a library that didnt have any external dependencies (like the previously mentioned avahi common/client and a bunch more), then referencing it in my makefile and inluding the the header file got it working.
Was also able to cross compile from my x86 based host.
I'm using Ubuntu 18.04 VM and trying to find a way to valgrind check an arm-Linux executable. I've tried compiling with local gcc but ran into some problems. The executable is created by Makefile provided from project. I've tried linaro emulator, following guides online, but faced multiple issues which for each one I've searched on online for solutions but all failed. What are the ways I can valgrind?
As long as I can check program for memory leak, any way is fine.
What I get when I valgrind executable now:
valgrind: failed to start tool 'memcheck' for platform 'arm-linux': No such file or directory
The file it self is fyi:
nrf52832_xxaa.out: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped
I've searched through multiple posts for solutions but couldn't find any.
Cross compile valgrind, and execute on the target. There are no other ways. Can't even use qemu to execute valgrind.
It is mandatory to run the executable on the device.
Please consider the option to download the precompiled package for your arch example from https://packages.debian.org/search?keywords=valgrind, follow the mandatory dependencies, and install all on you embedded device. I use to base the version according to the installed version of libc.
I need to use the GSL library in my program on LPCXpresso 4367(ARM CORTEX M4). I tried to follow the library linking procedure for LPC xpresso but the MCU linker is giving me these errors:
MCUXpressoIDE_10.3.0_2200\workspace\test1\Debug/../src/test1.c:53: undefined reference to 'gsl_linalg_LU_decomp'
MCUXpressoIDE_10.3.0_2200\workspace\test1\Debug/../src/test1.c:56: undefined reference to 'gsl_matrix_alloc'
MCUXpressoIDE_10.3.0_2200\workspace\test1\Debug/../src/test1.c:57: undefined reference to 'gsl_linalg_LU_invert'
and so on for other functions as well.
I have the libgsl.a and libgslcblas.a precompiled libraries for windows which works perfectly on codeblocks on windows with GCC compiler.
I read that I need to crosscompile library for the arm-none-eabi-gcc toolchain. But can someone please provide me the procedure as well?
the libgsl.a and libgslcblas.a precompiled libraries for windows
Those won't do for ARM.
In order to work on another platform, these libs need to be compiled from source code with the proper compiler (and settings - Cortex-M4F requires Thumb2 instruction set).
As the libraries are precompiled for Windows they don't work for ARM (as it is said in the other answer)
You need to cross compile the libraries first. If you install the GSL libraries following this procedure, you only need to change the parameters in the ./config according to your platform, for example I used:
./config --host=arm-linux-gnueabihf --prefix=/home/yourname/gsl_arm
Inside the .zip file with the gsl-2.5 files, there is a file called INSTALL. There you can find more details on the options for cross compiling.
Make sure to make clean before if you have already compiled the library for different settings. After cross-compiling the library when you run make check on the terminal you will probably get errors, but still it works. Continue with make install and you are ready to use it.
I am trying to cross compile libssh for ARM on a beaglebone black, following error happens when I run then 'make' command:
[ 52%] Linking CXX executable libsshpp_noexcept
../src/libssh.so.4.5.1: undefined reference to `deflateInit_'
I already run the cmake command with paths for libz and other arm gcc compiler paths, still facing the above error.
I was able to resolve this issue by rebuilding the correct arm version of zlib and re-installing it. Also using the ccmake GUI utility I removed the examples compilation which was creating other examples related errors. The correct installation of libssh requires, openssl, zlib, libzip all compiled for the same target arch as libssh.
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?
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.
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
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.
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.
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.