6

I have a c++ project with several subdirectories, e.g.

src/
  CMakeLists.txt
  main.cpp
  module1/
     CMakeLists.txt
     code.cpp
     code.h
  module2/
     CMakeLists.txt
     code2.cpp

It seems that the two ways to deal with this in cmake is to either use add_subdirectory(module1) or include(module1) in my src/CMakeLists.txt. Somewhere I read, that the include use is regarded legacy/deprecated. My src/module1/CMakeLists.txt looks like this:

include_directories(${CMAKE_CURRENT_LIST_DIR})

set( SRCS
    ${SRCS}
    ${CMAKE_CURRENT_LIST_DIR}/code.cpp
   )

set( QT_FILE_HEADERS 
    ${QT_FILE_HEADERS} code.h
   )

If I try to use the add_subdirectory method and want to usecode.h in main.cpp I have to write #include "module1/code.h". If I do the include method of adding module1, I can simply write #include "code.h". I would prefer not to specify the relative path of the include files when I use them somewhere else, is there a way to achieve this using the add_subdirectory method? I thought the include_directories line should have taken care of that.

numberCruncher
  • 595
  • 1
  • 6
  • 25
  • 2
    CMake's `include` is definitely not deprecated or legacy – AndyG Apr 23 '18 at 14:54
  • 1
    Often it is considered good practice to place header files into subdirectories to avoid name clashes and have a better structured `/usr/include` after an installation. It also removes the requirement to specify `-Imodule1` for users of your code. – mattmilten Apr 23 '18 at 14:56
  • If I remember it correctly, it was meant that using include to add subdirectories which contain their own CMakeList files – numberCruncher Apr 23 '18 at 14:59
  • I don't see why this is marked as duplicate. The other post has nothing to do with the `include` keyword. In short, `add_subdirectory` introduces a new scope, whereas `include` does not. You'll find some more explanation in this post: crascit.com/2016/01/31/enhanced-source-file-handling-with-target_sources. I think in general it's better to use `add_subdirectory`, unless you need to use `include` for some reason. This can happen sometimes when defining a new target or enabling a new language in a subdirectory, for example. – Raul Laasner Apr 23 '18 at 20:18
  • @numberCruncher Does your code compile at all with `add_subdirectory`? In your `set(SRC...` statement there is no `PARENT_SCOPE` so it seems like that source file is not actually included. – Raul Laasner Apr 23 '18 at 20:20

1 Answers1

8

This is not how you should make modules -- sure you can do it this way, it works, but it is not very useful. Given your layout, simply reference module1/code.cpp in the main CMakeLists.txt file.

However, if you want to use modules, make each one a separate static library. This will really simplify things!

In src/CMakeLists.txt write:

add_subdirectory(module1)

add_executable(myprogram main.cpp)
target_link_libraries(myprogram module1)

In src/module1/CMakeLists.txt write:

add_library(module1 STATIC code.cpp)
target_include_directories(module1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

This way, you are only passing one single thing back from the module1 CMake script: the module1 target. Your main doesn't need to know anything about what happens inside there. If the code in module1 requires specific external libraries, link them there, the main CMake script won't need to know about it. Simply by linking to module1, all the magic will happen behind the scenes, your program will be compiled with the right include directories and linked to the right libraries.

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120