I'm sure other people will be able to share reasons their organizations use C++
I'm sure other people will be able to share reasons their organizations use C++
Rust is great and offers a great path forward, but it was not around 20+ years ago when $BIG_PROJECT was written. C++ was around, popular, and useful so $BIG_PROJECT was written in C++. $BIG_PROJECT made $BIG_COMPANY millions and is still in use today.
$BIG_PROJECT engineers are looking into migrating parts of $BIG_PROJECT to Rust, but the work is still early and the $BIG_PROJECT's millions of lines of C++ won't be replaced overnight. Improved, more uniform tooling for C++ would simplify maintenance for $BIG_PROJECT and make it easier to move $BIG_PROJECT to newer C++ toolchains and even other C++ toolchain vendors.
Maybe one day $BIG_PROJECT will migrate fully to Rust, or perhaps $BIG_PROJECT will be re-written from the ground up in Rust, but for now $BIG_PROJECT has to work.
First, the hacky build systems of old are increasingly unsustainable; I've seen quite a few projects migrate to things like cmake in part because not having that kind of build system just doesn't work anymore. (And you get people like Mozilla or Google who write their own build system just for their software, but the end result is the same--you've got some sort of modern-ish build system being integrated). Even at $WORK, some of our old build system stuff with confusing make rules and the like is being shifted to a (hopefully) cleaner cmake stuff, albeit far more slowly than I'd like.
Second, it's worth noting that tooling improvements can motivate change. The ur-example here is the compilation database idea Clang introduced. From what I've seen, every build system that can support it (sorry, autotools) has added information to extract this useful tool. If you can come up with similarly useful build system summary information that is useful for tooling, you're likely to see relatively swift adoption of it.
Third, C++ is already undergoing changes that will introduce build system breakages. Most notably and obviously, modules. Build systems need to adapt to support this, and if people are already making the switch to get new features, incorporating other useful tooling additions at the same time would see adoption.
The problem is that CMake is also a cardboard castle built on numerous hacks that break every time a wind blows by. For library users it might be bearable, but for library writers it is absolute hell. And the consistent churn of new half-baked features and subpar documentation really doesn't help. (People talk about "modern" CMake like they do with "modern" C++, the churn is so similar...)
The solution that I've found now is: I've built my own build system in Python that outputs a Ninja file, dead simple. Don't really have the urge to use CMake again (unless when I need to at $WORK)
How it deals with:
- Use sanitizers
- Compile for several operating systems, even some later you might need to port to.
- Debug/relase/minsize builds
- disable/enable warnings as errors
- run test suites
- use ccache
- install stuff
- consume external libraries
- choose a nested common nested dependency for the same version for a lib, and, transitively, do it for all subdependencies (something I handle with Conan and/or Meson wraps)
- dll import/export and symbol exposure
- compile static/dynamic PIE/PIC libraries
- custom compilation flags to distribute your lib god-does-not-know-where-yet. (for example distro maintainers)
Now you might tell me you do not need much of that. And you would have a point. The problem is that when you start to mix and match projects
If you have done all that, you did it ad-hoc. CMake at least can do it for all your projects. And CMake is really bad, IMHO, I much prefer Meson.
For all the bad things CMake has, if you do even a 10th of this ad-hoc, you are already wasting time compared to using a battle-tested tool like CMake or Meson.
You don't need CMake for this. You just add the relevant flags onto the specific compiler you're using, and CMake doesn't really help you with that.
> Compile for several operating systems, even some later you might need to port to.
Have you tried using it with Windows, especially with Clang / Clang-CL? I've tried it for several days and gave up (the final reason I ditched CMake and went on building my own).
> Debug / Release / Minsize builds
> Disable / Enable warnings as errors
Again, add the relevant flags to your compiler? Don't see how CMake helps this.
> Run test suites
I personally use doctest for this, and you just need to compile your test executable with the header-only library. Again, no need for CMake. I really don't see how CTest really helps, maybe it's a teeny bit cleaner.
> Install stuff
> Consume external libraries
I really don't like how Fetch_ContentDeclare works, I prefer having my dependencies being explicitly inside my repo (instead of needing to download from the Internet) whether it be in source or as a git submodule.
And anyways, you need an external package manager other than CMake if you really want to manage this stuff properly in a more NPM/Cargo-esque way.
> choose a nested common nested dependency for the same version for a lib, and, transitively, do it for all subdependencies
I don't know if I have understood your sentence right... but CMake doesn't really like having different versions of the same library inside one project (because of CMake lacking any proper modules / namespaces), I remember struggling with this issue before.
> DLL import/export and symbol exposure
> Compile static/dynamic PIE/PIC libraries
> custom compilation flags to distribute your lib god-does-not-know-where-yet
Again, compiler flags.
Overall, CMake might be nice if you are just using other people's libraries, don't really have that many customizations needed, and have relatively simple build processes (no complex custom code generation / compiler needed to be run). But if you are anywhere outside of that then prepare for a hell-like experience struggling with all the archaic under-documented options and searching for obscure StackOverflow questions. Like, the whole experience of using CMake feels so ad-hoc, up to the point that it seems better to make your own that fits for your specific use-case.
Meson does, at least. And you might have at least clang/msvc/gcc with different flags for address/thread/ub sanitizers. You might be in that situation. If you are, it is not worth anymore to go do it yourself. You have this for CMake, btw (do not know quality-wise): https://github.com/arsenm/sanitizers-cmake.
> I don't know if I have understood your sentence right
I mean this:
- A uses B uses C 1.3.2
- D uses C 1.4.1
- C uses E 5.1
- F uses E 5.3
Now you have to use the same E and the same C nested dep version for both packages. This is not trivial with a realistic amount of dependencies it can get hairy very quickly. Conan deals with this. You can say: grab 5.2 and 1.3.2 and it will do the thing as long as you know that those versions are actually compatible with your packages.
> Overall, CMake might be nice if you are just using other people's libraries, don't really have that many customizations needed, and have relatively simple build processes (no complex custom code generation / compiler needed to be run).
Are you aware that this makes your project a personal thing that others cannot use? I mean, yes, you can do that, but it is useless outside of your uses unless you either package it for Conan/Vcpkg or build it with a reasonable build system (CMake/Meson/maybe Bazel?/Scons).
> the whole experience of using CMake
it sucks a bit but it works and it has improved. Also, even more important, it is battle tested. But let me recommend you Meson if you hate CMake as much as I do. I work with Meson when I can. The DSL is nice and easy. A piece of cake.
> it seems better to make your own that fits for your specific use-case
I understand your frustration and feeling. I have been there. It is easier to drop a Makefile or something you understand quickly and it will work for you. The problem is when you start with the builds/compilers/shared vs static/sanitized and install targets dance. That makes it unfeasible to run your own solution in many cases bc you are going to make mistakes all these tools already made and corrected and they are battle-tested.
Still, how is CMake helping with that situation? You've linked up an external repo with CMake scripts to solve this, why isn't this part of CMake then? Why am I resorted to use someone else's abandoned hacky build scripts from 4 years ago, which might probably have issues? I would rather just do this myself and add the relevant sanitizer flags (and I'm only using Windows LLVM at the moment, so I only need to deal with that).
> ...it can get hairy very quickly. Conan deals with this.
So CMake doesn't do this, Conan is actually doing all the work. And Conan is another complex piece of package manager machinery that I need to integrate into my workflow, which is slow, breaks often, and doesn't have the packages that I need (and even if they have them, don't have the options I need for customization). I've tried using it before and the experience wasn't that great.
> Also, even more important, it is battle tested
If it is battle tested, why are people still struggling with it so much? Why are people spending so much time fixing build scripts instead of writing actual code?
> But let me recommend you Meson
Does it work on Windows with LLVM Clang? That is the most important initial question. If not, I'll pass.
> Are you aware that this makes your project a personal thing that others cannot use?
If I'm building a end application (like a game or a GUI app), then I really don't need to worry about this.
But if I'm building a library for others to use, then I would make sure that there are minimal dependencies (as the tradition with good, frequently used C++ libraries) with ample room for customization of various options using #define flags. I would design it such that one can quickly integrate into any build system without much hassle. (Libraries that I use such as CGLTF, IMGUI, and physfs are all designed in this way. They all don't have CMakeLists.txt in their repos, but are still used frequently in production. It's fine.) For the few libraries that are a bit hard to build on source because of various reasons (like SDL2), I will precompile it and use the DLL binary with the headers.
> bc you are going to make mistakes all these tools already made and corrected and they are battle-tested.
Seeing from all the hackish solutions and workarounds people have written for CMake, I really don't think it is reducing the number of mistakes you're going to make.
There is a lot of CMake hacky code around, but there is also a proper way to do it that works :)
Also, in Meson at least, it is easy to change to compile dependencies from system to subpprojects without touching the build files or even choose selectively which dependencies to use. And it works well transitively.
You can argue that CMake is complex, but the truth is that it adds value.
I say this from a real hate to CMake. But it works.
As for SDL2, as an example, only in Windows you can have it compiled for different runtimes (debug release) in different modes ( static, dynamic), multithreaded and later you have to choose whether to compile SDL statically or dynamically. Now repeat configs for Linux/Mac/clang/gcc. I have done this before. No, it will not scale.
If it is for personal stuff u do not need to release u can do something hardcoded by hand. Otherwise you will be wasting a non-trivial amount of time doing it, wsy more than without a proper build system, no matter how much you hate them...