I am trying to compile omniORB on AIX 6.1 with gcc 4.2.0.
The initialization does not work as it is picking up the non pthreaded library.
If I set LIBPATH to /opt/freeware/lib/gcc/powerpc-ibm-aix6.1.0.0/4.2.0/ omniNames will not work, as the streams interface gives an exception.
Setting the LIBPATH to /opt/freeware/lib/gcc/powerpc-ibm-aix6.1.0.0/4.2.0/pthread seems to work, but other non pthreaded programs will pick up the pthreaded lib which may cause problems...
The link looks like this:
g++ -o omniNames -O2 -Wall -Wno-unused -fexceptions -Wl,-brtl -Wl,-blibpath:/lib:/usr/lib:/opt/dbx/omniORB-4/lib -L../../../lib -L../../../../lib omniNames.o NamingContext_i.o log.o omniNamesWin.o -lomniORB4-ar -lomnithread34 -lpthreads
How do I resolve this ??
Note that I have tried to change libpath using configure arguments but without success.
Launching via a wrapper script which set LIBPATH correctly is probably the easiest.
Then there is the RUNPATH/RPATH feature of ELF which allows to embded a search path for dynamic libraries in the executable; but I don't know if AIX implement it. It it does and is set with the same argument as for Linux and Solaris, -Wl,--enable-new-dtags -Wl,-R$(RUNPATH) for DT_RUNPATH, -Wl,--disable-new-dtags -Wl,-R$(RPATH) for DT_RPATH; you may want to test also simply -Wl,-R$(RPATH) (which will probably set the DT_RPATH).
Each OS uses its own unique set of environment variables to decide where to search for shared libraries.
Most UNIX like systems use LD_LIBRARY_PATH (but it varies).
I found that the most effective way to find which environment variable to use is to look at the man page for dlopen() on the platform you are building for.
Edited: also note that these variables act like the PATH environment variables, in that they are a list of paths that are ':' separated. So could you not set the environment like this:
# Using tcsh syntax for setting environment. Your shell may very.
setenv LIBPATH "/opt/freeware/lib/gcc/powerpc-ibm-aix6.1.0.0/4.2.0/:/opt/freeware/lib/gcc/powerpc-ibm-aix6.1.0.0/4.2.0/pthread"
The AIX ld man page states:
Note: If you specify a shared object, or an archive file containing a
shared object, with an absolute or relative path name, instead of with
the -lName flag, the path name is included in the import file ID string
in the loader section of the output file. You can override this
behavior with the -bnoipath option.
So, just specifying /my/path/to/libfoo.so instead of -lfoo should give you the behaviour you want.
Related
What's the difference between writing:
g++ test.cc -L/my/dir/ -lname
and
g++ test.cc /my/dir/libname.so ?
Are both correct?
The things that I can think of:
First one is cross platform, g++ from MINGW will look for DLL's
In the second one we explicitly specify we want dynamic linking
The difference is that
g++ test.cc -L/my/dir/ -lname
may succeed even if /my/dir/libname.so does not exist:
It can find libname.so from a system library directory (usually /lib, /usr/lib).
It can find libname.a, and do static linking.
Furthermore, it allows you to link to multiple libraries from the same directory without repeating the parent directory.
The first method looks into /my/dir directory for the library file at link time. However only a short library name libname.so (or whatever it finds according to OS) is written into the image. When the program starts, it will look for the library in some library path, i.e. LD_LIBRARY_PATH on linux. Now you can relocate the executable and the library into different new places and set a correct search path after relocation.
The second method writes the full path of the library into the image: /my/dir/libname.so. When the program starts, it will look for this particular path to get the library. This makes the image non-relocatable, unless the same library path exists in the new environment. The effect is similar to the '-rpath' method.
There is a laptop on which I have no root privilege.
onto the machine I have a library installed using configure --prefix=$HOME/.usr .
after that, I got these files in ~/.usr/lib :
libXX.so.16.0.0
libXX.so.16
libXX.so
libXX.la
libXX.a
when I compile a program that invokes one of function provided by the library with this command :
gcc XXX.c -o xxx.out -L$HOME/.usr/lib -lXX
xxx.out was generated without warning, but when I run it error like this was thrown:
./xxx.out: error while loading shared libraries: libXX.so.16: cannot open shared object file: No such file or directory , though libXX.so.16 resides there.
my clue-less assumption is that ~/.usr/lib wasn't searched when xxx.out is invoked.
but what can I do to specify path of .so , in order that xxx.out can look there for .so file?
An addition is when I feed -static to gcc, another error happens like this:
undefined reference to `function_proviced_by_the_very_librar'
It seems .so does not matter even though -L and -l are given to gcc.
what should I do to build a usable exe with that library?
For other people who has the same question as I did
I found a useful article at tldp about this.
It introduces static/shared/dynamic loaded library, as well as some example code to use them.
There are two ways to achieve that:
Use -rpath linker option:
gcc XXX.c -o xxx.out -L$HOME/.usr/lib -lXX -Wl,-rpath=/home/user/.usr/lib
Use LD_LIBRARY_PATH environment variable - put this line in your ~/.bashrc file:
export LD_LIBRARY_PATH=/home/user/.usr/lib
This will work even for a pre-generated binaries, so you can for example download some packages from the debian.org, unpack the binaries and shared libraries into your home directory, and launch them without recompiling.
For a quick test, you can also do (in bash at least):
LD_LIBRARY_PATH=/home/user/.usr/lib ./xxx.out
which has the advantage of not changing your library path for everything else.
Should it be LIBRARY_PATH instead of LD_LIBRARY_PATH.
gcc checks for LIBRARY_PATH which can be seen with -v option
I have a few related questions about my issues with compilation for embedded system. My questions are not only about HOW to do something, but more about WHY, because I have solutions for my problems (but maybe there are better ones?), but have no idea why some things works in some conditions, and does not work in others. I already spent some time with this, but until yesterday I was doing things a little blindly, with trials and errors, and without knowing what I was doing. Time to stop that! Please, help.
Scenario
I want to develop an application for Xilinx’s Zynq ARM processor, on Zedboard. The app will involve multithreading, some audio manipulation, and httpserver. So I will need pthread, alsa, sndfile and microhttpd libraries. I created rootfs with yocto. In original conf.local file I added/modified these lines:
BB_NUMBER_THREADS ?= "${#oe.utils.cpu_count()}"
PARALLEL_MAKE ?= "-j ${#oe.utils.cpu_count()}"
MACHINE ?= "zedboard-zynq7"
PACKAGE_CLASSES ?= "package_deb"
EXTRA_IMAGE_FEATURES = "debug-tweaks eclipse-debug"
IMAGE_INSTALL_append = "libgcc alsa-utils mpg123 libstdc++ sthttpd libmicrohttpd libsndfile1"
LICENSE_FLAGS_WHITELIST = "commercial_mpg123"
I also had to add some additional layers to bblayers.conf (and of course downloaded them):
meta-xilinx
meta-multimedia (from meta-openembedded)
meta-oe (from meta-openembedded)
meta-webserver (from meta-openembedded)
Lastly, I generated core-image-minimal with bitbake.
This, together with Linux kernel, and other stuff compiled separately, boots and works fine.
Problems
1. Simple app with this rootfs
It is app for Zynq, so I use XSDK, which is SDK from Xilinx, based on Eclipse. I created new Application project. In dialog window I chose Linux as platform, C++ as language, and I provided path to my unpacked rootfs (excactly the one that system boots with, via NFS). My rootfs path is /home/stas/ZedboardPetalinuxFS (it is not Petalinux, I just used to use it, and this folder name is still the same). This sets proper paths for library and headers search in rootfs.
I started with something very simple:
#include <pthread.h>
int main()
{
int i;
i = 1;
return 0;
}
I also added pthread library for linker (in Eclipse settings). Linking command at this point:
arm-linux-gnueabihf-g++ -L"/home/stas/ZedboardPetalinuxFS/usr/lib" -L"/home/stas/ZedboardPetalinuxFS/lib" -o "test.elf" ./src/main.o -lpthread
At this point it compiles. But it stops, when I add sndfile library
#include <sndfile.h>
This is reasonable, because this rootfs does not have all headers. I need to add another path for searching for headers. So I added path in yocto tmp folder, that has all the headers, that was needed for building rootfs. After I add it, it compiles again successfully. But problems started, when I added sndfile library for linking. Here is linking command and error:
arm-linux-gnueabihf-g++ -L"/home/stas/ZedboardPetalinuxFS/usr/lib" -L"/home/stas/ZedboardPetalinuxFS/lib" -o "test.elf" ./src/main.o -lpthread -lsndfile
/opt/Xilinx/SDK/2016.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabihf/5.2.1/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lsndfile
I looked to usr/lib to check if libsndfile.so is there, and I found only libsndfile.so.1 and ibsndfile.so.1.27. But it is also the case for pthread, and linker does not complain for that. I decided to create libsndfile.so by hand (I linked it to libsndfile.so.1). Linker stopped complaining about it, but started complaining about it’s dependencies. So I also creaded .so files for all the dependencies, and their dependencies, and added them for linking. Then it succeeded. At the end, linking command looked like this:
arm-linux-gnueabihf-g++ -L"/home/stas/ZedboardPetalinuxFS/usr/lib" -L"/home/stas/ZedboardPetalinuxFS/lib" -o "test.elf" ./src/main.o -lpthread -lvorbisenc -lvorbis -logg -lFLAC -lsndfile
So here goes the first question – why I did not needed .so file for pthread, but needed it for all other libraries? Or more general – when do I need .so file, and when .so.X file is enough?
2. Simple app - another approach
After the first try, I thought I should make another image, this time more suitable for development. Luckily, in Yocto it is quite easy – I just had to modify one line:
EXTRA_IMAGE_FEATURES = "debug-tweaks eclipse-debug dev-pkgs"
dev-pkgs option adds -dev packages for all installed packages.
So now I have rootfs with all needed headers, and .so files pointing where they should.
Before compilation, I removed unnecessary Include path, leaving only the one from rootfs, and removed all the libraries, except pthread, and sndfile. But then I get new errors:
arm-linux-gnueabihf-g++ -L"/home/stas/ZedboardPetalinuxFS/usr/lib" -L"/home/stas/ZedboardPetalinuxFS/lib" -o "test.elf" ./src/main.o -lsndfile -lpthread
/opt/Xilinx/SDK/2016.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabihf/5.2.1/../../../../arm-linux-gnueabihf/bin/ld: cannot find /lib/libpthread.so.0
makefile:48: polecenia dla obiektu 'test.elf' nie powiodły się (commands for ‘test.elf’ did not succeed)
/opt/Xilinx/SDK/2016.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabihf/5.2.1/../../../../arm-linux-gnueabihf/bin/ld: cannot find /usr/lib/libpthread_nonshared.a
I spotted, that it looks for libraries in my root folder. Quick search in Google (and SO:)) told me that I should set –-sysroot variable. So I added it to Eclipse option (in Miscelenious card in Linker options) like that:
--sysroot=/home/stas/ZedboardPetalinuxFS
So now linker command looked like this:
arm-linux-gnueabihf-g++ -L"/home/stas/ZedboardPetalinuxFS/usr/lib" -L"/home/stas/ZedboardPetalinuxFS/lib" --sysroot=/home/stas/ZedboardPetalinuxFS -o "test.elf" ./src/main.o -lsndfile -lpthread
And all succeed! I also wrote simple example that uses pthreads, and sndfile, and it also worked. But WHY? This leads me to second question:
Why do I need --sysroot option in this case? When do I need to use this option in general? And why this time I didn't have to add all the dependencies to linking command?
3. Another idea
At this point, I had an idea, to check what will happen, if I add --sysroot option having rootfs populated with old, non development image. But this gave me new errors:
arm-linux-gnueabihf-g++ -L"/home/stas/ZedboardPetalinuxFS/usr/lib" -L"/home/stas/ZedboardPetalinuxFS/lib" --sysroot=/home/stas/ZedboardPetalinuxFS -o "test.elf" ./src/main.o -lpthread -lvorbisenc -lvorbis -logg -lFLAC -lsndfile
/opt/Xilinx/SDK/2016.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabihf/5.2.1/../../../../arm-linux-gnueabihf/bin/ld: cannot find crt1.o: No such file or directory
makefile:48: polecenia dla obiektu 'test.elf' nie powiodły się
/opt/Xilinx/SDK/2016.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabihf/5.2.1/../../../../arm-linux-gnueabihf/bin/ld: cannot find crti.o: No such file or directory
/opt/Xilinx/SDK/2016.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabihf/5.2.1/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lpthread
/opt/Xilinx/SDK/2016.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabihf/5.2.1/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lm
So third question – what does this errors mean?
Thanks very much in advance!
"why I did not needed .so file for pthread, but needed it for all
other libraries?"
Actually you do need pthread.so file. You included pthread.h but didn't link with -lpthread. So it's normal you don't see any linker errors.
"when do I need .so file, and when .so.X file is enough"
When you give "-lNAME" parameter to g++, the compiler tells the linker to find libNAME.so within library search paths. Since there may exist multiple versions of the same library(libNAME.so.1, libNAME.so.1.20), *.so files link to desired actual library file. (Versioning of shared objects, ld man pages)
"Why do I need --sysroot option in this case? When do I need to use this option in general? And why this time I didn't have to add all the dependencies to linking command?"
The "dev-pkgs" in EXTRA_IMAGE_FEATURES changes your sysroot implicitly to let you link against the dev packages(yoctoproject image-features). That's why you need -sysroot option. You generally need this option when cross compiling to provide a root for standard search paths for headers and libraries. You didn't need it because you didn't have dev-pkgs image feature that changes your sysroot
"So third question – what does this errors mean?"
Even your the most basic hello world code gets linked with standard c library(if you didn't specify otherwise). libm.so, libpthread.so and crt1.o files are parts of libc library and come with libc dev package. So the linker can't see the standard library directories when it looks from your old sysroot
why I did not needed .so file for pthread, but needed it for all other libraries?
A cross compiler will normally come with a C Runtime (including pthread), typically in a directory that is part of the cross compiler installation.
The linker has built in search paths for libraries. These are in respect to the sysroot, which would by default be set to search the cross compiler's own included target C Runtime. If you added any -L options it would search those first and then move on to these pre-defined directories.
When you linked against pthread it would have found at least libpthread.a in the cross compiler's library directory.
Or more general – when do I need .so file, and when .so.X file is enough?
Shared libraries in Linux typically have a major and a minor version number. Libraries are ABI compatible between different minor versions with the same major version, but not between major versions. Sometimes there are three levels of versions but the principal is similar.
When installing libraries it is common to install the actual file with the full name, eg. libmy.so.1.2, then provide symlinks to libmy.so.1 and libmy.so.
If you are linking an application can work with any library version then you would just specify the name, eg. -lmy. In that case you would need symlinks from libmy.so to libmy.so.1.
If you required a specific version you would put -l:libmy.so.1. The ':' indicates a literal file name.
Linker scripts may affect things and may result in specific versions being selected even when you do specify the short name.
Why do I need --sysroot option in this case? When do I need to use
this option in general?
What --sysroot does is prepend the given path onto all the search directories which would normally be used to search for includes and libraries. It is most useful when cross compiling (as you are doing now) to get the compiler and the linker to search inside the target root instead of the build host's own root.
If you have specified a sysroot you probably do not need to specify include paths via -I or linker paths via -L, assuming that the files are within their normal spots inside your target root.
And why this time I didn't have to add all the dependencies to linking command?
One possible scenario is that the first time, sndfile for statically rather than dynamically linked. This would happen if your first root image had only sndfile.a in the lib dir, or elsewhere on the search path. To then satisfy the requirements of sndfile.a you would also need to link the other libs.
When linking against sndfile.so the dependencies will automatically get loaded via the dynamic linking process.
That's just a working theory at present.
So third question – what does this errors mean?
They mean it cannot find even the C runtime library to link.
As described for the first question, it was previously finding the C runtime in the pre-defined search path (relative to the predefined sysroot) which located the C runtime supplied by the cross compiler.
You disturbed this by supplying your own sysroot. It was now only searching the target root. Since this target root filesystem did not have development libs installed, there was no C runtime there to find.
You are doing several things wrong:
looks like you are not using environment variables, but calling cross-compiler directly. So, instead of compiling with arm-linux-gnueabihf-g++ ..., you should do $CXX .... The CXX is the environment variable set by the yocto script to set environment for cross compilation. Using CXX, you do not need to manually pass --sysroot
You should not link directly to pthread library with -lpthread. You should use -pthread
With Mac OS X 10.6 Apple changed the default target of g++ so it produces 64-bit rather than 32-bit code. I know I can specify "-arch i386" on the command line but is there any way to globally change the default architecture by means of an environment variable or similar? (I keep getting linking errors because I'm having real problems finding all the places I need to specify the architecture on the project I'm porting.)
Not that I know of. Depending on the configuration & build system you’re using, setting the CXXFLAGS, CFLAGS, and LDFLAGS environmental variables to include -arch i386 can help. However, some configuration & build system are tricky and it might not be sufficient to set those variables.
Another option is to provide a g++ (and friends as needed) bash script in a PATH location that precedes /usr/bin and invokes the actual command with -arch i386 along with the command-line arguments passed to the script.
An alternative to the solution described in the previous paragraph is to use arch(1) in one of its various forms. For instance, the shell script described above could invoke arch -i386 /usr/bin/g++. You can also set the ARCHPREFERENCE environmental variable to something like g++:/usr/bin/g++:i386,x86_64 and invoke arch /usr/bin/g++. However, note that you must use arch to invoke /usr/bin/g++.
Option 1
You could set your path so that it searches your private bin directory first.
In this bin directory place a g++ script that explicitly invokes the correct g++ compiler will the appropriate flags.
Option 2
Set a g++ alias. This will then be used in preference to a command. Set the alias to run the command with the appropriate flags.
Note: Both of these assume you are building from the command line as XCode probably explicitly executes the g++ binary.
I am building a C++ application that uses Intel's IPP library. This library is installed by default in /opt and requires you to set LD_LIBRARY_PATH both for compiling and for running your software (if you choose the shared library linking, which I did). I already modified my configure.ac/Makefile.am so that I do not need to set that variable when compiling, but I still can't find the shared library at run-time; how do I do that?
I'm compiling with the -Wl, -R/path/to/libdir flag using g++
Update 1:
Actually my binary program has some IPP libraries correctly linked, but just one is not:
$ ldd myprogram
linux-vdso.so.1 => (0x00007fffa93ff000)
libippacem64t.so.6.0 => /opt/intel/ipp/6.0.2.076/em64t/sharedlib/libippacem64t.so.6.0 (0x00007f22c2fa3000)
libippsem64t.so.6.0 => /opt/intel/ipp/6.0.2.076/em64t/sharedlib/libippsem64t.so.6.0 (0x00007f22c2d20000)
libippcoreem64t.so.6.0 => /opt/intel/ipp/6.0.2.076/em64t/sharedlib/libippcoreem64t.so.6.0 (0x00007f22c2c14000)
[...]
libiomp5.so => not found
libiomp5.so => not found
libiomp5.so => not found
Of course the library is there:
$ locate libiomp5.so
/opt/intel/ipp/6.0.2.076/em64t/sharedlib/libiomp5.so
By /path/to/lib do you mean path to the directory containing the library, or the path to the actual file?
The -R option given a directory argument is treated like -rpath by ld, which is the option you're actually wanting here. It adds the given directory to the runtime library search path. That should work, as long as you give it the directory and not filename. I'm fairly confident about that, having done it myself, and because it's one of the hints given by libtool:
Libraries have been installed in:
/path/to/library-directory
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
add LIBDIR to the `LD_LIBRARY_PATH' environment variable
during execution
add LIBDIR to the `LD_RUN_PATH' environment variable
during linking
use the `-Wl,-rpath -Wl,LIBDIR' linker flag
have your system administrator add LIBDIR to `/etc/ld.so.conf'
(I paste this here since conceivably one of the other options could be more desirable - for example LD_RUN_PATH can save you makefile modification)
As suggested by Richard Pennington, the missing library is not used directly by my application, but it is used by the shared libraries I use. Since I cannot recompile IPP, the solution to my problem is to add -liomp5 when compiling, using the -R option for the linker. This actually adds the rpath for libiomp5.so fixing the problem!
You can check if the path to the library is being picked up from your -R flag by running the ldd command or the readelf command on your binary. The LD_LIBRARY_PATH environment variable is an override, so shouldn't be necessary normally.
You should use the -R option if possible.
If not, rename your executable and create a launch script that runs your executable, and in there set LD_LIBRARY_PATH just for that scope.
Depending on platform, you can modify ld.so.conf via /etc/ld.so.conf.d (Redhat/Fedora come to mind) which makes deploying changes to ld.so "easier" from a deployment scenario.
Besides all the useful hints posted here.. you're not trying to use a 64-bit specific library on a 32-bit system (or viceversa, depending on other conditions), are you?
bash:
export LD_LIBRARY_PATH=/path/to/lib
tcsh:
setenv LD_LIBRARY_PATH /path/to/lib
Try configuring your ldconfig through ld.so.conf so it searches your /opt/... directory by default.