Some thoughts after an informal Module::Build brainstorming

Alias on 2006-03-03T07:52:36

Ken Williams came chasing after me to get more information about a Module::Build/YAML bug I reported that was creating problem getting Bundle::CPAN compatible with Vanilla Perl (but more on Vanilla Perl in a week or so)

It turned into a sort of 3 way brainstorming between Ken, Matt Trout and myself on how Module::Build worked now, and might be improved.

So at least now I finally got the chance to bitch about Module::Build in person to Ken rather than just lobbing grenades at evangelists in mailing lists. :)

And as seems to be the case for most situations like this, a conversation with the main author of a system was far more productive than talking to users of the system that evangelise it.

It helped to confirm for me that my main technical issue with Module::Build is valid, in that Module::Build does not provide a clean install/upgrade mechanism for end users.

In talking Ken seems quite keen to deal with this, and we talked about how it might be fixed. But for the sake for having a link to refer others to later I thought I should journal what I'd call the three main Installer Patterns.

Anyone planning on implementing a from-source installation system of any type is going to have to implement one of the following.

Installer Pattern 1 - Frozen Installer

This is generally the weakest of the three.

It involves writing an installation system, and never changing the API (even to add features).

This is kind of the current situation with ExtUtils::MakeMaker. It pretty much never changes in any significant way, and so any ExtUtils::MakeMaker Makefile.PL should work with a hell of a lot of old versions.

But this has a ton of problems. Introducing features causes damage (because the installer itself might require a newer installer-support library to be written) and so once locked in there's no room for improvement.

Which pretty much describes ExtUtils::MakeMaker.

Installer Pattern 2 - Bundled Installer

This is the approach taken by the Windows .exe installers, and to a lesser extent Module::Install (which is a hybrid Bundled/Frozen Installer, wrapping bundled code around ExtUtils::MakeMaker)

It works best when you don't really trust the target environment to be consistent. Hence the popularity on Windows and in Perl :)

It also makes it very easy to add new extensions, as the extra code only needs to be added by the author, and nothing is needed on the user's side. And as long as the code works everywhere, everything is great.

On the downside, it can bloat out your package (in the case of M:I the extra 20K is really negligable though). But more importantly, if there is a major bug in your installer you need to do an incremental release of every package created. And so you need to be relatively careful that the features available work reliably for all end-users.

But because the installer makes almost no demands on the user's intelligence (remember, popular on Windows), it works in the most environments for the most users. And if you measure the success of an installer by, well, how many places it installs, then you can see how attractive this pattern is.

The other big downside to the Bundled Installer is that you need strong control over the authors. For CPAN we actually do, there are only around 3500 of them, and we control the upload point PAUSE.

Installer Pattern 3 - Upgrading Installer

When you don't control the authors as much, and don't want to bundle, how do you have a standard installer.

The dominant way for handling this situation is to allow the installer to auto-upgrade. Indeed, to maintain your sanity and not cause maintenance prolems you have to FORCE the installer to upgrade.

So if you use Windows Update, or Redhat Network, or the Steam Installer, every now and then when it starts up it will do the "Please wait while Installer 2.0 installs Installer 2.1..."

So where to with Module::Build

Until Module::Build implements one or both of these patterns, it is going to continue to suffer. And until it implements one or more of these patterns I certainly think it doesn't belong in the core. It won't have the unique stability and adaptability requirements required from an installer.

Of course, the third option would be the best, but is also going to require the co-operation of both CPAN.pm and CPANPLUS to somehow support version checking and auto-upgrading of the core installer components.

And Ken also wants elements of bundling involved, for some of the same reasons we use them in Module::Install, to do things like bundle small testing modules and reduce the number of dependency installer iterations.

Now, I doubt any of this will be available in 0.28, but my hope is that some time after 0.28, we see some capability for bundling, following by some level of integration with CPAN.pm and CPANPLUS to allow auto-upgrading of the core components.

Now flame away :)


historical development

mr_bean on 2006-03-04T14:25:18

Looking at the MOTIVATION section of
Module::Build's man page, I don't think you see
any of the concerns of the problem of
installation as outlined here. It was a more
limited fixing of the problem of make and EU::MM.

When did the issue of the problems of software
users as distinct from software developers start
to arise? After the availability of CPAN.pm and
so on made it even easier than it had been to
install modules?

When did the problem arise?

Alias on 2006-03-05T17:52:54

Well, the problems have been there the whole time.

The reason it hasn't come up sooner is that installer deficiencies of this nature are creeping problems.

They build up gradually, and only start to impact strongly as the number of MB packages increases, and as the number of production versions of MB increases.

As long as few people are using it, and it isn't changing quickly, you have a Pattern 1 situation. The installers don't break if the installer infrastructure is static.

Add to that that most 9 out of 10, or more, users won't take the social risk of complaining in an open forum, and it takes even longer for things to come to light.

Look at the Apache2:: problem, which was a serious problem but didn't really come to a head until they release the first mod_perl2 release candidate and the number of higher level people installing it shot up.

The same sort of situation applies here. When I (for example) start to hear talk of it going core, and some of my private concerns that seem obvious still haven't been fixed, I start asking more questions.

The problems been there, it just wasn't as much attention paid to it, possibly on the assumption that it was obvious and would be fixed before it went core.

Not really talking about installers

dagolden on 2006-03-12T15:07:33

I think this taxonomy is lacking because it confuses several different tasks:

  • Package management -- managing available/installed software and retrieving software to be installed from a repository
  • Installation -- putting pieces of code/library into OS/user-specific locations for later use
  • Configuration management -- telling installers how to do their jobs
  • Distribution creation -- creating bundles of code, configuration, and -- in some cases -- an installer
  • Authoring tools -- helping authors with non-distribution related tasks, though ones which may be related to distribution (e.g. MANIFEST checks, test coverage checks, etc.)

The problem is that there tends to be tight coupling between many of these, but we have decentralized and largely uncoordinated tools and different toolchain combinations are needed to handle these tasks. Roughly in order of number of components:

  1. CPAN, Module::Build (2)
  2. CPAN, ExtUtils::MakeMaker, make (3)
  3. CPAN, Module::Install, Module::Build (3)
  4. CPANPLUS, CPANPLUS::Dist::Build, Module::Build (3)
  5. CPAN, Module::Install, ExtUtils::MakeMaker, make (4)
  6. CPANPLUS, CPANPLUS::Dist::MM, ExtUtils::MakeMaker, make (4)
  7. CPANPLUS, CPANPLUS::Dist::Build, Module::Install, Module::Build (4)
  8. CPANPLUS, CPANPLUS::Dist::MM, Module::Install, ExtUtils::MakeMaker, make (5)

Have I missed any? (I'm not even addressing Module::Build being used to generate a Makefile.PL, as that's Module::Build being used as an Authoring Tool to support #2 and #5 above. I'm also ignoring the complications that XS create.)

I may also have missed some Module::Install variations, as I'm not entirely sure where it ends and the other components begin from a task perspective.

I broke out the CPANPLUS::Dist::* ones separately, as *::Build is now a separate distribution -- in part to allow faster upgrades to the coupling between components.

So there's anywhere from 2 to 5 different components, each of which are maintained separately and have separate release cycles. Is there any wonder this breaks?

I like the Module::Install approach of bundling itself with the distribution because it helps a distribution to try to be good to users who have old versions of the other components. But it still sits on top of the rest of a cruddy toolchain, so it doesn't really address the core problem.

Things I think might help the situation:

  1. I think refactoring the whole process around the individual tasks would help. I think CPANPLUS had the good idea of breaking up front-end administration from back-end distribution-specific plugins. CPAN should do the same.

  2. CPAN and CPANPLUS should aggressively try to auto-upgrade themselves if they can, and they need to be seamless doing so (no lengthy configuration steps).

  3. I'd like to see a CPAN.PL file that tells CPAN what installation plug-in to use. CPAN should then aggressively try to upgrade that plug-in or use one bundled with the distribution.

  4. Potentially, distributions would use the Module::Install technique to bundle CPAN and appropriate plugins to upgrade CPAN if that was out of date. Yes that's even more bloat, but space is cheap these days and CPAN 1.87 is only 242K. I'd rather see bigger but more robust distributions over smaller ones that break under older versions of the toolchain.

That's my ramble for a Sunday morning. I think there's a lot more thinking that could be done about refactoring the whole process, but the big challenge will be getting the entire toolchain upgraded across current/legacy Perl's with and without network access. There, the Module::Install approach of bundling seems to have some interesting potential -- if anything, perhaps it doesn't go far enough!