Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Examples of when PUBLIC/PRIVATE/INTERFACE should be used in cmake

Tags:

c++

cmake

I was reading about the cmake keywords PUBLIC, PRIVATE, INTERFACE and came across this paragraph here in the cmake docs.

Generally, a dependency should be specified in a use of target_link_libraries() with the PRIVATE keyword if it is used by only the implementation of a library, and not in the header files. If a dependency is additionally used in the header files of a library (e.g. for class inheritance), then it should be specified as a PUBLIC dependency. A dependency which is not used by the implementation of a library, but only by its headers should be specified as an INTERFACE dependency.

I understand how your choice between these three keywords affects the behavior of target_link_libraries and target_include_directories but I don't understand the distinction between the three cases explained in this paragraph. Could someone provide a toy example of

  1. using a dependency in the implementation of a library, but not in the header files (PRIVATE)
  2. using a dependency in the implementation of a library and also in the header files (PUBLIC)
  3. using a dependency in the header files of a library but not in the implementation (INTERFACE)
like image 753
Alex Armbruster Avatar asked Nov 26 '25 23:11

Alex Armbruster


1 Answers

Let's first deal with PUBLIC and PRIVATE:

Let's say you're writing a tool with a Qt GUI. You know this GUI is supposed to allow you to dynamically add elements to the GUI using plugins. Furthermore the user should be able to activate and deactivate the plugins via settings and the same plugins need to be activated on future starts of the program.

Your library therefore provides 2 functionalities:

  1. Creating Qt GUI elements. You need to use types from Qt in your public headers, so you add Qt includes to those headers. Every library needs to have access to the Qt headers, so you link Qt PUBLICly
  2. For persisting the plugin settings you choose Boost.JSON to store the settings in a file at a given location on the file system. The user of your libary won't actually deal with the JSON parsing/writing themselves, so you don't include any boost headers in your public headers and link Boost.JSON PRIVATEly.

INTERFACE visibility

You'll rarely use this visibility. Usually you'll need access to the headers, ect. in your own libary.

Header only libraries are one scenario where INTERFACE visibility is used though. Header only libraries won't actually result in a target being created in your build system and they cannot be built separately. The CMake target itself is just a convenient way making headers and dependent libraries available via target_link_libraries.

Another scenario where INTERFACE visibility is used are imported targets. Those aren't compiled as part of your project either. They just contain information about an library that's already built. For imported targets you can only use INTERFACE visibility.

like image 144
fabian Avatar answered Nov 29 '25 12:11

fabian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!