> The current CMake language is fine. Nothing amazing, but good enough.
Lol CMake was a huge reason I got out of C++ development almost a decade ago. I was tired of scripting my own shitty build systems, especially ones which couldn't even manage packages. I never actually need the power CMake offers, but the stuff I do need (reproducible package management) CMake punted on. 99.9% of the time, all you need is a build tool that takes a list of dependencies and a lockfile (or similar).
It's really quiet glorious how absurdly complicated the C++ development environment is. Want to build something? Well, you'll need a c compiler. Want multiple files in it? Well, you'll need a Makefile. Want a dependency? Well, now you have to decide if you want cmake, autotools, bazel, scons, meson, ninja, or to write your own bash script? Why? Who knows! Oh, does that install the dependency for you? No, don't be silly, those tools simply determine what your current platform has.
Yeah, and the real tragedy is that these are all solved problems in other ecosystems. The C++ folks often don't know what they're missing out on. Which is too bad, because while C++-the-language gets a lot of flack, modern C++ is actually pretty cool (still a bit of a bear to figure out which features not to use). But the tooling is just insanely cumbersome (it's been a while since I've developed C++, but last I checked even getting decent editor support was absurdly hard and the various Vim/etc plugins that promised said support never worked out of the box).
> The C++ folks often don't know what they're missing out on.
This assumption implies that C++ developers are all one-track wonders that lock themselves in a basement and have no contact with any other programming language or tooling.
> But the tooling is just insanely cumbersome (...)
It really isn't. Node.js with npm or yarn is a far greater mess than anything that happened in C++.
I'd say that 9 out of 10 times people complain about the C++ ecosystem, they are actually talking from a place of ignorance and at best are only complaining about the mess they needlessly dug themselves into.
Case in point: who in their right mind feels the need to bolt on a different scripting language to cmake, a build system that only rarely needs a damn if statement in the project? These guys are clearly deeply invested in making their lives far hard and worse than they need to be. I mean, where's the need?
If anything, this wave of contrarian bullshit targeting C++ only shows the high volume of inexperient and clueless developers who decided to skip learning the basics and instead thought it was a good idea o dive head-first into wheels reinvented very poorly, and from there in proceed to depict their own mess as representative of everyone else's experience.
I don't have problems with dependencies in C++ using CMake. Maybe I'm doing it wrong xD.
It is harder to get 400 dependencies than with other ecosystems, I'll admit that. But I see this as a feature. I can't even start to imagine how people deal with security when the most basic app they write gets tens (hundreds?) of transitive dependencies. I guess they don't. Nobody cares about security.
That was not the point. It was “want to develop something?”
Not sure why a makefile is so bad.. it’s just a file generation tool which can check out-of-date files and specify dependencies by pointing out which input files are needed for an output.
Your answer is only good if you're writing an utterly trivial program. For any real application, you need some kind of build system, not just a g++ command line.
Makefiles don't work for extremely large and complex applications. That's the whole reason we have junk like CMake and Gradle.
The question you should be asking yourself is "why? why does my C++ project need 18 programming languages to build and java needs an xml file, javascript some json, or rust a toml file".
how many times did you have to build a java or javascript project where you are counting kilobytes, or are pre-generating data tables for maximum efficiency which you want to be configurable as a build option because you're going to need different tables for different hardware/target ? people with this sort of problem just aren't even considering using java or javascript so of course in C++ we end up with a hairier solution. A lot could be solved if there was good compile-time reflection for sure but still.
An example: the main software I work on, along with a few other software I know, has to generate a SDK as part of its build so that people can build plug-ins for it. How often do you have to do this in java or JS ? almost never. But this requirement implies having a build system powerful enough to do that.
Another example: another software I work on must produce a Max/MSP package ; this implies:
- working with multiple versions of the Max SDK which changed their structure on disk
- setting different build options such as file naming depending on the target architecture: .dll on win32, .dll64 on win64
- generating a relatively complex tree structure which combines a Windows and a macOS build together because people don't want the hassle of having two different download options
- generating some stub C file that will declare a function to be exported
- generating some .json file with various build information, build date, etc
- generating a symbols.txt file which contains all the symbols that are known to be explicitly exported to minimize binary size ; the build system has to: list the symbols (one per plug-in we build), write them to a symbols.txt file, pass that file to Apple's dyld like this:
> these are the requirements we have. can you solve these requirements with just Java's XML
Yes, actually. They don’t come up very often, but maven in particular has the ability to do everything you’ve mentioned. Most of them built right into the standard plugin set, like setting various compiler options, adding build information, or even platform specific build shenanigans (usually when dealing with javafx).
Maven also has a rarely used escape hatch plugin (ant run) which allows you to run custom scripts if you really need to.
can you show an example of how you'd parse, say, a .java.in file from Maven (say match some lines with regexes), and generate a .java file from it, that you'd add as part of the build? And could you really say that this would be cleaner than the same thing done with cmake?
> can you show an example of how you'd parse, say, a .java.in
The canonical way to do such a thing is through the java annotation processing api [1] and using a tool like java poet [2]. Before you did that, you'd probably decide if you wanted to instead use bytecode generation with a library like bytebuddy [3]
But, assuming for some reason, you wanted to torture yourself and actually consume a java.in file and apply a regex, then you'd probably pull out the "maven-replacer-plugin" [4] and configure that for the task at hand. (or use your favorite templating language plugin. There's a million of them).
Though, to be fair, this really isn't something that comes up in regular java programming due to the nature of the ecosystem. Anything you'd want to codegen likely already has a library and anything you didn't would receive (legitimate) push back.
> And could you really say that this would be cleaner than the same thing done with cmake?
Probably not. But not really the main point. cmake becomes a problem when you want to do anything more complex than string replacement. Imagine, for example, if you did want to use a code generation library within a project. The strength of maven is a new team dev only needs maven. Further, if they need to update that library they only need to change that maven file.
What happens with cmake if you wanted to update a minimum dependency?
I just don't understand in which universe having to look for X plug-ins which may or may not be maintained (the first I looked at had its last update in 2015) is better than cmake ; cmakelang could be literally a befunge variant of INTERCAL than it'd still be a better choice than this for me
Part of the answer is that C++ wants to interrogate your system or build root to understand its capabilities. "Call this function if available" or "Access this variable if it exists" are more common in C++ projects, compared to the other languages you listed.
Rust tries to avoid that by hard-coding availability into the libraries themselves, but the result is less reliable. For example I cannot use `libc::mkostemp` on macOS because Rust has (incorrectly) hard-coded that it is not available on that platform.
CMake is able to detect it, but we pay a cost in build system complexity. I wish instead this detection could be done at runtime.
But that was too boring, so people turned to gradle and we're back at ad-hoc scripting in a bizarre Turing-complete language. Believe me, I've hated maven with a passion (and still do) but this episode taught me build systems are nothing but a zero-sum game and typical junior-grade pastime.
Update: the story with Node.js is a bit different, but package.json was soon augmented by package-lock.json and yarn at about the same time Webpack and similar became kitchen sinks requiring config-generator tools such as create-react-app. The morale is, the grass is always greener on the other side I guess. Though tbh, cmake always was absolute garbage making autotools look sane in comparison. Now I hear there's legacy/unmaintained and new cmake syntax; what were people thinking?
This is a straw man. The objection was never "XML is too boring", the objection was "the XML models an actual programming language, so we're doing imperative programming but without the ergonomics and syntax of a programming language". "It's just XML/YAML/HCL! Way easier than programming in an imperative language!" is such a farce (not only among build systems but especially among infrastructure-as-code solutions).
Just because it accepts XML doesn't mean your build system is meaningfully declarative.
Oh, I fully agree with your argument as it applies to the old ant build tool, which is in fact a programming language using XML serialization - the author even apologized for it when he realized syntax wasn't the hard part. But a maven pom.xml is actually a component model serialization rather than a programming language in disguise - unless you're referring to embedded ant scripts in maven files which is a thing, but not common enough to warrant criticism IMO. Scripted deployment tasks in a Java context were more commonly seen in Jenkins, and only recently spill into gradle build scripts (I've always thought gradle was following Jenkins' Groovy syntax for eventual integration but that hasn't happened).
I have worked with Android (ant, maven, gradle), iOS (CocoaPods, Carthage, SwiftPM), C++ (CMake, autotools, meson) and some Python.
Never needed 18 programming languages to build. I actually don't think CMake is harder than Gradle or SwiftPM. Most people I see complaining about CMake actually write bad CMakeLists, so the way I see it is that they don't want to learn the basics. And that's maybe why e.g. gradle works better: for many projects, the IDE is probably able to automatically handle an imperfect and not-so-readable gradle configuration, so people don't need to learn gradle.
But the result is the same: they don't really master their build tool.
> The question you should be asking yourself is "why? why does my C++ project need 18 programming languages to build and java needs an xml file, javascript some json, or rust a toml file".
But your C++ project never needed 18 languages.
If you feel it does, you need to take a step back and take a serious look at the mess you're making because you're making at least 17 mistakes.
Tell me, what exactly does your build need that is not met with the following:
In fairness, many of the CMake criticisms also apply to Gradle in the Java world, but yeah, Go just needs its go.mod file, Rust just needs its Cargo.toml file.
I would argue that Gradle is fine, just like CMake is :-).
But there is a philosophical question here: I think that developers should master their basic tools to the point where they don't make a mess writing a CMakeLists.txt or a build.gradle.
It feels like many devs think that a tool is too complex if you need to learn it.
99% of the time but Rust also has build.rs as an escape hatch which lets you run your own code at build time (eg code generator like grpc). The sane part is that you do all this in the same language.
Agreed, but “escape hatch” is the salient distinction. It’s not the default, contra CMake. Also, Rust pays dearly for build.rs support in terms of difficulty optimizing compile times, so supporting that extra 0.1% ain’t free.
I mean, my remark was a bit of an oversimplification. Modern build systems do a bit more than take a list of dependencies--they'll also allow for bundling data files into the compiled artifact, platform-conditional compilation units, and a few other things. But they don't expose these things as a fully imperative scripting language / meta build system--a few bits of declarative configuration can cover 99.9% of use cases.
> CMake was a huge reason I got out of C++ development almost a decade ago
That's funny. After thirty-odd years of C++ development, it's only in the last year or so that I've started to take CMake seriously, since a critical mass of other people seem to have (inexplicably) decided to treat it as something akin to an official C++ build system.
Lol CMake was a huge reason I got out of C++ development almost a decade ago. I was tired of scripting my own shitty build systems, especially ones which couldn't even manage packages. I never actually need the power CMake offers, but the stuff I do need (reproducible package management) CMake punted on. 99.9% of the time, all you need is a build tool that takes a list of dependencies and a lockfile (or similar).