how to link third-part library in cmake - c++

I'm currently work with the project that chosen the CMake as the build system.
Nonetheless, I'm not very familiar with CMake. I spent much time on including the third-party library, the result is not very prefer. Could someone provide a way to fix my scenario?
My project tree is given in following section:
|--->top-Level
|--->ThirdLib
|------>Lib1
|---------->DLL
|---------->Include
|---------->LIB
|------>Lib2
|---------->DLL
|---------->Include
|---------->LIB
|--->UseThirdLib
|----->test.h //this file will used third-part lib

it seems u need some basic cmake tutorial?
https://cmake.org/cmake/help/latest/guide/tutorial/Adding%20a%20Library.html
target_include_directories
target_link_libraries

in Top level CmakeLists.txt
include_directories(${PROJECT_SOURCE_DIR}/ThirdLib/Lib1/include)
include_directories(${PROJECT_SOURCE_DIR}/ThirdLib/Lib2/include)
target_link_directories(your_target_name ${PROJECT_SOURCE_DIR}/ThirdLib/Lib1/lib)
target_link_directories(your_target_name ${PROJECT_SOURCE_DIR}/ThirdLib/Lib2/lib)
And all .dll should be placed in the same folder as executable or env:PATH should refer to folder with .dlls

Related

Convert from Xcode to CMake

I have a C++ project that I initially developed using Xcode on my Mac and I would like to set up the very same project using CMake. The project makes use of some external libraries, including eigen and boost. Xcode has a rather long list of Build Settings, including paths to external libraries, specification of the compiler version, additional linker flags, compiler optimization level, etc... and I am wondering where all of this information goes in the CMakeLists.txt file. I've searched extensively for help on this but have found precious little. I am new to CMake and have never written make files before. If there were a utility that could convert my Xcode project into a CMake project, that would be ideal. But I would be very glad to know of a tutorial on this, or to have some specific guidance. Any help on this would be greatly appreciated.
Conversion Strategy
I am pretty sure that the easiest and fastest way to move to CMake is a mixture of looking at comparable projects that link the same dependencies, and maybe copying a few relative file paths to your source files from XCode.
A well-written CMakeLists.txt that uses Eigen and Boost can be very small (and platform-independent).
One reason for this is CMake has a very different way to use dependencies.
For well-known libraries such as Boost, CMake includes scripts to include headers and link libraries.
Minimal CMakeLists.txt
A minimal example may look like this:
find_package(Eigen3 REQUIRED)
find_package(Boost REQUIRED COMPONENTS system)
add_executable(
app
src/main.cpp
)
target_include_directories(
app
${Eigen3_INCLUDE_DIRS}
${Boost_INCLUDE_DIR}
)
target_link_libraries(
app
${Boost_LIBRARIES}
)
Example Projects
For Eigen, there is no such pre-installed script that can be called by find_package.
Here are two real-world example projects that link Eigen and Boost: https://github.com/ompl/ompl/blob/master/CMakeLists.txt
https://github.com/roboticslibrary/rl
Here is an example for a find script for Eigen.
As a piece of advice, some CMake projects are out there are convoluted and use old syntax, newer project files tend to use small letters in commands.
If it happens that directly target linking libraries doesn't work, you'll have to write your own Find*.cmake files by yourself.
Here's a spec of what you should cover to make it (this is just one approach):
Imagine you have a library XYZ:
Your file
FindXYZ.cmake should have as a result a set of variables to use:
XYZ_LIBRARIES
XYZ_INCLUDE_DIR
For example:
set(XYZ_LIBRARIES ${SOME_PATH_TO_LIBRARY1} ${SOME_PATH_TO_LIBRARY2})
find_path(XYZ_INCLUDE_DIR NAMES xyz/xyz.h HINTS ${PLACE_WHERE_INCLUDE_SHOULD_BE}
PATH_SUFFIXES include
)
From your main cmake maybe you 'use' it:
find_package(XYZ REQUIRED)
# Now we use both _INCLUDE_DIR and _LIBRARIES
include_directories(SYSTEM "${XYZ_INCLUDE_DIR}")
# TARGET_NAME is the current target, the 'client' of XYZ
# append XYZ to our list of libraries to link
target_link_libraries(${TARGET_NAME} ${XYZ_LIBRARIES})
I'm surely missing details but that's the general idea. Here are some cmake scripts that I know work in a big project:
Example with OpenSSL
Find:
https://github.com/highfidelity/hifi/blob/Android/cmake/modules/FindOpenSSL.cmake
Client (in this case is a library that indeed needs OpenSSL):
https://github.com/highfidelity/hifi/blob/Android/domain-server/CMakeLists.txt

Where to place CMake macro definitions?

I'm writing an application that relies on the Poco project. I just need a few sub modules but they use macros defined by the Poco project which are stored in a cmake folder at the root of the Poco folder structure.
I don't want to drag the whole Poco folder as I don't want to link my project to the whole Poco framework. How can I make those macros available to my project?
I'm not sure to well understand what you need. But why not simply include de file containing the macros by this way with cmake ?
include(path/to/Poco/cmake/macros.cmake)
Take the Poco project
Open the main CMakeLists.txt of Poco and comment (with #) all the add_subdirectory commands for the directories you don't need.
Try to build Poco
If it fails, add back the directories which contains the missing dependencies (in short, you might think you don't need a directory, but it might be that one of the directories you need depends on another directory)
When it builds, you can delete all the directories for which you have removed the command add_subdirectory

How to direct CMake to use libraries in specific directory only

I am trying to get all dependent libraries in my project in one directory and read from only that directory in CMake. I want to do this so that I may have portability of my project and so that it can run on any computer as long as that directory with all the libraries is present with the executable. Is this possible somehow? I am using Ubuntu 14.10.
I have a LOT of static libraries used in my project and they are in places such as usr/lib, usr/lib/i386-linux-gnu, usr/lib/x86_64-linux-gnu.
Any help would be appreciated! Thanks in advance.
Seems that you need to use link_directories to tell where to find your libs.

CMake - Depending on another cmake project

I have the following structure to a project I am working on:
---Library1
------build
------include
------src
------CMakeLists.txt
---Library2
------build
------include
------src
------CMakeLists.txt
---Executable1
------build
------include
------src
------CMakeLists.txt
Library1 is a library I am developing that needs to link with Library2 which is a 3rd party library. When I build Library1, I need it to automatically build Library2 and link with it. Executable1 will need to build and link with Library1. I'm not sure how to do with with Cmake, and I was wondering if anyone could guide me in the right direction. I think I may need to use the add_dependencies command or add_subdirectory but I'm not sure how to go about using them and making sure they are linked to my library. Any help would be appreciated.
I'd think the best commands here are likely to be add_subdirectory (as you suspected) and target_link_libraries.
I guess with your directory structure, I'd expect to see a "top-level" CMakeLists.txt in the root. In that CMake file, you'd invoke the subdirectories' CMakeLists using add_subdirectory.
I imagine both Library1 and Library2 are actual CMake targets, included via add_library, and similarly you have add_executable(Executable1 ...). In this case, you can add the following to Library1/CMakeLists.txt:
target_link_libraries(Library1 Library2)
CMake now automatically links Library2 whenever Library1 is specified as a dependency. If Library2 is modified, then it will be rebuilt automatically before being linked to Library1 again.
Likewise in Executable1/CMakeLists.txt you can then do:
target_link_libraries(Executable1 Library1)
Probably the only thing to watch for here is that the order of the add_subdirectory commands would need to be
add_subdirectory(Library2)
add_subdirectory(Library1)
add_subdirectory(Executable1)
so that the dependencies are defined before they're referred to in the target_link_libraries calls.
A final point which seems odd to me is that you have a build directory per target. Normally there should only be a need for a single build directory (preferably outside the source tree).

Including my own shared library with cmake

I have the following code in my CMakeLists.txt for finding my shared library libsieve.so
set(CPPLIB_DIR "${CMAKE_SOURCE_DIR}/../core/build")
find_library(CPPLIB_SIEVE_LIBRARY NAMES libsieve PATHS CPPLIB_DIR)
But it fails and won't find my library. I have the following directory structure:
core
build: libsieve.so
project: CMakeLists.txt
What am I doing wrong?
I don't know why cmake doesn't find the needed library but I can suggest a way to make it happen with the help cmake-gui: if the first run of "configure" fails to find the library you can point it to the needed library manually (set the full absolute path). Most of the time such solution works for me.
Also if the library was built with one tool chain (say, Intel C++) and you project is being built with another tool chain (say, clang) the failure to find the library may be due to binary incompatibility between the project and the library.
Upd. The original problem was referencing CPPLIB_DIR. It should have been:
find_library(CPPLIB_SIEVE_LIBRARY NAMES sieve PATHS ${CPPLIB_DIR})
Cmake find_library expect you to provide the library name or the library file name.
You mixed the two by adding a "lib" prefix to your library name. So you should try to replace libsieve by either sieve or libsieve.so.