# project(..), cmake\_minimum\_required(..)

**URL:** https://discourse.cmake.org/t/project-cmake-minimum-required/953
**Category:** Usage
**Created:** [April 8, 2020, 10:30am UTC](https://discourse.cmake.org/t/project-cmake-minimum-required/953 "2020-04-08T10:30:12Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![Guru\_Gajah](https://discourse.cmake.org/user_avatar/discourse.cmake.org/guru_gajah/32/486_2.png) [@Guru\_Gajah](https://discourse.cmake.org/u/Guru_Gajah)
#### Post date: [April 8, 2020, 10:30am UTC](https://discourse.cmake.org/t/project-cmake-minimum-required/953/1 "2020-04-08T10:30:12Z")

</div>

Hello,

I’m concerned about cmake version-race and project maintainability especially in deeply embedded project.

I have inherited certain habits/practices since cmake 2.6 which I’m reluctant to change. One of the reasons is because I don’t want people stuck with an older cmake-version disabled by their systems ability (or own willingness) to upgrade if not necessary. But another is personal strong unwillingness to mess with stuff that works. Once done, stuff should be left alone (as per old UN\*X philosophy). But things aren’t always as easy as they seem and one can’t always be as anal as one would like…

So in short my question is about the “proper” (or best practice) use of project(…) and cmake\_minimum\_required(…). In addition, also the habit of having complete CMakeLists.txt in each source sub-directory. (I.e. I have a strong preference towards molecularity, yet some people fear the perceived extra maintenance).

**Modularity:**

To me modularity even beyond the obvious scope for coarse level big project, makes sense also for minuscule levels. It makes re-use even for wrap-around debugging much easier, especially in cross-build environments where setting up debugging can be a real pain, the ability to wrap-and-debug even a small parts can makes life much easier and save tons of time. What do you think of this practice? I’ll personally take the small extra lines penalty (mostly adding include\_directories) as these lines don’t usually change anyway and can furthermore be abstracted using common\_functions.cmake files. There is ONE irritating drawback however. Cmake isn’t very good at composing higher level libraries out of libraries from sub-project (think static, cross built ones. These are usually preferred to be ONE library, not a plethora). The ability to have system-specific ldtool re-composition easily

would be a deeply appreciated ability to add to Cmake.

**Project(), version and VERSION:**

project(…) first argument is “name”. This used to be sensitive to the same level directory-name and I’ve always used the exact same name, spelling and capitals and all. I don’t remember if issue was when build out-of-source, when cmake projects included each other or combination of both, but I’m 100% certain there was one. Confirming or correcting is appreciated as having several cmake projects called “src” when using cmake recursively seems… stupid.

project(…) can also take take the option VERSION which has caused much confusion, especially with recursive project files. I therefore avoid it altogether, as setting explicit _VERSION_\* is just as easy and will make the CMakeLists.txt both future proof and cmake\_minimum\_required downgradeable if needed.

As mentioned, I usually make an effort to keep cmake\_minimum\_required as low as possible to not disable users, unless there IS an actual feature that is essential. Hence, my projects can include sub-modules where cmake\_minimum\_required is different. Is there any drawbacks with that?

I’ve assumed that cmake\_minimum\_required not only **requires** a certain version, but if set lower than the actual cmake version being in use, it will also set that version specific policies. Is that correct? I.e. the VERSION behavior and project name issue above will differ not only on which actual version of cmake itself, but also with how cmake\_minimum\_required is set. I have also assumed that when used recursively, the right policies will follow accordingly to each CMakeList.txt setting. Is this correct? I.e. policies change with CMakeLists.txt and aren’t defined on top-level.

Comments, discussion or references to best-practices deeply appreciated  
Regards -Gajah

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 8, 2020, 12:23pm UTC](https://discourse.cmake.org/t/project-cmake-minimum-required/953/2 "2020-04-08T12:23:12Z")

</div>

> [@Guru\_Gajah](#):
>
> I have inherited certain habits/practices since cmake 2.6 which I’m reluctant to change.

If you declare a minimum version of 2.6, that should still work. However, I think everything in the past ~10 years distributes at least 2.8.12 (RHEL 7 being the main holdout, though EPEL has 3.14 leaving Ubuntu 16.04 and Ubuntu 18.04 as the “oldest” ones in typical use today (AFAIK)).

> [@Guru\_Gajah](#):
>
> In addition, also the habit of having complete CMakeLists.txt in each source sub-directory.

This sounds quite unnecessary. There’s a lot of boilerplate that goes into top-level projects (at least to make “good” packages) I would be loathe to duplicate. Every dependency would need a `find_package()` alternative to all-together builds, so “good” packages would be really useful in this case. I recommend just picking a few places in the tree to support such things and I think you’d greatly reduce the amount of busy work you have to deal with.

> [@Guru\_Gajah](#):
>
> the ability to wrap-and-debug even a small parts can makes life much easier and save tons of time. What do you think of this practice?

I think you’d have to balance the `find_package()` load versus the benefit of building each library individually. Of course, if the libraries never depend on each other, that’s not such a problem. But then, I’d just build that directory/target set individually if I was debugging just that one (though I don’t tend to do cross-compilation things).

> [@Guru\_Gajah](#):
>
> There is ONE irritating drawback however. Cmake isn’t very good at composing higher level libraries out of libraries from sub-project (think static, cross built ones. These are usually preferred to be ONE library, not a plethora). The ability to have system-specific ldtool re-composition easily

I think you want `OBJECT` libraries with `STATIC` libraries at various levels making components available individually while also being able to combine everything into a single library at the end as well. I don’t know how well this works with symbol exports on Windows, but if you don’t care about it or shared builds, that’s likely a moot point.

> [@Guru\_Gajah](#):
>
> would be a deeply appreciated ability to add to Cmake.

Using `OBJECT` libraries in a manner like this would need CMake 3.12 to really get their full power (they were exempted from various CMake mechanisms before that).

> [@Guru\_Gajah](#):
>
> project(…) first argument is “name”. This used to be sensitive to the same level directory-name and I’ve always used the exact same name, spelling and capitals and all. I don’t remember if issue was when build out-of-source, when cmake projects included each other or combination of both, but I’m 100% certain there was one.

Pretty sure there hasn’t been. Seems like a convention to me. But maybe 2.6 was overly strict here. I recommend dropping 2.6 support if that’s the issue.

> [@Guru\_Gajah](#):
>
> Confirming or correcting is appreciated as having several cmake projects called “src” when using cmake recursively seems… stupid.

I recommend leaving `project()` out of any non-top-level directories. As above, I wouldn’t make every directory top-level.

> [@Guru\_Gajah](#):
>
> Hence, my projects can include sub-modules where cmake\_minimum\_required is different. Is there any drawbacks with that?

Policy scopes are…weird. Here, they’ll line up with directories nicely, but be careful of cross-project CMake `function` and `macro` calls since they get executed with the policy scope of their definition, not use.

> [@Guru\_Gajah](#):
>
> I’ve assumed that cmake\_minimum\_required not only **requires** a certain version, but if set lower than the actual cmake version being in use, it will also set that version specific policies. Is that correct?

Yes.

> [@Guru\_Gajah](#):
>
> I.e. the VERSION behavior and project name issue above will differ not only on which actual version of cmake itself, but also with how cmake\_minimum\_required is set.

It should only differ based on `cmake_minimum_required`.

> [@Guru\_Gajah](#):
>
> I have also assumed that when used recursively, the right policies will follow accordingly to each CMakeList.txt setting. Is this correct? I.e. policies change with CMakeLists.txt and aren’t defined on top-level.

`cmake_minimum_required` should Just Work properly, but any `cmake_policy` calls affect the current policy scope. You may need `cmake_policy({PUSH,POP})` around those regions.

---

<div class="post-metadata">

### Author: ![Guru\_Gajah](https://discourse.cmake.org/user_avatar/discourse.cmake.org/guru_gajah/32/486_2.png) [@Guru\_Gajah](https://discourse.cmake.org/u/Guru_Gajah)
#### Post date: [April 29, 2020, 3:40pm UTC](https://discourse.cmake.org/t/project-cmake-minimum-required/953/3 "2020-04-29T15:40:43Z")

</div>

Thanks Ben for your thoughtful advice and comments.

I agree with most but would just like to add some aspects:

I don’t practice having top-level C Make projects in every source directory, only in those where it makes sense.

The boiler-plate code is not a big penalty in deeply embedded cross-development, but agreed - for OS based targets that would indeed be a penalty - not so much for performance perhaps, as the cache will cover for test already made, but for complexity.

“Using `OBJECT` libraries…” that may be a real motive for updating cmake\_minimum\_required(…). Tried this with lesser version and couldn’t get it working without defining (non-portable) functions. Great advice!

Policy scopes comment and cmake\_policy({PUSH,POP}) also greatly appreciated.

Thanks //G
