develooper Front page | perl.makemaker | Postings from February 2002

The provisional ExtUtils::MakeMaker class hierarchy

From:
Michael G Schwern
Date:
February 4, 2002 01:41
Subject:
The provisional ExtUtils::MakeMaker class hierarchy
Message ID:
20020204094116.GC1093@blackrider
5.49_01 simplified MakeMaker's class hierarchy somewhat.  Lemme
'splain.

Before going on, I'd suggest a skim of the "Why Does ExtUtils::MM_Unix
have VMS code in it?" explaination to get an idea of the state of the
hierarchy before 5.49_01 and the problems being solved.
http://archive.develooper.com/makemaker@perl.org/msg00099.html


Prior to 5.49_01 it basically went like this (subclasses on top).

                        MY (created by ExtUtils::MakeMaker)
                        |
                        MM (created by ExtUtils::MakeMaker)
                        |
[ExtUtils::MM_NonUnix (chosen by EU::MakeMaker, added by MM_NonUnix)
 ExtUtils::MM_Unix 
 ExtUtils::Liblist::Kid (which is inside ExtUtils::Liblist)
 ExtUtils::MakeMaker]

(the stuff in the [] represents multiple inheritence)

Each of the ExtUtils::MM_NonUnix (ie. MM_Cygwin, MM_Win32, etc...) 
have no direct parent.  They are only usable via MM and assume that MM
will have ExtUtils::MM_Unix as a superclass after them.  So its *as
if* each MM_NonUnix inherited from MM_Unix.

Basically, ExtUtils::MakeMaker declares MM and figures out which
MM_NonUnix module to require.  Then the MM_NonUnix makes
itself a subclass of MM.

As if that isn't bad enough, inside MM_Win32 is an MM_Win95 class.
Its placed onto the MM hiearchy after MM_Win32 if you're using Win95.

Confused?  Good, you should be.


Here's what it looks like now (this is somewhat simplified)

                    MY (created by ExtUtils::MY)
                    |
                    MM (created by ExtUtils::MM)
                    |
[ExtUtils::MM_NonUnix  ExtUtils::Liblist::Kid  ExtUtils::MakeMaker]
            |
 ExtUtils::MM_Unix

MY and MM have been moved out of ExtUtils::MakeMaker and moved into
their own .pm files (this maybe a temporary solution, dunno).  This
makes them more accessable and less prone to be overly chummy with the
rest of MakeMaker.

Along with that goes all the "Which MM_NonUnix should I use"
logic.  That's all in MM now.

Finally, the MM_NonUnix modules are now explicitly subclasses of
MM_Unix (again, a simplicification, see below).  This removes a lot of
the complexity from the hiearchy and makes it easier to apply some
normal OO techniques (see MM_NW5 below).


So the MM_OS hierarchy now looks like this:

                                        MM_Win95   MM_NW5
                                              \      /
MM_BeOS     MM_Cygwin   MM_OS2    MM_VMS      MM_Win32
      \             |      |         |        /
       ---------------------------------------
                           |
                        MM_Unix

So essentially, everything inherits from MM_Unix except for the
Windows set.  The Netware and Win95 modules are both MM_Win32
subclasses, which is as it should be.

An interesting thing fell out of this.  For some reason I diffed
MM_Win32 against MM_NW5 and noticed large chunks were exactly the
same.  So I ran it in tkdiff to get a better look and found that over
TWO THIRDS of it was exactly the same as MM_Win32 (mod a few bug fixes
in MM_Win32 that never made it into MM_NW5).

So MM_NW5 just went on a big diet.  From 29 methods and an embedded
class (a copy of MM_Win95) to 4 methods.  1000+ lines down to about
350+.  The magic of subclassing.


Finally there's ExtUtils::Liblist::Kid.  What the hell is that doing
in there?  ExtUtils::Liblist::Kid is really just the guts of
ExtUtils::Liblist with a somewhat overly clever wrapper to avoid
loading it until absolutely necessary.  There's also lots and lots of
life-support code everywhere its used to avoid loading it.  Defering
from loading a method is sort of difficult when you inherit from it.

ExtUtils::Liblist consists of one, and only one, "function", ext() and
its only used in a handful of places.  This function takes an MM
object as its first argument, so its really a method.  To make things
more interesting, Liblist::Kid has Unix, Win32 and VMS specific
versions of ext() and its own logic to figure out which one to use.
And they're huge.

I'm not really sure what to do with Liblist, but I do know one thing.
Next version its going out of the MM hierarchy.


So this is only an intermediate stage.  What I'd eventually like the
hiearchy to look like is:

                        MY
                        |
                        MM
                        |
               ExtUtils::MM_OS_Specific
                        |
                ExtUtils::MM_Any

(astute readers might realize this is what Module::Build already looks
like).

I don't quite yet know what MM_Any is going to look like.  Here's a
sketch of the immediate future:

    Fix MakeMaker on Win32 and VMS

    Tear Liblist out of the hierarchy

    Get the Win32 and VMS specific code out of MM_Unix

    Examine the relationship between ExtUtils::MakeMaker and
    ExtUtils::MM_Unix and see if I can find some sort of sensible
    dividing line.

    Pull as much non-OS specific code out of MM_Unix and MakeMaker
    and put it into MM_Any.

    Break things up into 'make independent code' and 'make dependent
    code'.  This makes it much easier to deal with various
    flavors of make (and things that aren't make at all).

    Restructure MM_Unix/Any/MakeMaker so MM_NonUnix subclasses
    don't have to repeat so much code.

    Hand off to someone that actually knows make, XS and C.


-- 

Michael G. Schwern   <schwern@pobox.com>    http://www.pobox.com/~schwern/
Perl Quality Assurance	    <perl-qa@perl.org>	       Kwalitee Is Job One
I'll tell you what beats voodoo every time, a big ass knife.
	-- "Overkill" Battlebot driver



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About