1

I have a project with the following file structure (transitioning to CMake), with source and header files in the same directories:

root
 +- module1
   +- a.hpp
   +- a.cpp
   +- b.hpp
   +- b.cpp
   + module1a
     +- a.hpp
     +- b.cpp
 +- module2
   +- a.hpp
   +- a.cpp

Header files are included in each other as #include<projectname/module1/a.hpp>. How can I instruct CMake to install all headers into the build directory as this structure, prior to building the .cpp files? I was briefly looking at install(DIRECTORY "${CMAKE_SOURCE_DIR}/module1" DESTINATION "projectname/module1" FILES_MATCHING PATTERN "*.hpp") (from CMake install header files and maintain directory heirarchy) but it does install those headers into the build directory (nothing happens).

The headers are needed only at compile-time, not at runtime.

Can I get some hint how to achieve this?

EDIT: The directory layout is different in the source three than how #include directives include it. For example, consider #include<projectname/module1a/a.hpp>. include_directories will not work for this header. The same for #include<projectname/module1/a.hpp as root!=projectname. Headers must be copied/symlinked from the old layout to the new layout first.

eudoxos
  • 18,545
  • 10
  • 61
  • 110
  • You have to use `include_directories(/path/to/the/headers)` to provide the headers for build. – Th. Thielemann Nov 18 '19 at 12:28
  • The first component is unfortunately not the same, otherwise I would just use `root/..` as include path (`root` vs. `projectname`). – eudoxos Nov 18 '19 at 12:35
  • Don't get it. Possible I do not understand your project structure. But you can add as much include_directories as you want. – Th. Thielemann Nov 18 '19 at 12:45
  • Headers are included as `#include`. So I need to create the `projectname` directory somewhere and then copy/symlink all headers into it (or symlink module subdirectories). There is no directory I can put to `include_directories` which will work. – eudoxos Nov 18 '19 at 13:08
  • "* it does not seem to do what I need*"... Why is this not what you need? What are you trying to achieve, if not this? Why not just use `include_directories()` for including headers into your project? Why does `include_directories()` not work? – Kevin Nov 18 '19 at 13:11
  • I added an explanation, hopefully it makes more sense now. `include_directories` is not the answer, sorry. – eudoxos Nov 18 '19 at 13:16
  • I'm not sure if there's a solution out of the box. The ideal solution is to change your project's directory structure to match what your `#include` lines look like, so can you add a `projectname` folder at the top that has symlinks to each module? – Stephen Newell Nov 18 '19 at 13:26
  • @StephenNewell I agree, that would be ideal but is not possible ATM. – eudoxos Nov 18 '19 at 13:28
  • "Install" by definition comes after the "build", so the title is confusing. As for copying the files into build directory, see that question: https://stackoverflow.com/questions/24311402/copy-all-files-with-given-extension-to-output-directory-using-cmake – Tsyvarev Nov 18 '19 at 22:59
  • @Tsyvarev I adjusted the title, agreed. – eudoxos Nov 27 '19 at 07:41

1 Answers1

0

This is the solution (perhaps not perfect, but working) which will create symlinks at configure-time:

macro(create_symlink target linkname)
    execute_process(
        COMMAND ln -sf "${target}" "${linkname}" 
        RESULT_VARIABLE HEADER_LINK_STATUS
        ERROR_VARIABLE HEADER_LINK_ERROR
    )
    if(NOT "${HEADER_LINK_STATUS}" EQUAL 0)
        message(FATAL_ERROR "Symlinking headers failed:\n${HEADER_LINK_ERROR}")
    endif()
endmacro()

MESSAGE(STATUS "Symlinking headers …")
FILE(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/projectname")
create_symlink("${CMAKE_SOURCE_DIR}/module1" "${CMAKE_BINARY_DIR}/projectname/module1")
create_symlink("${CMAKE_SOURCE_DIR}/module1/module1a" "${CMAKE_BINARY_DIR}/projectname/module1a")
create_symlink("${CMAKE_SOURCE_DIR}/module2" "${CMAKE_BINARY_DIR}/projectname/module2")
eudoxos
  • 18,545
  • 10
  • 61
  • 110