It was time again to update CMake on FreeBSD. That’s always a guarantee for a good time, since there are about 2500 FreeBSD ports (software packages) that use CMake directly as their (meta-) build system. An update is a special moment to try to break them.

[13amd64-area51] [2023-03-20_22h10m35s] [parallel_build:] Queued: 1969 Built: 1359 Failed: 9    Skipped: 6    Ignored: 19   Tobuild: 576   Time: 14:47:58

It’s also a good time to keep my CPU warm, since building all those ports locally takes a while. I choose to do this as part of the update so that I don’t end up with a lengthy remote cycle: submit a proposed update to CMake, then wait for the FreeBSD build cluster to grind through it .. and then remember to check back on the results the next day. Having a build log in a konsole on my screen is more in-my-face.

Not all of the build failures (there are 9 mentioned, above) come from the CMake update itself. Some are existing problems with ports sources, or known issues when running additional checks (like I do) on ports.

Stuff I’ve fixed or updated in this update:

  • CMake itself, obviously
  • openkim-models (there’s some weirdness with CMAKE_SIZEOF_VOID_P)
  • libnatpmp (not CMake-related, packaging list)
  • readstat (not CMake-related, modern C style)

No-Language projects

There’s a handful of projects that do not declare a language; this is something you can do in CMake’s project() command, like so:

project(MyThing LANGUAGES CXX)

By default, C and C++ are enabled. If you list something specific, only that is enabled. And you can list NONE to get .. no languages enabled. Sometimes useful if you have to decide later what languages to support, or there’s another project() command in a subdirectory.

However, if there’s no language selected, then CMake doesn’t bother figuring out what the size of a pointer is (sizeof(void *), that is) which is normally 4 (bytes, on a 32-bit machine) or 8 (on a 64-bit machine). It’s not particularly interesting information except that there is an increasing number of libraries that keeps track of what they were compiled for (32- or 64-bit).

What happens – what happened in openkim-models – is that:

  • no language is specified, so CMAKE_SIZEOF_VOID_P is not set,
  • find_package() is called to find a dependency,
  • that dependency wants to match the installed versions of the library with the requested bit-size,
  • there is no bit-size set, and find fails.

It’s now a bit of a standard-thing-to-do when patching up CMake-time failures of arbitrary software that I don’t care about: check if there’s a language specified and if not, bung in C.

Deprecated C constructs

I spend 95% of my programming time writing C++ code, usually C++17 or later. The rest is Python. So I read a function declaration like int my_function() as “returns an int, takes no parameters”.

Turns out the C language (a different language from C++, but superficially similar) has a subtle difference between

int my_function(); /* a declaration */

and

int my_function(void); /* a prototype */

The latter explicitly says “no parameters”, the former doesn’t say anything about allowable parameters and is apparently – according to the Clang-16 error messages I was dealing with – deprecated in C:

In file included from src/readstat_bits.c:9:
  src/readstat_bits.h:10:29: error: a function declaration without
  a prototype is deprecated in all versions of C
  [-Werror,-Wstrict-prototypes]
int machine_is_little_endian();

I ended up patching readstat multiple times to catch all the cases where there isn’t a prototype. And then I submitted the patches upstream.

Takeaway

All-in-all this was a fairly “lightweight” CMake update, but it still – and every release does this – shakes out some weird-ass code that exists on the internet. And that’s fine by me, it keeps my CPU warm.