
Allowing CMake functions to return(value) - ingve
https://oleksandrkvl.github.io/2020/08/09/allowing-cmake-functions-to-return-value.html
======
MaxBarraclough
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)

~~~
klodolph
> 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
Bazel 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
While 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.

~~~
mehrdadn
Note I was explicitly talking about spaces in the current directory (which is
only dependent on _where_ the user clones the repo), not spaces in the
workspace (which depends on what's in the repo). Your examples are about the
latter. The latter isn't as big of a deal because the repo owner at least has
control over the contents and can avoid putting spaces in file names (and use
relative paths everywhere). But they can't control where the user clones their
repo.

~~~
klodolph
Ah, that makes sense. Maybe I've just suffered abuse from projects that can't
be built anywhere for so long that it seems normal--I remember a particular
team I worked on where the project needed to be spread across the X:, Y:, and
Z: drives with bind mounts.

------
rumanator
> Most part of my career I used Visual Studio and when switched to Linux I was
> slightly shocked. Compared to MSVS, makefiles felt like bows and arrows
> against machine gun.

I honesty have no idea how some people come up with these absurd comparisons.
I mean, who in their right mind feel is appropriate to compare a Makefile with
a build system? And how clueless about things are "in the Linux world" do you
need to be to claim that Makefiles are how people build software in Linux?

I mean, I've been using Linux for a couple of decades now and I can't remember
the last time I saw a project that relied on Makefiles to build. At best
projects use some kind of Makefile generator. The ancient ones use autotools
and even those are going the way of the dodo.

> CMake allows us to handle almost all those things right except one - it
> doesn’t have return values

This is a red flag. If you're hoping to write functions with cmake... You're
doing it wrong. Very wrong. You add targets, and you add rules to the target.
If you find yourself wanting to do anything other than this then you should
take a step back and read a modern cmake tutorial again, because odds are
you're doing it wrong.

~~~
kazinator
> _I can 't remember the last time I saw a project that relied on Makefiles to
> build_

I don't know what GNU/Linux you're using, because in my experience, most
packages going into a distro use make.

Oh, and then there is that whole denominator in the GNU/Linux fraction that's
built with GNU Make.

Maybe you don't see Makefiles because you're relying on binary packages?

~~~
jcelerier
> I don't know what GNU/Linux you're using, because in my experience, most
> packages going into a distro use make.

no, they use autotools or cmake, which happens to generate makefiles. the
package authors themselves definitely don't write any makefiles by hand except
maybe for trivial packages (and frankly I'm not sure)

~~~
kazinator
Autotools generate a Makefile project, and nothing but a Makefile project. All
the buiding in the development cycle is done by typing "make". Autotools
projects include a template makefile: Makefile.am. Make is not concealed in
any way.

Also note that not all Autotools-based projects use Automake. Using only
Autoconf, with a hand-maintained Makefile, is a thing.

The goal of Autotools is to produce a software distribution that doesn't
require the end user to have Autotools. The end user has a shell to run the
configure script, and that's it. If that works, they run "make".

About the most sophisticated generation the user will see is that some
Makefile.in template is passed through sed to substitute @@XYZ@@ variables.

~~~
de_watcher
Make is like an assembly language of the build systems. This layer gives
structure and debuggability (otherwise you're spending time poking at some
opaque UI or something).

------
fluffy87
The claim that CMake is the least worst C++ build system that we have is pure
BS.

In my last 3 professional C++ projects I’ve actually used Rust’s cargo tool as
my build tool for C++ code. Infinitely better than CMake, plus you use Rust as
your scripting language for your build system, which has great libraries for
it like the cc crate, and pretty much a crate for whatever it is you want to
build (eg ispc? no problem).

~~~
Firecracker
Fluffy, could I ask you to give a few more details about how you set this up?
Sounds interesting!

------
lalaland1125
I personally find it surprising that so many people are still stuck on old,
outdated build systems like CMake. Modern alternatives like Bazel
([https://bazel.build/](https://bazel.build/)) are light years ahead.

~~~
hoseja
Right now, CMake is being actively integrated into QtCreator and Visual Studio
where they previously had their own bespoke defaults. It might be shit but
it's also becoming more and more "standard" as one DSL you need for cross-
platform builds, instead of fifteen xkcd-927 style.

------
saghm
> CMake allows us to handle almost all those things right except one - it
> doesn’t have return values

One of my former bosses once quipped "CMake is confusing until you realize
it's just a shitty version of BASIC that only has global variables"

~~~
wyldfire
Is there a dialect of BASIC that has scoping/namespaces or even locals?

~~~
AlphaSite
Visual Basic was ok from what I remember.

~~~
s_gourichon
Technically yes, also VB.net . Reminds me that old joke that any language can
run on .Net runtime (a.k.a. CLR) as long as that language is C#. Somehow
VB.net is kind of C# with VB syntax and some corners cut that they could not
fit.

------
amedvednikov
So glad that new languages don't need build systems.

go build .

~~~
rfoo
I'm sure you can find people ranting about how their "xxx_windows.go" files
got silently ignored by go build. Just like every part of Go, everything ugly
is hidden and "just works" until it can't, and major WTF moments strikes after
that.

------
bob1029
I've given up on these sorts of build systems. If I ever had to screw with a
C/C++ codebase again, I would just write my entire toolchain in C#. I know for
a fact that modern C# 8.0+ will not bite me in the ass with inconsistent
ideologies. I also have extreme confidence that I could add in complex build
concerns such as communication with other systems for obtaining dependencies
or logging important information.

