CMake is awful. It's awful enough that writing about how awful CMake is is a stereotyped blog entry. It's so awful that I feel compelled to write about how awful it is, even knowing how unoriginal that is. I need catharsis.
CMake is bad at its job. It has a bad job, and it does it badly. In some ways it has many jobs, but the bit that matters is the bit that gets in your face. CMake is a dependency finder.
A decade ago, when I last used it in anger, it was a build file generator. We used it to generate build files for our project that would work on a bunch of different platforms with their various build systems. It was boring, it did the job. This is not a hard job: Your code is supposed to work together, making it do so is not so hard.
It turns out the tricky bit is building disparate stuff together: Taking random libraries etc. and gluing them into a coherent whole. CMake's real-world role is to make your dependencies work together.
It's a miserable job. This isn't even dependency management in the sense of package management: It doesn't have the authority or responsibility to own installations and make things work together. Oh no, it just has to scrape around your system, deal with what's provided, trying to find the dependencies, and staple them together.
The canonical failure mode of CMake is that you have a dependency installed on your system, and it cannot find it. You can see it there, sitting in the file system, while CMake's just refusing to see it. It's embarassing.
No human wants to care about this. When a piece of software breaks, I want to debug it. To debug, I need to build. And to build, I need the dependencies to work. I hardly want to care about installing dependencies. Why on earth should I care about getting CMake to recognise them?
No sensible human being, tasked with making software work, wants to have to care about the details of how CMake finds things. The fundamental problem of CMake is that it makes you become an expert in something you really couldn't care less about.
CMake, along with other tools that most people use glancingly and couldn't care less about, should follow two simple rules: 1) Work 2) When you don't work, be really, really easy to debug, so we can stop breaking rule #1.
CMake breaks this rule most egregiously. Old-school Make is... actually not that bad at being diagnosable. By default it has a relatively straightforward approach, and there are decent-enough tracing flags. Make is decades old, and gets this right.
Let's compare with CMake. In an ideal world, there would be a simple, obvious flag that puts it into a diagnostic trace mode, allowing you to see what happens. If it fails, it would explain in detail how it failed and/or explain how to get more info. CMake does not do that. Instead:
In short, it's a user-hostile piece of software. It does not care about the use case of "This thing isn't working. How do I easily make it work?". It... feels like the kind of person who thinks C++ templates are good because they're subtle and complicated and tricky, and thus make them feel smart that they understand them. It piles up accidental complexity and assumes its essential complexity. It's utterly awful.
In many ways, you can tell it's going to be bad when the standard usage recommendation is "mkdir build; cd build; cmake ..". Baked in, at the very first level, is that the obvious way to use it is wrong. It's a warning for all that follows.