Are homebrew packages static libraries or dynamic? - c++

I was using the SDL2 library I installed with homebrew. I was just wondering if the libraries I linked were statistic or dynamic and how to tell with these package managers.

Homebrew installs both libraries for dynamic and static linkage. It installs also the useful utility sdl2-config. Run
sdl2-config --cflags --static-libs
--cflags Print the compiler flags that are necessary to compile a program or library that uses SDL.
--static-libs Print the linker flags that are necessary to statically link a program that uses SDL.
If you have not linked SDL like --static-libs showed, you have linked the shared SDL library.
FYI A library can not be dynamic, it is either a shared or a static library, for either dynamic (at runtime) or static (at compile time) link respectively.

Related

Link poco static library to target in cmake

I read a lot of post but I don't yet well understood how to link my target to a static version of a library.
My project depends on poco libraries and, while in linux they are stored in /usr/local/lib (both the static and shared versions) in my windows machine are in d:\libs\poco\lib and d:\libs\poco\bin (where I have an enviroment variable called POCO_DIR = D:\libs\poco)
So, how can I have to write the find_library() directive in cmake file?
Thanks in advance.
You never link with a Poco DLL on windows, not even when you use shared Poco libraries. Linking is always with entries in the %POCO_BASE%/lib. For shared builds, .lib is just a stub ("import library") that takes care of loading the DLL at runtime. See Linking Implicitly for details on how this works.
Poco static libraries can be distinguished from the import libraries for DLLs by the file name - static libs have "mt" ("mtd" for debug binaries, "md" and "mdd" when runtime library DLLs are used) appended to the name. So the import library for PocoFoundation.dll will be named PocoFoundation.lib, while the static library using static runtimes is named PocoFoundationmt.lib. Static library using dynamic runtimes is PocoFoundationmd.lib. See Use Run-Time Library for details.
As for CMake, I am not an expert, but for e.g. static Foundation and Net libraries should be something like this:
FIND_LIBRARY(Poco_LIBRARIES NAMES PocoFoundationmt PocoNetmt PATH_SUFFIXES ${POCO_DIR}/lib)
EDIT: If you define POCO_STATIC in your project, static linking will be automatic through library headers, see e.g. Foundation.h.

Removing linker dependencies

I'm working on a c++ app on linux using g++. My app links in a shared library that exposes a simple API I need. This library internally references a large number of additional shared libs. I've had to find each and every one and add them to my Makefile to get them linked in.
I assume my app has to link to any of the libs the primary lib depends on. Is the only way around this linking requirement, having the primary lib compile in the static libs of all its dependencies? Does this apply to using the plug-in model via dlopen/dlsym?
ty
Is the only way around this linking requirement, having the primary lib compile in the static libs of all its dependencies?
No. The shared library could itself link to the shared libraries it depends on. Most linkers would pick up those libraries as well, and link your executable to those libraries without you mentioning them at the linker stage.
In your case, it sounds like the shared library did not link to the libraries it required. the ldd tool can be useful in this regard.
As an example, say you produce this shared library:
gcc -shared foo.o -o libfoo.so -lm
Now the libfoo.so is linked to the math library (libm). Any application linked to libfoo.so
would be linked to libm as well, i.e. you'd just have to do
gcc -o prog main.o -lfoo
If on the other hand the shared library was not linked to lib, but was produced with only
gcc -shared foo.o -o libfoo.so
You'd have to explicitly link to libm when linking your application:
gcc -o prog main.o -lfoo -lm
When you dlopen() a shared library, the runtime linker will load all the libraries that shared library was also linked against - unless they're already loaded. So - if a library you dlopen() is not linked against libraries it depends on, and your executable are not linked against those libraries either, dlopen() will fail (unless you specify RTLD_LAZY, in which case things fail later on)
I assume my app has to link to any of the libs the primary lib depends on.
It sounds as though either your app is using those symbols directly (not just indirectly through the API shared lib) or that shared lib hasn't been linked properly, so it wasn't linked to the libraries it depends on. If when that shared library was created its dependencies were linked to with -l then it would cause them to be linked to automatically when linking your app to the API lib.
Is the only way around this linking requirement, having the primary lib compile in the static libs of all its dependencies?
That's one way, but not the only way.
Does this apply to using the plug-in model via dlopen/dlsym?
As long as the plugins are correctly linked to the libs they depend on ... No, in that case the linker cannot possibly know what libs you will dlopen at run-time, so can't know what their dependencies will be, so you don't need to name them at link-time. It wouldn't be possible to without knowing in advance all the plugins that might get loaded.
If the plugin libraries weren't properly linked you'd get the same problem when trying to dlopen them.
I assume my app has to link to any of the libs the primary lib depends on. Is the only way around this linking requirement, having the primary lib compile in the static libs of all its dependencies?
Off course. There are no ways around : either static linking, or having libraries (correct versions, if not ABI compatible) in libraries run-time search path.
Does this apply to using the plug-in model via dlopen/dlsym?
No. For that, you need to have shared library in a path from which you want to load it.

How to compile a standalone OpenCV executable?

I compile my my OpenCV programs as follows:
g++ `pkg-config --cflags opencv --libs opencv` <filename>.cpp
It works perfectly on my computer. Can I complile the shared libraries alone with the program so that it can be run on other computers which doesnt have opencv on it? If so, how do I do it?
The program during compilation are dynamically linked to Shared Libraries (.so files) on our computer. The executable compiled use these shared libraries during run-time. But these shared libraries may not be present on other computers, hence might not be able to run the executable.
Solution to this will be to statically link Archive Libraries (.a files) instead of dynamically linking Shared Libraries. OpenCV does not distribute archive libraries as such. So one will have to compile archive library from the its source using cmake -DBUILD_SHARED_LIBS=OFF. This archive library can be used to create standalone executable.
Yes to some degree: lookup static linking. Your opencv copy must have .a versions of the libraries (not just .so you mention) and that is also true for any other dependencies.
No. You need to use static libraries.

Why doesn't Libtool want to link with a static library?

I want to build a shared library that uses ZipArchive using GNU Autotools but I'm having this problem:
Warning: linker path does not have real file for library -lziparch.
I have the capability to make that library automatically link in when
you link to this library. But I can only do this if you have a
shared version of the library, which you do not appear to have
because I did check the linker path looking for a file starting
with libziparch and none of the candidates passed a file format test
using a file magic. Last file checked: /usr/local/ZipArchive/ZipArchive/libziparch.a
The inter-library dependencies that have been dropped here will be
automatically added whenever a program is linked with this library
or is declared to -dlopen it.
If I build a static library or if I use a shared library of ZipArchive it works but the problem is that the makefile that comes with ZipArchive source code only builds a static library.
How can I force Libtool to link with a static library?
Generally, static archives are created with non-pic object files and they cannot be put into shared libraries.
What this message is telling you though, is that when a program links to YOUR library using Libtool, that -lziparch will get added to the link. So you don't need to change anything unless you're building a module for an interpreted language. In that case, you will have to build ZipArchive as a shared library. In addition, this wouldn't work on a platform like MS Windows where shared libraries (DLLs) have to resolve all their symbols at link time.
All that said, if your ziparch static lib is PIC code, you can use the -whole-archive flag when linking it to your library. This would be the least portable solution though.

Linking a dynamic library to a static library that links to other static libraries

In my C++ application I have a static library (libCOMMON.a) that links to boost libraries: system, filsystem, timer and chrono.
I am using CMake and here is how I create and link libCOMMON.a:
ADD_LIBRARY(COMMON ${COMMON_SRCS})
target_link_libraries(COMMON
${BOOST_LIB_DIR}/libboost_filesystem.a
${BOOST_LIB_DIR}/libboost_system.a
${BOOST_LIB_DIR}/libboost_timer.a
${BOOST_LIB_DIR}/libboost_chrono.a
)
I also have plugins for this application that links to libCOMMON.a. The plugins are built as dynamic libraries. Everything compiles ok (using gcc) but when I start the application, the plugins can't be loaded because some symbols in the dynamic libraries related to boost cannot be resolved.
The solution was to link each of the plugins to boost. Is there a better way ?
I thought that if boost libraries are linked statically into libCOMMON.a, it would be enough to link the plugins to libCOMMON.a.
Can someone explain what's happening ?
Thanks
I think the problem is that boost libraries are built as dynamic libraries by default. Even if the ".a" suggests that they are built as static libraries, the lib folder of boost contains a ".so" library with each ".a". Which means that libCOMMON.a is linked dynamically to boost libraries. For this reason, the plugins that statically links to libCOMMON.a has also to dynamically link to boost libraries. A better solution would be to build boost libraries as static libraries.