6 ms·
CMake is legitimately the worst software I've ever used. cargo > Bazel > autotools > "the IDE" > handwritten Makefiles >>>>>> build.sh >>>>>>>>>>>>>>>>>>>>>>>>
by zelly 5y ago
CMake is legitimately the worst software I've ever used.
cargo > Bazel > autotools > "the IDE" > handwritten Makefiles >>>>>> build.sh >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> CMake
- enriquto 5y agohandwritten makefiles have a certain kind of deep, pure beauty if you are in the right mindset
- rualca 5y agoHandwritten makefiles can be the best option on the table in scenarios not involving a lot of boilerplate code or having to do any platform check at all. Once you stray out of that niche, anyone is better suited if they just automate all the boilerplate generation and compiler checks. And that's what CMake does.
- enriquto 5y agoMaybe it wasn't your intention, but your comment is the most scathing critique I've ever read of cmake. Boilerplate code and "compiler checks" are strongly negative anti-patterns. Maybe the worst in programming. That cmake makes it easy to do these awful things just shows how evil it is! People: write simple, portable code!
- rualca 5y agoI'm not sure you understood what I've said at all. CMake eliminates boilerplate code and compiler checks. They do not exist, at all. With CMake you state that you have a C++11/14/17/20 project, it builds N static/shared libs and M executables, you set dependencies, and you're done. They do exist in Makefile projects because Makefiles only define the DAG for the build, and don't perform any sanity check at all. So if you have to include dependencies or use specific compilers then you have to manually check each and every single thing yourself, because Makefiles do not handle that at all. Think about it: why did the entire industry adopted makefile generators such as CMake instead of just using a standard tool like make, which just works and is ubiquitous? And no, relying on tools and a layer of abstraction to eliminate all janitorial work is not evil or awful. Checking if a lib you depend on already exists in the system is not evil or superfluous. Checking if the compiler you're using supports a specific version of C++ is not evil or superfluous. Do you expect things to just work when you aren't even aware of which compiler you're going to use? Do you want to spend time looking at weird compiler error dumps just because your build machine happens to have a different version of, say, Boost installed? The main problem of cmake is that some people seem totally oblivious to the problem domain, and what/how much work it takes to get stuff to work reliably given very basic usecases such as... Upgrading a version of a compiler, such as VS. Think about it: How exactly do you think simple, portable code is done? Do you expect code to compile on different platforms by magic?
- enriquto 5y ago> Checking if the compiler you're using supports a specific version of C++ is not evil or superfluous. It is both evil and superfluous. It is evil because you should be writing portable code and do not depend on compiler specificities. It is superfluous because if you do not check, the compilation will still fail, which is precisely the expected behaviour. > How exactly do you think simple, portable code is done? By writing it carefully and testing it on different systems. You test with -Wall -Wextra -Werror -pedantic on all systems but you distribute the Makefile without these compiler flags. > Do you expect code to compile on different platforms by magic? No, of course. At first you will have a few linuxisms or macOS-isms, that you will gradually remove through a few rounds of multi-platform testing (which is free and easy to do nowadays).
- jcelerier 5y ago> It is both evil and superfluous. It is evil because you should be writing portable code and do not depend on compiler specificities. It is superfluous because if you do not check, the compilation will still fail, which is precisely the expected behaviour. But now I get 2 dozen error reports because there is a lot of users who run builds because they're on Linux and that's what $BLOGPOST said to do to have the last version of some software, but have no clue about software development. > No, of course. At first you will have a few linuxisms or macOS-isms, that you will gradually remove through a few rounds of multi-platform testing (which is free and easy to do nowadays). So how do you handle that you need to link against Ws2_32 on windows or "-lwebsocket.js -s PROXY_POSIX_SOCKETS=1 -s USE_PTHREADS=1 -s PROXY_TO_PTHREAD=1" on emscripten if you want to use sockets ? Don't use sockets because they're not portable ?
- MaxBarraclough 5y ago> People: write simple, portable code! That isn't always how it works in practice, though. It's useful for your build system (or meta-build system) to be able to check for, say, C++17 support, and cause the build to fail early if this is missing. Similarly, you can use a tool like CMake to detect libraries. If a library is missing, you might want the build (or, rather the 'configure' stage) to instantly fail, or you might want to build with certain features removed to cope with the library being missing. CMake supports both, as does autotools. I agree with everyone who says CMake's scripting language is atrocious and that it's often miserable to work with, [0][1] but that's because CMake specifically is terrible. The problem it's solving is a legitimate one. An example: you can write a desktop application with two different platform-specific front-ends, and have CMake compile the appropriate one given the target platform. This is nicer than relying on the two platform-specific build systems directly. [0] https://news.ycombinator.com/item?id=24203172 https://news.ycombinator.com/item?id=24203172 [1] https://news.ycombinator.com/item?id=24565266 https://news.ycombinator.com/item?id=24565266
- jasode 5y ago>, you can use a tool like CMake to detect libraries. If a library is missing, you might want the build (or, rather the 'configure' stage) to instantly fail, or you might want to build with certain features removed to cope with the library being missing. CMake supports both, as does autotools. The gp enriquto had a rigid stance on so-called "optional" libraries. If the library is not there, the build should fail and that's it. I don't know if my previous reply to him explaining the benefits of building even with missing libraries was satisfactory: https://news.ycombinator.com/item?id=25913562 https://news.ycombinator.com/item?id=25913562
- enriquto 5y agoHey! I remember that interaction (and sorry for my crass language, I was having a hard time by then). Your explanation was certainly satisfactory. Now I understand a bit the motivation of people who want to compile different programs depending on what happens to be installed at a particular moment in their computers. I still think that it is "an exceptionally bad idea which could only have originated in California" ;)
- jcelerier 5y ago> People: write simple, portable code! that does not work as soon as your users are on both windows and a unix-like platform and you are making a non-trivial app (for instance, an app with networking, audio, and video support). A simple example: how do you share a GPU texture handle across multiple processes portably with a single code that works across windows / mac / linux's graphics APIs ?
- pjmlp 5y agoYeah, now throw game consoles, embedded systems or classical mainframes into that mix as well.
- zelly 5y agoTrying to do that is a massive waste of time. It's legitimately easier to maintain separate codebases for each of the different platforms. The code that doesn't need to change can be a library. Or you use some super high level abstraction like Unity, Qt, JVM, Electron, React Native. Portability != cross-platform.
- maccard 5y ago> People: write simple, portable code! How do you memory map a file, or spawn a subprocess simply and portably? Every way that I've seen it done that doesn't hand the logic off to the build system is an unmaintainable error prone mess.
- maccard 5y agoIf you have a project that you don't want to embed in another project, doesn't build on windows, doesn't have any spaces in filenames, and do'nt mind manually ordering dependencies wrt the quirks of your toolchain.
- user-the-name 5y agoI don't see how make is at a disadvantage with relation to other tools with embedding. No build tool is easily embedded in a project that uses a different build tool. And I've used make on Windows for years and years, so not sure why that is a problem?
- maccard 5y agoMy understanding is that recursive make is considered an antipattern (and I'm not aware of any other way to embed makefiles in other makefiles). Cmake's add_subdirectory is first class support for nesting other projects,and the FindX.cmake pattern means you can consume prebuilt libraries inside cmake, which I don't think make supports? You are technically right about make on windows, but in practice makefiles on windows tend to be written for GCC/clang, and require manual translation to work with MSVC. There's also no IDE support for visual studio, which cmake gives you out of the box;
- AlotOfReading 5y agoI used to agree, but I eventually needed to add support in CMake for a particular IDE and got far too familiar with it. It's easy to debug and the syntax could be worse. Whoever came up with the list representation needs to be arrested though. It might be stockholm syndrome, but I'd rank it worse than Meson and better than Makefiles. Autotools can go die in a fire. Cargo is wonderful, but having something that user-friendly and well designed in C would feel incongruous with the rest of the ecosystem.
- volta83 5y ago> Cargo is wonderful, but having something that user-friendly and well designed in C would feel incongruous with the rest of the ecosystem. You really did say this. Cargo does get some flak from C and C++ build systems. It is definitely not perfect, but which build system is? The coolest thing about cargo is that it can be and is significantly improved over time. The whole dependency resolution was improved to resolve some long standing issues lately in a backward compatible way and that’s just astounding that they managed to ship this. Do I like cargo? No. Do I like it better than CMake Meson Bazel Auto tools and make files? Hell yeah, by far, I’d rather get shot than go back to cmake or Auto tools .
- rualca 5y agoI disagree, to the point I honestly doubt you are not trolling, specially taking into account how you decided to rank "the IDE" between autotools and handwritten makefiles, which makes absolutely no sense at all either way you look at it. It's also dumbfounding how Bazel is ranked so high when it doesn't even support integrating system libraries as part of it's happy path. The main reason why CMake, with all it's flaws, is the undisputed build system for c and C++ projects is the uncomfortable fact that all other alternatives are awful in comparison, even and specially in very basic happy path scenarios such as putting together a lib that any user can pick whether its static of shared and install it in the system folder or anywhere without even bothering with which compiler tool chain you're using. In CMake, anyone can get a complete project up and running with less than a dozen lines of code, and that project will assuredly work on multiple OSes as-is. You'd be hard pressed to find another C++ build system that comes close to doing the same.
- jcelerier 5y agoCrazy, I'd definitely use CMake above autotools (does not even work natively on windows LOL), handwritten makefiles (not supporting filenames with spaces in 2021 LOL), "the IDE" (do you even do cross-platform?). I'd use Bazel but afaik it mostly uses a rebuild-the-world approach.. I'm already getting flak from Linux distros maintainers because I use some vendored header-only libraries and not system ones so I don't see how that is even supposed to work.
- zelly 5y agoBazel does the opposite of rebuild-the-world. That's more of a CMake thing (rm -rf build && mkdir build && cd build && cmake ..). Bazel won't even run tests if the code the tests depend on have not changed. A lot of thought went into Bazel. It caches everything it possibly can. > I'm already getting flak from Linux distros maintainers because I use some vendored header-only libraries and not system ones so I don't see how that is even supposed to work. That's where you use autotools. It has been around long enough that every package manager knows how to deal with it. For most C/C++ programs, autotools is all you need. You should learn it because it's not going away. "the IDE" (like VS project files) is definitely not cross-platform (although it can be), but not everything needs to be cross platform. For game devs building on DirectX, for example, it's completely pointless to support other platforms when the runtime depends on a single platform.
- jcelerier 5y ago> Bazel does the opposite of rebuild-the-world. by "rebuild the world" I don't mean "do a clean rebuild" (which frankly isn't a problem in 2021 with CMake + Ninja, the last time I had to rebuild is when the compiler changed from clang-11 to clang-12) but "to build a bazel-based software, all its dependencies must be built with bazel too", e.g. it's harder if you want to link against system-provided Qt, ffmpeg, ... > That's where you use autotools. It has been around long enough that every package manager knows how to deal with it. and yet it still sucks on windows if you want to use cl.exe (or if you want Xcode / VS solutions, which is regularly my case).
- h_anna_h 5y agoI think I had the best experience with Meson/Ninja so far. I am also interested in using Nix for building. As for Cargo, I did not like how it recompiled all dependencies when I changed a warning flag on my project. I also found it unusable because it provided no way to check for the hash or signature of the dependencies that it downloads. I don't think that I have ever been able to successfully compile a project that uses CMake. Its code is horrifying too, for example cmake-3.21.0-rc3/Modules/CheckFunctionExists.c contains #ifdef CHECK_FUNCTION_EXISTS # ifdef __cplusplus extern "C" # endif char CHECK_FUNCTION_EXISTS(void); # ifdef __CLASSIC_C__ int main() { int ac; char* av[]; # else int main(int ac, char* av[]) { # endif CHECK_FUNCTION_EXISTS(); if (ac > 1000) { return *av[0]; } return 0; } #else /* CHECK_FUNCTION_EXISTS */ # error "CHECK_FUNCTION_EXISTS has to specify the function" #endif /* CHECK_FUNCTION_EXISTS */
- yakubin 5y ago> As for Cargo, [...] I also found it unusable because it provided no way to check for the hash or signature of the dependencies that it downloads. Afaik Cargo does it out of the box, based on Cargo.lock. UPDATE: This doc page seems to confirm that: <https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lo...>
- h_anna_h 5y agoI did not know about rev, thanks. Though, since there is no way to specify a signature you are forced to use potentially outdated packages.
- yakubin 5y ago"cargo update" will update the packages along with Cargo.lock content. As for not updating them without a manual trigger, I consider it a feature, but I guess it's a matter of opinion.
- 5y ago
- Royi 5y agoHave you tried `Xmake` or `Meson`?