Internal/external headers

I have a project C++ project with both private and public headers. I want to make the private headers available to other targets, plugins and executables I’m building in the project, but only the external headers available to end users. I’m not sure how to do this. I thought maybe I should make an “internal” library with both private and public headers, and a “public” library linked to the “internal” library with only public headers available. But I’m not sure how to do that?

You can use $<BUILD_LOCAL_INTERFACE> (new in CMake 3.26) to hide targets from EXPORT sets. So something like:

add_library(internal_headers INTERFACE)
# prep `internal_headers`

## All project-local users of `public_headers` will be able to use internal headers
add_library(public_headers INTERFACE)
target_link_libraries(public_headers INTERFACE "$<BUILD_LOCAL_INTERFACE:internal_headers>")

## Or use on specific targets (still possible if `public_headers` is not required)
target_link_libraries(mylib PRIVATE "$<BUILD_LOCAL_INTERFACE:internal_headers>")

$<BUILD_INTERFACE> will hide it from install(EXPORT), but still require the target for export(EXPORT) uses though, but it is new from CMake 3.0.

Hm I still don’t understand…Why do we need an interface target?

Say I have something like this:

add_library(MyLibrary SHARED ${my_sources})
target_include_directories(MyLibrary PRIVATE ${private_include_dirs})
target_include_directories(MyLibrary PUBLIC ${public_include_dirs})

add_library(InternalPlugin SHARED ${internal_plugin_sources})
target_link_libraries(InternalPlugin PRIVATE MyLibrary)

add_library(RegularPlugin SHARED ${regular_plugin_sources})
target_link_libraries(RegularPlugin PRIVATE MyLibrary)

Is there a way to make the headers in ${private_include_dirs} available to InternalPlugin but not RegularPlugin?

The genex has nothing to do with target types; it’s about the interface of the exported information of the target.

Move the private headers to an INTERFACE target that you link where needed. In order to avoid having to export it, you can use the $<BUILD_LOCAL_INTERFACE> or $<BUILD_INTERFACE> generator expressions.