Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between (target_)link_libraries and (target_)include_directories [closed]

Tags:

c++

cmake

I'm struggling with a large C++ project that uses CMake. Now I'm trying to add a dependency (a pre-compiled and installed library), but I'm not sure where to add is, what to include, and where to link it.

Particularly, I'd like to know the difference between the following commands:

  • include_directories
  • target_include_directories
  • link_libraries
  • target_link_libraries

Also, when I need to use the following commands:

  • find_package and
  • add_library

I know it has something to do with header-only libraries and so on, but I couldn't find a comprehensible and condensed explanation.

Also, how should I handle the following case:

The included library requires for example Boost, but the core project not. How can I avoid bloating up the entire CMakeLists.txt file and the binaries, and still use the precompiled library? (I think this is also part of this question)

like image 657
Dorian Avatar asked Jun 12 '19 15:06

Dorian


1 Answers

*include_directories is used to supply a list of include directories to the compiler. When a file is included using the pre-processor, these directories will be searched for the file.

*link_libraries is used to supply a list of libraries (object archives) to the linker. If the linked item is a cmake target, with specified include directories, they don't need to be specified separately with *include_directories.

The target_* versions apply only to the target that is given as an operand. The non-target versions apply to all targets in the directory. The target_* versions should be used whenever possible (i.e. pretty much always).

find_package is used to search for cmake settings from external sources i.e. outside of the project. If you want to link with a library without including the source of the library in a sub directory of your project, then you use find_package. From a lower level point of view, find_package(Foo) looks for a cmake module FindFoo.cmake and executes the module. The purpose of the module is to generate cmake variables or targets that can be used to include the corresponding dependency.

add_library is similar to add_executable, except it adds a target for a library, rather rather than an executable. Library targets can be used as items in link_libraries, and their dependencies are transitive by default.

I know it has something to do with header-only libraries and so on,

All of these have to do with libraries in general. Except *include_directories are also used for specifying the include directory of the project's own header files, not only those of the libraries.


The included library requires for example Boost, but the core project not. How can I avoid bloating up the entire CMakeLists.txt file and the binaries, and still use the precompiled library?

If the find_package module has created a cmake target for the library (using add_library(... IMPORTED)), which itself specifies the dependencies of the dependency, then simply link with it using link_libraries, and cmake takes care of linking with the dependencies. Same goes for the include directory of the target.

Old cmake modules don't necessarily provide targets, in which case you may need to write your own module in order to avoid bloating the project configuration.

like image 111
eerorika Avatar answered Sep 30 '22 17:09

eerorika