Interface Library Directory Structure vs #include Path

Hey, there. I suspect there’s a simple answer to my question but that I’m using the wrong search terms to find it, so please bear with me if this has been asked and answered before.

I’m trying to write a CPP library to use in an application (actually several applications; trying to be DRY) that I’m also writing. I want the name of the library to be obvious in #include statements (e.g. #include <my_lib/some_file.hpp>), so I’ve previously used the following directory structure:

my_lib/
├── CMakeLists.txt
├── include
│   ├── my_lib
│   │   ├── something.hpp
│   │   └── ...
└── src
    └── my_lib
        ├── something.cpp
        └── ...

with the following in my CMakeLists.txt:

...
add_library(my_lib INTERFACE)
target_include_directories(my_lib INTERFACE
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/>
)
target_sources(my_lib
  INTERFACE
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/my_lib/something.cpp>
    ...
)

install(TARGETS my_lib EXPORT my_lib)
install(EXPORT my_lib DESTINATION lib/my_lib)

That works pretty well for me. However, in an effort to move toward more uniformity in project structure at my organization, I’m trying to write this new library with the following directory structure that other folks are using:

my_lib/
├── CMakeLists.txt
└── src
    └── main
        ├── cpp
        │   ├── something.cpp
        │   └── ...
        └── include
            ├── something.hpp
            └── ...

I currently have a very similar CMakeLists.txt for this new project:

...
add_library(my_lib INTERFACE)
target_include_directories(my_lib INTERFACE
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/include/>
)
target_sources(my_lib
  INTERFACE
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/something.cpp>
    ...
)

install(TARGETS my_lib EXPORT my_lib)
install(EXPORT my_lib DESTINATION lib/my_lib)

However, now my #include statements don’t have a path prefix. So I can only do #include <something.hpp>, not #include <my_lib/something.hpp> like I want.

I’ve looked over the docs for install(), and I feel like there’s something there I can use, but I’m not familiar enough with CMake to know what it is.

For completeness, here’s what my CMakeLists.txt looks like in a project where I’m trying to use this library:

...
FetchContent_Declare(
  my_lib
  GIT_REPOSITORY http://uri/my_lib.git
  GIT_TAG        v0.1.0
)

FetchContent_GetProperties(my_lib)
if(NOT my_lib_POPULATED)
  FetchContent_Populate(my_lib)
  add_subdirectory(${my_lib_SOURCE_DIR} ${my_lib_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
...
target_link_libraries(my_app my_lib other_lib)
...

An ugly workaround could be to add symlink called include and points to itself.
You’d make it like this: ln -s . include from the directory containing the headers.

But I think that’s arguably a worse solution than your old setup, which is also much easier to use cross-platform (if you care about that sort of thing).

I’d just keep it as-is.