add_library() for header-only c++ target... again

Hello!

I’m trying to make a header-only target in my c++ project.

Environment: MSVC 2019, CMake 3.20 bundled with MSVC, c++ 20, WIndows 10

Here is a sample structure of my project:

/proj/common/CMakeLists.txt
/proj/common/Common.h
/proj/src/main.cpp
/proj/dll/CMakeLists.txt
/proj/dll/dll.cpp
/proj/CMakeLists.txt

Both main.cpp and dll.cpp use Common.h: #include <Common.h>.
/proj/common/CMakeLists.txt contents are like said in most examples:

add_library(common_headers INTERFACE)

target_include_directories(common_headers 
    INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> 
              $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

Now, when I’m referring common_headers target in /proj/CMakeLists.txt like this:

add_executable( main WIN32 src/main.cpp)
target_link_libraries(main common_headers dll)

everything compiling fine. No erros.
But, when I try to reference the targets a different way (pointet by a CMake docs btw):

add_executable( main WIN32 src/main.cpp)
target_link_libraries(main 
   INTERFACE common_headers 
   PRIVATE dll
)

I get a compiler error in main.cpp “Unknown header Common.h”
Could someone please explain finally a correct way of doing a header-only targets in CMake? Because literally half of an examples on this topic I found in google does not work in my case.

You specified the wrong keyword for the compilation of target main.
The INTERFACE keyword means that consumers of the main target will be allowed to use the common_headers target, but it is not available for the main target itself. To ensure the main target can use the common_headers target, the keyword PRIVATE or PUBLIC must be used (PUBLIC is a synthetic way to specify the target for both PRIVATE and INTERFACE).

In your case, I think you can use PRIVATE keyword for both targets:

add_executable( main WIN32 src/main.cpp)
target_link_libraries(main PRIVATE common_headers dll)
1 Like

Thank you!

The usage specifics of these keywords was not obvious for me.