2

I am new to CMake and just want to understand some details about how target_link_libraries works.

To include a library, let's say boost. We can simply do include_directories(BOOST_LIBRARY_PATH). This allows my project to compile correctly and no errors report.

But after reading some posts online, I notice that people usually add target_link_libraries(executable boost_library) after include directories, so I just wonder why this line is needed.

Since my project is quite sensitive in terms of performance (i.e., I want it to run as fast as possible) my questions are as follows:

(1) What target_link_libraries actually do? (2) If we don't add this line, does it hurt performance? (3) What are the advantages of including target_link_libraries?

PleaseHelpppp
  • 75
  • 1
  • 6
  • `target_link_libraries` is responsible for adding a library into the linker's command line. If you use some library but doesn't specify it for the linker, you will got an "undefined reference" (or an "unresolved externals") **error** when create an executable or a shared library: https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix – Tsyvarev Jun 03 '21 at 07:35
  • @Tsyvarev But for the hearder-only library (like boost), do we still need to add target_link_libraries? It seems like this line is compeletly redundent, at least I dont see any errors so far. – PleaseHelpppp Jun 03 '21 at 08:30
  • 1
    Oh, so you are using the header which doesn't require implementation. (Note, that Boost in whole is NOT a header only library: many of its headers have implementation in corresponding library files). For use headers which don't require implementation `target_link_libraries` is not needed. But [Boost provides](https://cmake.org/cmake/help/latest/module/FindBoost.html) utility target `Boost::Boost` (or `Boost::headers`). Calling `target_link_libraries` with that target would add only include directories, without libraries. – Tsyvarev Jun 03 '21 at 08:48
  • @Tsyvarev Thanks for the clear explaination. If I understand correctly, include_directries should work properly if we are using a hearder library or some parts of the library that only contains hearder file. But It's alway good to have target_link_libraries link the library to the executable, so we dont get any weird errors. But really they dont make much differences. – PleaseHelpppp Jun 03 '21 at 09:09

1 Answers1

2

target_link_libraries does different things depending on the parameter passed. If you should use it or not depends on what exactly you're trying to achieve. (I'd recommend using target_include_directories instead of include_directories though, since it limits the use of the include dir to a single target and also allows you to make include dirs available to linking cmake library targets, if the headers are used in public headers of a library target.)

  • You can pass the name of a library target. Passing an INTERFACE library target is an option which can be used with header only libraries. Furthermore for installed external libraries providing cmake find/configuration scripts (usually) allows you to gain access to IMPORTED library targets that automatically make include dirs and dependencies for the target available to the target linking via target_link_libraries, if set up properly. I strongly recommend using this option with boost.
  • You can pass the full path to a library file. I recommend creating an imported library target instead though; this may be a bit more work, but it also allows you to attach info to the target such as include directories which puts related info in the same place and allows for easier reuse.
  • You can pass names of libraries the linker is able to find, e.g. target_link_libraries(executable pthread) on Linux.
  • ... (Some other options I don't really consider relevant here.)

My recommendation in your case would be:

  • Make sure you've installed boost
  • Use find_package + target_link_libraries to "link" the header lib which in this case is just a clean way of making the headers available to your target. (I assume you're using boost as a header only lib, not the static or shared version of the lib.)
find_package(Boost REQUIRED COMPONENTS headers CONFIG PATHS "/your/boost/install/path")
target_link_libraries(executable PRIVATE Boost::headers)

Note that the program won't be any faster of slower compared to using include_directories to specify the input directory; the speed of the cmake configuration may change a bit, but I don't recommend cutting any corners there.

fabian
  • 80,457
  • 12
  • 86
  • 114