Program cannot load shared library GCC - c

First things first, here is the error message:
./Game: error while loading shared libraries: libEngine.so: cannot open shared object file: No such file or directory
There was no problems while compiling.
Library directories passed to GCC while compiling Game: -L../../bin -L.
Directory tree:
ENGINE
-bin
--Game (executable)
--libEngine.so
-Game
--src
---source code + Game makefile
-Engine
--src
---source code + shared library makefile
I can provide more info on demand.

Setting LD_LIBRARY_PATH is a possible, but usually not the best solution. In particular, dependence on environment produces programs which work for you, but not for your coworkers or your professor (because their environment is different).
Adding -rpath=/path/to/bin to the link line eliminates the need to muck with environment.
Even better: -rpath='$ORIGIN' lets you move the entire installation directory to a different place, and the program will still find its shared libraries in its own bin/ directory.

Related

Does a .so library need to be present at run time in all cases

My question is in relation to .so shared libraries. I am building a project that uses cmake on one ubuntu machine but running the application on another ubuntu machine.
In the CMakeLists.txt file, I have the following lines:
project (clientapp)
add_executable(${PROJECT_NAME} ${SOURCES} ${WAKAAMA_SOURCES} ${SHARED_SOURCES})
LINK_DIRECTORIES(/home/user//mraa-master-built/build/src)
target_link_libraries (clientapp libmraa.so)
target_link_libraries(clientapp m)
These lines add two libraries libmraa.so and the math library to the executable and it runs successfully on the other machine.
My understanding of shared libraries is that they must be present at compile time, and when the application starts. But I do not have the libmraa.so file on the other machine and the application runs ok. I expected it not to work.
Is my assumption correct?
In general, gcc and clang support lazy linking/binding of symbols, but not for entire libraries. This means that all of the shared objects (ie: .so files) should be present at application startup, at a minimum. The one exception to this is if you modified your makefile to not link against these libraries, and you manually call library functions via dlopen()/dlsym(), etc.
The binding of individual symbols within those libraries can be postponed until they are needed, or you can force all the symbols to be resolved at startup, using -z lazy or -z now, respectively.
It is strange that your application runs without libmraa.so being present. The two most likely reasons your application is running in the absence of the library is:
Your application isn't using any symbols defined in the library, so the linker ignores the library at build time (try ldd app_name and see if your library is present in the list of libraries provided by ldd).
Something is amiss in your build script, and you are statically linking against a .a archive of the library.
Edit: In response to how the application knows how to find the library, your linker (ld in this case) will use rpath lookup to decide which directories to use in its search for the appropriate library. You can see how this works by doing something like LD_DEBUG=libs app_name from the command line. You can also add an extra path via LD_LIBRARY_PATH=/some/path app_name.
Is my assumption correct?
Yes.
There are two likely explanations for why the application runs anyway:
You are mistaken, and there is libmraa.so somewhere on the machine (though perhaps not in the place where you looked), or
Your compiler defaults to -Wl,--as-needed by default, and your binary does not in fact depend on libmraa.so despite the fact that it appears on your link line.
You can trivially confirm or disprove either of the above guesses.
To confirm guess 2, do this:
readelf -d clientapp | grep NEED | grep libmraa
# if there is no output, guess 2 is correct
If guess 2 is wrong, to confirm guess 1, do this (on machine without libmrra.so):
ldd clientapp | grep libmraa.so
# if guess 2 is incorrect, and this command produces no output, then
# your dynamic loader is broken, which is very unlikely.

best practices on my library coded in C

it is awkward, but until now i always copy the *.h and the *.c files to my projekts location. this is a mess and i want to change it!
i want to build my own c library and have a few questions about it.
where should i locate the *.h files?
should i copy them in the global /usr/include/ folder or should i create my own folder in $HOME (or anywhere else)?
where should i locate the *.a files and the *.o files and where the *.c files.
i am using debian and gcc. my c projects are in $HOME/dev/c/.
i would keep my lib-sources in $HOME/dev/c/lib (if this is the way you could recommend) and copy the *.o, *.a and *.h files to the location i am asking for.
how would you introduce the lib-location to the compiler? should i add it to the $PATH or should i introduce it in the makefiles of my projekt (like -L PATH/TO/LIBRARY -l LIBRARY).
do you have anny further tips and tricks for building a own library?
I would recommend putting the files somewhere in your $HOME directory. Let's say you've created a library called linluk and you want to keep that library under $HOME/dev/c/linluk. That would be your project root.
You'll want a sensible directory structure. My suggestion is to have a lib directory containing your library and an include directory with the header files.
$PROJECT_ROOT/
lib/
liblinluk.so
include/
linluk.h
src/
linluk.c
Makefile
Compiling: When you want to use this library in another project, you'd then add -I$PROJECT_ROOT/include to the compile line so that you could write #include <linluk.h> in the source files.
Linking: You would add -L$PROJECT_ROOT/lib -llinluk to the linker command line to pull in the compiled library at link time. Make sure your .so file has that lib prefix: it should be liblinluk.so, not linluk.so.
A src directory and Makefile are optional. The source code wouldn't be needed by users of the library, though it might be helpful to have it there in case someone wants to remake the .so file.
As I commented, you should try first to build and install from its source code several free software libraries, e.g. like libonion or gdbm or GNU readline etc (don't use any distribution package, but compile and install these from source code). This will teach you some good practice.
You probably want to install these libraries system-wide, not for your particular user. Then, assuming that your library is called foo (you need to give it some name!),
the header files *.h go into /usr/local/include/foo/
the shared objects (dynamic libraries) go into /usr/local/lib/libfoo.so (with perhaps some version numbering)
if relevant, static library go into /usr/local/lib/libfoo.a
You need to add once /usr/local/lib/ into /etc/ld.so.conf and run ldconfig(8)
and you usually don't want to copy any source file *.c or object file *.o
(except for homoiconic programs, bootstrapped compilers, Quine programs, generated C code, etc... See RefPerSys or Jacques Pitrat systems as an incomplete example of self generated C or C++). In some weird cases, you may want to copy such "source" or "generated C" code under /usr/src/.
Read Program Library HowTo (and later, Drepper's paper: How To Write Shared Libraries)
You could consider making your library known by pkg-config. Then install some foo.pc under /usr/local/lib/pkgconfig/
BTW, I strongly suggest you to publish your library as free software, perhaps on github or elsewhere. You'll get useful feedback and could get some help and some bug reports or enhancements.
You probably should use some builder like make and have an install target in your Makefile (hint: make it use the DESTDIR convention).

Cmake: linking shared library

I've done this before a couple of times, but somehow I'm stuck this time. I have an executable "myapp" and a own shared library "mylib". In my cmakelists I have the following:
ADD_LIBRARY(mylib SHARED ${SOURCES_LIB})
INSTALL(TARGETS mylib DESTINATION .)
ADD_EXECUTABLE(myapp ${SOURCES_APP})
TARGET_LINK_LIBRARIES(myapp ${QT_LIBRARIES} mylib)
INSTALL(TARGETS myapp DESTINATION .)
Everything compiles and links correctly, but when I start myapp, I get the following error:
error while loading shared libraries: libmylib.so: cannot open shared object file: No such file or directory
The lib and the executable are present in the install directory. When I make my library static by changing the first line of the above cmakelists to:
ADD_LIBRARY(mylib STATIC ${SOURCES_LIB})
then everything works 100%.
Does anyone know what I'm doing wrong?
During the installation of your library and executable, the runtime paths to find the library are stripped from the executable. Therefore your library has to reside in the runtime library search path. For example under Linux, try to set LD_LIBRARY_PATH to the directory that contains the installed library when starting your executable.
This is a very common question about "make install". Actually, there are 3 ways to link a library to your executable file. First, you may use -l -L flags in simple cases. As Benjamin said you may use LD_LIRARY_PATH and write something like: export LD_LIBRARY_PATH=/usr/local/my_lib. In fact this is not a good way. It's much better to use RPATH. There is a very useful doc page about it. Check it out. Well if you write something like this in your top level CMakeLists.txt, it will solve the problem:
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib64")
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib64")
Add the path of the directory containing the library to the LD_LIBRARY_PATH environment variable, by appanding a new path:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/the/library/
You can check the library is correctly found with the 'ldd' tool:
lld ./executable
If the library is not stated as "not found" it is OK and your executable will be executed properly.
Add the 'export' command to your bashrc to properly set the LD_LIBRARY_PATH variable after each system reboot, otherwise you will have to execute again the 'export' command.

Linking with -R and -rpath switches on Windows

I,m using gcc compiler(MinGW) on Windows XP.I created a .dll library libdir.dll than I tried to build a program that is using that library.
I don't want to put that .dll file into System or System32 folder nor to set path to it in PATH variable, what i want is to give that information to the program itself.
I know there is a -R and -rpath switches available so i was gonna link it with one of them.
First -rpath:
gcc -L/path/to/lib -Wl,-rpath,/path/to/lib main.o -ldir -o prog
Than -R:
gcc -L/path/to/lib -Wl,-R,/path/to/lib main.o -ldir -o prog
This links successfully into prog but when i start the program Windows prints message that it cannot find libdir.dll.
So my question is what went wrong, why path to libdir.dll is not known in runtime even when I'm using appropriate switches?
Let's say i have prog1 and prog2 each containing their own copy of libdir.dll and both of them start to run at the same time loading code in the library.What happens in memory is there a two copies loaded or linker figures out that there is a copy and uses that for both programs?
Second question is about how libraries are loaded(any OS).Does linkers always load entire library or just parts needed?For example if program references function foo() which is in the library, does linker maps into memory only that function or entire library first?
There are only two real alternatives: put the DLL in the same folder as the EXE or put it in the working directory for the EXE. The latter being not much of an option since you'd have to create a shortcut to make the default working directory different from the directory that contains the EXE.
Not putting the DLL in the same directory as the EXE only makes sense if you want to share the DLL with other applications. To avoid the inevitable DLL hell this causes, you'd need to store the DLL in the side-by-side cache. The tooling you need to create the manifest and embed it in the EXE and the installer you'd need to deploy the DLL to the target machine are probably hard to come by with your tool chain. It is very rarely done anyway.
Part of this question is a duplicate of this one: Is there a Windows/MSVC equivalent to the -rpath linker flag?
The summary of the answer is that there is no direct equivalent of RPATH on Windows.
Since you precluded placing your DLLs in the default library search path (which on Windows includes the system directories you listed and the directories in the PATH environment variable), you are left with these options:
using batch files
placing all the DLLs and executables in the same directory
making OS-level calls in your program for adding to the DLL search path

How do you actually use a C library?

I'm sure this question has been asked many times, but I can't figure this out. Bear with me.
So when you download a library, you get a bunch of .c and .h files, plus a lot of other stuff. Now say you want to write a program using this library.
I copy all the .h files into my project directory. It just doesn't compile.
Great, so then I get the library as a bunch of .dll's, and i copy the dlls into my project directory. Still doesn't compile.
How does this work?
What do you do, like right after creating the folder for your project? What parts of the library package do you copy/paste into the folder? How do you make it so that it can compile? Go through the steps with me please.
Where to put the .h files?
Where to put the .dll files?
How to compile?
Thanks.
(the library I'm trying to get working is libpng, I'm in windows with MinGW, and i'm looking to compile from command-line like usual.)
(from what i gather, you put the .h files in directory A and the .dll files in directory B and you can use -l and -L compiler options to tell the compiler where to find them, is this correct?)
Here's a brief guide to what happens when you compile and build a basic C project:
The first stage compiles all your source files - this takes the source files you've written and translates them into what are called object files. At this stage the compiler needs to know the declaration of all functions you use in your code, even in external libraries, so you need to use #include to include the header files of whatever libraries you use. This also means that you need to tell the compiler the location of those header files. With GCC you can use the -I command line to feed in directories to be searched for header files.
The next stage is to link all the object files together into one executable. At this stage the linker needs to resolve the calls to external libraries. This means you need the library in object form. Most libraries will give you instructions on how to generate this or might supply it ready built. Under Linux the library file is often a .a or .so file, though it might just be a .o. Again you can feed the location of the library's object file to GCC with the -L option.
Thus your command line would look like this:
gcc myProg.c -I/path/to/libpng/include -L/path/to/libpng/lib -lpng -o myProg.exe
(Note that when using the -l command line GCC automatically adds lib to the start of the library, so -lpng causes libpng.a to be linked in.)
Hope that helps.
Doing it under windows (supposing you user Visual Studio)
After unpacking add the library include directories to your projects' settings (Project -> Properties -> C/C++ -> Additional Include Directories)
Do the same thing for the Libraries Directory (Project -> Properties -> Linker -> Additional Library Directories)
Specify the name of the library in your Linker Input: Project -> Properties -> Linker -> Input -> Additional Dependencies
After this hopefully should compile.
I don't recommend adding the directories above to the Global settings in Visual Studio (Tools -> Options -> Project and Solutions) since it will create and environment where something compiles on your computer and does NOT compile on another one.
Now, the hard way, doing it for a Makefile based build system:
Unpack your stuff
Specify the include directory under the -I g++ flag
Specify the Library directory under the -L g++ flag
Specify the libraries to use like: -llibrary name (for example: -lxml2 for libxml2.so)
Specify the static libraries like: library name.a
at the end you should have a command which is ugly and looks like:
g++ -I/work/my_library/include -L/work/my_library/lib -lmylib my_static.a -o appname_exe MYFILE.CPP
(the line above is not really tested just a general idea)
I recommend go, grab a template makefile from somewhere and add in all your stuff.
You must link against a .lib or something equivalent i.e. add the ".lib" to the libraries read by the linker. At least that's how it works under Linux... haven't done Windows so a long while.
The ".lib" contains symbols to data/functions inside the .dll shared library.
It depends on the library. For examples, some libraries contain precompiled binaries (e.g. dlls) and others you need to compile them yourself. You'd better see the library's documentation.
Basically, to compile you should:
(1) have the library's include (.h) file location in the compiler's include path,
(2) have the library stubs (.lib) location in the linker's library path, and have the linker reference the relevant library file.
In order to run the program you need to have the shared libraries (dlls) where the loader can see them, for example in your system32 directory.
There are two kinds of libraries: static and dynamic (or shared.)
Static libraries come in an object format and you link them directly into your application.
Shared or dynamic libraries reside in a seperate file (.dll or .so) which must be present at the time your application is run. They also come with object files you must link against your application, but in this case they contain nothing more than stubs that find and call the runtime binary (the .dll or the .so).
In either case, you must have some header files containing the signatures (declarations) of the library functions, else your code won't compile.
Some 'libraries' are header-only and you need do nothing more than include them. Some consist of header and source files. In that case you should compile and link the sources against your application just as you would do with a source file you wrote.
When you compile, assuming you have the libs and the headers in the same folder as the sources you are compiling, you need to add to your compile line -L . -I . -lpng. -L tells the linker where to look for the library, -I tells the compiler where to look for the headers and -lpng tells the linker to link with the png library.
[Edit]
Normal projects would have some sort of hierarchy where the headers are in an /include folder and the 3rd party libs are in a /libs folder. In this case, you'd put -I ./include and -L ./libs instead of -I . and -L.
[Edit2] Most projects make use of makefile in order to compile from the command line. You can only compile manually for a small number of files, it gets quite hectic after that
Also,
you may want to look over Dynamic Loading support in various languages and on various
platforms.
This support is very handy in cases when you want to use a library optionally and you don't want your program to fail in case that library is not available.

Resources