How do I include packages in different directory with CMake? - c++

I am trying to compile a piece of C++ code on a server with CentOS. I need to include a library (NLopt) that is installed as a module at the location "/services/tools". I have tried "module load NLopt", but CMake does still not find the library.
What do I need to do to make CMake find the package?

"By default, [it] installs the NLopt static library (libnlopt.a) in /usr/local/lib and the NLopt header file (nlopt.h) in /usr/local/include, as well manual pages and a few other files."
So, you can include the header as
include_directories("/usr/local/include")
and link the library as
target_link_libraries(project "/usr/local/lib/lbnlopt.a")
Ideally you could try to find a CMake find module for the library.

Assuming your libraries are in /service/tools/lib and the headers in /service/tools/include, you can also set CMAKE_PREFIX_PATH, like this:
list(APPEND CMAKE_PREFIX_PATH /service/tools)

Related

What's the shape of CMake library when using find_library()

What is the file structure of CMake library?
For example, here is my library located in library folder:
library
\mylib1.so
\mylib2.so
The headers are in other dir out of library.
Can I use find_library(mylib1 PATHS library) to find my library and use target_include_directories() or include_directories() to include my headers? For my testing, it's failed. So what's the right structure?
Do I need put the header files (.h or .hpp) into library/include folder and put .so in lib folder or put them all into the library folder?
I didn't find any explain in CMake documents. I also find other commands in CMake documents but they are lack of something in details that I don't understand. So I'd like to known how do I find the documents like this.
find_library is used to find a file, but it doesn't create identify provide any information about include directories or other information required by the linking target.
To be able to use your lib after installing it's best to make use of find_package.
You could place files like into a install directory MyLibrary like this:
MyLibrary/lib/MyLib-0.1.1/MyLibraryConfig.cmake
MyLibrary/lib/MyLib-0.1.1/MyLibraryConfigVersion.cmake
MyLibrary/lib/MyLib-0.1.1/libmylibrary.so
MyLibrary/include/MyLib-0.1.1/include/...
MyLibraryConfigVersion.cmake
This file is used to check, if the version of the library is compatible with the build configuration of the project using find_package. Additionaly it provides cmake with information about the version of the library:
set(PACKAGE_VERSION 0.1.1)
if(NOT UNIX # must be the same target platform
OR NOT CMAKE_SIZEOF_VOID_P EQUAL 8 # assuming the installed lib is 64 bit
OR PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
set(PACKAGE_VERSION_COMPATIBLE FALSE) # inform find_package this is not a suitable version of the lib
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()
MyLibraryConfig.cmake
This file is used to actually create the imported lib to use by the project calling find_package; It's only included, if the version file considers the configuration suitable.
if (NOT TARGET MyLibrary) # avoid issues with using find_package(MyLibrary) multiple times
add_library(MyLibrary IMPORTED)
# provide the necessary info about the target
set_target_properties(MyLibrary PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/libmylibrary.so" # specify absolute library file location using the directory containing this cmake file
)
target_include_directories(MyLibrary INTERFACE "${CMAKE_CURRENT_LIST_DIR}/../../include/MyLib-0.1.1/include")
endif()
This allows you to "tell" cmake about the location of the install dir and use find_package like this:
list(APPEND CMAKE_PREFIX_PATH /path/to/MyLibrary) # this could be passed via -D option during configuration instead
find_package(MyLibrary REQUIRED)
Note that there are alternative paths where to put the cmake configuration files, see the documentation of find_package. Furthermore there is cmake functionality that can take over generating some, if not all of the cmake configuration files for you automatically on installation, see
install()
The CMakePackageConfigHelpers cmake module

How to know variable such as 'OpenCV' in CMake

I am using OpenCV with gcc and cmake. And I found a tutorial https://docs.opencv.org/3.4.0/db/df5/tutorial_linux_gcc_cmake.html .In the file CMakeLists.txt, there are some variables such as OpenCV and OpenCV_INCLUDE_DIRS.
cmake_minimum_required(VERSION 3.9)
project(VideoRecord)
set(CMAKE_CXX_STANDARD 11)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(VideoRecord main.cpp)
target_link_libraries(VideoRecord ${OpenCV_LIBS})
I want to know where to find these variables definition.
EDIT
Thanks #qbranchmaster's answer. I tried to search FindOpenCV.cmake but failed.
First try.
➜ ~ cmake --help-module-list | grep "FindOpen"
FindOpenACC
FindOpenAL
FindOpenCL
FindOpenGL
FindOpenMP
FindOpenSSL
FindOpenSceneGraph
FindOpenThreads
Another try.
➜ / find . "FindOpenCV.cmake"
In addition, my os is osx and I install cmake with brew. I comiple and install OpenCV manually.
These variables are part of the package config script shipping with OpenCV.
Note that find_package is a two-headed beast. The classic mode of operation is finding libraries through find-scripts. This is still the approach being used today for third-party libraries that are not aware of CMake. However, if your dependency is itself being built with CMake, it can provide a package config file instead, which allows for a more powerful mode of operation.
The idea here is that instead of you telling CMake how to find a dependency, the dependency itself tells CMake how clients can find it. This is the approach that is taken by libraries like OpenCV and Qt.
To answer your question, those variables are being set by the package config file in your local OpenCV installation, the template of which can be found in the OpenCV source code under cmake/templates/OpenCVConfig.cmake.in.
They are defined in CMake OpenCV module. CMake has numerous modules that aid in finding various libraries like OpenCV (FindOpenCV.cmake module).
Using this command you can get a list of modules that your CMake supports:
cmake --help-module-list
Some libraries come with their own *.cmake modules which should be installed in some system path. If you are using Ubuntu, your cmake modules should be localised in:
/usr/share/cmake/Modules/
If not, just search system for file FindOpenCV.cmake. In that file you will find these variables.
In general, you get variable names from the documentation or source code of the package you want to find.
Often you can derive the name to put into find_package from the provided FindFoo.cmake module file name, because "Foo" would be the name. The find module is either part of CMake or comes with the third-party library.
If there is no find module, some modules provide FooConfig.cmake files, where "Foo" is again the string to put into find_package.
If you have neither a find nor a config file, you need to find the library by other means, e.g., FindPkgConfig or find_library / find_file.

cmake does not find boost header on linux

Boost header files are on /usr/include/boost.
In CMakeLists.txt I include the folder with include_directories
include_directories(/usr/include /usr/include/boost/
/usr/include/boost/smart_ptr)
However, cmake insists in not finding header files. The problem arises in intrusive_ptr.hpp, which includes #include <boost/smart_ptr/intrusive_ptr.hpp:
boost/smart_ptr/intrusive_ptr.hpp: No such file or directory
/usr/include/boost/intrusive_ptr.hpp
My guess is it does not like boost/smart_ptr/ prefix.
So, include_directories did not work.
CMake Error:
CMake Error at /usr/local/share/cmake-3.3/Modules/FindBoost.cmake:1245
(message):
Unable to find the requested Boost libraries.
Unable to find the Boost header files. Please set BOOST_ROOT to the root
directory containing Boost or BOOST_INCLUDEDIR to the directory containing
Boost's headers.
What should I do?
Thanks.
While I do not know what failed in your case, I'd recommend to simply use find_package with the included FindBoost.cmake file:
find_package(Boost REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
Done
I think you are using 3.3 cmake version, which support target_include_directories.
Even target_link_library should help here which gives the include path free if we link the library.
How do you add boost libraries in CMakeLists.txt

how to add library source in cmake

i can't seem to find in google/stackoverflow how do i add a library to my project using the library sources so that in make time it will compile the library and then my project and then link between them.
the library i'm trying to add is curlpp
as of now I've tried the following:
add_library(curlpp STATIC IMPORTED ./curlpp)
target_link_libraries(myExec curlpp)
link_directories(./curlpp/src/)
include_directories(./curlpp/includes)
but it has no effect
You first need to add the subdirectory to actually build the library, then you can add the actual library for linking.
If the library is not a CMake project you might need to add a simple CmakeLists.txt file in the library, that executes the actual configuration and building.
You might also use custom commands from the top-level CMakeLists.txt file to configure/build the library.
Basing off on Some programmer dude's response the following commands allowed me to statically link with curlpp:
add_subdirectory(./vendor/curlpp)
set_property(TARGET curlpp PROPERTY IMPORTED_LOCATION ./vendor/curlpp/libcurlpp.a)
target_link_libraries(my_target curlpp)

"No rule to make target" error in cmake when linking to shared library

In Ubuntu, I have downloaded a third-party shared library, mylibrary.so, which I have placed in the directory /home/karnivaurus/Libraries. I have also placed the associated header file, myheader.h, in the directory /home/karnivaurus/Headers. I now want to link to this library in my C++ code, using CMake. Here is my CMakeLists.txt file:
cmake_minimum_required(VERSION 2.0.0)
project(DemoProject)
include_directories(/home/karnivaurus/Headers)
add_executable(demo demo.cpp)
target_link_libraries(demo /home/karnivaurus/Libraries/mylibrary)
However, this gives me the error message:
:-1: error: No rule to make target `/home/karnivaurus/Libraries/mylibrary', needed by `demo'. Stop.
What's going on?
While the other answer posted here is valid, it is out-dated. CMake now provides better solutions for using a pre-built external library in your code. In fact, CMake itself even discourages the use of link_directories() in its documentation.
The target_link_libraries() command takes very specific syntax for linking to an external library. A more modern solution is to create an IMPORTED CMake target for your external library:
add_library(MyExternalLib SHARED IMPORTED)
# Provide the full path to the library, so CMake knows where to find it.
set_target_properties(MyExternalLib PROPERTIES IMPORTED_LOCATION /home/karnivaurus/Libraries/mylibrary.so)
You can then use this imported CMake target later on in your code, and link it to your other targets:
target_link_libraries(demo PRIVATE MyExternalLib)
For other ways to use an external third-party library in your CMake code, see the responses here.
You may use a full path to the static library. To link w/ dynamic one, better to use link_directories() like this:
cmake_minimum_required(VERSION 2.0.0)
project(DemoProject)
include_directories(/home/karnivaurus/Headers)
link_directories(/home/karnivaurus/Libraries)
add_executable(demo demo.cpp)
target_link_libraries(demo mylibrary)
and make sure mylibrary has prefix lib and suffix .so in file name (i.e. full name is /home/karnivaurus/Libraries/libmylibrary.so).
To make you project more flexible, you'd better to write a finder module and avoid hardcode paths like /home/karnivaurus/*