In cmake, what is a "project"?
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.
It should go without saying that using the word project to define project is less than helpful.
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?
Solution 1:
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.