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

Oh no, not PREFIX again!

Thread Next
From:
Michael G Schwern
Date:
November 26, 2002 02:12
Subject:
Oh no, not PREFIX again!
Message ID:
20021126061406.GA518@ool-18b93024.dyn.optonline.net
I've been receiving bug reports that 5.8.0's MakeMaker broke this style:

     perl Makefile.PL PREFIX=foo
     make test
     make install PREFIX=bar

ie. configure and build the module in one prefix, but actually install it in
another.  This is commonly used for packaging like dpkgs and RPMs.

     perl Makefile.PL PREFIX=/where/it/will/ultimately/be/installed
     make test
     make install PREFIX=/directory/where/im/building/the/package

It broke because the make variables no longer retain the $(PREFIX). So
5.6.1's MakeMaker you might have:

    PREFIX=foo
    INSTALLPRIVLIB = $(PREFIX)/lib/perl/5.6.1
    INSTALLSITELIB = $(PREFIX)/lib/perl/5.6.1

which means "make install PREFIX=something/else" will still work.  5.8.0's
MakeMaker fully expanded the directories:

    PREFIX=foo
    INSTALLPRIVLIB = foo/lib/perl/5.6.1
    INSTALLSITELIB = foo/lib/perl/5.6.1

It made a lot of the internals easier and it wasn't realized that "make
install PREFIX=something/else" was important.


The simple fix might be to just put $(PREFIX) back into the INSTALL*
variables.  But it gets complicated because there are really *four*
prefixes, not one.  5.8.0's MakeMaker tries to honor all of them properly
and it makes things complicated.

Here's a quick tour of the prefixes:

Core libraries: 
Stuff that comes with the core or CPAN distributions of core modules.
Anything with INSTALLDIRS => 'perl' in the Makefile.PL.  If you download
Test::Harness from CPAN it goes in here.  This is PREFIX inside MakeMaker
and $Config{prefix} in Config.  Hereafter I'll refer to it as PERLPREFIX to
disambiguate it from the user prefix.

CPAN ('site') libraries: 
The default prefix for MakeMaker, so most anything you install from CPAN
will go here.  SITEPREFIX in the Makefile and $Config{siteprefix}.

Vendor libraries:
Anything installed from your "vendor".  For example, Redhat, Debian,
Solaris, Apple, etc...  If you install the libcgi-pm-perl Debian package it
will go here.  VENDORPREFIX in the Makefile and $Config{vendorprefix}.
While the concept of vendor libraries has been in Perl for a while,
MakeMaker was only recently adapted to support it.  Some vendors have had
their own patched versions for a while (Debian is one).

User specified prefix:
This is the prefix specified by "perl Makefile.PL PREFIX=~" or "make install
PREFIX=~".  If set will override all the other prefixes.  It is currently
represented in the Makefile by PREFIX which confuses things.


The problem:  What happens when your core prefix and your site prefix are
different?  [1]

Consider the following.  Let's say you run "perl Makefile.PL".
Your $Config{prefix} is /usr and $Config{siteprefix} is /opt.  So the
Makefile might have:

    PREFIX =   	    	# no user prefix given
    PERLPREFIX = /usr
    SITEPREFIX = /opt

and your INSTALL* variables should look something like this:

    # where core libraries will go.
    INSTALLPRIVLIB = $(PERLPREFIX)/lib/perl/5.8.0
    
    # where site libraries will go.
    INSTALLSITELIB = $(SITEPREFIX)/lib/perl/5.8.0

and you run "make install" and everything goes in the right place.  That
works fine.  But that's the easy part.

What if you had said "make install PREFIX=somewhere/else".  The INSTALL*
variables aren't using $(PREFIX) so it won't work.

What about "make install SITEPREFIX=somewhere/else".  That will change where
CPAN modules go, but what if you were installing Test::Harness?  You have to
change the PERLPREFIX, too.  And that's no good.  Users shouldn't have to
know if what they're installing is a core or site module.


Somehow the SITEPREFIX and PERLPREFIX have to be PREFIX if and only if
PREFIX was set.  Using an imaginary Perl/make fusion syntax I might say:

    SITEPREFIX = $(PREFIX) ? $(PREFIX) : /opt
    PERLPREFIX = $(PREFIX) ? $(PREFIX) : /usr

And then all these combinations work:

       perl Makefile.PL	  # PREFIX not set, SITE/PERLPREFIX use defaults
       make install	  # ditto

       perl Makefile.PL PREFIX=~ # PREFIX set, SITE/PERLPREIFX use PREFIX
       make install	      	 # ditto

       perl Makefile.PL       # PREFIX not set, SITE/PERLPREFIX use defaults
       make install PREFIX=~  # PREFIX set, SITE/PERLPREFIX use PREFIX

       perl Makefile.PL PREFIX=~ # PREFIX set, SITE/PERLPREFIX use PREFIX
       make install PREFIX=foo   # PREFIX reset, SITE/PERLPREFIX use new PREFIX

and this even works:

       perl Makefile.PL PREFIX=~   # PREFIX set, SITE/PERLREFIX use PREFIX
       make install SITEPREFIX=foo # PREFIX set, SITEPREFIX set.  
       	    	    		   # PERLPREFIX uses PREFIX.  SITEPREFIX
				   # overriden by command line arg.

unfortunately, there's no portable way to do if/else logic in make that I
know of. [2]  So I proposed the problem to the Portland Perl Mongers and 'lo
and behold they had a solution:

       PERLPREFIX = $(PERLRUN) -e 'q{$(PREFIX)} ? q{$$(PREFIX)} : "/usr"'
       SITEPREFIX = $(PERLRUN) -e 'q{$(PREFIX)} ? q($$(PREFIX)} : "/opt"'

I think that'll work.  Thoughts?


[1] I'm ignoring the vendor prefix just to make things simpler.

[2] Potential challengers: remember we're covering Gnu make, Perl make, Sun
make, Borland make, nmake, dmake, mmk/mms (ie. VMS Module Management System)
and MPW's build tool (ie. MacOS Classic).


-- 

Michael G. Schwern   <schwern@pobox.com>    http://www.pobox.com/~schwern/
Perl Quality Assurance      <perl-qa@perl.org>         Kwalitee Is Job One
How can you get very far,
If you don't know Who You Are?
How can you do what you ought,
If you don't know What You've Got?

Thread Next


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