uclinux - link with libc.so.0 library - linux

I'm trying to compile "hello world" C application for embedded system with ARM processor running uClinux.
I'm using this toolchain
When I compiled C application with -static compilation flag the application is working fine.
When I removed -static flag - I got an error: can't load library 'libc.so.6'
libc.so.6 does not exists on the target,
into /lib folder on the target device the symbolic link libc.so.0 points to libuClibc-0.9.33.2.so
How can I "tell" compiler to link with libc.so.0?

I had a similar problem when cross-compiling a simple helloworld from an openwrt toolchain (using uClibc, target IPQ4028) to my router Gl-iNet-B1300.
After compiling successfully, I scp the file to the router and when trying to execute this error came up:
root#GL-B1300:~# ./helloworld
/root/helloworld: can't load library 'libc.so.0'
When I run 'ls -la | grep libc.so.' on /lib/, this came up:
libc.so.1 -> libuClibc-1.0.14.so
So as libc.so.0 wasn't there, I just created a link in /lib/
lib/# ln -s libc.so.1 libc.so.0
Running again 'ls -la | grep libc.so.':
libc.so.0 -> libc.so.1
libc.so.1 -> libuClibc-1.0.14.so
And then, executing the file:
root#GL-B1300:~# ./helloworld
Hell! O' world, why won't my code compile?
The value of pi is 3.141593
I guess the real problem here is that the toolchain I'm using is not the right one for the router firmware.

Seems like the toolchain you are using is built for glibc. But the target board has uClibc installed.
These two libraries are incompatible.
At runtime they are incompatible, and at compile-time they are incompatible.
You cannot "tell the compiler to use a different & incompatible library.
You need to obtain a toolchain that is built specifically for uClibc instead of glibc/eglibc.
The site gnuarm.com used to have some reliable toolchains, but that site is no more.
You could try and build your own toolchain using crosstool-NG, which is a lot easier than building the individual toolchain packages. Try the arm-unknown-linux-uclibcgnueabi configuration and customize it to your needs.

You should add the code "load XXX.lib" in your code if you remove -I.
There are some differences between static and dynamic link which you can find in Google.

Related

Understanding target_link_libraries

I am new to Linux. I see in my CMakeLists.txt the following;
target_link_libraries(app wiringPi
serializer
iothub_client
iothub_client_mqtt_transport
umqtt
aziotsharedutil
ssl
crypto
curl
pthread
m
ssl
crypto)
My question/understanding is; by doing this
Are we telling CMake tool to build wiringPi, serializer etc. and link with app(which is an executable created in my code)?
Where are all these libraries located?
When I do ldconfig -p | grep <libraryname>, for the above libraries
sometimes I find outputs like the following and sometimes nothing, why is that?
Is target_link_libraries smart enough to look for libraries under
the sub-directories too? I mean I see that some are just there under
user/lib and some are one more level under such as
/usr/lib/arm-linux-gnueabihf
pi#raspberrypi:~ $ ldconfig -p | grep curl
libcurl.so.4 (libc6,hard-float) => /usr/lib/arm-linux-gnueabihf/libcurl.so.4
libcurl-gnutls.so.4 (libc6,hard-float) => /usr/lib/arm-linux-gnueabihf/libcurl-gnutls.so.4
pi#raspberrypi:~ $ ldconfig -p | grep wiringPi
libwiringPiDev.so (libc6,hard-float) => /usr/local/lib/libwiringPiDev.so
libwiringPiDev.so (libc6,hard-float) => /usr/lib/libwiringPiDev.so
libwiringPi.so (libc6,hard-float) => /usr/local/lib/libwiringPi.so
libwiringPi.so (libc6,hard-float) => /usr/lib/libwiringPi.so
Are we telling CMake tool to build wiringPi, serializer etc. and link with app(which is an executable created in my code)?
Not exactly. That command tells CMake that the libraries wiringPi, serializer, etc. must be linked to target 'app' during the link stage for that target. It says nothing about building the libraries themselves, and usually they are expected to already be available rather than built.
Where are all these libraries located?
It can vary. The compiler has a default list of directories in which it looks for libraries. Other CMake commands can add link options that add directories to that list.
When I do ldconfig -p | grep <libraryname>, for the above libraries sometimes I find outputs like the following and sometimes
nothing, why is that?
ldconfig reports on libraries known to the dynamic linker. This is distinct from the linker that runs at compile time, and the directories and libraries the two know about are not necessarily the same. Reasons why ldconfig might not list a given library include:
The library is not installed.
Only a static version of the library is installed.
The library is not in any of the locations that the dynamic linker checks by default (additional directories can be specified when a program is launched, in at least two different ways).
Is target_link_libraries smart enough to look for libraries under the sub-directories too? I mean I see that some are just there under user/lib and some are one more level under such as /usr/lib/arm-linux-gnueabihf
This is not a function of CMake, but rather of the chosen toolchain and its configuration (on Linux, that's often the GNU toolchain, featuring GCC). It is usually safe to assume that the toolchain uses all the right standard library directories by default. CMake sometimes can successfully be instructed to search for specific libraries in other likely places, too, but target_link_libraries is not part of that.
When you pass to target_link_libraries a plain name (not a path) which is not a target, CMake just transforms this name into the linker flag. E.g. on Linux this is flag
-l<library-name>
So questions about searching the library you may address directly to the linker - CMake is out of the game here.

Keep gcc linker from using non-system libraries found in system /lib64 folder

I am porting a large C++ library (libcoro.so) and example application (coro-example.cpp) from Windows to RedHat Linux 7.4. I have very little development experience on Linux, so this is probably a 'newbie' question. I have libcoro and the example app compiling, linking, and running on my RHEL 7.4 VM. However, the gcc linker fails to link the app on the customer's RHEL 7.4 machine when he tries to link coro-example.o to libcoro.so. The error message is:
/usr/bin/ld: warning: libusb-0.1.so.4, needed by ./bin/libcoro.so not
found (try using -rpath or -rpath-link) libcoro.so: undefined
reference to 'usb_open' libcoro.so: undefined reference to
'usb_release_interface' ...etc...
Running 'ldd coro.so' on my machine displays:
libusb-0.1.so.4 => /lib64/libusb-0.1.so.4 (0x00007f71115db000)
...etc...
And on the customer's machine:
libusb-0.1.so.4 => not found [many other libs] => not found ...etc...
Indeed, these libraries are in my /lib64 folder, but are not in the customer's. I'm not sure how they got installed on my machine. I have access to the missing libraries and can deliver them with my libcoro.so library. I really want my app to be self-contained and run on any RHEL 7.x machine. My question is:
What is the best way to identify which libraries are not part of the RHEL 7.x installation and have the linker fail on my machine if I'm not delivering a local copy? I tried linking with -nodefaultlibs, but the link fails on functions like printf() and I haven't found a way to locate these standard libraries. They don't appear to be in /lib64.
Is there a way to exclude /lib64 from the default library search?
There is a linker switch -Wl,--no-undefined which seems to do what I want. It fails to link and generates an error is the library is isn't explicitly named. Also, the command ldd libcoro.so lists all dependencies and where they are being resolved. I also found this this article very helpful.

Compiling my C program with my customized library (.h) using Linux

Hi team,
I have three files which I need to compile for testing, btw im using CentOS linux.
source_code.c
library.h
library.c
how do I put the library.h in the gcc library, so I can use it?
how do I compile the source_code.c to use that library?
Thank you very much.
This is basic knowledge of your tools, but you can do this:
#include "library.h" in the include section of the library.c code (at top of the file).
gcc source_code.c library.c in the linux terminal will link and compile both source_code.c and library.c. This will generate an executable named "a.out" (if there were no compilation problems). You can change its name, by adding the option -o name to the gcc command (gcc source_code.c library.c -o mycode will generate an executable named "mycode").
If you really need a library that will be used by a lot of other programs, you can look for "shared libraries", but I think that you are asking for a basic thing.
You dont need this library.h while building and executable (with gcc) as you should have specified the exact location of the library in the source file. All you need to do is gcc sourcefile1.c sourcefile2.c -o exename

How to cross compile a C++ file with LTIB

I have installed LTIB from freescale (by way of Congatec) and would like to compile a "hello, world" program. gcc gives me the native executable. How do I compile for my ARM processor?
You need to install a cross compiler for ARM. gcc on your machine is the native compiler, a cross compiler has a different prefix that determines the target architecture, operating system and libc. In your case, the target system has probably an ARM architecture, is running a Linux kernel with the GNU libc.
arm-none-linux-gnueabi-gcc -o hello hello.cpp
Run ./ltib -m shell. In this mode all of the standard tools are setup to allow ./configure and other setups to build for an ARM by default. From this shell gcc -o hello hello.cpp will create an executable for you. It will be setup for your rootfs, be it uCLibc or glibc. You can also take external open-source packages and run the ./configure - make cycle.
The documentation in the LTIB FAQ has much more information on using LTIB. LTIB typically installs tools in the /opt/freescale directory. If you are not using a custom compiler you will find the compiler under /opt/freescale and can use it directly. In this directory, the compiler will be named something like arm-none-linux-gnuabi-gcc. With the ./ltib -m shell, it is aliased to gcc as are many other standard commands for cross-building.
Look at the -march=name option in the gcc man page. The exact architecture you will specify depends on the version of ARM you need to compile for. v5 ARM example:
gcc -o ARM.exe -march=armv5 source.c
First move to the LTIB folder.
cd "ltib folder"
Then enter the ltib shell
./ltib -m shell
then compile using
gcc -static "program name" .c -o "program name".sabre
Then run the command
file "program name".sabre

relocation error & Linux sw distributing

This is my goal: I developed software in Linux and I need to distribute it without source code. The idea is to create a zip file that contains all the necessary items to run the executable. The user will download the zip, extract it, double-click, and the software will start on any Linux-based machine. For motivations that I'm not gonna explain, I can't use deb/rpm/etc or an installer.
The sw has the following dependencies:
some libraries (written by myself that depends on OpenCV), compiled with g++, creating .a files (i.e. static libraries)
OpenCV, in shared libraries, that have several depenencies
I compile my program with gcc, and I link it with:
$ gcc -o my_exe <*.o files> -L<path my_lib> -Wl,--rpath,\$$ORIGIN/lib -lm -lstdc++ -lmy_lib -lopencv
Then I do:
$ ldd my_exe
and I copy all the libraries here listed in ./lib, and I create the .zip.
I copy the zip in an another machine, the dependencies listed by ldd my_exe are satisfied and correctly point to ./lib but when I launch the program, I get the following error:
$ ./my_exe: relocation error: lib/libglib-2.0.so.0: symbol strncmp, version GLIBC_2.2.5 not defined in file libc.so.6 with link time reference
What's wrong? Where is my mistake?
Some additional info:
$ -bash-3.2$ nm -D lib/libc.so.6 |grep strncmp
0000000000083010 T strncmp
$ -bash-3.2$ strings lib/libc.so.6 |grep GLIBC_2.2
GLIBC_2.2.5
GLIBC_2.2.6
I'm using gcc 4.4.5, Ubuntu with a kernel 2.6.35 SMP, 64bit. The machine that I tried is 64bit SMP kernel 2.6 as well.
You seems to re-invent what package managers (for .deb, .rpm, ...) are doing. Why don't you want to make a real package. It would make things simpler and more robust.
And since you code in C++, you will have hard time in making a thing which will work with different versions of libstdc++*.so

Resources