cmake

Specifying private and public headers as file set in target_sources gives an error


How can I define private and public headers (as file sets) for target_sources ? The following will give me an error:

## Globbing even though it's discouraged because we're lazy
file(GLOB_RECURSE LIB_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
file(GLOB_RECURSE LIB_PRV_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h")
file(GLOB_RECURSE LIB_PUB_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h")

## Define headers and sources
target_sources(mm_cpp_lib
    PRIVATE
        ${LIB_SOURCES}
    PRIVATE
        FILE_SET HEADERS
        FILES
            ${LIB_PRV_HEADERS}
    PUBLIC
        FILE_SET HEADERS
        BASE_DIRS "include" # Will install headers in include/
        FILES
            ${LIB_PUB_HEADERS}
)

The error is:

CMake Error at CMakeLists.txt:26 (target_sources):
  target_sources Scope PUBLIC for file set "HEADERS" does not match original
  scope PRIVATE

However the docs states that:

INCLUDE_DIRECTORIES

If the TYPE is HEADERS, and the scope of the file set is PRIVATE or PUBLIC, all of the BASE_DIRS of the file set are wrapped in $<BUILD_INTERFACE> and appended to this property.

INTERFACE_INCLUDE_DIRECTORIES

If the TYPE is HEADERS, and the scope of the file set is INTERFACE or PUBLIC, all of the BASE_DIRS of the file set are wrapped in $<BUILD_INTERFACE> and appended to this property.

which left me with the impression that it should be possible to define two headers sets, one private and one public? Isn't this the case?


Solution

  • Single set has a single scope (PRIVATE/INTERFACE/PUBLIC). You are attempting to assign different scopes (PRIVATE and PUBLIC) for the (predefined) set named HEADERS, thus you got the error. Correct is to use different names for those sets:

    target_sources(mm_cpp_lib
        PRIVATE
            ${LIB_SOURCES}
        PRIVATE
            FILE_SET PRIV_HEADERS # Name of the set, must be unique for a target
            TYPE HEADERS # This set describes headers
            FILES
                ${LIB_PRV_HEADERS}
        PUBLIC
            FILE_SET PUB_HEADERS # Name of the set, must be unique for a target
            TYPE HEADERS # This set describes headers
            BASE_DIRS "include"
            FILES
                ${LIB_PUB_HEADERS}
    )