Create a shared lib that depends on dlib using Cmake - c++11

I'm building a shared library in C++ that depends on dlib using CMake.
While it has been possible for me to build and install a shared dlib using make and make install, so far I haven't figured out the way to link to this shared dlib library.
The examples of usage given in the DLib website always link to a static library.
This is what I have so far:
cmake_minimum_required(VERSION 2.8.12)
project(face_align)
set(CMAKE_CXX_STANDARD 11)
find_package(dlib)
add_library(face_align SHARED src/mylib.cpp)
target_link_libraries(face_align dlib::dlib)
The linker complains like so:
/usr/bin/ld: cannot find -ldlib::dlib
collect2: error: ld returned 1 exit status
CMakeFiles/face_align.dir/build.make:94: recipe for target 'libface_align.so' failed
make[2]: *** [libface_align.so] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/face_align.dir/all' failed
make[1]: *** [CMakeFiles/face_align.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
If I remove the SHARED from
add_library(face_align SHARED src/mylib.cpp) the project builds successfully. This makes me think that dlib:dlib is pointing to the static library. I see that there is a dlib:dlib_shared but no success linking to this one either.

The answer seems to be (1) linking to dlib as a static library (2) making the code linking to dlib position independent:
cmake_minimum_required(VERSION 2.8.12)
project(face_align)
set(CMAKE_CXX_STANDARD 11)
# Unfortunately, this only links dlib as static library
add_subdirectory(libs/dlib dlib_build)
add_library(face_align SHARED src/mylib.cpp)
# This makes the target position independent, allowing to link an static library to a dynamic one.
set_target_properties(face_align PROPERTIES POSITION_INDEPENDENT_CODE ON) # This made it work
# Link Dlib
target_link_libraries(face_align dlib::dlib)
EDIT:
Also, in Linux (I haven't tested this in other S.O.s) CMake does some magic and, after installing dlib library in shared mode:
$ cd $DLIB
$ mkdir build && cd build
$ cmake ../dlib
$ make && make install
Is possible to simply add the library using target_link_libraries as follows:
cmake_minimum_required(VERSION 2.8.12)
project(face_align)
set(CMAKE_CXX_STANDARD 11)
add_library(face_align SHARED src/mylib.cpp)
# Link Dlib
target_link_libraries(face_align dlib)
Then, in your code, include headers as follows:
#include <dlib/your_dlib_header_here.h>

Related

How to fix undefined reference LLVM error while linking CXX executable

I was trying to build a llvm-slicer from:
https://github.com/IAIK/ios-analysis-llvmslicer
and I follow the instructions:
cd llvm-slicer
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE="Release" -DLLVM_TARGETS_TO_BUILD="AArch64;X86" -DLLVM_ENABLE_EH=YES -DLLVM_ENABLE_RTTI=ON ..
make -j4 opt
make -j4 llvm-slicer
But when I execute the last command make -j4 llvm-slicer, I got an error:
[100%] Built target LLVMAnalysis
[100%] Linking CXX executable ../../bin/llvm-slicer
/usr/bin/ld: ../../lib/libLLVMSlicer.a(FunctionStaticSlicer.cpp.o): in function `llvm::Pass* llvm::callDefaultCtor<(anonymous namespace)::FunctionSlicer>()':
FunctionStaticSlicer.cpp:(.text._ZN4llvm15callDefaultCtorIN12_GLOBAL__N_114FunctionSlicerEEEPNS_4PassEv+0x1c): undefined reference to `vtable for (anonymous namespace)::FunctionSlicer'
collect2: error: ld returned 1 exit status
make[3]: *** [tools/llvm-slicer/CMakeFiles/llvm-slicer.dir/build.make:116: bin/llvm-slicer] Error 1
make[2]: *** [CMakeFiles/Makefile2:9647: tools/llvm-slicer/CMakeFiles/llvm-slicer.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:9654: tools/llvm-slicer/CMakeFiles/llvm-slicer.dir/rule] Error 2
make: *** [Makefile:2740: llvm-slicer] Error 2
I have no idea about how to fix it and I couldn't find any similar issues on Google, I hope someone can help me to figure it out, many thx.
There can be several scenarios for this issue, but in my opinion, here the scenario is for the given information that your default compiler (_ZN...something errors mostly because of compilers or linkers) is earlier version of gnu (gcc for c, g++ for c++) in your host pc (or maybe another compiler other than clang) and struggling about resolving a c++ feature anonymous namespace, as, a part of given error says:
/usr/bin/ld: ../../lib/libLLVMSlicer.a(FunctionStaticSlicer.cpp.o): in function `llvm::Pass* llvm::callDefaultCtor<(anonymous namespace)::FunctionSlicer>()':
FunctionStaticSlicer.cpp:(.text._ZN4llvm15callDefaultCtorIN12_GLOBAL__N_114FunctionSlicerEEEPNS_4PassEv+0x1c): undefined reference to `vtable for (anonymous namespace)::FunctionSlicer'
For this, there are several things you can do:
1-) You can change your compiler for building. In command window, you can export clang and clang++ as your compiler before cmake configuration. Here I assume that you installed new versions of clang compiler from anywhere, even github clone, I can give several examples here how to export and you can adapt one of them to your case easily:
export CC=clang
export CXX=clang++
another version:
export CC=clang-11
export CXX=clang++-11
another version:
export CC=/usr/bin/clang
export CXX=/usr/bin/clang++
another version:
export CC=/usr/bin/clang-12
export CXX=/usr/bin/clang++-12
another github clone version:
export CC=~/llvm/llvm-project/build/bin/clang
export CXX=~/llvm/llvm-project/build/bin/clang++
Even if this does not change your compiler, you can change your compiler while configuring with cmake by -DCMAKE_C_COMPILER={your-c-compiler} and -DCMAKE_CXX_COMPILER={your-c++-compiler} cmake flags. Try either with gcc or clang. Here is an example configuration in your case:
cmake \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_BUILD_TYPE="Release" \
-DLLVM_TARGETS_TO_BUILD="AArch64;X86" \
-DLLVM_ENABLE_EH=YES \
-DLLVM_ENABLE_RTTI=ON ..
2-) Error can be because of c++ standard, you can add -DCMAKE_CXX_STANDARD=14 (Default C++ standard using by LLVM) flag as cmake configuration like:
cmake -DCMAKE_BUILD_TYPE="Release" -DLLVM_TARGETS_TO_BUILD="AArch64;X86" -DLLVM_ENABLE_EH=YES -DLLVM_ENABLE_RTTI=ON -DCMAKE_CXX_STANDARD=14 ..
3-) Even if didn't work above cases, you can remove anonymous namespace from FunctionStaticSlicer.cpp file (given in the error message) and try to build again. You can find these lines like this:
// some code here and do not delete
namespace { // delete this line
// as you can see there is no name of namespace that's why called 'anonymous'
// if it was it would be like 'namespace nmspcName {'
// some code here and do not delete
} // and delete this line, too
// some code here and do not delete
But this is really bad practice, even if it can solve your problem, I do not recommend.
Also you can try to do similar changes in CMakeLists.txt file or adding other cmake configuration flags, however in my opinion, you could solve your problem easily by 1. option which is changing your default compiler.

Caffe build gives GCC Link Error "can not be used when making shared object.; recompile with -fPIC"

I'm trying to install caffe, using CMake, but when I run make all (after running cmake .. from a build directory) I get the following error:
me#gimli:~/Downloads/caffe/build$ make all
[ 1%] Built target caffeproto
[ 1%] Linking CXX shared library ../../lib/libcaffe.so
/usr/bin/x86_64-linux-gnu-ld: /usr/local/lib/libleveldb.a(db_impl.cc.o): relocation R_X86_64_PC32 against symbol `_ZN7leveldb10EnvWrapper8ScheduleEPFvPvES1_' can not be used when making a shared object; recompile with -fPIC
/usr/bin/x86_64-linux-gnu-ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
src/caffe/CMakeFiles/caffe.dir/build.make:40060: recipe for target 'lib/libcaffe.so.1.0.0' failed
make[2]: *** [lib/libcaffe.so.1.0.0] Error 1
CMakeFiles/Makefile2:267: recipe for target 'src/caffe/CMakeFiles/caffe.dir/all' failed
make[1]: *** [src/caffe/CMakeFiles/caffe.dir/all] Error 2
Makefile:129: recipe for target 'all' failed
make: *** [all] Error 2
I don't really understand CMake, but gather that somewhere I'm supposed to add -fPIC to a gcc command. But, I have no idea where I should make this change, or if there's somewhere in Cmake where I should tell it to construct the gcc command correctly.
How can I force CMake to create/use a gcc command with the -fPIC option, or is there something else entirely I should be doing?
The error is not from CMake but from the linker. It actually tells, that:
You cannot build shared library libcaffe.so with PIC (Position independent code) feature and link it with the static library libleveldb.a compiled without this feature.
Possible solutions are:
Get shared version of the static library (libleveldb.a in your case), so it will be compiled with PIC. This is what the error message suggests you.
Instead of building shared library (Caffe in your case), build static one, without using of PIC. Note, that in this case your will face with similar issues when trying to use resulted library in the future shared libraries.
For most CMake projects forcing the building static libraries can be performed with:
cmake -DBUILD_SHARED_LIBS=OFF <other parameters>
Strictly speaking, PIC feature is independent from the type (shared or static) of a library. So you may have a static library with PIC, or build a shared library without it.
For many CMake projects you may control PIC feature of the created libraries with
cmake -DPOSITION_INDEPENDENT_CODE=<ON|OFF> <other parameter>

Adding ffmpeg to clion project

I would liket to add ffmpeg to Clion but I have some problems with it.
My MakeLists.txt looks liek this:
cmake_minimum_required(VERSION 3.10)
project(ffmpeg)
set(CMAKE_CXX_STANDARD 11)
include_directories(libs/ffmpeg/)
include_directories(libs/ffmpeg/include/libavutil/)
include_directories(libs/ffmpeg/include/libaccodec/)
include_directories(libs/ffmpeg/include/libavdevice/)
include_directories(libs/ffmpeg/include/libavfilter/)
include_directories(libs/ffmpeg/include/libavformat/)
include_directories(libs/ffmpeg/include/)
link_directories(libs/ffmpeg/lib/)
set(SOURCE_FILES main.cpp)
add_executable(ffmpeg main.cpp)
target_link_libraries(
ffmpeg
avcodec
avdevice
avfilter
avformat
avresample
avutil
postproc
swresample
swscale
)
I am not sure if I added the libraries and includes in the right way, beacause in my simple main.cpp it can't resolve avcodec_configuration().
My project layout looks as follows:
ffmpeg
-libs
-include
-libavcodec
.
.
.
-lib
-avcodec.lib
-main.cpp
EDIT:
Now all includes are found by the compiler. BUt if I compile I get following error:
c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe: cannot find -lavresample
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe[2]: *** [ffmpeg.exe] Error 1
mingw32-make.exe[1]: *** [CMakeFiles/ffmpeg.dir/all] Error 2
mingw32-make.exe: *** [all] Error 2
CMakeFiles\ffmpeg.dir\build.make:96: recipe for target 'ffmpeg.exe' failed
CMakeFiles\Makefile2:66: recipe for target 'CMakeFiles/ffmpeg.dir/all' failed
Makefile:82: recipe for target 'all' failed
I don't recommend to hardcode paths to the headers/libraries in your CMakeLists.txt; this is not portable.
Search for a ready FindFFmpeg.cmake (maybe this one will work?),
add it to your project directory (e.g. into a cmake/ subdirectory),
and connect it to CMAKE_MODULE_PATH. E.g. list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake").
Then refer to ${FFMPEG_LIBRARIES}, ${FFMPEG_INCLUDE_DIRS} and ${FFMPEG_DEFINITIONS}.
Sometimes you have to fix up the FindXXX.cmake modules.
I was able to include the precompiled ffmpeg library to cmake project by creating find cmake scripts and including them in main CMakeLists.txt.
Full example is here : https://github.com/tomkordic/Java-native-HTTP/tree/master/src/main/cpp
In my project a FFMPEG_INCLUDE_DIRECTORY and FFMPEG_LIB_DIRECTORY are passed by gradle build script you can set these manually or discover them in some other way.
FFMPEG_INCLUDE_DIRECTORY is a path to ffmpeg installation include directory, in my case:
/mnt/7fab2260-fb19-41a7-ac7c-816bab2f3b92/install/ffmpeg_build/include
FFMPEG_LIB_DIRECTORY is a path to ffmpeg installation lib directory, in my case:
/mnt/7fab2260-fb19-41a7-ac7c-816bab2f3b92/install/ffmpeg_build/lib
Make sure to set CMAKE_MODULE_PATH to the directory where your find cmake scripts are located.
Build system is for ubuntu 18.04.

How to link jemalloc shared library using cmake

I'm trying to link the jemalloc library into my application at build time using it as a generic implementation. According to https://github.com/jemalloc/jemalloc/wiki/Getting-Started the linking flags to use are:
-L`jemalloc-config --libdir` -Wl,-rpath,`jemalloc-config --libdir` -ljemalloc `jemalloc-config --libs`
So I did the following CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.12.2)
project(widget)
include_directories(include)
file(GLOB SOURCES "src/*.cpp")
add_executable(widget ${SOURCES})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L`jemalloc-config --libdir` -Wl,-rpath,`jemalloc-config --libdir` -ljemalloc `jemalloc-config --libs`")
But when I do make I get the following errors:
Linking CXX executable widget
c++: error: `jemalloc-config: No such file or directory
c++: error: unrecognized command line option ‘--libdir`’
c++: error: unrecognized command line option ‘--libdir`’
c++: error: unrecognized command line option ‘--libs`’
make[2]: *** [widget] Error 1
make[1]: *** [CMakeFiles/widget.dir/all] Error 2
For future generations, as this still comes up as one of the first links on Google.
Jemalloc comes with pkg-config setup, which can be used like this:
find_package(PkgConfig REQUIRED)
pkg_check_modules (JEMALLOC jemalloc)
pkg_search_module(JEMALLOC REQUIRED jemalloc)
include_directories(${JEMALLOC_INCLUDE_DIRS})
target_link_libraries(your_target_name ${JEMALLOC_LIBRARIES})
execute_process() command is your friend. Use it to run jemalloc-config executable and then put its output into CMake variables.
find you root_dir of jemalloc. Mine is /Users/lion/homebrew/Cellar/jemalloc/5.2.1_1/lib/
(I install jemalloc by brew on macOS)
link (soft link) all its lib to your local lib ln -s /Users/lion/homebrew/Cellar/jemalloc/5.2.1_1/lib/* /usr/local/lib
Then it works!

Compiling GDAL/OGR with MinGW on Windows

I've been trying to link the GDAL library to qt-creator this last week, but have been having problems compiling the library in order to correctly link it.
I am getting this error
libtool: link: g++ .libs/gdalinfo_bin.o -o .libs/gdalinfo.exe -L/local64/lib /c/gdal-2.1.0/.libs/libgdal.a -lodbc32 -lodbccp32 -lz -lpthread -lws2_32
C:/MinGW/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2/../../../../x86_64-w64-mingw32/lib/../lib/libiconv.a(localcharset.o):localcharset.c:(.text+0x8): undefined reference to `__imp_GetACP'
collect2.exe: error: ld returned 1 exit status
make[1]: *** [gdalinfo.exe] Error 1
make[1]: Leaving directory `/c/gdal-2.1.0/apps'
make: *** [apps-target] Error 2
After having so many problems with the compiler, I am unsure whether this is a problem with setup or whether I need to reconfigure something in the gdal library for windows/mingw consumption.
Can anyone help me with this?
EDIT: This may causing the problem, although I am unsure how to fix it
*** Warning: linker path does not have real file for library -lz.
*** 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 libz and none of the candidates passed a file format test
*** using a file magic. Last file checked: C:/MinGW/mingw64/x86_64-w64-mingw32/lib/libz.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.
*** Since this library must not contain undefined symbols,
*** because either the platform does not support them or
*** it was explicitly requested with -no-undefined,
*** libtool will only create a static version of it.
Previous attempt lead me to believe that I needed the MinGW-64 version which was not designated by the GDAL instructions, so I used this tutorial to modify MinGW for 64 bit libraries
I would strongly suggest moving your development toolset to use MSYS2 and its package manager. It includes a ton of precompiled libraries, such as GDAL, so you don't have to spend time on trying to get those to compile.
Had the same problem. Solved it by by:
compiling ZLib,
placing zlib1.dll in MinGW/bin,
placing libz.a and libz.dll.a in MinGW/lib.

Resources