Cross Compile Cannot Link Curl and Crypto - c++

I installed arm-linux-gnueabihf via sudo apt-get install arm-linux-gnueabihf and i want to do cross compile for Raspberry Pi.
My make file is like that:
arm-linux-gnueabihf-g++ *.cpp *.h b64.c -o file -lcurl -lcrypto -lpthread -lssl
and an error occured like that:
/usr/arm-linux-gnueabihf/bin/ld: cannot find -lcurl
/usr/arm-linux-gnueabihf/bin/ld: cannot find -lcrypto
Also I tried to link with -L/usr/lib/x86_64-linux-gnu/libcurl.so but it is still same error.
Also i don't understand why libssl a is linked but others do not.
How can I link these libraries to arm-linux-gnueabihf?
Thank you.

You cannot link x86-64 bit libraries with arm-linux-gnueabihd.
You need to get gnueabihf libraries of curl and crypto.
One way: cross-compile curl and crypto libraries, use -L to specify directories where cross-compiled libcurl.so and libcrypto.so for gnuaebihf machine reside.
Another way: copy libcurl.so and libcrypto.so from raspberrypi onto your computer, specify directory where they reside with -L and try to compile, it should work.
ssl and pthread is linked, because you provide ssl and pthread libraries compiled for gnueabihf architecture. Look in /usr/arm-* for those files, probably in /usr/arm-linux-gnueabihf/lib.
Generally, for beginners, just compile your program on your raspberry pi (with curl and crypto installed), it will spare you much trouble.
The line -L/usr/lib/x86_64-linux-gnu/libcurl.so is invalid. You don't specify file using -L command line, you specify directory which contains libcurl.so. Also you specified directory with x86-64 architecture specific libraries while using gnueabihf compiler, they will not work, they are not compatible, no. You cannot link x86_64-linux-gnu/libcurl.so or any x86-64 library with a gnueabihf program.
The whole idea of crosscompiling is that you compile for another architecture. You don't mix those architectures, as they are not compitable with each other, just like you can't run x86-64 program on you raspberry pi, and you can't run a rapberry pi program on you computer. The machine codes of two architectures are not compatible with each other.
When you compile a program for gnueabihf architecture, you need to link gnuabihf libraries and use gnuabihf object files and use a compiler that will generate gnueabihf specific machine code. When you compile program for x86-64 machine, you need to link x86-64 libraries and use x86-86 object files and use a compiler that will generate x86-64 machine code.
Probably it may be also worth to you, use file command to determine file type. You may run file /usr/lib/x86_64-linux-gnu/libcurl.so to see that this libcurl.so is a x86-64 shared object.

Related

Winlibs and libcurl

I am asking here because I couldn't get any support elsewhere. Also consider that I am quite a beginner so bear patience.
I am using Winlibs (winlibs.com, a ready to use mingw gcc10+ distribution) to code under Windows because after having tried other alternatives I judged it the best to my purposes, easiest to install and the most functional. I never had any problems with it.
But recently I had the need of writing some simple code to send a POST request. I wanted to do it in a possibly portable and c++ friendly manner, so I was suggested to use Curl. No libcurl is included in winlibs so I tried to load one from here
https://curl.se/download.html
I chose the windows 64 binary of course (7.83.1) since I am working on windows 64 with winlibs 64. I installed everything in the right place and linked against libcurl.a.
Unfortunately the linker complains of unresolved symbols so I have to supppose the curl binaries I used are not suitable.
How can I use libcurl with winlibs then ? Before bothering here I really googled but could find no info!
The MinGW-w64 tools from https://winlibs.com/ are only a build toolchain, so they don't contain libraries for you to link with (yet).
You need a Windows build of libcurl and use that.
To use it you must include the location to the header files using the -I compiler flag, and then link with the library by pointing to the location of the .a file with the -L linker flag and then link with the library using the -l flag (-lcurl in this case). If you don't have .a files you can also try to link with the full path of the .dll file and gcc will know it's a shared library.
An easier way is to get libcurl via MSYS2's pacman package manager.
If you want to statically link you need to use the output of pkg-config --static --libs libcurl as link flags.
In practice though I noticed that sometomes pkg-config --static --libs libcurl is missing some dependencies and you still need to add some manually. An example of a project of mine that builds on Windows with winlibs MinGW-w64 (both 32-bit and 64-bit) can be found at https://github.com/brechtsanders/winlibs_tools/blob/main/Makefile (specifically look for the definition of CURL_LDFLAGS)

linaro compiler cannot find library when adding -static

I am trying to statically cross-compile an Application for ARM using the Linaro-Toolchain 7.1.1 . The final elf file is dependent on two shared-objects. I need to statically compile the application because there are dependencies that are not available on my target-system (eg. libstdc++). The -L and -I flags are in the makefile and everything works normally without the -static Flag. However when i use the -static flag, my linaro-linker tells me that it cannot find the dependencies, even though i know they are there as liba.so and libb.so. Any help or point to literature is appreciated, i feel like i did not fully understand what -static does, eventhough i did my research online.
Thanks
Thanks to your comments i was able to solve my problem and understand why i had it.
As user RPGillespie mentioned, the -static flag needs archived (libx.a) versions of the objects, so i had to compile the .o files to .a files using the ar-tool from the linaro toolchain.
Furthermore, as user RPGillespie refered me to, i had to specify the archives x using -l:libx.a instead of -lx in the g++ command.
Also it took me some time to notice that if the x.a files are not present, the linker will link dynamically. In my makefile the executable was compiled before the x.a file was available (because i just modified the makefile used to build the x.so).

Trying to run a cross-compiled executable on target device fails with: No such file or directory

I've got caught in the not-so-sunny world of cross-compilation.
I'm trying to compile a simple hello world application for my BeagleBone Black (which runs a TI Cortex-A8 processor).
First of all, I compiled and ran successfully the hello world application on x86 with gcc
Then I changed my compilation settings to the following:
arm-linux-gnueabi-gcc -c -O0 -g3 -Wall main.c -o bin/obj/main.o
arm-linux-gnueabi-gcc bin/obj/main.o -o bin/hello_world
I transferred the file via SCP to the BeagleBone, and set executable permissions with chmod +x hello_world
Upon running it (./hello_world), my only response is:
-bash: ./hello_world: No such file or directory
The output of file matches that of /sbin/init as I would expect:
$ file hello_world
hello_world: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=0x24b659b7a41fe043a6f4649d4ebfb5e692ebf0c7, not stripped
$ file /sbin/init
/sbin/init: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xd21f6957ec031a27d567b3d5e6aa14b9e0c30c37, stripped
The result of ldd is:
$ ldd hello_world
not a dynamic executable
I tried adding a suitable platform and CPU type, changing my compilation to:
arm-linux-gnueabi-gcc -c -O0 -g3 -Wall -march=armv7-a -mtune=cortex-a8 main.c -o bin/obj/main.o
arm-linux-gnueabi-gcc bin/obj/main.o -o bin/hello_world
This initially started giving me a new error: Text file busy, but I have since been unable to get that error back again as it now returns No such file or directory. I'm guessing that particular attempt was just a bad transfer or something.
Since nobody from the comments posted the answer, I guess I get the pleasure ;)
No such file or directory comes from when the kernel tries to invoke the dynamic linker specified by the ELF executable's .interp field, but no such file exists.
The .interp field can be found with the following command:
objdump -j .interp -s ./hello_world
In the case of this example, the executable's .interp field was /lib/ld-linux.so.3, but the name of the dynamic linker on the BeagleBone Black is /lib/ld-linux-armhf.so.3.
This happened because the program was compiled with a slightly different toolchain to the one required for the platform. It should be arm-linux-gnueabihf-* rather than arm-linux-gnueabi-*.
The difference between the two is that the Cortex-A8 uses specific floating point registers with the hard-float version (armhf) of the EABI, but the original EABI (armel) uses integer registers for passing around floating point numbers. As a result, armel programs will run on armhf (provided the dynamic linker is set to the correct path!), but not vice versa.
Simply adding a symbolic link ln -s /lib/ld-linux-armhf.so.3 /lib/ld-linux.so.3 is enough to resolve this issue, but the correct fix is to use the right toolchain when compiling the program in the first place.
I had the same problem. I downloaded and installed gcc-arm-linuc-gnueabihf package to my Ubuntu PC from the Ubuntu repository using apt-get. Then I compiled a helloworld test program and downloaded it using sftp to my BeagleBone.
Trying to run the program on BBB gave the error: "No such file or directory"
Using objdump I found that the .interp field in the ELF executable was /lib/ld_linux_armhf.so.3. My BBB had dynamic linker /lib/ld-linux.so.3.
I created a symbolic link on the BBB:
ln -s /lib/ld-linux.so.3 /lib-linux-armhf.so.3
Now the cross-compiled application works on BBB. The BBB is running the original Angstrom distribution.
This is not the ideal fix. Now I need to either confgure the toolchain in Ubuntu to add the correct dynamic linker name to the app, or update the BBB to have a dynamic linker specified in the toolchain.
I assume the error message is due to the dynamic linker file not found, not that the application doesn't exist.
How to identify the problem?
file cross_compiled_executable
Contains something like:
interpreter /lib/ld-uClibc.so.0
and the problem is that that file does not exist on the target.
How to solve the problem?
Use a proper compiler, either:
the person who created the disk image must provide you the cross compiler or tell you exactly how to build it, e.g. with crosstool-ng. For BeagleBone asked at: Toolchain to crosscompile Applications for BBB
compile your own image and cross compiler, e.g. with Buildroot. Here is a generic QEMU example. Buildroot has BeagleBone support.
use a native compiler on the target. But generally targets are much slower than your host, and space constrained, so you likely don't want to do this.
You might also be able to use a functional emulator such as QEMU to build, and then only run the programs on a slower platform, e.g. gem5 or a slow board.
Just hacking up the interpreter is potentially not enough, notably you have to ensure binary compatibility between the program and the target libc, or program and kernel interfaces (syscalls, /proc, etc.) if you try to use -static (the target kernel might be too old and not contain the required interfaces). The only robust solution is to use the correct toolchain.

Glibc issue using g++

I have a problem, i'm compiling my C++ app in Linux machine. Then i move executable to other machine, but i have an error:
./server: /lib64/libc.so.6: version `GLIBC_2.7' not found (required by ./server)
How can i fix it? Without recompiling on second machine where this error happens (it is my client machine)
Compile command:
g++ -o server test.cpp server.cpp ... -lboost_system -lboost_thread -std=c++0x
Thanks!
Your app is using glibc-2.7 library, and app can not find it on other machine. It probably have older version of this library. You have following options:
Upgrade this library on target host
Link you app against older library version
Use static linking
Ship library together with app
How statically link to just one library:
gcc main.c mylibrary.a -o main
Note that most distros do not install static libraries by default.
There are three choices:
compile on the original machine with -static given to the compiler, which will include the relevant libraries in your binary [and possibly give you a warning or two about "this may not work right"]
compile the code on the new machine.
Install the correct version of library on the target machine.
I tend to use option 1 most of the time, but have used all three at various points.

compile against libc++ statically

I wrote some custom c++ code and it works fine in ubuntu, but when I upload it to my server (which uses centos 5) its fails and says library is out of date. I googled all around and centos cannot use the latest libraries. How can I compile against the stl so that it is included in the binary and it doesn't matter that centos uses an old library?
P.S. I don't want to upload the source to the server and compile there.
In your linking step, you can simply add the "-static" flag to gcc:
http://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Link-Options.html#Link-Options
You may install on your Ubuntu box the compiler that fits the version of the library on your server.
You may ship your application with libstdc++.so taken from the system you compiled it at, provided you tune the linking so it gets loaded instead of centos' one.
You may compile it statically. To do this, you should switch your compiler from g++ to
gcc -lgcc_s -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic
Choose whatever you like. Note that approaches (2) and (3) may arise the problem of dependencies: your project (particularly, the stdc++ implementation that, being statically linked, is now a part of your app) may require some functions to present in the system libraries on centos. If there are no such functions, your application won't start. The reason why it can happen is that ubuntu system you're compiling at is newer, and forward compatibility is not preserved in linux libraries.