How to install an interface library with generated source in build folder

We have a header-only library apiDefines (INTERFACE) which has a generated API.h (declspec imports/exports) as source which is used as a helper target to link to in other library targets:

  set(generatedFile ${CMAKE_CURRENT_BINARY_DIR}/API.h) 
  set_property(SOURCE ${generatedFile} PROPERTY GENERATED ON)

  set(linkTarget "apiDefines")
  add_library(${linkTarget} INTERFACE)
  target_sources(${linkTarget} PUBLIC ${generatedFile})
  set_property(TARGET ${linkTarget} PROPERTY PUBLIC_HEADER)

  target_compile_definitions(${linkTarget}
                             INTERFACE "API_EXPORTS")
  target_include_directories(${linkTarget}
                             INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
                                                  $<INSTALL_INTERFACE:include>)

When we want to install this cmake complains about:

Target "apiDefines" INTERFACE_SOURCES property contains
  path:

    "/workspaces/cmake-general/tests/project/build/linux-clang-libstdc++-debug/src/plugins/internal/API.h" 
 which is prefixed in the build directory.

If we use target_sources(${linkTarget} PRIVATE ${generatedFile}) that would certainly solve the problem, but this is somehow wrong as API.h is a public source for apiDefines.

I am not quite sure how to achieve that I can install a header-only library which uses generated sources in the binary tree?

To do this, you should use CMake 3.23’s FILE_SET feature. If you need older versions, just make it PRIVATE and make a manual install(FILES) call for the headers.

1 Like

Jeah, I exactly did this, and it works flawlessly. Awesome.

target_sources(
    ${linkTarget}
    PUBLIC FILE_SET
           "publicHeadersBin"
           TYPE
           HEADERS
           FILES
           ${generatedFile}
           BASE_DIRS
           ${CMAKE_CURRENT_BINARY_DIR})

@ben.boeckel : The strange thing is when I use FILE_SET to add the source in the build directory the add_custom_command producing the ${generatedFile} does not run anymore? Is that a bug?

 add_custom_command(
    OUTPUT ${generatedFile}
    COMMAND ${cmd}
    MAIN_DEPENDENCY ${configureTemplate}
    COMMENT "Generating API header at '${generatedFile}'."
    VERBATIM)

Yes. I see you filed this issue.