Which libraries should go to a pkg-config file as a dependencies? - linux

I'm writing a shared library that itself depends on boost and pcl libraries.
When generating .pc file for my library should I add all these libraries also to the .pc file as dependencies?
It's been a long time since I last time studied these things and I'm a bit confused how this worked again on Linux. When my test app links to my lib I have to add all these pcl and boost libs again to the build even though the lib already has been linked against these libs.
But when I look at the deps of libQtGui.so, for example, it has tens of all kinds of libs it links to, but I don't need to make my app link to those libs...only -lQtGui is enough.
I have just used CMake and link_libraries to add boost and pcl libs.

When generating .pc file for my library should I add all these libraries also to the .pc file as dependencies?
It depends on API of your library:
if public (i.e. installable) headers of your lib use boost/pcl (i.e. have #inclue <boost/...>) (in other words you used PUBLIC (or INTERFACE) named keywords when link your library against boost/pcl in CMake+target_link_libraries) -- then yes you need to add 'em;
otherwise, it depends on what exactly you have at the end -- i.e. does your DSO has DT_NEEDED entries for boost/pcl libs (most likely) or not (you can check it w/ ldd <your-lib>.so). For the last case, you also need to add your dependencies to the *.pc files.
Also, in case of binary dependency from boost/pcl (dunno if the latter has any DSO or not) please make sure you specify exact location of the linked libs -- cuz a user may have multiple (co-existed) boost installations (potentially incompatible) or can do upgrade (later) to other (binary incompatible) version (and you can't really do smth w/ it)… It is important to be linked to the same (or at least binary compatible, which is kinda hard to guarantee for boost) library as you did…
I have just used CMake and link_libraries to add boost and pcl libs.
Please read smth about "Modern CMake" and stop using link_libraries :-) -- use target_link_libraries instead…

Related

How to compile with make but also include all dependencies

I'm compiling a C++ program on linux, and I can run make and it all compiles, but when I need to downgrade or change one of it's dependencies for another program, it breaks. I was wondering if it was possible to create a standalone executable, with dependencies bundled inside? There's not many dependencies, so size isn't an issue.
So, what you're asking is, can you link with static versions of libraries (which are included in the program directly) instead of dynamic versions of libraris (shared libraries) which are kept external to your program.
The answer is "yes", but it's not always straightforward. First you have to ensure you actually have the static versions of the libraries installed in your system: the static and dynamic libraries are different files and often the "standard" installation provides only the dynamic library.
If you're already compiling code against those libraries you probably already have the static libraries installed because, at least on GNU/Linux systems, the static libraries are often included in the "dev" packages along with the header files etc. needed to compile code.
To make this work you need to modify your linker command line. If you have a sufficiently new version of the binutils package (which provides the linker), you can change your link line to replace arguments like -lssl -lcrypto with arguments like -l:libssl.a -l:libcrypto.a (don't forget the colon after the -l) and that should do it.

GNU/Debian Linux and LD

Lets say I have a massive project which consists of multiple dynamic libraries that will all get installed to /usr/lib or /usr/lib64. Now lets say that one of the libraries call into another of the compiled libraries. If I place both of the libraries that are dependent on eachother in the same location will the ld program be able to allow the two libraries to call eachother?
The answer is perhaps yes, but it is a very bad design to have circular references between two libraries (i.e. liba.so containing function fa, calling function fb from libb.so, calling function ga from liba.so).
You should merge the two libraries in one libbig.so. And don't worry, libraries can be quite big. (some corporations have Linux libraries of several hundred megabytes of code).
The gold linker from package binutils-gold on Debian should be useful to you. It works faster than the older linker from binutils.
Yes, as long as their location is present in set of directories ld searches for libraries in. You can override this set by using LD_LIBRARY_PATH enviroment variable.
See this manual, it will resolve your questions.
If you mean the runtime dynamic linker /lib/ld-linux* (as opposed to /usr/bin/ld), it will look for libraries in your LD_LIBRARY_PATH, which typically includes /usr/lib and /usr/lib64.
In general, /lib/ld-* are used for .so libraries at run-time; /usr/bin/ld is used for .a libraries at compile-time.
However, if your libraries are using dlopen() or similar to find one another (e.g. plug-ins), they may have other mechanisms for finding one another. For example, many plug-in systems will use dlopen to read every library in a certain (one or many) directory/ies.

Installing package from source on an initial ram filesystem

I'm trying to install multiple packages into an initial ram file system. I'm using uclibc as my C library. This could be a stupid question but...
Would the compiled program also need a C library installed onto the initramfs?
Am I right in thinking that when a program is compiled from source, it is compiled into some sort of executable? Will the application on the initramfs be ready to run once I have make installed (with the correct prefix and providing dependencies are met )?
Whether a compiled program needs a C library - or any kind of library, for that matter - depends on how it was linked.
In general, if your program was linked statically then it does not have any external dependencies - it only needs a working kernel. The executable code of any library that it depends on will have been incorporated into the final executable.
If, on the other hand, it is linked dynamically, then it still needs the shared object files of the libraries it depends on. On Linux, most library shared objects (also known as shared libraries) follow the convention of having a filename with either a .so extension or, in general, a *.so.* format. For example /lib/libssl3.so and /lib/libncurses.so.5.9 are both shared libraries on my system.
It is also possible to have an executable that is statically linked against some libraries and dynamically linked against others. A common case where this happens is when rare or proprietary libraries are linked in statically, while standard system libraries are linked in dynamically.

Remove references in a shared object to another shared object

I want to remove references in a shared object to symbols of another shared object because the referenced object is GPL'd and I don't want to release my code under that license. (I don't think that the symbols provided by the referenced object are used by my code.) What are the steps to take to do this on Linux? I'm not steeped in this technology and it would help if you provided commands. Would another approach be better? Would it be better to somehow create a stub object replacing the referenced object?
Edit 1: I am using PyInstaller to build a self-contained archive containing the binaries for the code I've written along with all libraries that code requires and all libraries those libraries require. These libraries are shared objects that already exist on the build system. It would be too much work to forego PyInstaller and re-compile everything so that the GPL'd libraries are not linked in.
On Linux, the only libraries directly referenced by an executable or library are libc.so, ld-linux.so, linux-gate.so, plus anything you explicitly request on the compiler command line. As such, you can remove these references simply by removing them from the compiler command line.
Note that many times, pkg-config scripts will return all indirect dependencies as well as direct dependencies when queried for linker flags. You can either remove the unnecessary dependencies manually, or pass the -Wl,--as-needed flag to the linker to instruct it to remove unnecessary direct references to shared libraries automatically.
As for the pyinstaller bundling, keep in mind that indirectly linking GPL'd libraries via an intermediate library is already kind of a grey area; if you in addition merge them into a single file, this may not count as 'mere aggregation' and may not avoid the GPL restrictions. Also note that the GPL never mentions 'linking'; it's all about derivative works. I'm no lawyer and this is not legal advice, but the mere addition or removal of a NEEDED entry for a GPL'd library when no symbols are used seems unlikely to affect whether you are in violation of the GPL, when the GPL itself never mentions such a thing.

Loading multiple shared libraries with different versions

I have an executable on Linux that loads libfoo.so.1 (that's a SONAME) as one of its dependencies (via another shared library). It also links to another system library, which, in turn, links to a system version, libfoo.so.2. As a result, both libfoo.so.1 and libfoo.so.2 are loaded during execution, and code that was supposed to call functions from library with version 1 ends up calling (binary-incompatible) functions from a newer system library with version 2, because some symbols stay the same. The result is usually stack smashing and a subsequent segfault.
Now, the library which links against the older version is a closed-source third-party library, and I can't control what version of libfoo it compiles against. Assuming that, the only other option left is rebuilding a bunch of system libraries that currently link with libfoo.so.2 to link with libfoo.so.1.
Is there any way to avoid replacing system libraries wiith local copies that link to older libfoo? Can I load both libraries and have the code calling correct version of symbols? So I need some special symbol-level versioning?
You may be able to do some version script tricks:
http://sunsite.ualberta.ca/Documentation/Gnu/binutils-2.9.1/html_node/ld_26.html
This may require that you write a wrapper around your lib that pulls in libfoo.so.1 that exports some symbols explicitly and masks all others as local. For example:
MYSYMS {
global:
foo1;
foo2;
local:
*;
};
and use this when you link that wrapper like:
gcc -shared -Wl,--version-script,mysyms.map -o mylib wrapper.o -lfoo -L/path/to/foo.so.1
This should make libfoo.so.1's symbols local to the wrapper and not available to the main exe.
I can only come up with a work-around. Which would be to statically link a version of the "system library" that you are using. For your static build, you could make it link against the same old version as the third-party library. Given that it does not rely on the newer version...
Perhaps it is also possible to avoid these problems with not linking to the third-party library the ordinary way. Instead, your program could load it at execution time. Perhaps then it could be shadowed against the rest. But I don't know much about that.

Resources