CMake Library Target, Public and Private Headers in Single Directory

212 Views Asked by At

Assume I have the following project structure (inherited code - cannot change structure):

MyProject
├── CMakeLists.txt
├── src
│   └── foo.cpp
│   └── bar.cpp
├── include
│   └── foo_public.h
│   └── foo_private.h
│   └── bar_public.h
│   └── bar_private.h

CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)
project(MyProject)

add_library(MyLibrary
    foo.cpp
    bar.cpp)

target_include_directories(MyLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

set_target_properties(MyLibrary PROPERTIES PUBLIC_HEADER foo_public.h bar_public.h)

install(TARGETS MyLibrary
        LIBRARY DESTINATION ${INSTALL_LOCATION}/lib
        PUBLIC_HEADER DESTINATION ${INSTALL_LOCATION}/include)

Will this allow other executables/libraries to link to MyLibrary at the install location without visibility into the private header files?

Does it matter that both the public and private headers are in the same location passed to target_include_directories?

Note: The target environment is Red Hat Enterprise Linux

1

There are 1 best solutions below

0
Marek R On BEST ANSWER

This statment in CMakeLists.txt:

target_include_directories(MyLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

Means:

  • MyLibrary target or any target linking target MyLibrary should use MyProject/include directory as include path (since PUBLIC keyword is used). (PRIVATE would mean only MyLibrary should use this include path, INTERFACE only those who link target MyLibrary).

As a result other targets will be able include your private header. This can happen if someone will include your whole project into his source. If someone will just install library, public headers will be copied to respective locations, without private ones.

Best way to fix this is move private headers to Src directory. You do not have to change anything else.

Note good library should contain tests. Those test should not use private headers to check that everything works without private headers. Now your tests will see private headers implicitly, so you may missed that some private symbol is in use in public header.

I recommend to see this instruction what is best practice to organize library project. It contains contains lots of nice technical details. Here is github project.