I’ve recently been playing with CMake again, with much more success than last time. I still don’t love it, but:
- CMake is now very widely used in the C++ world, so supporting it can attract contributions.
- JetBrains’s CLion IDE supports CMake, and only CMake. I wanted to try its inspections and refactoring features, though these are rather disappointing so far.
- I wanted to try clang-tidy. But it needs a compile-commands.json file that they suggest you generate from CMake . However, I found the bear utility that does this for generic make builds, so I didn’t need CMake in the end for this.
I first tried it in the cmake branch of my little PrefixSuffix application because its build is rather simple.
I then finally allowed libsigc++ to have an additional CMake build system, at least in libsigc++-3.0, and Marcin Kolny got it done. This was possible now that libsigc++ doesn’t generate code from .m4 files. We wouldn’t have wanted to maintain two complicated build systems, but two simple build systems seems acceptable. I noticed many questions on StackExchange about actually using libsigc++ in CMake builds systems, so I added a hint about that to the documentation.
I also added a CMake build system to my Glom source code, to test something bigger, with many awkward dependencies such as Python, Boost, and PostgreSQL. It’s working well now, though I haven’t yet added all the tests to the build. This let me really try out CLion.
Minor Conclusions
I’m fairly pleased with the result. CMake doesn’t now feel massively more annoying than autotools, though it makes no attempt to do the dist and distcheck that I really need. I have now achieved a level of acceptance that means I wouldn’t mind much working on a project that uses CMake. I wouldn’t even need to hold my nose. The following complaints don’t seem to bother me quite so much any more:
I still find invoking CMake horribly obscure compared to ./configure. For instance
cmake -DCMAKE_INSTALL_PREFIX:PATH=/opt/something
seems ugly compared to
./configure --prefix=/opt/gnome
and I don’t see an equivalent for “./configure –help” to list all generic and project-specific build options. I also haven’t tried to replace mm-commons‘s wonderfulĂ‚Â –enable-warnings=fatal to easily turn on compiler warnings as errors, encouraging my code to be free of warnings and deprecated API while not troubling people who just want to build the project with the least difficulties.
I still cannot understand how it’s normal in the CMake world to create these awful little Find*() scripts for each library that you might depend on, instead of just using pkg-config, though CMake’s pkg-config support seems to work well now. And hoping that your own library’s Find*() script ends up in CMake itself does not seem scalable.
It’s also a little odd that I cannot specify the link directories (-L flags) per target. link_directories() seems to apply to all targets.
CMake’s syntax still seems like a toy language. Its quoting (none/implicit/unknown) and separating (spaces, not commas) and use of whitespace (occasionally significant) sometimes makes m4 feel almost friendly. The non-case-sensitivity of function names (but case-sensitivity of variable names) just leads to arbitrarily inconsistent code and unnecessary style differences between projects.
I don’t like the CMake tradition of having separate CMakeList.txt files in sub-directories, because this can lead to duplication and makes it harder to see the whole build system at once. I prefer non-recursive autotools, so I tried to use just one CMakeList.txt for my CMake projects too, which was only a little awkward.