1

I'm not sure about the best approach for larger cmake projects with submodules and an executable to use those modules.

Solution 1:

foo/                # project root directory
- CMakeLists.txt
- build/
- executable/
-- CMakeLists.txt   # call to add_executable
-- include/
-- src/
-- test/
- modules/
-- core/
--- CMakeLists.txt  # call to add_library
--- include/
---- core/          # interface of core module
--- src/
--- test/
-- utils/
--- CMakeLists.txt  # call to add_library
--- include/
---- utils          # interface of utils module
--- src/
--- test/

Creating different targets for each module allows for easy reuse of modules in other projects.

But now it is hard/uggly to associate a module with a project an allowing includes like #include "foo/core/..." or even a whole project interface like #include "foo/foo.hpp"

Solution 2:

foo/                # project root directory
- CMakeLists.txt
- build/
- executable/
-- CMakeLists.txt   # call to add_executable
-- include/
-- src/
-- test/
- modules/
-- CMakeLists.txt   # call to add_library
-- include/         # interface of the whole module
--- core/           # interface of core module
--- utils/          # interface of utils module
-- src/
--- core/
--- utils/
-- test/

With this approach, the problems with the module interface are solved but the reuse of certain modules becomes picky copy-paste work.

Which structure do you prefer?

Do you use a completely different structure to manager larger projects?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Symlink
  • 383
  • 2
  • 12
  • An idea : you can do dll (or equivalent on linux) and install them. After, you reuse them with a find package. – Kafka Feb 12 '21 at 09:28
  • `But now it is hard/uggly to associate a module with a project an allowing includes like` why should that be a problem? In the module, you define the include paths relevant for that module, and adding the module in the executable will also add the corresponding include paths. I don't see at which part this is _"hard/uggly"_. How do you currently do that and why do you think it is _"hard/uggly"_? – t.niese Feb 12 '21 at 09:36
  • "But now it is hard/uggly to associate a module with a project an allowing includes like `#include "foo/core/..."` or even a whole project interface like `#include "foo/foo.hpp"`" - I don't quite understand that problem. Assuming `core` library (created in `foo/modules/core/CMakeLists.txt`) has its `include/` directory as its PUBLIC interface, and the executable links with the `core` library target, then this include directory becomes **automatically** accessible for executable, so `#include "foo/core/..."` should work. – Tsyvarev Feb 12 '21 at 09:36
  • Approach with large hierarchal cmake project and submodules makes it impossible to reuse those modules in other projects. – user7860670 Feb 12 '21 at 09:52
  • @user7860670 Why? Each submodule could create an object or static library, exporting include paths using the public interface. Those sub modules could e.g. be each in a distinct git repository brought together using git submodules. So I don't see why this should be true. – t.niese Feb 12 '21 at 11:22
  • @t.niese Then each new project using these modules needs to pull and build the same submodules creating excessive duplication. – user7860670 Feb 12 '21 at 11:39
  • @user7860670 You can make a CMake project both installable and usable as a submodule. There is no problem with that (did that many times). And it is not always wanted that submodules are installed as libraries in the system or you might want/need to use different revisions. (Sure you could do that with version numbers, but that could be even less use able than the approach of submodules). – t.niese Feb 12 '21 at 11:49
  • @t.niese Making project installable requires considerable efforts. From my experience people relying on defaults and doing something like YOLO sudo make install end up polluting the system. Working with "installed" modules is problematic because in order to make changes visible to projects using them installation step must be performed after each change. Header file duplication is troublesome. Source code duplication if project is used as installable and as a submodule at the same time is troublesome. Actually any kind of duplication is a big no-no when working with sufficiently large codebase – user7860670 Feb 12 '21 at 12:31
  • @Tsyvarev Lets say i have a class `bar` in the `foo/core` module. The problem im facing now is, that the include path for `bar` is relative to the module path which does not contain the project name. `target_include_directory(core PUBLIC include)` now points to `foo/modules/core/include` and in an executable that links with `core` i have to call `#include "core/bar.hpp"` instead of the desired `foo/core/bar.hpp` to show that `core`-module is part of the `foo`-project – Symlink Feb 12 '21 at 13:50
  • @Symlink You normally setup your directory structure in the same way you do with your namespace. If you want to use the module in various projects, then dedicate them to an own namespace: `your_root_namespece::your_project_name::type_name`, `your_root_namespace::your_module_name::type_name`, and don't include the module in the namespaces of the project, if you want to use it in different projects. And structure the include directories accordingly. – t.niese Feb 12 '21 at 14:06
  • @user7860670 `Making project installable requires considerable efforts.` sure, but if you want to reuse the modules in a different project without duplication what other option do you have? `Working with "installed" modules is problematic because in order to make changes visible to projects using them installation step must be performed after each change.` not more than with any other library you use and update. – t.niese Feb 12 '21 at 14:23
  • @user7860670 `Source code duplication if project is used as installable and as a submodule at the same time is troublesome.` You can set your modules to either use it as a submodule without the need of installing it or to actually install it. – t.niese Feb 12 '21 at 14:23
  • Please, do NOT *describe* your code in the **comments**. Instead, [edit] the **question post** and add the code into it. Without the code your question is very vague. – Tsyvarev Feb 12 '21 at 15:22
  • @t.niese I prefer to use flat, workspace-based project organization: no submodules, nothing is getting installed. Project resources that can be consumed by other projects out of box (i.g. headers) are consumed directly from project source. Project build artifacts are consumed directly from build location. – user7860670 Feb 12 '21 at 15:50

0 Answers0