Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

target_include_directories resulting include path

Tags:

c++

cmake

Say I have a project that looks like:

 Project (dir)
   -- CMakeLists.txt
   -- MyLib (dir)
     |-- CMakeLists.txt
     |-- MyLib.h
     |-- MyLib.cpp

   -- MyOtherLib (dir)
     |-- CMakeLists.txt
     |-- MyLib.h (note that this is exactly the same name as in MyLib above)
     |-- MyLib.cpp

If in MyLib/CMakeLists.txt I do this:

target_include_directories(MyLib PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>

Then anything that target_link_libraries to MyLib will have the "correct" include path to do #include "MyLib.h". However, if another executable MyExecutable depends on both libraries using target_link_libraries(MyExecutable MyLib MyOtherLib) you'd like to be able to instead specify which one is intended with #include "MyLib/MyLib.h" or #include "MyOtherLib/MyLib.h". The only way I see to do that is to instead use:

target_include_directories(MyLib PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>

which kind of defeats one of the nice things about target_include_directories in that it really strongly enforces avoiding accidental header dependencies, because you literally can't include things that you aren't explicitly claiming to use.

Is there another way to get this #include "MyLib/MyLib.h" behavior?

like image 397
David Doria Avatar asked Sep 13 '25 03:09

David Doria


1 Answers

You should reconsider your directory tree as follows:

Project (dir)
   -- CMakeLists.txt
   -- MyLib (dir)
     |-- CMakeLists.txt
     |-- src (dir)
         MyLib.cpp
     |-- include/MyLib (two dirs)
         MyLib.h

   -- MyOtherLib (dir)
     |-- CMakeLists.txt
     |-- src (dir)
         MyLib.cpp
     |-- include/MyOtherLib (two dirs)
         MyLib.h

In this way you avoid including the ../, i.e. Project, folder and everything therein, which is not a clean approach and may lead to other problem should you add other files/folders in the future. Then, you can write in MyLib/CMakeLists.txt

target_include_directories(MyLib PUBLIC 
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/include)

and in MyOtherLib/CMakeLists.txt

target_include_directories(MyOtherLib PUBLIC 
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/include)

As a result, you will be able to write #include "MyLib/MyLib.h" and #include "MyOtherLib/MyLib.h" in any program linking against the libraries in the build-tree.

If you also want to differentiate the include directories between the build-tree and the install-tree have a look at target_include_directories documentation and the useful cmake-generator-expressions.

like image 80
Claudio Avatar answered Sep 14 '25 18:09

Claudio