9 ms·
A semi-relevant rant about CMake, for those interested in that kind of thing: The CMake scripting language is just awful. It breaks with convention to do thing
by MaxBarraclough 6y ago
A semi-relevant rant about CMake, for those interested in that kind of thing:
The CMake scripting language is just awful. It breaks with convention to do things in its own unintuitive way. (Who though the endfunction() syntax was a good idea? Or the bizarre function-call syntax?) It's error-prone, it shows cryptic error-messages, it's able to break in subtle ways, much of the documentation is for deprecated functionality, and worst of all, it lacks a consistent design pattern. One shouldn't have to think when making a Find... CMake script so that CMake can find an installed package. It should be a very boring task of adapting existing boilerplate. But it's not so. It's an agonising uphill battle with this atrocious language.
Subtle bugs like [0] wouldn't even be possible in a well-designed build-system, but CMake lets you shoot yourself in the foot as punishment for not knowing its every subtlety.
It's unfortunate that CMake is the least bad build system we have. You should probably still use CMake for multi-platform code. You shouldn't expect people to learn some obscure rival build-system just to work on your code. I'll certainly continue using CMake for what little C++ I write myself. Once you've beaten your CMake scripts into submission (generally thanks to the extensive body of knowledge on StackOverflow, in my experience), CMake works a treat on a bunch of different platforms. It's just a pity the language is so terrible.
[0] https://github.com/dankamongmen/notcurses/issues/711 https://github.com/dankamongmen/notcurses/issues/711
- Arnavion 6y ago>It's unfortunate that CMake is the least bad build system we have. You should probably still use CMake for multi-platform code. You shouldn't expect people to learn some obscure rival build-system just to work on your code. What little C I write I compile with Makefiles, but I've seen many new C projects on Github using meson. It look better than cmake at a glance, and at this point in time isn't obscure either.
- kabdib 6y agoThanks for the pointer to meson. Ten minutes into it and it's already far less broken than other build systems I've been test driving recently. I'm sure it will let me down soon, but so far ... :-) (My reaction to CMake's scripting language was unprintable).
- marcthe12 6y agoMeson is quite good. It's biggest issue is it is not Turing complete so it has certain limits of extensibility.
- leafboi 6y agoCMake is a meta programming language designed to compile into Makefiles. It can compile into visual studio projects or xcode projects. That's how it achieves multiplatform support. Basically by writing it in CMake rather then make you've automatically written your make file as well as many other platform configurations. Of course the caveat like the OP is that CMake syntax and design decisions are just plain bad.
- Arnavion 6y agoI think you replied to the wrong comment.
- throwaway894345 6y agoI don’t think so. The parent was saying that Make isn’t a replacement for CMake because it isn’t multi platform.
- deleted 6y ago[deleted]
- Arnavion 6y agoThey replied to a comment mentioning meson as a replacement for cmake by explaining how cmake works.
- nyanpasu64 6y agoMeta-build systems need a clean separation between variables computed by the program (or cached), and parameters set by the user. Placing both in a single CMakeCache blob causes confusion and nasty semantics when local set() variables, option() variables, and command-line -DKEY=VALUE collide.
- klodolph 6y ago> It's unfortunate that CMake is the least bad build system we have. With caveats--I've switched to Bazel. Bazel does solve the very real, very hairy problems of compiling C++ programs for different platforms, on different platforms. It is a damn beautiful thing. There are a few places where Bazel really shines. For example, generated sources, multi-language projects, and building third-party dependencies from source (without monorepos or Git submodules--you can get your third-party sources from HTTP, Git, etc). If my project does any of these things (third-party dependencies, uses multiple languages, or generated sources), I reach for Bazel immediately. That said--it is also impossible to give an unqualified recommendation for Bazel. The documentation and community is catching up, and a few simple things (like using pkg-config) are a bit more difficult to get working than they should.
- mehrdadn 6y agoBazel is the least bad build system I've used too. Just wanted to note, though, it is not damn beautiful. Maybe its internal (idealistic) model is beautiful, but the outer parts are something else. It does have awesome features, but it has lots of bugs, rough edges, and weird behavior too. Try specifying your own compilers, or adding your own steps to the build process, getting things working on Windows, etc. and if you don't already know how to do it, you will probably hate your life trying to figure it out. And forget about putting your workspace into a path with spaces, even if your repo path lacks spaces inside it and you use relative paths everywhere -- it simply can't do that (while even Make can). There are lots of random issues with undeclared headers and ungenerated files that come up from time to time that make absolutely no sense and are likely bugs that are incredibly hard to track down. (Of course some of these errors are legitimate too, just painful to track down. I'm saying not all of them are. Some are even nondeterministic.) And good luck if your user name (and hence home directory) has a space in it, which it very well might if you're on Windows. All in all, it might be better than anything else I've used, but not in every case, and that's not an unconditional endorsement.
- klodolph 6y agoWhile Make can deal with spaces, you have to pass them through multiple layers of splitting. I've done it before, but I've given up on anything besides escaping every single space and pasting it into the Makefile (with a script), and not using any of Make's variable expansion functionality. Spaces are how Make separates items in arrays, after all. For example, take this contrived example: foo.c\ bar.c echo $(patsubst %.c,%.h,$@) If Make had some concept of arrays, it would echo "foo.c bar.h", but it does not. While this example is super contrived, it should illustrate the general problem.
- formerly_proven 6y agoI find it remarkable how rarely Find... CMake scripts actually work, even if they're shipped by the distro (especially if they're shipped by the distro). Also, on !Linux CMake scripts tend to require at least one manual variable change per dependency.
- hoseja 6y agoMost Find... scripts are just hoping you have the dependency installed in some default location.
- de_watcher 6y agoAnd it works with Linux distributions.
- m463 6y ago"It's unfortunate that CMake is the least bad build system we have" I think build systems (and packaging and installers and...) are sort of like doing your own taxes. Things start out simple, and but at some point things become complicated and you want to just get through it and get out and forget about it until next year. (just pay someone else to do it!) It's really too bad, I think in the software development process, there are some friction points that if they just had a little lubrication, would make everything go so much faster. I suspect these sorts of things aren't "sexy" like machine learning, or game programming or writing a new language. But things that are important don't always correlate that way.
- j1elo 6y ago> CMake lets you shoot yourself in the foot as punishment for not knowing its every subtlety. Seems adequate for the somewhat-de-facto standard for C++ projects!
- throwaway189262 6y agoIm glad it's not just me. I've spent weeks learning basic C to contribute a few patches to my favorite OSS project. I swear it's taken me longer to figure out how to build and include libraries with CMake than learn C. And it still makes no sense to me. Seriously, what the fuck is wrong with C/C++ package management. I gave up on learning the build system. I recreated a working build setup in Code::Blocks UI then exported it to a makefile. Then exported that to CMake and copy pasted shit into the original build setup until it worked. Fuck it. C library management is harder than the language
- earthboundkid 6y agoYes, everyone on HN likes to make fun of JavaScript because of leftpad, but the C/C++ ecosystem is much, much worse, which is a real achievement.
- de_watcher 6y agoNo, C/C++ is straightforward when you stick to a distribution because there are people who are dedicated to packaging and deal with inconsistencies that individual library developers love to multiply.
- rcxdude 6y agoAnd anyone who tries to build your software on another distribution will feel the pain.
- MaxBarraclough 6y ago> I swear it's taken me longer to figure out how to build and include libraries with CMake than learn C I had a similar experience learning C++. Learning the C++ language isn't all that straightforward, but there are at least plenty of resources available. Build-systems felt much more like a black-box, until I'd hit them with a stick for long enough that they felt familiar. I started out with single-file C++ programs, invoking g++ manually with the appropriate flags for include directories and linking. I think that's probably the best way to go. Work up to proper build systems a little later on. Perhaps another good way to start off would be to just use an IDE, and ignore the build process while you're starting out.
- bch 6y ago...it gets worse: it was born to manage a medical imaging project[0][1] that was already using a proper, regular embedded scripting language. Then they decided “we need a build system - let’s not use the battle-hardened proven language we’re already using in this very project we’re working on”. I always feel a pang of guilt complaining about cmake, because people made it, certainly with good intentions, and it is an engineering feat... but to my mind passing over Tcl for what was created was a huge mistake. I tried to love CMake for years; turns out I’m happier writing a plain-Jane Makefile. [0] https://vtk.org/ https://vtk.org/ [1] https://en.wikipedia.org/wiki/VTK https://en.wikipedia.org/wiki/VTK
- wyldfire 6y agoI am not by any means a tcl fan. But after years of banging my head against cmake I would probably prefer a tcl build system. Scons never quite found a critical mass. I suppose it had its own quirks but I think I'd have preferred it over cmake too.
- glouwbug 6y agoI recently discovered unity builds, only applied to C, and I love the quick build times. 10,000 lines of code, included directly into main from other .c files, compiles in 1 second on my machine with -01 optimizations
- moonchild 6y agoUnity builds are a neat idea, but they just don't scale. One of my projects is about 3k loc (for the time being...) Takes 1.6s to build right now, under clang. (Amazingly, it takes 68ms with tcc, but that's a separate issue.) If I switch to a parallel build, that time halves to only 0.8s. You can't do unity builds in parallel, because there's only one translation unit. Most people will probably get much better than 2x performance from parallel builds; I only have 4 cores. You also can't do incremental builds in unity. If I touch just my biggest file (so only that has to be rebuilt), my compile time halves. Touch the next-biggest file, and it halves again. As a project grows, time it takes to do a full rebuild gets bigger, but incremental builds take about the same amount of time. (They may take slightly longer, as your headers grow or as the linking stage takes more time.) You may have slightly better compile times right now, but they won't last. Incremental, parallel builds still have problems (especially when you get to the scale of linux or chromium), but but there's a reason few people use unity builds.
- enriquto 6y ago> CMake is the least bad build system we have. Hell, no. If you do C or C++ (with no or a small set of dependencies) then a portable makefile is certainly easy and beautiful to write.
- deleted 6y ago[deleted]
- MaxBarraclough 6y agoRaw makefiles aren't good enough. I want cross-platform package-detection and Visual Studio support. Autotools is the Unix-only solution to package-detection + environment-detection + build. The cross-platform solution is CMake (not counting its various obscure and immature competitors).
- enriquto 6y ago> Autotools is the Unix-only solution to package-detection I do not understand the concept of "package detection". I guess you mean about dealing with dependencies that are not copied into your code. In that case, either your dependency is correctly installed into your system (and then, by definition, it is automatically found by the compiler and the linker), or it is not. If your dependecy is not correctly installed, either the compilation will fail (which is correct behavior), or you will have to manually edit the configuration so that it can be found, by specifying its path (which is also correct behavior). Both of these things can be perfectly done with plain makefiles. No need for autotools (which is shit) nor cmake (which is shit squared). The alternative is to have your build system to search around your disk for possible versions of the required dependency. This is a completely untoward behavior and in very bad taste.
- MaxBarraclough 6y ago> I do not understand the concept of "package detection". The detection of software packages depended on by my code. Typically this means libraries, and perhaps also executables, either executables needed for the build process (such as code-generators) or executables that will be needed at runtime. If my code uses a Boost library, the Autotools configure script (or CMake) can check that Boost is installed on the machine, check that it has an acceptable version number, and configure the build to look in the right place to find Boost's header files. If Boost is not installed, the configure script (or CMake) will fail with an error. It will do this quickly, not part-way through a build, which is poor form and can be annoying for the user. Configure scripts can also handle optional dependencies. They can also detect platform-specific attributes and produce a header file of the values, helping the developer cope with the platform's quirks. (It might check for the availability of a compiler intrinsic, or something of that sort.) > In that case, either your dependency is correctly installed into your system (and then, by definition, it is automatically found by the compiler and the linker), or it is not. There is no canonical installation path for a Unix package. You're right that the linker can be expected to, well, handle the linking, but that's not the whole story. Different distros (and different Unix-like OSs) install things (such as header files) in different places. Even within a distro, installing a package from source (rather than through the package-manager) may result in it being placed in a different directory. On Ubuntu the convention is that /usr/include holds headers installed through the package-manager, and /usr/local/include holds headers for libraries installed from source. Of course, Windows isn't a Unix-like, and things have to be handled differently there. The configure script should figure out that stuff automatically, the user shouldn't be given a pile of errors to manually fix. They shouldn't have to make any source-code changes just to get things to build. Robustly portable scripts to find packages, can be surprisingly involved. [0] This is why CMake encourages us to write self-contained Find... scripts that be reused by other codebases. > Both of these things can be perfectly done with plain makefiles Doing so manually with raw Makefiles, isn't scalable. This is why systems like Autotools exist. The configure script handles this sort of machine-specific detail. Large programs may have dozens of dependencies. It may be a sizeable task for the user to fix them all. > The alternative is to have your build system to search around your disk for possible versions of the required dependency. This is a completely untoward behavior and in very bad taste. C and C++ are not like Java. There isn't a single idealised system that you can target. You are exposed to platform-specifics, and it's on you to cope with them. This is true both at the source level (good code doesn't rely on sizeof(long) giving any particular value), and at the build level. [0] https://github.com/Kitware/CMake/blob/master/Modules/FindImageMagick.cmake https://github.com/Kitware/CMake/blob/master/Modules/FindIma...
- qznc 6y agoIf the syntax is the primary problem, there is Meson (reduced Python) and XMake (Lua). I wonder why CMake cannot embed an alternative language? You could have CMakeLists.lua files modify the same targets and properties using Lua.
- MaxBarraclough 6y agoThose are entirely different build systems, and they're obscure and immature. CMake scripting is bad. Fragmentation of build-systems is probably even worse. Like I said, it still makes sense to use CMake for multi-platform code. If the CMake folks made more of an effort with documentation, many of my complaints would go away. It's not necessary to burn down CMake and start afresh. The awful language wouldn't matter so much if there was clear and thorough documentation with plenty of complete examples, and in particular, definitive guidance and reusable boilerplate for the most common jobs (e.g. package discovery). > I wonder why CMake cannot embed an alternative language? The last things CMake needs are even more complexity and even less consistency.