dragonchild has asked for the wisdom of the Perl Monks concerning the following question:
(This is in reference to Re: When you change Perl versions, how do you resync all the CPAN modules you have installed [tag://sysadmin,cpan,modules,upgrade] and its parent)
I working on cpan-izing a pair of scripts for building Perl in a given location and installing a set of CPAN against that perl so that using that perl automatically finds the modules (as opposed to needing to use lib $dir; all over the place). I've got a few questions:
- The name. Right now, I'm leaning towards Perl::Install, but Perl:: is a new TLN and I'm a bit leery of taking that. Where else would it go?
- The distro packaging. I've got a lot of CPAN modules out there, but they're all .pm files with occasional scripts. This is purely a pair of scripts (at least, initially) with no .t files. How should I package this? Is there another distro with a similar setup that I can look at?
- Alien dependencies. The script depends on, among other things, wget. While I expect that (should the script be deemed useful), it will improve beyond that hard dependency, right now it has that dep. Do I just document it or should I test for it? How would I test for it?
Update: Thanks for all the feedback. I have gone ahead and released it as Perl::Install, but will be amenable to renaming later.
My criteria for good software:
- Does it work?
- Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: CPANization of a script for building Perl
by Corion (Patriarch) on Dec 15, 2007 at 13:52 UTC
|
Personally, I find that any script of sufficient complexity better lives as a module and a "wrapper script" anyway. Most of the time, this process starts once I have to debug the script and have to write tests against specific functionalities of the script. If you find your script is larger than (say) 100 lines, excluding documentation and switch parsing, I think wrapping the script into a module and calling App::BuildPerl::do_it() from the calling script is a sane approach and allows for later utilization/customization of the "application" by another calling script.
External/alien dependencies are hard, but in your case, you could use File::Fetch as a prerequisite, which is what CPANPLUS uses to retrieve files specified via URIs; this is still slated to become core with Perl 5.10. I would specify/optionally require File::Fetch and in case that fails blindly fall back to `wget -o $target "$url"`. You could verify the wget functionality through a test though, or, if you're using Module::Install as your build mechanism, it has requires_external_bin().
Of course, in all cases, it's better to release something than fretting over how to best specify the finer details to make the script work everywhere.
| [reply] [d/l] [select] |
|
Personally, I find that any script of sufficient complexity better lives as a module and a "wrapper script" anyway. Most of the time, this process starts once I have to debug the script and have to write tests against specific functionalities of the script. If you find your script is larger than (say) 100 lines, excluding documentation and switch parsing, I think wrapping the script into a module and calling App::BuildPerl::do_it() from the calling script is a sane approach and allows for later utilization/customization of the "application" by another calling script.
I agree completely: moving the guts of a script to a module facilitates testing a lot. Consider that you can use the perl debugger to trace through a test file that makes calls to do_it(), but any place you shell out to an external script you'll run into a hard wall that the debugger can't step into.
And of course, if you can break out the functionality of that do_it into multiple subs, it becomes possible to write finer-grain tests that examine each of the subs.
One thing though: I've gradually come to the conclusion that it should be the job of the script to unpack any command-line options (from Getopt::Std or whatever) and translate them into options used by the module. Don't write subs that work by having the options hash passed in from the script: then you get stuck being unable to change
the external interface without re-writing internal code.
Of course, if you'd rather not re-engineer the code at all for the first release, nothing stops you from attaching your scripts to a dummy pm that to begin with contains nothing but pod
for the scripts.
| [reply] [d/l] [select] |
Re: CPANization of a script for building Perl
by polettix (Vicar) on Dec 15, 2007 at 14:01 UTC
|
When starting the cpan utility for the first time you're presented with a set of questions whose goal is to customise a configuration module; among the questions there are also requests to know which system programs should be used, like wget, ncftp and so on.
That could be a good example, in many senses: first of all, having an external configuration file where one can put weird paths for some needed external program; secondly, to get a clue about how actually check that there is some needed external software, and bail out if it's not available (which gives you dependency check as well).
Regarding hard dependencies and tests, you could make a test for the dependency. Something along the lines: use Test::More tests => 1;
use English qw( -no_match_vars );
qx{ wget --version };
is($CHILD_ERROR, 0, 'wget is available');
Flavio
perl -ple'$_=reverse' <<<ti.xittelop@oivalf
Io ho capito... ma tu che hai detto?
| [reply] [d/l] [select] |
Re: CPANization of a script for building Perl
by ww (Archbishop) on Dec 15, 2007 at 12:20 UTC
|
1. Maybe, despite its verbosity, Perl::VersionUpdate ???
3. Document? yes! Test? Also yes (but this view is merely based on personal taste; not any skills in testing). | [reply] |
|
I think that conveying the concept of update would restrict the scope of dragonchild's scripts. Perl::Install seems more in target IMHO.
Flavio
perl -ple'$_=reverse' <<<ti.xittelop@oivalf
Io ho capito... ma tu che hai detto?
| [reply] [d/l] |
Re: CPANization of a script for building Perl
by BrowserUk (Patriarch) on Dec 15, 2007 at 06:24 UTC
|
but Perl:: is a new TLN
Que?
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] |
Re: CPANization of a script for building Perl
by Herkum (Parson) on Dec 16, 2007 at 13:48 UTC
|
I don't like Perl::Install, it seems ambiguous. Example: Perl::Install::Java. Does this mean it installs Java? Perl::Install would then appear to be a base module for Perl::Install::Java.
How about Perl::Installation? It is a minor difference from Perl::Install; especially since there are so many Foo::Install modules but I do think it is a little clearer in what it is supposed to do.
As for dependencies Module::Build has calls for getting information from the user, it is called prompt().
Example from a Build.PL script I wrote, (Note: This is not a complete script).
my $code<<"END";
## Your custom installation code goes here
END;
use Module::Build;
my $class = Module::Build->subclass(
class => 'Custom::Build',
code => $code,
);
my $builder = $class->new(
# You need to add some of your stuff here!
)
if ($builder->args('default') or
$builder->args('quick-install')) {
my %notes = _get_default_settings();
foreach (keys %notes) { $builder->notes( $_ => $notes{$_} ) }
}
else {
my %notes = _get_prompt_settings();
foreach (keys %notes) {
$builder->notes( $_ => $builder->prompt(
$notes{$_}{message}, $notes{$_}{default}
))
}
}
$builder->create_build_script();
exit;
#################################################
sub _get_default_settings {
warn "OS is $OSNAME\n";
if ($OSNAME eq 'MSWin32') {
return (
config => 'c:/EEBL/tmp',
cgi => 'c:/EEBL/tmp/cgi',
tmpl => 'c:/EEBL/tmp/tmpl',
url => '/EEBL',
)
}
else {
return (
config => '/var/www/eebl',
cgi => '/var/www/eebl/cgi',
tmpl => '/var/www/eebl/tmpl',
url => '/EEBL',
)
};
};
#################################################
sub _get_prompt_settings {
my %settings = _get_default_settings;
return (
config => {
message => 'Where will the config.txt file be installed?',
default => $settings{config},
},
cgi => {
message => 'Where will the cgi files be installed?',
default => $settings{cgi},
},
tmpl => {
message => 'Where will the template files be installed?',
default => $settings{tmpl},
},
url => {
message => 'What is the root url for the web site?',
default => $settings{url},
},
);
}
Hope this gets your started. | [reply] [d/l] |
Re: CPANization of a script for building Perl
by doom (Deacon) on Dec 16, 2007 at 21:58 UTC
|
Right now, I'm leaning towards Perl::Install, but Perl:: is a new TLN and I'm a bit leery of taking that. Where else would it go?
How about Admin? Pehaps Admin::Install or Admin::Installation?
Of course, once there's an Admin at the top level, it's going to attract all sorts of system administration tools...
| [reply] [d/l] [select] |
|
|