Thread: [Module-build-general] A better passthrough Makefile.PL
Status: Beta
Brought to you by:
kwilliams
From: Dave R. <au...@ur...> - 2002-10-03 23:54:22
|
I wanted to create a Makefile.PL that would pass all functionality through to Module::Build, _and_ that would make sure that Module::Build got installed if necessary. I also wanted to make sure that the user did not have to run "perl Makefile.PL" twice, once for installing Module::Build, and once to install the desired module. Having to do this basically makes the install fail with CPAN or CPANPLUS. Here's what I came up with: use Cwd; use File::Spec; unless (eval { require Module::Build::Compat; 1 }) { require ExtUtils::MakeMaker; print "This module required Module::Build to install itself.\n"; my $yn = ExtUtils::MakeMaker::prompt( ' Install Module::Build', 'y' ); if ($yn =~ /^y(es)?/i) { # save this cause CPAN will chdir all over the place. my $cwd = cwd(); my $makefile = File::Spec->rel2abs($0); require CPAN; CPAN->install('Module::Build'); chdir $cwd or die "Cannot chdir to $cwd: $!"; exec( $^X, $makefile, @ARGV ) } else { warn "Cannot install Thesaurus without Module::Build. Exiting ...\n"; exit 0; } } require Module::Build::Compat; Module::Build::Compat->run_build_pl( args => \@args ); Module::Build::Compat->write_makefile; |
From: Autrijus T. <aut...@au...> - 2002-10-12 18:06:13
|
On Thu, Oct 03, 2002 at 06:54:15PM -0500, Dave Rolsky wrote: > unless (eval { require Module::Build::Compat; 1 }) { This may very well pass whilst the M::B requirement (0.11) exceeds the user's own version (0.10), a situation that occured to me today. Maybe should test for the minimal M::B version here? > my $yn = ExtUtils::MakeMaker::prompt( ' Install Module::Build', 'y' ); > if ($yn =~ /^y(es)?/i) { > # save this cause CPAN will chdir all over the place. > my $cwd = cwd(); > my $makefile = File::Spec->rel2abs($0); > require CPAN; > CPAN->install('Module::Build'); This is largely a skeletal rework of ExtUtils::AutoInstall functionalities. Are you interested with the idea that I work a M::B compatibility layer into EU::AI, and for the bootstrap code to include the EU::AI bootstrap code that, in addition to fetch M::B automatically, also installs the prereqs at 'Build' time? Thanks, /Autrijus/ |
From: Dave R. <au...@ur...> - 2002-10-12 18:23:48
|
On Sun, 13 Oct 2002, Autrijus Tang wrote: > > unless (eval { require Module::Build::Compat; 1 }) { > > This may very well pass whilst the M::B requirement (0.11) exceeds > the user's own version (0.10), a situation that occured to me today. > > Maybe should test for the minimal M::B version here? Yep, good thinking. That should probably test for 0.11 at least. Something like: unless (eval { require Module::Build::Compat; Module::Build->VERSION(0.11) ? 1 : 0 }) or something like that. > > my $yn = ExtUtils::MakeMaker::prompt( ' Install Module::Build', 'y' ); > > if ($yn =~ /^y(es)?/i) { > > # save this cause CPAN will chdir all over the place. > > my $cwd = cwd(); > > my $makefile = File::Spec->rel2abs($0); > > require CPAN; > > CPAN->install('Module::Build'); > > This is largely a skeletal rework of ExtUtils::AutoInstall > functionalities. Are you interested with the idea that I work > a M::B compatibility layer into EU::AI, and for the bootstrap > code to include the EU::AI bootstrap code that, in addition > to fetch M::B automatically, also installs the prereqs > at 'Build' time? Actually, what I was thinking of was putting chunks (all?) of EU::AI into Module::Build somehow. Given that M::B will (I really hope) end up in the core for 5.10, I think this makes the most sense. My goal re: M::B is to help it become a much easier to use, more featureful replacement for EU::MakeMaker. In addition, I think it works really well as a generic _application_ installer. For example, the example web site for the MasonBook is distributed with a Build.PL that besides just installing a couple modules, also does the following: 1. Asks the user where to install the Mason components. 2. Asks about how to connect to the RDBMS to be used for the site. 3. When 'Build install' is run, it installs the Mason components _and_ sets up the database (with Alzabo's help), including inserting some default data (like categories and an admin user). -dave /*================== www.urth.org we await the New Sun ==================*/ |
From: Ken W. <ke...@ma...> - 2002-11-01 05:11:45
|
On Saturday, October 12, 2002, at 01:23 PM, Dave Rolsky wrote: > On Sun, 13 Oct 2002, Autrijus Tang wrote: > >>> unless (eval { require Module::Build::Compat; 1 }) { >> >> This may very well pass whilst the M::B requirement (0.11) exceeds >> the user's own version (0.10), a situation that occured to me today. >> >> Maybe should test for the minimal M::B version here? > > Yep, good thinking. That should probably test for 0.11 at least. > Something like: > > unless (eval { require Module::Build::Compat; > Module::Build->VERSION(0.11) ? 1 : 0 }) > > or something like that. I think what I'll do is bump the M::B::Compat version to 0.02, and document it as: unless (eval "use Module::Build::Compat 0.02; 1" ) { I was trying to avoid eval-expr, but c'est la vie. > >>> my $yn = ExtUtils::MakeMaker::prompt( ' Install >>> Module::Build', 'y' ); >>> if ($yn =~ /^y(es)?/i) { >>> # save this cause CPAN will chdir all over the place. >>> my $cwd = cwd(); >>> my $makefile = File::Spec->rel2abs($0); >>> require CPAN; >>> CPAN->install('Module::Build'); >> >> This is largely a skeletal rework of ExtUtils::AutoInstall >> functionalities. Are you interested with the idea that I work >> a M::B compatibility layer into EU::AI, and for the bootstrap >> code to include the EU::AI bootstrap code that, in addition >> to fetch M::B automatically, also installs the prereqs >> at 'Build' time? > > Actually, what I was thinking of was putting chunks (all?) of EU::AI > into > Module::Build somehow. Given that M::B will (I really hope) end up in > the > core for 5.10, I think this makes the most sense. My goal re: M::B is > to > help it become a much easier to use, more featureful replacement for > EU::MakeMaker. I've been ruminating on this, and I think what I want to do is put hooks into M::B that will use EU::AI if it's installed (and if the user wants auto-installation), but that EU::AI should remain the way to automatically install modules. M::B should use EU::AI, not Borg its code. Obviously this is better from a separation-of-labor & modularity point of view, and I think it feels better from a policy point of view too. EU::AI can be a recommended dependency for M::B then. > In addition, I think it works really well as a generic _application_ > installer. For example, the example web site for the MasonBook is > distributed with a Build.PL that besides just installing a couple > modules, > also does the following: > > 1. Asks the user where to install the Mason components. > 2. Asks about how to connect to the RDBMS to be used for the site. > 3. When 'Build install' is run, it installs the Mason components _and_ > sets up the database (with Alzabo's help), including inserting some > default data (like categories and an admin user). Yeah, it's nice if M::B can be used for stuff like this. One of the main things that needs to be figured out for M::B is how to determine other kinds of dependencies that aren't Perl module dependencies. This is probably pretty important for generic application installation. It's also a good way to make installation more intuitive (here's *why* the build failed). Unfortunately I don't have a great answer to this problem. Autrijus, weren't you working on something like this a while back, or am I remembering wrong? A very related problem is the idea of alternative dependencies - for instance, Crypt::SKey needs either Digest::MD4 or Digest::MD5, but there's no great way to indicate that with M::B's dependency specification right now. -Ken |
From: David W. <da...@wh...> - 2002-11-01 06:29:53
|
On Thursday, October 31, 2002, at 07:17 PM, Ken Williams wrote: > This is probably pretty important for generic application > installation. It's also a good way to make installation more > intuitive (here's *why* the build failed). > > Unfortunately I don't have a great answer to this problem. Autrijus, > weren't you working on something like this a while back, or am I > remembering wrong? Actually, I think that was me. I developed App::Info to manage non-Perl dependencies, and I think that it could work very nicely with M::B. Unfortunately, I don't have much time to work on it at the moment, but it's definitely on my To Do list. App::Info is on the CPAN, for those of you who are interested. Regards, David -- David Wheeler AIM: dwTheory da...@wh... ICQ: 15726394 http://david.wheeler.net/ Yahoo!: dew7e Jabber: Th...@ja... |
From: Ken W. <ke...@ma...> - 2002-11-01 07:05:15
|
On Friday, November 1, 2002, at 12:29 AM, David Wheeler wrote: > On Thursday, October 31, 2002, at 07:17 PM, Ken Williams wrote: > >> This is probably pretty important for generic application >> installation. It's also a good way to make installation more >> intuitive (here's *why* the build failed). >> >> Unfortunately I don't have a great answer to this problem. Autrijus, >> weren't you working on something like this a while back, or am I >> remembering wrong? > > Actually, I think that was me. I developed App::Info to manage non-Perl > dependencies, and I think that it could work very nicely with M::B. > Unfortunately, I don't have much time to work on it at the moment, but > it's definitely on my To Do list. > > App::Info is on the CPAN, for those of you who are interested. Ah yes! Thanks for piping up, that's what I was thinking of. I'm installing now to check it out. -Ken |
From: Dave R. <au...@ur...> - 2002-11-01 07:22:54
|
On Thu, 31 Oct 2002, Ken Williams wrote: > I've been ruminating on this, and I think what I want to do is put hooks > into M::B that will use EU::AI if it's installed (and if the user wants > auto-installation), but that EU::AI should remain the way to > automatically install modules. M::B should use EU::AI, not Borg its > code. Obviously this is better from a separation-of-labor & modularity > point of view, and I think it feels better from a policy point of view > too. > > EU::AI can be a recommended dependency for M::B then. But some of what EU::AI just makes sense for M::B. M::B already breaks up dependencies in a more fine-grained way the EU::MM, so why not go a step further and do what EU::AI does, and offer a break not only by build/test/run but also by feature. This is just generically useful. I also like the idea of being able to specify that _specific tests_ have a dependency, so M::B can just skip them if that dependency is not satisfied. In other words, I think have a very full-featured dependency handling feature is an important goal for M::B. Auto-installing of modules is not what I was aiming at. M::B should cooperate with CPAN and CPANPLUS in this regard (or use EU::AI, etc.) > A very related problem is the idea of alternative dependencies - for > instance, Crypt::SKey needs either Digest::MD4 or Digest::MD5, but > there's no great way to indicate that with M::B's dependency > specification right now. Good thing to add. I wonder if the current way of doing this as a hash of "module name => version spec" is too inflexible? I almost wonder if supporting a mini-language might be best. We already have the beginning with the version spec, so maybe something like: 'Foo::Bar >= 2, <= 3.5 | Foo::Baz == 2.1' ?? -dave /*================== www.urth.org we await the New Sun ==================*/ |
From: Ken W. <ke...@ma...> - 2002-11-01 07:47:26
|
On Friday, November 1, 2002, at 01:22 AM, Dave Rolsky wrote: > On Thu, 31 Oct 2002, Ken Williams wrote: > >> I've been ruminating on this, and I think what I want to do is put >> hooks >> into M::B that will use EU::AI if it's installed (and if the user wants >> auto-installation), but that EU::AI should remain the way to >> automatically install modules. M::B should use EU::AI, not Borg its >> code. Obviously this is better from a separation-of-labor & modularity >> point of view, and I think it feels better from a policy point of view >> too. >> >> EU::AI can be a recommended dependency for M::B then. > > But some of what EU::AI just makes sense for M::B. M::B already breaks > up > dependencies in a more fine-grained way the EU::MM, so why not go a step > further and do what EU::AI does, and offer a break not only by > build/test/run but also by feature. This is just generically useful. Oh, maybe I don't understand what EU::AI is for. I'll download and investigate. > I also like the idea of being able to specify that _specific tests_ > have a dependency, so M::B can just skip them if that dependency is not > satisfied. Specific tests can already be skipped by various criteria, but that happens inside the test by emitting specific Test::Harness stuff rather than being controlled by the builder. > In other words, I think have a very full-featured dependency handling > feature is an important goal for M::B. Auto-installing of modules is > not > what I was aiming at. M::B should cooperate with CPAN and CPANPLUS in > this regard (or use EU::AI, etc.) Agreed on the last part - I'll read more about EU::AI. >> A very related problem is the idea of alternative dependencies - for >> instance, Crypt::SKey needs either Digest::MD4 or Digest::MD5, but >> there's no great way to indicate that with M::B's dependency >> specification right now. > > Good thing to add. I wonder if the current way of doing this as a hash > of > "module name => version spec" is too inflexible? > > I almost wonder if supporting a mini-language might be best. We already > have the beginning with the version spec, so maybe something like: > > 'Foo::Bar >= 2, <= 3.5 | Foo::Baz == 2.1' I wonder too. Hmmmm. I'm not too thrilled with that particular syntax, I've seen something somewhat better in Fink (which I guess is probably taken from debian's stuff). -Ken |
From: Dave R. <au...@ur...> - 2002-11-01 07:58:35
|
On Fri, 1 Nov 2002, Ken Williams wrote: > > 'Foo::Bar >= 2, <= 3.5 | Foo::Baz == 2.1' > > I wonder too. Hmmmm. I'm not too thrilled with that particular > syntax, I've seen something somewhat better in Fink (which I guess is > probably taken from debian's stuff). That was a _very_ off-the-top-of-my-head syntax. I'm just thinking that we may want to offer a mini-language option in addition to a simple hash based option. I suspect Fink is using the mini-language used by Debian, which would certainly be a good thing to take a look at. -dave /*================== www.urth.org we await the New Sun ==================*/ |
From: Ken W. <ke...@ma...> - 2002-11-01 05:11:24
|
On Thursday, October 3, 2002, at 06:54 PM, Dave Rolsky wrote: > I wanted to create a Makefile.PL that would pass all functionality > through > to Module::Build, _and_ that would make sure that Module::Build got > installed if necessary. I also wanted to make sure that the user did > not > have to run "perl Makefile.PL" twice, once for installing Module::Build, > and once to install the desired module. Having to do this basically > makes > the install fail with CPAN or CPANPLUS. > > Here's what I came up with: > > > use Cwd; > use File::Spec; > > unless (eval { require Module::Build::Compat; 1 }) { > require ExtUtils::MakeMaker; > > print "This module required Module::Build to install itself.\n"; > > my $yn = ExtUtils::MakeMaker::prompt( ' Install Module::Build', > 'y' ); > > if ($yn =~ /^y(es)?/i) { > # save this cause CPAN will chdir all over the place. > my $cwd = cwd(); > my $makefile = File::Spec->rel2abs($0); > > require CPAN; > CPAN->install('Module::Build'); > > chdir $cwd > or die "Cannot chdir to $cwd: $!"; > > exec( $^X, $makefile, @ARGV ) > } else { > warn "Cannot install Thesaurus without Module::Build. Exiting > ...\n"; > exit 0; > } > } > > require Module::Build::Compat; > Module::Build::Compat->run_build_pl( args => \@args ); > Module::Build::Compat->write_makefile; I think this is a decent change. Autrijus, I think it's better to use ExtUtils::MakeMaker here than ExtUtils::AutoInstall, simply because the user will have the former but probably not the latter. Actually, I just had an idea - would the following small change work (note the 'touch' line, "open $0")? unless (eval "use Module::Build::Compat 0.02; 1" ) { # Workaround with old CPAN.pm and CPANPLUS.pm require ExtUtils::MakeMaker; ExtUtils::MakeMaker::WriteMakefile( PREREQ_PM => { 'Module::Build::Compat' => 0.02 } ); warn "Warning: prerequisite Module::Build::Compat is not found.\n"; sleep 2; # Wait a couple seconds after writing Makefile open my($fh), ">> $0" # Change modification date or warn "You may have to run 'perl Makefile.PL' again."; exit(0); } Module::Build::Compat->run_build_pl(args => \@ARGV); Module::Build::Compat->write_makefile(); The idea is that it changes the modification time for Makefile.PL to be after the Makefile's, so that Makefile.PL gets re-run. This is kind of tough to test out - Dave, how did you test this before? -Ken |
From: Dave R. <au...@ur...> - 2002-11-01 07:12:54
|
On Thu, 31 Oct 2002, Ken Williams wrote: > I think this is a decent change. Autrijus, I think it's better to use > ExtUtils::MakeMaker here than ExtUtils::AutoInstall, simply because the > user will have the former but probably not the latter. > > Actually, I just had an idea - would the following small change work > (note the 'touch' line, "open $0")? > > unless (eval "use Module::Build::Compat 0.02; 1" ) { > # Workaround with old CPAN.pm and CPANPLUS.pm > require ExtUtils::MakeMaker; > ExtUtils::MakeMaker::WriteMakefile( > PREREQ_PM => { 'Module::Build::Compat' => 0.02 } > ); > warn "Warning: prerequisite Module::Build::Compat is not found.\n"; > sleep 2; # Wait a couple seconds after writing Makefile > open my($fh), ">> $0" # Change modification date > or warn "You may have to run 'perl Makefile.PL' again."; > exit(0); > } > Module::Build::Compat->run_build_pl(args => \@ARGV); > Module::Build::Compat->write_makefile(); > > The idea is that it changes the modification time for Makefile.PL to be > after the Makefile's, so that Makefile.PL gets re-run. This is kind of > tough to test out - Dave, how did you test this before? I tested this by uploading a module to CPAN with this Makefile.PL (Thesaurus 0.21) and installing it. Very elegant ;) FWIW, it did work quite well. I think your change above may work just as well. If anyone knows of a way to force CPAN to install something from a tarball (as opposed to fetching the tarball from elsewhere), that'd be very helpful in testing this sort of stuff. -dave /*================== www.urth.org we await the New Sun ==================*/ |
From: Ken W. <ke...@ma...> - 2002-11-01 07:18:57
|
On Friday, November 1, 2002, at 01:12 AM, Dave Rolsky wrote: > On Thu, 31 Oct 2002, Ken Williams wrote: >> This is kind of tough to test out - Dave, how did you test this before? > > I tested this by uploading a module to CPAN with this Makefile.PL > (Thesaurus 0.21) and installing it. Very elegant ;) Heh - that's sort of a "plan Z" scenario. > FWIW, it did work quite well. I think your change above may work just > as > well. If anyone knows of a way to force CPAN to install something > from a > tarball (as opposed to fetching the tarball from elsewhere), that'd be > very helpful in testing this sort of stuff. I'll see if I can figure that out. -Ken |
From: Ken W. <ke...@ma...> - 2002-11-02 01:32:03
|
On Thursday, October 31, 2002, at 09:33 PM, Ken Williams wrote: > Actually, I just had an idea - would the following small change work > (note the 'touch' line, "open $0")? > > unless (eval "use Module::Build::Compat 0.02; 1" ) { > # Workaround with old CPAN.pm and CPANPLUS.pm > require ExtUtils::MakeMaker; > ExtUtils::MakeMaker::WriteMakefile( > PREREQ_PM => { 'Module::Build::Compat' => 0.02 } > ); > warn "Warning: prerequisite Module::Build::Compat is not found.\n"; > sleep 2; # Wait a couple seconds after writing Makefile > open my($fh), ">> $0" # Change modification date > or warn "You may have to run 'perl Makefile.PL' again."; > exit(0); > } > Module::Build::Compat->run_build_pl(args => \@ARGV); > Module::Build::Compat->write_makefile(); > > The idea is that it changes the modification time for Makefile.PL to be > after the Makefile's, so that Makefile.PL gets re-run. I got this working, but only sort of. I had to change the open() stuff to utime() (duh) to get an effective touch. But the problem is that even though the Makefile is rebuilt, CPAN.pm doesn't notice. See below. > This is kind of tough to test out - Dave, how did you test this before? I figured out a really kludgey way to test it. To get CPAN to build from local tarballs, I did this: 1) Disconnect from the network so CPAN can't reload its metafiles. 2) Replace the Makefile.PL for Params::Validate with a pass-through Makefile.PL like the one above, and create a Build.PL for it. 3) Make a tarball of Params::Validate and put it in ~/.cpan/sources/authors/id/D/DR/DROLSKY/. 4) Uninstall Module::Build and Module::Build::Compat from my system. 5) Make a tarball of Module::Build and put it in ~/.cpan/sources/authors/id/K/KW/KWILLIAMS/. 6) Delete the checksums for Module::Build and Params::Validate from the CHECKSUMS files in ~/.cpan/sources/authors/id/... since they're no longer valid. Then in the cpan shell I did 'install Params::Validate' to see what would happen. CPAN successfully notices that Module::Build is a prerequisite and installs it. Then when it goes back to install Params::Validate, 'make' notices that the Makefile is out of date and rebuilds it, returning an error status. But then for some reason CPAN extracts the tarball *again*, and rebuilds the blib/ or something, and everything goes to hell (where it can stay, as far as I'm concerned). This means that in order to install Params::Validate, I had to do 'install Params::Validate', 'clean Params::Validate', 'install Params::Validate'. Ish. I think it also didn't get the prerequisites right - CPAN probably only registered a prereq of Module::Build, and not Attribute::Handlers. So I think we'll indeed have to invoke CPAN->install if we want it to be all in one step. I'll try that next. -Ken |
From: Ken W. <ke...@ma...> - 2002-11-02 01:31:57
|
On Friday, November 1, 2002, at 04:44 PM, Ken Williams wrote: > > So I think we'll indeed have to invoke CPAN->install if we want it to > be all in one step. I'll try that next. Okay, there's a patch for this in Module::Build::Compat. -Ken |