FILE(COPY header_set) or file_set

It would be useful to be able to copy a file_set to the build tree so other targets could depend on it.

In the case where header files are installed in a specific directory layout different from the source tree, this would enable other targets to properly #include based on this layout.

https://gitlab.kitware.com/cmake/cmake/-/issues/24341 was closed, so I’d like to discuss how to achieve this.

File_set works great to take header files from the project, remove base_dirs, and install in a certain destination in the install directory. I have other files in my project that include the public headers both based on their install path, and based on their source tree path (it’s a mix). Ultimately I’d like to create a target that can use target_include_directory on the file_set based on the install path. Currently, it doesn’t seem possible to do this without copying the file_set to the build tree, which seems also isn’t possible.

I can’t change the directory structure for this project; is the only way to run configure_file on each header to copy it to the build tree?

Yeah, pretty much. Note that doing this means that the copy gets reported for warnings, errors, or “go to declaration” when using an editor to look for things. Editing these usually ends up poorly because it doesn’t end up where it should: in the copy’s source path. I’m a pretty big believer in “make the build tree look like the install tree”, but copying headers and (installed) source files has just caused more headaches than it’s worth IME.

Thanks for the response. I ended up creating the desired public header directory structure in the build tree first, by using execute_process with the CMake command create_hardlink on each file. It was then extremely simple to create a file_set from those files.

Hardlinks could work (on platforms/filesystems that support it at least). Note that some editors do “write new file, rename to target file” when saving which will break hardlinks.

Instead of a copy you can do a reference to the original, with a configure file something like:
header_template.in

// This file is generated by CMake. Do not edit.
#include "@HEADER_FILE_LOCATION@"

Then given headerpath among your sources:

get_filename_component(headername ${headerpath} NAME)
get_filename_component(HEADER_FILE_LOCATION ${headerpath} ABSOLUTE)
configure_file(header_template.in ${CMAKE_BINARY_DIR}/yoursubdir/${headername})