Subject: Re: [RFC PATCH v4 00/19] Modernize the build system

From: Patrick Steinhardt <[email-masked]>
Date: Mon, 4 Nov 2024 13:17:00 +0100

On Fri, Oct 25, 2024 at 03:59:30PM -0400, Taylor Blau wrote:
> On Thu, Oct 24, 2024 at 02:39:43PM +0200, Patrick Steinhardt wrote:
> > Hi,
> >
> > this is the fourth version of my patch series that modernizes our build
> > system. It refactors various parts of it to make it possible to perform
> > out-of-tree builds in theory and then wires up Meson.
> 
> I was thinking a little bit about this topic last night and wanted to
> collect my thoughts somewhere.
> 
> I think that there are a couple of things that I'm not 100% clear or
> sold on, which are:
> 
>   - What is the eventual goal of this series? Do we plan to transition
>     the existing make-driven builds to instead be built with Meson? Will
>     we have both? Something else?
> 
>   - What is the eventual plan for CMake, which is maintained currently
>     in the contrib directory? Will it be deprecated in favor of Meson?
>     Will we continue to support it?

My goal is to end up with a single build system eventually, so yes, we'd
at one point in time drop both the Makefile and our CMake build
instructions. That would of course not happen over night, but across
multiple releases such that devs and packagers can start exercising the
new build infra before we remove it.

> Let me expand a little on each of those in turn:
> 
> == What is the eventual goal?
> 
> From reading [PATCH 17/19], it seems the main arguments in favor of
> using Meson are:
> 
>   - Ease of use: easy to use, discovering available options is easy. The
>     scripting language is straight-forward to use.
>   - IDE support: Supports generating build instructions for Xcode and Microsoft
>     Visual Studio, a plugin exists for Visual Studio Code.
>   - Out-of-tree builds: supported.
>   - Cross-platform builds: supported.
>   - Language support:
>     - C: Supported for GCC, Clang, MSVC and other toolchains.
>     - Rust: Supported for rustc.
>   - Test integration: supported. Interactive tests are supported starting with
>     Meson 1.5.0 via the `--interactive` flag.
> 
> I don't think that when reading these any of them stick out to me and
> compel me to learn a new build system. I understand and am sympathetic
> to the fact that GNU Make has odd syntax and can be cumbersome. But I
> don't think that incrementally modifying our Makefile over time is
> difficult, and it has certainly worked well over the years.

My main goal isn't necessarily to make things work better for old
timers, but _especially_ to make it easier for newcomers. You of course
can wire up many missing features with Makefiles, but that only goes so
far. What you won't get with them is good cross-platform support, deep
integration with IDEs and good discoverability.

> Certainly there is ample support for IDE integration with Make.

Not quite. While there is ample support for executing Makefile targets,
there isn't really a lot of integration for "advanced" features:

  - Auto-configuration.
  - Multiple build types.
  - Code completion.
  - Discovery of the working set of source files.

So the integration that exists for Makefiles is for most of the part
extremely shallow.

Also, I'd claim that Makefiles are really only well-integrated on Linux
or BSDs. For other systems like Windows it is extremely awkward and you
don't really have a nice developer experience there.

There are other factors as well, like auto-detection of the system. Our
Makefile only works well for specific platforms that somebody uses on a
regular basis, and wiring up a new platform requires manual code in our
"config.mak.uname" file. That's somewhat awkward and hard to maintain
going forward as every single platform requires its own bits and pieces.

The solution to that problem is autoconfiguration by detecting platform
specific bits and pieces. And we _also_ have such a build system in the
form of autoconf, but now we're entering territory that is awfully hard
to maintain. Most people don't use it at all, the only user seems to
really be distros. And they tend to hit many issues with autoconf
because we devs don't use that infra in the first place, creating a bit
of an awkward situation. Unifying this infrastructure such that devs and
packagers use the same build infra is thus another goal of my series.

> Out-of-tree builds and cross-platform builds could be supported in
> theory as you note within the existing build system. Another suggestion
> you make is that Meson has better native support for Rust, which I agree
> may be important to consider in the future.
> 
> But I don't think that any of those three (out-of-tree builds,
> cross-compilation, or Rust support) are insurmountable challenges in
> Make. Certainly there is a lot of inertia there, but I don't think
> that's a bad thing. Contributors are used to the existing build system,
> it has worked well for us, works across many platforms and has (IMO)
> stood the test of time.

We indeed can wire up all of these features. But the way things are
wired up right now is extremely fragile and very manual. I don't
disagree with your statement that we old-timers know our way around the
build system. But I certainly don't think it is easy to hack on, and
that is a problem especially if we want to set up Git for success for
the next decade. I want to ensure that the Git project is easily
accessible to people.

> I admittedly have a hard time squaring the benefits and goals we have
> with Meson with the cost of learning a new build system, and/or moving
> away from Make entirely.

I guess this depends on the exact persona you're optimizing for. There
are three main personas involved here:

  - Long-time Git contributors. I don't worry about that persona too
    much. Folks in this category tend to be highly skilled, and they
    should not have much of an issue with adapting to Meson.

  - New contributors. This is a group of people that I think would
    benefit from Meson. They get integration with their favorite IDE,
    have easy ways to discover how to tweak build instructions and can
    use standard invocations for Meson that they might already know from
    other projects.

  - Packagers. This is another group of people that would benefit from
    my point of view. This is mostly because Meson has certain standards
    for how to approach problems, and thus the packager would know for
    how to handle things. They don't have to manually track build
    options and changes thereof, as these can be easily discovered and
    because Meson will error out in case invalid options are passed.

> I am entirely open to the possibility that there is something that I am
> missing here, and that Meson really is a better choice for Git given our
> current direction. But I think if that's true, then the series needs to
> explain that more prominently.

Sure, I am happy to update the commit message.

> == What is the eventual plan for CMake?
> 
> From [PATCH 18/19], you write:
> 
> > If this patch lands the expectation is that it will coexist
> > with our other build systems for a while. Like this, distributions can
> > slowly migrate over to Meson and report any findings they have to us
> > such that we can continue to iterate. A potential cutoff date for other
> > build systems may be Git 3.0.
> 
> I don't view this is a good intermediate state, and is in my view making
> an existing problem that we have worse. On the "existing problem": I
> think that landing CMake support in contrib was a mistake. In my view,
> CMake support should have either been a first-class citizen in Git (such
> that we don't consider a change "done" until it can be built by CMake),
> or should have been maintained out-of-tree.
> 
> But I think we struck a worst-of-both-worlds balance by landing it in
> contrib. It's maintained in the tree, so people expect to be able to
> build the project with it because it comes with a bog-standard clone of
> git.git.
> 
> But despite living in the project's tree, it is not a first-class
> citizen, and subjectively it seems that we get an awful lot of mail
> asking why something doesn't build in CMake, etc. (To your credit, I
> think you have been one of the main people to help with that, often
> fixing those bugs yourself, which is greatly appreciated).
> 
> I don't want to see the project have to pseudo-maintain three build
> systems. It seems like doing so would be cumbersome, and error-prone. I
> am already probably guilty of breaking CMake builds when I add a new
> compilation unit to the project, because of a combination of my lack of
> familiarity with CMake, and the fact that we don't have a project-wide
> convention of treating it with the same care as we do the Makefile. I
> think that having three build systems (even if they only co-existed
> until Git 3.0) would make that problem worse.
> 
> I feel that if we are going to pursue Meson over CMake and/or Make, we
> should have a clear plan to either get rid of CMake, keep it up-to-date,
> or something else.

I fully agree with all you're saying here. Whatever the solution, the
new build system should be a proper first-class citizen and should be
exercised by our CI systems such that they don't silently break.

I also agree that it's going to be a hassle to maintain three (or three
and a half if you count autoconf) build systems. But I don't want to
break any users out there by dropping everything but Meson immediately,
so I think we just have to accept multiple build systems as an
intermediate step. How exactly that would look like is certainly up for
debate. My take would be:

  1. Adopt the new build system and start exercising it via CI.

  2. Drop CMake.

  3. Drop autoconf.

  4. Drop Makefiles.

This should happen over multiple releases such that every step will pull
in additional user groups, which will make the new build system more
solid overall. I could see that one step corresponds to one release
cycle, but I'm also happy to adapt the pacing as necessary.

Patrick