Determine appropriate version for cmake_minimum_required() - cmake

From a set of CMakeLists.txt files, how can I determine an appropriate version number for cmake_minimum_required()? Is there a better way than being familiar with the history of CMake features and using trial and error?

CMake has per-version documentation on its website. Using it, you may check that all features you use in your project are supported by a specific CMake version.
Features include command names, command options and their possible values, names of modules shipped with CMake.
Usually project does not need precise minimum CMake version. You may take reasonable version, which is accessible for users, and check whether this version supports all features you use.

Related

Support multiple cmake minimum versions for one project

I have a fairly popular open source project that has a minimum cmake version set that is fairly old (~Oct 2013).
cmake_minimum_required(VERSION 2.8.12)
This is great for supporting a wide variety of users, but it makes adding new things to our cmake builds challenging, since we cannot use any of the new features in later cmake versions. This leads to complicated cmake files and more maintenance burden to emulate future improvements made to cmake.
I would like to support two CMakeLists.txt files for the project that have different minimum versions, one legacy one at the 2.8.12 version, and another more modern one at a later 3.x version. Is there any canonical way to do this? It doesn't look like there is a way to support multiple CMakeFiles.txt at the root of the project.
The naive way is to just rename the legacy file CMakeFiles_Legacy.txt and have users that depend on the older cmakes manually switch out the CMakeFiles.txt on their own.
tl;dr: Just don't support old versions.
CMake is absurdly easy to upgrade. Literally every halfway-modern development platform natively packages at least CMake 3.16+, but Windows and macOS are both way ahead of the curve with constant updates to the included version.
Visual Studio receives periodic updates and 2022 includes CMake 3.21. The version on Chocolatey is always up to date.
On macOS the Homebrew version is always up to date.
On Debian derivatives, Kitware provides an official APT repo that is always up to date. There is also a Snap package that is always up to date.
On most other Linux distros, one can use the official binaries directly from Kitware without sudo access at all. They have x86_64 and aarch64 binaries. The binaries are statically linked and require only libc6 as a dependency. Glibc has been ABI-stable since 1997. It will work on your system. But even if it doesn't, building a recent CMake version isn't difficult anyway. Your users maintaining such archaic systems shouldn't be your liability.
(aside: I wrote an entire blog post on this... https://alexreinking.com/blog/how-to-use-cmake-without-the-agonizing-pain-part-1.html)

Is there an easy way to find what the minimum required version for CMake should be?

Is there a convenient way to find what the minimum compatible CMake version should be (besides testing it with every single version)? I'm looking for a tool that will parse my CMakeLists.txt, find all the features I'm using, look up the CMake version they were added, and spit out the maximum. A quick look though cmake --help didn't show an option to do this. Is there an external tool that will do this for me?
As of now, there is no such tool. This is because there are a number of problems with creating such a tool.
Most importantly is that CMake has never made any promises of forwards-compatibility. Listfiles authored with a newer version of CMake have never been guaranteed to work with older versions, regardless what cmake_minimum_required setting appears. This is due to several factors: new features added, improved logic in Find modules and compiler detection, and so on. Basically anything that doesn't break old code, but makes newer code more intelligent and robust, even without source changes.
Thus, a tool that only checked for new features (like generator expressions) would miss out on changes to other parts of the overall system.
This means any such tool would have to model CMake so closely that it would be easier to simply automate running an old CMake version and testing the build. If you feel you need to do this, you should automate it yourself.
Taking a step back, CMake is amazingly, ludicrously easy to upgrade and you can save yourself and others a lot of backwards compatibility headaches like this by simply sidestepping the issue. Use a recent version, declare it as a minimum and encourage your users to upgrade. On Linux, Kitware provides statically linked executables for x86 and arm that require nothing besides libc. I have never heard of these executables not working. I use them on old Raspberry Pis. I have yet to see any remotely valid reason to support versions of CMake older than a year or so.

cmake target_compile_features C++17

Adhering to the best practice for modern CMake I want to use this command instead of flags or set-based commands. However, I cant seem to make it work, since I cannot find associated commands for the newly introduced C++17 features. For C++14 I can do something along the following lines
target_compile_features(Foo
PUBLIC
cxx_strong_enums
PRIVATE
cxx_lambdas
)
I guess what I am asking is, what is the proper way to enable the latest standard of C++ in cmake without resorting back to legacy cmake
You're going in the right direction, you may just need to update your CMake version.
It started with CMake Version 3.8:
The Compile Features functionality is now aware of C++ 17. No specific features are yet enumerated besides the cxx_std_17 meta-feature.
For VS you need e.g. at least CMake Version 3.10.
References
How to enable /std:c++17 in VS2017 with CMake
ccmake using cmake version 3.10

How can I tell which minimum CMake version to require in CMakeLists.txt?

In CMakeLists.txt scripts, it is customary to have a:
cmake_minimum_required(VERSION x.y)
for the appropriate x.y version number. But - how can you tell what that minimum version is? I don't work with older versions; and as my distribution gets updated, so does CMake, so I may have even introduced commands requiring newer versions over time and I just don't know it.
I could theoretically require the versions I've tested this CMakeLists.txt with - but they're pretty new, and I don't want to restrict users of my code to just that.
There is no automatic way to do this. Here are some approaches I've used:
If you have used CMake for a while, you may roughly remember what features are newer and older. Select some of the features you use which you think are newer, and read the documentation to discover what version supports them.
If you can install just one or two old versions, it may be enough. CMake 2.8.x is very popular, so installing that and testing to see if it works (perhaps fixing it so it does) would be a nice service to some users.
Don't worry about it. Set the minimum to 2.8.10 and then accept patches or bug reports if users have specific issues. It's not likely that setting this number too low will cause any serious harm--typically it will just result in a different error message than "The CMake version is too old."
tl;dr: Try building with different CMake versions.
Download the CMake binary from https://cmake.org/files/ according to the claimed minimal required version. You can unpack them in some directory and use this CMake to ensure it is still the minimal required version. You can have as many versions as you wish in parallel. Don't forget to delete the build directory.
A problem you did not mention, but is also important: Check your code with newer version. New policies can lead to dozens of warnings, many projects try avoiding warnings in releases. So it might be good to have the latest version with the same procedure.

Library search path for libstdc++

I have compiled shared libraries dynamically linked against libstdc++.so using GLIBCXX_3.4.11. I want to send my code to someone whose stdc++ library is only of version 3.4.10. Rather than ask him to update his library version (this is a software customer, so I can't assume they'll be willing or able to change system files) I would like to ship the appropriate version of libstdc++.so, placed in a lib folder with the directory location of my code. How do I get my own code to use the appropriate (later) version? I find that /etc/ld.so.conf includes the directory /lib64, where an offending older version of libstdc++.so resides. Setting LD_LIBRARY_PATH does not override this. This seems to deviate from the advertised behavior. Any idea why this is happening? How do I complete my rather simple task?
Thanks.
I understand that this question is old, but I found it while trying to sort out my own linking trouble which was similar. You will have to build your program against a version of libstdc++ which is compatible with your colleague's version of the library. The easiest solution, of course, is to link against his version of the library so he doesn't need to make special tweaks on his side to link your library.
To do this, you will want to install a version of GCC which can build binary compatible libraries so you can actually link against his version of libstdc++. GLIBCXX_3.4.11 is from gcc-4.4 and later, so you will need gcc-4.3. Build your program using this and you should be in good shape.
You can consult the following page for a list of library ABI compatabilities:
http://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html
You could also build an rpm/deb which requires the version of libstdc++ you already have and if it's not available, refuse to install. This gives you a bit of an interface which gives him a promise that if his system is setup with the correct dependencies, he can use your library. In that sense, it's like a loose SLA for your library in what you do and don't support.
Hope that helps!