2

I'm quite new to CMake, and me and my colleagues decided on using it in some project we're developing. In this work, everybody is responsible for some module of the project. The layout is as follows:

ROOT
  -> Module1
     ...
  -> Module2 (depends on Module 1)
     ...
  -> Module3 (depends on Module 2 and 1)

Each ModuleN has its own CMakeLists.txt file and must be able to be compiled, tested, and finished before they can be put together into the whole project. Now, I'm quite confused about what approach to use to make those dependencies work.

My research showed me some ways (like adding add_directory directives, etc.), but some of them complained that this way the projects can be compiled many times unnecessarily (like Module1 in this example); or requires a full path to be given.

The project won't be installed to the target machine, so I cannot use system library folders, includers, etc. either. Every developer has this repository in different folders, so I cannot give "exact" folders either. Can I use a syntax like "../Module1" for the add_directory command? Would this cause "unnecessary builds" as told?

Also, people usually recommend putting a CMakeLists.txt file in the root of the project as well, but I think this way we always have to build from the root directory - so modules cannot be built and tested separately.

What is the "noob way" to make this possible? As I said, I'm quite new to CMake, and honestly I don't even know the "keyword" to search for such a thing (searching "adding dependency" brings some results that I am simply drowned in :) )

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ahmet Ipkin
  • 882
  • 1
  • 10
  • 20
  • 1
    Is it really a C++ question? – YSC Mar 15 '16 at 13:21
  • 1
    Those things are common problems in CMake, I've had a similar question like [CMake: How to setup Source, Library and CMakeLists.txt dependencies?](http://stackoverflow.com/questions/31512485/cmake-how-to-setup-source-library-and-cmakelists-txt-dependencies). My recommendation can be found in [preferred cmake project structure](http://stackoverflow.com/questions/33534115/preferred-cmake-project-structure). Hope this helps. – Florian Mar 15 '16 at 13:27
  • Project is a C++ project, does it count? So Linkers, Compilers etc should be configured accordingly. Sorry if it doesn't :) – Ahmet Ipkin Mar 15 '16 at 13:29

2 Answers2

2

The CMakeLists.txt in Module1 should create a library target [add_library(Module1 ...sources...)] (e.g. called Module1).

The target in Module2 can then link this library [target_link_library(mytarget Module1)].

Module 3 can then link the target in Module2.

You can also imbue the targets Module1 and Module2 with public and private include directories, so that targets that use them can inherit the include search paths.

Take a deep breath and read the documentation (twice!)

Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • Do I have to put a CmakeList.txt at the root of the project this way and call Cmake from there? My concern is, for instance, whether the maker of the module 2; working on his/her module, calling Cmake from her module; can still resolve the dependency for the Module1. Or should we always use the "top level" Cmake for this kind of dependencies? – Ahmet Ipkin Mar 15 '16 at 13:32
  • this is a big subject. too big for an answer here. but yes, one way to do it is to have a master cmakelists at the root which has add_subdirectory() for each subordinate project. The targets will be aware of the ones that have been mentioned previously. Also, don't run cmake from the source root - run it from a binary directory outside the source tree - and provide the path to the source tree the first time you run cmake. – Richard Hodges Mar 15 '16 at 13:41
  • My concern is, if Module2 user calls Cmake from, say Module2/build directory (directly); can "target_link_library" still resolve that "Module1"? I don't think it can if I didn't somehow say CMake how to find that Module1. Is there an easy way of making this, other that "root cmakelists.txt"? Also, I might want to compile the whole project (from the root cmakeList.txt, I mean), so, say, Module1 shouldn't be compiled 3 times, just once. Whatever configuration we make must accomplish this either.. That part confuses me... – Ahmet Ipkin Mar 15 '16 at 13:46
  • 1. don't allow developers to check in code unless it compiles and passes tests! 2. there are a number of ways to organise cmake. You can treat each module as self-contained or as part of a larger build. sometimes this requires a bit of scripting in the cmake files. 3. you can also import ready-built cmake projects. have a look at the export and import keywords. Like I said, take a deep breath. – Richard Hodges Mar 15 '16 at 13:56
1

Putting a CMakeLists.txt file at the root does the job. This doesn't mean you will always have to compile everything each time. When you will run the CMake command (or CMake GUI), you will generate a set of makefiles, an Xcode project, Visual C++ solution, etc. for the whole project. But you will be free to compile only what you want. The way you can achieve this will depend on the generation you will choose (IDE project, makefiles, Ninja files, etc.).

The main thing to understand is CMake generation and compilation are two separated steps.

  • CMake generation: from CMakeLists.txt files, generate a project or a set of makefiles
  • Compilation: from the "things" generated by CMake and your source code, create the libraries, software, etc.
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Antwane
  • 20,760
  • 7
  • 51
  • 84
  • So this way, CMakeLists.txt from the project root should be used for CMake generation of the submodules, right? Is there an 'elegant' and 'easy' solution for making this per module? So that Module2 worker calls CMake from her folder, but it still adds the dependencies of Module1 successfully: and Module3 does the same thing and adds the Module2 and Module1 dependency .. so on and so forth. – Ahmet Ipkin Mar 15 '16 at 13:35