DISCLAIMER: I am new to CMakeLists.txt, I have a working implementation and would like to improve and enhance it, problem described below:
If I want root/sub-directories/
as separate sub-projects that can be compiled using the individual CMakeLists.txts
in their folders I find myself literally copy pasting almost the entire root file CMakeLists.txt
per sub-directory.
I was wondering if there is a better way to have a main project and then sub-projects that get the shared dependencies from main project and can be compiled without cmake
-ing the root CMakeLists.txt
. My directory structure is;
CMakeLists.txt (root project)
| __ sub_dir-1
| __ | __ CMakeLists.txt (sub-project)
| __ sub_dir-2
| __ | __ CMakeLists.txt (sub-project)
| __ sub_dir-3
| __ | __ CMakeLists.txt (sub-project)
...
Essentially, I want to be able to:
cmake root/CMakeLists.txt
, which creates an entire project that includes the sub-projects (I already have this implemented using individual CMakeLists.txts inside sub-directories.cmake root/sub-dir/CMakeLists.txt
and only compile the sub-project, which essentially also finds the necessary dependencies and includes them from maybe .cmake
includes or root/CMakeLists.txt
. What is the best way to approach this structure;
sub-dir/CMakeLists.txt
too much with redundant code? Appreciate any suggestions! Thank you.
Run the cmake executable or the cmake-gui to configure the project and then build it with your chosen build tool. Run the install step by using the install option of the cmake command (introduced in 3.15, older versions of CMake must use make install ) from the command line, or build the INSTALL target from an IDE.
About CMake. CMake is an extensible, open-source system that manages the build process in an operating system and in a compiler-independent manner. Unlike many cross-platform systems, CMake is designed to be used in conjunction with the native build environment.
CMake, CTest, and CDash have proven to be invaluable tools for us to build multiplatform code, track changes, run tests, and improve code quality by performing code coverage and memory leak analysis.”
CMake is a meta build system that uses scripts called CMakeLists to generate build files for a specific environment (for example, makefiles on Unix machines). When you create a new CMake project in CLion, a CMakeLists. txt file is automatically generated under the project root.
There are a few strategies which may work, some of which could be combined.
STRATEGY 1:
If you are using the Unix Makefiles
generator with CMake, then simply invoking make
from the build output dir that corresponds to the subdirectory you want to build should largely accomplish what you describe. Targets from other directories won't get built unless they are needed by a target for the subdirectory you are building in (or a subdirectory below that). So while you do run CMake from the root directory, you still only build just the subdirectory(s) you want.
Pros: Easy, requires no changes to your CMakeLists.txt
files.
Cons: Only works with Unix Makefiles
generator, requires all parts of the source tree to be processed by CMake whether you want to build them or not.
STRATEGY 2:
As mentioned by @Emil in his comment to your question, you could simply just build the specific target(s) you want from the top level of your build output directory. This assumes you know the relevant targets you want to build though, or put another way, it requires you to have a good understanding of what targets are provided by which subdirectories.
Pros: Flexible, works with any CMake generator, requires no changes to your CMakeLists.txt
files.
Cons: Requires some knowledge of what each subdirectory provides, requires all parts of the source tree to be processed by CMake whether you want to build them or not.
STRATEGY 3:
In the top level CMakeLists.txt
file, you could make the add_subdirectory()
call for each subdirectory depend on an option variable. This would allow you to turn inclusion of each subdirectory on or off individually, giving you precise control over what gets built. You could build everything, just one subdirectory or a set of subdirectories (more flexible than your requirements, but potentially useful).
Conditionally including a subdirectory with an option variable would typically be done something like this:
option(BUILD_SUBDIR1 "Enable building subdir1" ON) option(BUILD_SUBDIR2 "Enable building subdir2" ON) if(BUILD_SUBDIR1) add_subdirectory(subdir1) endif() if(BUILD_SUBDIR2) add_subdirectory(subdir2) endif()
If some subdirectories depend on others, then the logic for whether to add a subdirectory or not would need to account for that (i.e. implement dependencies between options). It shouldn't be hard to do if required.
Pros: Flexibility to build precisely whatever set of subdirectories you want in one build, CMake only has to process those subdirectories you are interested in (saves time for huge project trees and allows you skip problematic parts of the project tree) and works for any CMake generator.
Cons: You need separate build directories if you want to build different subdirectories individually. You can't simply cd
to a different part of your build output directory structure and run a build from there, for example. You still have just one source tree, but you have multiple build output trees. In practice, this may not be an issue depending on what you ultimately want to be able to do (I regularly have multiple build dirs for a given source tree, but that's usually for Debug and Release builds rather than different sets of CMake options). Also requires an understanding of dependencies between subdirectories. Requires mild changes to top level CMakeLists.txt
file.
Hopefully one of the above options or some combination thereof gives you some ideas for how to ultimately achieve what you are aiming for. I had a quick look at the top level CMakeLists.txt
in the github project you linked to and it looks like it already makes use of options like in strategy 3, just not quite to turn on/off individual subdirectories.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With