Hello folks!
I use module-starter to sketch up my modules and it defaults to good 'ol ExtUtils::MakeMaker which is a basic author tool and also an end user tool. After it many more featured authoring tools appeared on the perl scene and I have collected a bounch of useful links at the end of this post, for your pleasure. But...
After asking and digging about let Makefile.PL to do the Readme file for me -- new target? I realized an extra target what not was I needed. To much work to remember to even call it. So I have investigated
a bit about standard targets to see if I had the chance to hack some of them and the Makefile.PL iteself, treated as a normal perl program.
My goals..
I had two goals and they are reached with the below code: firstly I needed a way to generate my README file automatically from the pod section of the main module and secondly I want my eventual git repository added automatically to my META.yml and META.json files as explained in perlmaven article but in a lazier way.
With the help you gave me and some important contribution given by the irc #perl channel I have now something working the way I like and that you can review in details below.
..and yours?
I'm sure many of you have other interesting things to show as makefile recipes or makefile tricks as the wise monk pryrt shown in his Re: let Makefile.PL to do the Readme file for me -- new target? about his Win32::Mechanize::NotepadPlusPlus module.
Here you have the basic Makefile.PL produced by module-starter with my modification clearly marked by big comments at start and end:
use 5.010;
use strict;
use warnings;
use ExtUtils::MakeMaker;
################################
# BEGIN CUSTOMIZATION
################################
# used to be passed to WriteMakefile
my %meta_merge_args;
if (!-e 'META.yml') {
my $ask_for_git = prompt ("*** CUSTOM *** (only relevant for autho
+r) Do you want to specify a git repository (y or N)?:");
if ( $ask_for_git =~ /^y/i ){
my $git_repo = prompt ("*** CUSTOM *** Full URL of the git rep
+ository:");
die "Empty git repository! Answer n to the previous question i
+f you dont want to specify a git repository!"
unless length $git_repo;
$git_repo =~ s/\/$//;
my $git_file = prompt ("*** CUSTOM *** Full URL of git repos
+itory file:", $git_repo.'.git');
my $git_issues = $git_repo.( $git_repo =~ /gitlab.com/ ? '/-'
+: '').'/issues';
$git_issues = prompt ("*** CUSTOM *** Full URL for git issues:
+", $git_issues);
my $home_page = prompt ("*** CUSTOM *** Full URL of an eventu
+al homepage?:", $git_repo);
# fill in the %meta_merge_args in the main package
$meta_merge_args{ META_MERGE } = {
'meta-spec' => { version => 2 },
'resources' => {
'repository' => {
'type' => 'git',
'url' => $git_file,
'web' => $git_repo,
},
'bugtracker' => {
'web' => $git_issues,
},
'homepage' => $home_page,
}
};
}
}
# override MY::distdir
# see https://perldoc.perl.org/ExtUtils::MakeMaker#Overriding-MakeMake
+r-Methods
package MY; # so that "SUPER" works right
sub distdir {
# SAVE WHAT RECEIVED BY THE ORIGINAL distdir
my $inherited = $_[0]->SUPER::distdir(@_);
#print "DEBUG -->$inherited<--\n"; # uncomment to see what is pas
+sed
# CALL THE DEFAULT distdir
$_[0]->SUPER::distdir(@_);
# README: update the README using the POD from main module
my $make_readme =<<'MAKE_README';
$(TOUCH) README
$(NOECHO) $(ECHO) > README
$(NOECHO) $(ECHO) *** CUSTOM *** Generating README from POD of $(V
+ERSION_FROM)
$(PERLRUN) -MPod::Text \
-e "Pod::Text->new (sentence => 1, width => 78)->parse_from_file(
+qq( $(VERSION_FROM) ) ) or die $$!;" >> README
$(NOECHO) $(ECHO) *** autogenerated by a lazy Makefile.PL *** >> R
+EADME
$(NOECHO) $(ECHO) *** CUSTOM *** Regenerating MANIFEST
$(PERLRUN) -M"5;push @ARGV,'MANIFEST'" -nle "print unless /^README
+$$/" >> MANIFEST.new
$(NOECHO) $(ECHO) *** CUSTOM *** Updating MANIFEST with README ent
+ry
$(NOECHO) $(ECHO) README >> MANIFEST.new
$(MV) MANIFEST.new MANIFEST
$(CP) MANIFEST $(DISTVNAME)/MANIFEST
$(CP) README $(DISTVNAME)/README
MAKE_README
# make NEEDS tabs: ensure they are there
$make_readme =~ s/^\s+/\t/gm;
return join '', $inherited, $make_readme;
}
# back to main package
package main;
WriteMakefile(
%meta_merge_args,
##################################################
# END CUSTOMIZATION
##################################################
# DEFAULT content made by module-starter
NAME => 'Games::Dice::Roller',
AUTHOR => q{LorenzoTa <LORENZO@cpan.org>},
VERSION_FROM => 'lib/Games/Dice/Roller.pm',
ABSTRACT_FROM => 'lib/Games/Dice/Roller.pm',
LICENSE => 'artistic_2',
PL_FILES => {},
MIN_PERL_VERSION => '5.010',
CONFIGURE_REQUIRES => {
'ExtUtils::MakeMaker' => '0',
},
BUILD_REQUIRES => {
'Test::More' => '0',
'Test::Exception' => '0',
},
PREREQ_PM => {
Carp => 0,
},
);
In details:
%meta_merge_args is used to add repository metadata to the final
WriteMakefile call.
Then the if (!-e 'META.yml') { checks is to distinguish between author and end user: if META.yml is not there it is me running Makefile.PL so I ask for an eventual git repository. By other hand if the file is there it means that Makefile.PL was called by the end user while installing the module (nice trick from #perl irc channel).
ExtUtils::MakeMaker provides an handy prompt facility and other infos are asked with sane defaults (this version support issues both on gitlab and github ;) and these will be passed directly to WriteMakefile
The real makefile hack is overriding the distdir default target that is called inside the normal make dist action. The original arguments are saved and the original behaviour is replicated ( via my $inherited = $_[0]->SUPER::distdir(@_); and $_[0]->SUPER::distdir(@_); respectively) and then a big heredoc is used to inject new code directly into the generated Makefile
Inside Makefile there are already a lot of useful things to use as the definition of PERLRUN = "C:\ulisse\perl5.24-64b\perl\bin\perl.exe" to be invoked as $(PERLRUN) and bash like commands provided by ExtUtils::Command like MV = $(ABSPERLRUN) -MExtUtils::Command -e mv -- to be used as $(MV) origin destination so even perl oneliners are easy to use, with some caveats: the $ needs to be doubled as in the regex /^README$$/ and I had problems to pass filenames to oneliners and so I used the Maori Farewell trick to simulate a BEGIN block in $(PERLRUN) -M"5;push @ARGV,'MANIFEST'" -nle "print unless /^README$$/" >> MANIFEST.new
So the README is created by the main module pod ( $(VERSION_FROM) is handy there) then MANIFEST is updated and both files are copied to $(DISTVNAME) ie: the directory with the version numer that then wil be tarballed.
The whole output of the distro creation is (using my recent module):
io@COMP:C>ls -l
total 13
-rw-rw-rw- 1 user group 791 Jan 28 17:03 Changes
-rw-rw-rw- 1 user group 361 Jan 28 17:01 MANIFEST
-rw-rw-rw- 1 user group 42 Jan 24 16:27 MANIFEST.SKIP
-rw-rw-rw- 1 user group 5171 Jan 24 16:27 MANIFEST.bak
-rw-rw-rw- 1 user group 3490 Jan 28 17:40 Makefile.PL
drwxrwxrwx 1 user group 0 Jan 28 21:26 lib
drwxrwxrwx 1 user group 0 Jan 28 21:26 t
drwxrwxrwx 1 user group 0 Jan 28 21:26 xt
io@COMP:C>perl Makefile.PL
*** CUSTOM *** (only relevant for author) Do you want to specify a git
+ repository (y or N)?: y
*** CUSTOM *** Full URL of the git repository: https://gitlab.com/Lor
+enzoTa/games-dice-roller
*** CUSTOM *** Full URL of git repository file: [https://gitlab.com/Lo
+renzoTa/games-dice-roller.git]
*** CUSTOM *** Full URL for git issues: [https://gitlab.com/LorenzoTa/
+games-dice-roller/-/issues]
*** CUSTOM *** Full URL of an eventual homepage?: [https://gitlab.com/
+LorenzoTa/games-dice-roller]
Checking if your kit is complete...
Looks good
Generating a dmake-style Makefile
Writing Makefile for Games::Dice::Roller
Writing MYMETA.yml and MYMETA.json
io@COMP:C>dmake dist
"C:\ulisse\perl5.24-64b\perl\bin\perl.exe" -MExtUtils::Command -e rm_r
+f -- Games-Dice-Roller-0.04
"C:\ulisse\perl5.24-64b\perl\bin\perl.exe" "-MExtUtils::Manifest=manic
+opy,maniread" \
-e "manicopy(maniread(),'Games-Dice-Roller-0.04', 'bes
+t');"
mkdir Games-Dice-Roller-0.04
mkdir Games-Dice-Roller-0.04/lib
mkdir Games-Dice-Roller-0.04/lib/Games
mkdir Games-Dice-Roller-0.04/lib/Games/Dice
mkdir Games-Dice-Roller-0.04/t
mkdir Games-Dice-Roller-0.04/xt
Generating META.yml
Generating META.json
"C:\ulisse\perl5.24-64b\perl\bin\perl.exe" -MExtUtils::Command -e touc
+h -- README
*** CUSTOM *** Generating README from POD of lib/Games/Dice/Roller.pm
"C:\ulisse\perl5.24-64b\perl\bin\perl.exe" -MPod::Text \
-e "Pod::Text->new (sentence => 1, width => 78)->parse_from_fi
+le( qq( lib/Games/Dice/Roller.pm ) ) or die $!;"
>> README
*** CUSTOM *** Regenerating MANIFEST
"C:\ulisse\perl5.24-64b\perl\bin\perl.exe" -M"5;push @ARGV,'MANIFEST'"
+ -nle "print unless /^README$/" >> MANIFEST.new
*** CUSTOM *** Updating MANIFEST with README entry
"C:\ulisse\perl5.24-64b\perl\bin\perl.exe" -MExtUtils::Command -e mv -
+- MANIFEST.new MANIFEST
"C:\ulisse\perl5.24-64b\perl\bin\perl.exe" -MExtUtils::Command -e cp -
+- MANIFEST Games-Dice-Roller-0.04/MANIFEST
"C:\ulisse\perl5.24-64b\perl\bin\perl.exe" -MExtUtils::Command -e cp -
+- README Games-Dice-Roller-0.04/README
tar cvf Games-Dice-Roller-0.04.tar Games-Dice-Roller-0.04
Games-Dice-Roller-0.04/
Games-Dice-Roller-0.04/Changes
Games-Dice-Roller-0.04/lib/
Games-Dice-Roller-0.04/lib/Games/
Games-Dice-Roller-0.04/lib/Games/Dice/
Games-Dice-Roller-0.04/lib/Games/Dice/Roller.pm
Games-Dice-Roller-0.04/Makefile.PL
Games-Dice-Roller-0.04/MANIFEST
Games-Dice-Roller-0.04/MANIFEST.bak
Games-Dice-Roller-0.04/MANIFEST.SKIP
Games-Dice-Roller-0.04/META.json
Games-Dice-Roller-0.04/META.yml
Games-Dice-Roller-0.04/README
Games-Dice-Roller-0.04/t/
Games-Dice-Roller-0.04/t/00-load.t
Games-Dice-Roller-0.04/t/01-single-die.t
Games-Dice-Roller-0.04/t/02-identify-type.t
Games-Dice-Roller-0.04/t/03-roll-basic-check.t
Games-Dice-Roller-0.04/t/04-validate-expr.t
Games-Dice-Roller-0.04/t/05-some-roll.t
Games-Dice-Roller-0.04/t/06-keep-drop-rolls.t
Games-Dice-Roller-0.04/t/07-rand-custom-funcion.t
Games-Dice-Roller-0.04/t/08-result-summation.t
Games-Dice-Roller-0.04/t/09-dice-pool.t
Games-Dice-Roller-0.04/t/manifest.t
Games-Dice-Roller-0.04/t/pod-coverage.t
Games-Dice-Roller-0.04/t/pod.t
Games-Dice-Roller-0.04/xt/
Games-Dice-Roller-0.04/xt/boilerplate.t
"C:\ulisse\perl5.24-64b\perl\bin\perl.exe" -MExtUtils::Command -e rm_r
+f -- Games-Dice-Roller-0.04
gzip --best Games-Dice-Roller-0.04.tar
'Created Games-Dice-Roller-0.04.tar.gz'
Interesting resources:
Other authoring tools (not complete list):
Interesting readings:
update 2021 Feb 08 I have added a check to ensure tabs are prepended to make recipe because spaces breaks everything.
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.