Please, everyone, stop using CMake. It doesn't do its one job.
Please, everyone, stop using CMake. It doesn't do its one job.
A lot of fancy new build tools don't even have proper Windows support.
Take autotools. You get EXACTLY what it did, and you see why it failed. With CMake it just goes "you don't have X installed". But I do. It's right there. CMake refuses to say under what cmdline or whatever it tried, and what the error was. Just "X IS NOT THERE!".
And then it depends on some version of cmake being installed, which it may not be.
I don't do windows coding, but shouldn't autotools be more viable now that Windows ships with bash?
But even if not, CMake stuff as a rule is not even portable between different flavors of Unix, so why even use CMake if it's only going to work on Ubuntu more recent than 18.04 or whatever? It's not a silly suggestion. OpenBSD generally just has raw Makefiles.
A stock Windows system doesn't have these tools. Cygwin and MinGW/MSYS provide these, but you're using stuff which is non-standard for the platform and which if you need to integrate with other libraries and tools, end up being incompatible.
If you want to use MSVC, the Autoconf/Automake support is poor. Generating output other than Makefiles is possible, but limited and quite the undertaking.
CMake supports all these other use cases out of the box. Which is why it gets used. It works on every platform, and with every compiler, build system and IDE of note.
I always end up vendoring the dependencies, because it's too tedious to find the correct installed libraries in a cross-platform way.
autotools are great, but at the same time it's a monstrosity, and easy to misuse (you should never commit the configure script, because it's the autotools that are supposed to generate it according to the platform it's running on).
For C++ dev, I did take a look at buck[1], but it doesn't really support Windows platforms.
I wish we had something like cargo (IMHO, the tooling is one of the top reasons of Rust's success), in the meantime simple Makefiles do the job perfectly.
The configure script is not generated according to the platform it is running on. The whole reason tbe configure script is such a monstrosity is because its supposed to be portable, its written in the lowest common denominator of shell. You are supposed to distribute it. Its also fine to check in if you want end users building directly from VC rather than from tarballs. Just dont modify it by hand.
I always wrapped it up in a autogen.sh script that I did commit. Also, end users generally prefer prebuilt binaries, if one wants to compile the software themselves, I expect him to have autotools installed, and mention it as a requirement in the README.
https://www.gnu.org/prep/standards/standards.html#Managing-R...
The intention was that software would be released as source code "tarballs" and contain a configure script, written in the lowest common denominator scripting language to configure that source code to compile on the users system. Additionally by distributing the configure script itself instead of configure.ac, users tend to need fewer dependencies that they don't already have.
It's _less_ applicable now that most users get pre-built binaries from package managers and it just feel pretty antiquated overall. But yeah the intention is that configure is platform agnostic and prepares your source code tree to build on the current platform. Whereas autoconf/autoreconf is intended as a tool for the developer to make writing "configure" a lot easier.
If youre just trying to get something to build as a user, its actually quite easy to read the configure script and see why its failing. The accompanied config.log is also quite detailed.
Autotools are not the best, but i always prefer building autotools packages over cmake. Worst case i can modify the configure script directly.
What I mean though is that ./configure outputs a config.log that says exactly what was done. Exactly what command line was run and exactly what the error was.
I guess I'm confused why you're even looking at the compiled scripts. Would you not look at logfiles and stderr output before you start looking at assembly?
CMake doesn't. The logs are completely useless, even when I get a CMake expert to come and agree, yes that's useless.
With autotools you can see that it failed to build because it couldn't find library foo when building with "gcc blah blah blah", and you go "well yeah, you need -L/opt/foo/lib", so you just add that. (or pkg-config equiv).
CMake, on the other hand, seems to force you to look at CMake "source code" (CMakeLists.txt), which is a horrible mess. I'm not saying autotools isn't (yay, m4 :-( ), but the point is you don't have to, because it actually logs what it does.
So this is one of the many many reasons CMake sucks.
... so does CMake ? you get log of the errors in CMakeFiles/CMakeError.log, and you can trace what happens line by line in a very verbose way with cmake --trace (or cmake --trace-expand if you want variables to be expanded)
It looks like if you dive head first into learning autotools, then m4 is going to look like nuisance.
But if you allocate time to learn m4 for what it is, instead of just something you have to put up with as part of your autotools adventure, then you'll hate m4.
m4 is the only (or one of a very few) well-known general-purpose language-agnostic macro processor I know of.
I used to build websites using m4 back in the 90s. Back when static site generats were popular, before the latest slight resurgence.
To misquote Mitch Hedberg: People either love it or hate it, or they think it's ok.
If you mean cmake versions, I'm not sure what you expect, should cmake just freeze in time and stop adding features so someone gets to use cmake from 5 years ago?
Also, the bit about autotools on windows is silly. If it can't build native windows stuff, it's not at all viable for windows.
I also dislike cmake (particularly dependency management) and wish for something better, but I think our criticisms should be well-founded.
Not sure what your experience has been but I've had zero problems with cmake portability on nixes.
Raw makefiles are so much worse from a maintainability point of view.
I find it kinda fascinating to be honest. Two devs come to totally opposite conclusions.
Also to get more logging try this: https://stackoverflow.com/a/22803821/3988037
Google "cmake --trace-expand"
Is that your main gripe with Cmake?
Meson is more or less equivalent in the functionality it provides. There is also Gradle, but it doesn’t seem to have gained much traction outside of Android development.
My personal favorite is Bazel (and others from the Blaze family of build systems). It uses a python-based language for describing build rules, an extensive documentation and developers that respond to issues. Among the downsides is the lack of proper dependency management which is critical for public, open source projects.
There is also Nix which takes it even further, but it requires much more involvement from the developer.
It would take a lot to persuade me to move away from CMake and to use something 'non-standard' that few developers are familiar with:
* Excellent support for command-line builds on Unix
* Excellent support for Visual Studio
* Excellent cross-platform package-detection. (Acid test: Can it detect and link against OpenCL without me having to write my own cross-platform OpenCL-detection script?)
* Excellent documentation, including clear and consistent best practices and design patterns
* A sensible language, whether a scripting language or a declarative language. Must follow the principle of least astonishment and be relatively free of foot-guns. (CMake fails tragically on both counts.)
I haven't seen anything except autotools get this right.
I disagree here. CMake has working FindXyz modules for most major libraries. To write one of those modules is an exercise in soul-destroying tedium, but there's a pretty impressive body of existing modules out there, many of them officially bundled with CMake.
When used correctly, both CMake and Autotools are capable of robust package-detection.
Regarding point 1: CMake works pretty well on Unix, but it's a pity there's a runtime dependency on the CMake package. Autotools is much better in that particular regard: just about any Unix system can run a configure script, as it's just a plain old shell script.
CMake certainly falls short on the final 2 points, as I rambled about at https://news.ycombinator.com/item?id=24203172
It's too late for me to edit my earlier comment, but here's another alternative to CMake for the list: Bazel.
Unless you have that library installed anywhere that is not /usr/include Then you have to just hope and pray that there's some magic incantation that will make it find the right one (especially if your system-installed version is the wrong version and you'd really like to use the newer version you installed to $HOME)
The alternative is to have a global database, like the Windows registry or like pkg-config (which I have to admit I don't know much about). Perhaps CMake could have better support for pkg-config, I don't know.
but meson needs everything to be quoted which is frankly a gigantic PITA - like, look at that, there's more quoted stuff than anything else: https://mesonbuild.com/Generating-sources.html
Given the popular success of Ada I'm not sure I would call that "having it right" except in very specific circumstances
Code review? You're in the business of reading code. Fixing bugs? You're in the business of reading code. Modifying/extending/porting an existing codebase? You're in the business of reading code.
If you're writing trivial single-use 'throwaway' code that needs no review, then readability doesn't much matter, but it's an important factor for just about all serious codebases.
Of course, there's also the question of whether Ada's specific syntax really succeeds in being more readable. It makes extensive use of English words in ways that are sometimes awkward and unnatural. I'm not a fan of its and then / or else short-circuit operators, for instance, and think they should just have gone with something like C's && / || operators. Neither syntax is self-explanatory to someone who doesn't know the language, but at least C's syntax doesn't counterintuitively collide with English.
The D compiler used to have a bunch of fairly flaky makefiles (different make vendors => pain), but now there's a shebang script written in D that not only does it's job well but also handles args properly and to top all that off is actually readable by people who aren't used to building software on Linux
There is already talk of such a system and even some implementations. I am sure many people have thought to themselves "This is so complicated! So much legacy cruft! I bet I could build a way cleaner c/c++ build system! " only to run into all of the complexity of cross platform c++.
I highly doubt there will be a cargo for c/c++, because it simply isn't rust.
https://gitlab.kitware.com/cmake/cmake/-/issues/19891
https://gist.github.com/stryku/4c69aa510711c9da6705fa4df4545...
Maybe some time after modules become available and then a known quantity.
If you like CMake more, that would be a good argument if CMake worked. But it doesn't. So in the choice between the thing that works, and the thing you may like more, please do go with the one that works.
E.g. this comment I just wrote: https://news.ycombinator.com/item?id=25702345
It could. But it's an incredible coincidence that it's always cmake projects.
Generally on nonstandard installs the others (e.g. scons) won't even run, so portability of the conf is not relevant.
what are you talking about ? take for instance kcachegrind, it builds with cmake and works on every architecture that debian supports (https://packages.debian.org/en/sid/devel/kcachegrind). I also never had issues with x32 when I used it, nor on freebsd. Can't say for openbsd but I'd be surprised it does not work there - this seems to point that other than a minor path issue things just work: https://www.sizeofvoid.org/posts/2020-03-29-how-to-build-qt5....
I'm not saying CMake itself doesn't work. Though I have run into both "CMake version is too old!" and "CMake version is too new!", which by its nature can't happen with autotools.
The reason it hasn't been seen recently is that there has been no significant development of note for the past 15 years.
Even so, it's still common for the distributed config.sub and config.guess to be outdated. That's the price you pay for embedding stuff in each package, as opposed to requiring the build tool to be provided on the build system just like all the other tools.
Yes. Again squared: project after project etcetera.
They were the go-to tools for the portability problems of the mid-late 90s and early 2000s. Unfortunately, since then they have stagnated, and they are now stuck solving portability problems very few of us have. But they don't do much for contemporary portability issues, while CMake most certainly does.
Most recent problems I've encountered are that Autotools failed to build properly with MinGW and Cygwin. CMake worked perfectly.
Since the decline and obsolescence of proprietary UNIX platforms, the main purpose of the Autotools has been effectively removed. Today, the Autotools work on Linux, BSDs and MacOS, but with pretty much everything else having been long obsoleted, the amount of testing on other UNIX platforms is both minimal and completely pointless. Few people care. They are dead. But, they still don't support the most popular platforms of today: Windows, Android and iOS. But CMake does.
But yes it really is ugly once you get off the well beaten track of "here's my source now make a library out of it with a C compiler and a few standard options." I have a personal project I fiddle with that glues together verilator, fusesoc, CMake, a RISC-V compiler toolchain, and some custom scripting into xilinix vivado.. and it terrifies me just a little.
You mean, besides Cmake being the absolute best build system for C and C++ available, right?
> Please, everyone, stop using CMake. It doesn't do its one job.
What are you talking about? Can you provide a single example where you show Cmake not working?
It doesn't log what it attempted, or why it failed.
It can't find out how to link binaries (always awesome to set up som execsnoop (because no logs, remember) only to see that it tries to link with "-llibfoo". In what world could that be correct?. And again it doesn't log how and why it chose that)
I could go on, but it's too much for a comment field.
That isn't a complete list .
Despite the above cmake is your best choice of build system for C. Though some competitors could overtake it.
I have extracted some knowledge from the source code. It's more underdesigned than overdesigned and I think that's the better side to err on. Kinda awkward but you can figure it out.
any thoughts on why are build tools so hard to get right?
What makes it hard is the problem is a lot deeper than most people realize, so most attempts are not powerful enough to be useful. They are clean until someone points out one of the many edge cases that were not thought of, and by the time you support even a few of them your clean design is a mess of uglyness.
Making it worse build systems are an afterthought to most develpers so you end up with a mess just because the programers are not taking care to write good clean code in the build system.
Everything is a string, even lists are just semicolon-separated lists. The argument expansions rules for calling functions are literally impossible to remember. All variables are implicitly defined as empty strings. Typos silently break things. `if` is completely broken. The separation of the configure step from the build step is needlessly confusing and makes some things impossible. This is just scratching the surface.
It does have a couple of redeeming qualities: they have a pretty great versioning mechanism which allows them to make breaking changes. Though inexplicably they haven't used it to fix any fundamental flaws, only little tweaks. And most importantly it has been around for ages so loads of the many many weird C++ compilation knobs have been solved.
One of my favorite comments in a while. :-)
I'm confused. How do you propose CMake supports all those build generators without doing this?
(PS. I really don't think the syntax is that bad, aside that it is jarring for C programmers, most complaints are overblown and you get used to it once you learn the rules. It might be interesting if someone made a CMake variant with a less obscure syntax but I don't see much motivation for that to actually happen)
I do fantasize about a new Cmake frontend implemented with Tcl scripting. That would be far more consistent and flexible and you can disable much of the language by default to minimize footbullets then allow commands to be reenabled for times they're needed.
Beyond that the difficulty lies in that calling any command lacks consistency and the output is just that some global variable without any convention were reassigned. There is no common semantics so you can not take the knowledge you learned from one operation and apply to the next one, everything is unique and non-composable. The solution to almost everything is just paste this random magic string anywhere in your cmakelist and it will work.
I propose that it doesn't support build generators. It should do the build itself, like QBS did.
It's great that one person can be using Visual Studio on Windows while another uses CLion on MacOS and another uses Eclipse or Emacs on Linux, all working on the same codebase. It's a huge benefit for cross-platform tooling-independent development.
This would of course be a huge improvement, but there are many details to get right to support the old and new scripts in parallel to effect a smooth transition. But in the long term, this will resolve many complaints about CMake and really improve the semantics of the language and development and debugging of scripts.
I am saying that cmake is fundamentally broken and unfit for purpose even in addition to what you mention. I've mentioned some in another comment here, but really why cmake should be thrown in the garbage is too long a rant to fit into a comment field.
I am VERY interested in hearing new ideas. If you have a truly better way, then I want to use it.
Though I'm not sure why you say generating code is so bad. Code gets compiled to machine language, and (especially with optimizations and all the new fancy instructions) are not a thing that most people usually look at anymore.
Yes, actual developers need automake/autoconf installed. Of a sufficiently recent version. But what exactly is your suggestion? Autotools at least makes this an issue only for the developers (and not even all of them, since they may not need to change things), not for the orders of magnitude more users.
But this is not a unique thing to developers. There may be other generated code. E.g. they need to have protobuf compiler installed, with all the plugins required. End users, even those who build, don't. Developers who don't modify those parts don't.
But here's the main thing though: Any portable build system, that already requires EVERY user to have that build system installed, is DoA for being a viable portable build system.
It's incredibly frustrating to download a package, only to find that the build system the author in their infinite wisdom chose to use, has not been ported to your platform (or if it has, you have to yak shave for a few hours to get it and its dependencies installed). So you can't compile the thing.
The beauty of autotools is that it "compiles" to a "virtual machine" (shell) that will truly run anywhere. Nowadays even on Windows, which now ships bash.
CMake too fails on this aspect, in addition to all the other aspects this box won't be able to fit.
But please, I truly mean that if you have a better way, then I do want it. It's incredibly hard to build something portable though. Hence the minimal dependency of "just a POSIX shell" for autotools.
Why? I don't see how it's different from requiring a user to install a compiler to build a particular language. Operating systems don't have every compiler installed by default. To fulfill your requirements, one would have to re-implement every build system and compiler in POSIX shell. Honestly the "better way" that I see a lot of projects going with is to just support multiple options for build systems, because there is no one perfect solution that is going to work on all platforms.
The elephant in the room here is windows, and at this current point in time, CMake is about as portable there as autotools because Visual Studio has built in support for it.
The various build systems I've seen, including CMake, are portability projects in themselves. Yes, to build a C++ program you need a C++ compiler. But if it's using CMake then you need CMake. Oh, but you don't have that. Ok, now you have to install that.
Oh, it requires Python X.Y (I'm not saying CMake does, but I've seen others that do, and CMake has other similar things)? Oh, this system doesn't have that. So now I need to build Python from source. Does Python have any dependencies, perhaps? (or worse, you have to use backports, which pull in 1000 dependencies so that now you have a frankensystem)
If you've ever been at the point where two steps down the dependency chain you have to build something as fundamental as Python, then you probably know that this is not a fun experience. And in fact you may run out of disk space, several gigs of source and object code later. (not every system is a 100TB server)
The whole thing about portability is that it should actually work even on systems the original developer does not have access to. If all you need to support is Ubuntu 18.04 (or newer) and Windows, then why not just have a Makefile and a MSVC project file? That would be much easier than CMake or autotools.
Oh, and I've also been hit by dependencies of the build system being too NEW. E.g. CMakeList.txt using features removed in newer versions.
And that's how autotools is different. The ONLY dependency is a POSIX shell. Do you have that? Then you can build.
The number of times I've seen CMake try to link with "-llibfoo" (it's "-lfoo") or be entirely confused about how I'm not running the exact same system the developer is, I can't even count. (e.g. failing to build because "this is not an amd64 system"… uh, yes it is, with zero logs about why it thinks that)
> The elephant in the room here is windows, and at this current point in time, CMake is about as portable there as autotools because Visual Studio has built in support for it.
Well that just means CMake has nothing at all going for it, if they are as portable.
you don't, CMake is able to bootstrap from nothing, it only requires a C++ compiler
> The whole thing about portability is that it should actually work even on systems you do not have access to. If all you need to support is Ubuntu 18.04 (or newer) and Windows, then why not just have a Makefile and a MSVC project file? That would be much easier than CMake or autotools.
having been in that exact place it's definitely not true
>Well that just means CMake has nothing at all going for it, if they are as portable.
Sorry, just to be clear, Visual Studio does not have built in support for autotools. (Unless they added it recently and I wasn't aware) But, there are a number of other less convenient ways to get that to work on Windows.
So then you need to either compile from src, or sideload install it and pray that cmake finds your new version instead of preferring the distro installed version.
Keep in mind that I have to do all this just to build some C++ binary because someone decided to not use autotools.
I've voted this post down for this in particular. It is truly an absurd criticism, especially when you refute it yourself when you admit bash on Windows is a relatively new phenomenon (and I still struggle with bash env on Windows). If you use a build system, you need a build system installed, full stop. Cmake is pretty easy to bootstrap on a new host with minimal assumptions. Literally just `./bootstrap; make` on basically any 'nix.
Cmake is designed to run truly anywhere, with many backing generators, not just make. It doesn't even assume a posix shell iirc.
Sounds like many of your complaints are with the library authors not writing with portability in mind.
I don't understand the argument, it seems very circular.
Most software packages have a number of build dependencies as prerequisites for building, including a compiler, build tool like make/ninja, libraries and headers, other processors and tools like doxygen, sphinx, static analysis etc.
What makes the "build system generator" so unique in its requirements that this one tool must be embedded in the source package?
Nothing.
It's a convention adopted by the GNU Autotools initially for pragmatic reasons--the requirement that the end user install m4, perl, and a few other tools, and that in the early days the breakage between autoconf and automake minor versions was routine and really annoying. Today you can just run "autoreconf -fvi" for the same effect, and many packages have stopped distributing the generated scripts. Many distributions regenerate them as a matter of course, making the distributed copies redundant. Today, when we have fully-described and automatic installation of build-dependencies on most platforms, the need for embedding no longer exists.
I'm afraid that I don't buy your argument. Don't mistake historical conventions established for a single tool with a hard requirement. The requirement doesn't actually exist.