Including Shared Libraries (.so) with CMake - c++

I've been trying to include different types of libraries with CMake.
.a
.dylib
.so
I finally, got both the .a and .dylib to work with this code.
find_library(libname NAMES libcef.dylib PATHS ${libname_PATH})
along with this, underneath where I add_executable to initialize all my files for the build.
target_link_libraries(${PROJECT_NAME} ${libname})
However, I tried using the same code on a .so file and it doesn't seem to work.
I get this statement from cmake when I try building.
Target "project name" links to item
-- path of file --
which is a full-path but not a valid library file name.
I'm not sure if this is the correct way to handle .so files or perhaps I'm not even fully understanding what an .so file is. Any input and/or clarification would be much appreciated.
edit:
THEORY- my theory is because it doesn't have a lib in front of the name of the library name its called ffmpegsumo.so. However, when i try renaming it the file name still saves into the variable name very strange.

The same should work with .so files also, just make sure the required .so file is present at ${libname_PATH} which you have given.
find_library treats all types (.a / .so/ .dylib/ .dll) the same way. Problem may be the following
-- path not set up correctly
-- error because of absolute path
-- .so not present
-- If the error is from build (not from configure only) the .so might be corrupt, try replacing it
--Your library does not seem to be valid

Shared libraries are linked dynamically. That means that your OS will automatically look for and load the .so files when the time comes to run the application. You only need to tell cmake the name of the library and the OS will take care of the rest.
For example, if you want to link to the dynamic library for libSDL.so, you just say: target_link_libraries(${PROJECT_NAME} SDL)
As a sanity check, your linker will look to make sure that the SDL library does exist on your computer. That's why you might get a linking error if that library is not available at link-time, even if it's really a dynamic library.

Related

CMake links against wrong version of library

I have some CMake packages that depend on Protobuf v2.5, and one that depend on Protobuf v3.4. I have v2.5 installed system-wide in /usr, whereas v3.4 is only used in a single package. Therefore, I put the headers for v3.4 in a 3rdparty subdirectory inside the package where it is being used, and then I call include_directories(3rdparty) in my CMakeLists.txt so it can be found.
As for the shared libraries, the .so files for v2.5 are present in /usr/lib/x86_64-linux-gnu, and I installed the .so files for v3.4 to /usr/lib. In short, this is what the directory structure looks like:
v2.5:
headers: /usr/include
libraries: /usr/lib/x86_64-linux-gnu
v3.4:
headers: <MY_PACKAGE_SRC_DIRECTORY>/3rdparty
libraries: /usr/lib
Now, the problem arises when I try to link against v3.4. To simplify things, I don't use any CMake module files to find protobuf v3.4, rather I just add a hard-coded path /usr/lib/libprotobuf.so to the list of libraries to link against when creating a target. But even so, when I run ldd my_target_executable, the result is:
libprotobuf.so.8 => /usr/lib/x86_64-linux-gnu/libprotobuf.so.8
meaning that it is linking against the libraries for v2.5 in /usr/lib/x86_64-linux-gnu, even though I added a hard-coded path to the correct .so file in /usr/lib in the call to target_link_libraries when building this executable.
What is worth noting is that if I remove the .so files in /usr/lib/x86_64-linux-gnu, then it does link against the correct .so file in /usr/lib, so it appears that for some reason, CMake searches in /usr/lib/x86_64-linux-gnu before using the library path that I provide it. How can I change this behavior, or fix this problem in any other way?
UPDATE
The library file for v3.4 /usr/lib/x86_64-linux-gnu/libprotobuf.so is a link to /usr/lib/x86_64-linux-gnu/libprotobuf.so.14 which in turn is a link to the actual file /usr/lib/x86_64-linux-gnu/libprotobuf.so.14.0.0.
Now, if I change the hard-coded path that I give in target_link_libraries from /usr/lib/x86_64-linux-gnu/libprotobuf.so to either the second symlink /usr/lib/x86_64-linux-gnu/libprotobuf.so.14, or to the actual file /usr/lib/x86_64-linux-gnu/libprotobuf.so.14.0.0, then my executable correctly links againt v3.4. It appears that the name of the provided symlink has some effect on CMake's behavior.
This isn't cmake specifically but also how things work on Linux with gcc and shared libraries.
http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
When you specify target_link_libraries( target /usr/lib/x86_64-linux-gnu/libprotobuf.so) this sets up linking as -lprotobuf. In this case it should just use any version of the library it finds first.
target_link_libraries( target /usr/lib/x86_64-linux-gnu/libprotobuf.so.14) adjusts the cmake generated link line to use a specific library version. This seems to tell gcc to link against that version which will change what happens at run-time and library searches.
target_link_libraries
There are some cases where CMake may ask the linker to search for the library (e.g. /usr/lib/libfoo.so becomes -lfoo), such as when a shared library is detected to have no SONAME field. See policy CMP0060 for discussion of another case.

How to use external DLLs in CMake project

I've been searching over the internet but I couldn't find anything that would answer my question (or I don't know what to search for).
Anyway here's my issue:
I want to use 3rdParty libraries (.dll files) in my CMake project. Library (https://github.com/pitzer/SiftGPU) that I want to include is open source and is also available in binary which I would like to use and also uses CMake as build tool if that's relevant.
I hope I was clear enough.
First, edit your CMakeLists.txt to include your third party library. You'll need two thing: path to header files and library file to link to. For instance:
# searching for include directory
find_path(SIFTGPU_INCLUDE_DIR siftgpu.h)
# searching for library file
find_library(SIFTGPU_LIBRARY siftgpu)
if (SIFTGPU_INCLUDE_DIR AND SIFTGPU_LIBRARY)
# you may need that if further action in your CMakeLists.txt depends
# on detecting your library
set(SIFTGPU_FOUND TRUE)
# you may need that if you want to conditionally compile some parts
# of your code depending on library availability
add_definitions(-DHAVE_LIBSIFTGPU=1)
# those two, you really need
include_directories(${SIFTGPU_INCLUDE_DIR})
set(YOUR_LIBRARIES ${YOUR_LIBRARIES} ${SIFTGPU_LIBRARY})
endif ()
Next, you can do the same for other libraries and when every libraries are detected, link to the target:
target_link_libraries(yourtarget ${YOUR_LIBRARIES})
Then you can configure your project with CMake, but as it doesn't have any magic way to find your installed library, it won't find anything, but it'll create two cache variables: SIFTGPU_INCLUDE_DIR and SIFTGPU_LIBRARY.
Use the CMake GUI to have SIFTGPU_INCLUDE_DIR pointing to the directory containing the header files and SIFTGPU_LIBRARY to the .lib file of your third party library.
Repeat for every third party library, configure again and compile.

Statically linking to libarchive on Windows with MinGW

I've been using libarchive in my project for some time now and it's working great, at the moment I am dynamically linking to it, so on Windows the libarchive.dll file has to present on the system.
I would now like to statically link to the library so I don't have to bother distributing the DLL, but I'm having real trouble trying to achieve this!
Currently, in my make file, I have something like this:
-Lpath/to//libarchive/ -larchive
And this works, but it does a dynamic link. I don't know how to enforce a static link.
I can see in the libarchive directory there are two a files, libarchive.dll.a and libarchive_static.a. I suppose I want to link to libarchive_static.a but I can't seem to specify this, doing -larchive_static in the make file results in linker errors.
I was under the impression that static libraries under windows are lib files, but I get no such file type when I build libarchive.
How can I make a .lib file from libarchive. Also, as an extra question, what is the difference between an a file and a lib file?
Update
To statically link to libarchive, your library command for make should contain:
-Lpath/to//libarchive/ -larchive_static
This will link to the libarchive_static.a file. However, you also need to define LIBARCHIVE_STATIC in your code.
Now the problem is that libarchive depends on the bzip2 libraries (as well as others), and if you do not have a static build of them you will get linker errors something like:
undefined reference to `BZ2_bzCompressInit'
You need a static build of the dependent libraries and a similar command to the linker after the libarchive command:
-Lpath/to/bzip2/ -lbzip2
You can either build bzip2 from source, or do it the easy way and get a pre-built binary from the Gnu32Win project here: http://gnuwin32.sourceforge.net/packages.html
Just add libarchive_static.a explicitly to your link command.
gcc -o YourApp.exe $(OBJS) path/to/libarchive_static.a $(OtherLibs)
".lib" files differ from compiler to compiler (Borland, Microsoft etc.), ".a" is an old "archive" format from UNIX's ar tool. It is now used only for the bundling of static libraries.
Currently, in my make file, I have something ...
And this works, but it does a dynamic link
The .a file actually contains some code for dynamic linking to the .dll file, not the libarchive itself. On the startup the pointers to functions are allocated and dynamic linking is done.

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.

eclipse sfml library issues

I pulled out an application that I wrote in C++ using the sfml library, but I'm having trouble setting up the library in Eclipse. I specified the include path, the lib path and included all the necessary .so libraries to link to. the application compiles fine but it complains at runtime about missing libraries. Why is this happening? Didn't I include the path to the libraries in the project settings already? I have even tried to place all the .so's in the executable directory with no luck.
There is only the name of the shared lib stored in the executable. At program startup the dynamic linker then searches for the specified libs in its search paths. You can add/specify search paths by placing them colon separated in the environment variable LD_LIBRARY_PATH or by specifying them in /etc/ld.so.conf (at least if you use some unix based OS). On windows the whole PATH environment variable is used when searching for dynamic-link libraries (DLL).
To see the paths of shared libraries used by a given application run ldd applicationPath.