0

Note: I'm currently tinkering with more modern CMake styles, not trying to accomodate an existing project. I'd consider alternative approaches to what I am doing as perfectly acceptable as long as they are scalable (i.e., downstream target shouldn't need to know about the internals of the upstream target).

Let's say I have two targets in the same CMake build, down and up, where down depends on up:

target_link_libraries(down PUBLIC up)

Let's say the headers of up are inside up/src/:

+---up
    +---CMakeLists.txt
    +---src
        +---header.hpp
        +---<other headers/sources>

Now let's say that inside down I want to include the headers of up like so:

// down/foo.cpp

#include "up/header.hpp"

If down is an external dependency (i.e. in a separate CMake build), that's easy: I just have to install all the headers of up in some kind of include/up/ directory and then use that:

target_include_directories(up
  INTERFACE
    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include/up>")

But what if down is part of the same CMake build as up? I want to uniformize the code; I don't want down's sources to have to do any of...

#include "up/src/header.hpp"
#include "src/header.hpp"
#include "header.hpp"

The headers of up wouldn't be installed inside include/up until after all the targets, including down, would be built, since down is inside the same CMake build.

Is that sort of thing even possible without using horrible manual file copies? Should I just put all up's sources inside a up/src/up/ directory then?

My motivation is: up might be depended on by libraries both inside and outside the CMake build, so I want to uniformize the code accross internal and external targets.

adentinger
  • 1,367
  • 1
  • 14
  • 30
  • _I'd consider alternative approaches to what I am doing_ Have you tried bazel? – Taekahn Jan 22 '23 at 20:47
  • @Taekahn Nope, never have. I'd really want a CMake solution without having to rely on a specific generator (one of CMake's goals is to be mostly generator-independant), but is there any particular reason why you're suggesting this? I suppose that would allow a solution? – adentinger Jan 22 '23 at 20:56
  • Related: [Include headers with same name but from different libraries using CMake](/q/74879035), and [this](/a/74593941). – starball Jan 22 '23 at 22:03
  • 1
    What about using a `${PROJECT_SOURCE_DIR}/include/${PROJECT_NAME}/{up,down}/
    ` structure? Read `{up,down}` as two folders at that level, and `
    ` as the header files for each of those targets. After all, that is quite a common CMake project structure. Once you add the `${PROJECT_SOURCE_DIR}/include/${PROJECT_NAME}` folder to both the `up` and `down` target include directories, you can `#include "up/blah.h"`.
    – rturrado Jan 22 '23 at 22:18
  • 1
    @AnthonyD973 The reason i was suggesting it because it should be easy to do what you're asking in it. There is both a `include_path` _and_ a `strip_include_path` to "relocate" things. – Taekahn Jan 22 '23 at 23:40
  • @rturrado Hmmm... Yes, that seems to be a good approach. That `include/` directory would also be the location of the `PUBLIC` headers of the various libraries of the project, this way the `PRIVATE` headers could directly go into the source directory along with the `.cpp` files. – adentinger Jan 23 '23 at 03:41

1 Answers1

3

If you want #include "up/header.hpp" to work, then the file header.hpp should be physically located in the directory up. This is how all major compilers work, so CMake simply cannot "emulate" location of a header file.

However, it is quite easy to copy headers into desired directory. E.g. by using file(COPY) command. List of files to copy can be obtained using file(GLOB), like in that answer:

file(GLOB UP_HEADERS /path/to/up/src/*.h)
file(COPY ${UP_HEADERS} DESTINATION /path/to/some/dir/include/up)
Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • 1
    Hmmm. Or maybe the OP can work some magic with symlinks. – Paul Sanders Jan 22 '23 at 23:24
  • No support for compilers to do that sort of thing. Yeah, I sort of guessed that would be the answer, but you never know until you actually ask! Thanks, and thanks for the copy suggestion too. – adentinger Jan 23 '23 at 03:32