This question is about the project
command and, by extension, what the concept of a project
means in cmake. I genuinely don't understand what a project
is, and how it differs from a target
(which I do understand, I think).
I had a look at the cmake documentation for the project
command, and it says that the project
command does this:
Set a name, version, and enable languages for the entire project.
Nowhere on the page does it seem to explain what a project actually is (it goes through some of the things the command does, but doesn't say whether that list is exclusive or not). The cmake.org examples take us through a basic build setup, and while it uses the project
keyword it also doesn't explain what it does or means, at least not as far as I can tell.
What is a project? And what does the project
command do?
A project logically groups a number of targets (that is, libraries, executables and custom build steps) into a self-contained collection that can be built on its own.
In practice that means, if you have a project
command in a CMakeLists.txt
, you should be able to run CMake from that file and the generator should produce something that is buildable. In most codebases, you will only have a single project per build.
Note however that you may nest multiple projects. A top-level project may include a subdirectory which is in turn another self-contained project. In this case, the project
command introduces additional scoping for certain values. For example, the PROJECT_BINARY_DIR
variable will always point to the root binary directory of the current project. Compare this with CMAKE_BINARY_DIR
, which always points to the binary directory of the top-level project. Also note that certain generators may generate additional files for projects. For example, the Visual Studio generators will create a .sln
solution file for each subproject.
Use sub-projects if your codebase is very complex and you need users to be able to build certain components in isolation. This gives you a very powerful mechanism for structuring the build system. Due to the increased coding and maintenance overhead required to make the several sub-projects truly self-contained, I would advise to only go down that road if you have a real use case for it. Splitting the codebase into different targets should always be the preferred mechanism for structuring the build, while sub-projects should be reserved for those rare cases where you really need to make a subset of targets self-contained.