# MyMakeMakerExtra.pm -- my shared MakeMaker extras # Copyright 2009, 2010, 2011 Kevin Ryde # MyMakeMakerExtras.pm is shared by several distributions. # # MyMakeMakerExtras.pm is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 3, or (at your option) any later # version. # # MyMakeMakerExtras.pm is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # You should have received a copy of the GNU General Public License along # with this file. If not, see . package MyMakeMakerExtras; use strict; # uncomment this to run the ### lines #use Smart::Comments; my %my_options; sub WriteMakefile { my %opts = @_; if (exists $opts{'META_MERGE'}) { # cf. ExtUtils::MM_Any::metafile_data() default ['t','inc'] foreach ('devel', 'examples', 'junk', 'maybe') { my $dir = $_; if (-d $dir) { push @{$opts{'META_MERGE'}->{'no_index'}->{'directory'}}, $dir; } } $opts{'META_MERGE'}->{'resources'}->{'license'} ||= 'http://www.gnu.org/licenses/gpl.html'; _meta_merge_shared_tests (\%opts); _meta_merge_shared_devel (\%opts); } $opts{'clean'}->{'FILES'} .= ' temp-lintian $(MY_HTML_FILES)'; $opts{'realclean'}->{'FILES'} .= ' TAGS'; if (! defined &MY::postamble) { *MY::postamble = \&MyMakeMakerExtras::postamble; } foreach ('MyMakeMakerExtras_Pod_Coverage', 'MyMakeMakerExtras_LINT_FILES', 'MY_NO_HTML', 'MY_EXTRA_FILE_PART_OF') { $my_options{$_} = delete $opts{$_}; } ### chain to WriteMakefile() ### %opts ExtUtils::MakeMaker::WriteMakefile (%opts); ### done } sub strip_comments { my ($str) = @_; $str =~ s/^\s*#.*\n//mg; $str } #------------------------------------------------------------------------------ # META_MERGE sub _meta_merge_shared_tests { my ($opts) = @_; if (-e 'xt/0-Test-Pod.t') { _meta_merge_req_add (_meta_merge_maximum_tests($opts), 'Test::Pod' => '1.00'); } if (-e 'xt/0-Test-DistManifest.t') { _meta_merge_req_add (_meta_merge_maximum_tests($opts), 'Test::DistManifest' => 0); } if (-e 'xt/0-Test-Synopsis.t') { _meta_merge_req_add (_meta_merge_maximum_tests($opts), 'Test::Synopsis' => 0); } if (-e 'xt/0-Test-YAML-Meta.t') { _meta_merge_req_add (_meta_merge_maximum_tests($opts), 'Test::YAML::Meta' => '0.15'); } if (-e 'xt/0-META-read.t') { if (_min_perl_version_lt ($opts, 5.00307)) { _meta_merge_req_add (_meta_merge_maximum_tests($opts), 'FindBin' => 0); } if (_min_perl_version_lt ($opts, 5.00405)) { _meta_merge_req_add (_meta_merge_maximum_tests($opts), 'File::Spec' => 0); } _meta_merge_req_add (_meta_merge_maximum_tests($opts), 'YAML' => 0, 'YAML::Syck' => 0, 'YAML::Tiny' => 0, 'YAML::XS' => 0, 'Parse::CPAN::Meta' => 0); } } # return hashref of "maximum_tests" under $opts, created if necessary sub _meta_merge_maximum_tests { my ($opts) = @_; $opts->{'META_MERGE'}->{'optional_features'}->{'maximum_tests'} ||= { description => 'Have "make test" do as much as possible.', requires => { }, }; return $opts->{'META_MERGE'}->{'optional_features'}->{'maximum_tests'}->{'requires'}; } sub _meta_merge_shared_devel { my ($opts) = @_; _meta_merge_req_add (_meta_merge_maximum_devel($opts), # the "make unused" target below 'warnings::unused' => 0); if (-e 'inc/my_pod2html') { if (_min_perl_version_lt ($opts, 5.009003)) { _meta_merge_req_add (_meta_merge_maximum_devel($opts), 'Pod::Simple::HTML' => 0); } } } # return hashref of "maximum_devel" under $opts, created if necessary sub _meta_merge_maximum_devel { my ($opts) = @_; $opts->{'META_MERGE'}->{'optional_features'}->{'maximum_devel'} ||= { description => 'Stuff used variously for development.', requires => { }, }; return $opts->{'META_MERGE'}->{'optional_features'}->{'maximum_devel'}->{'requires'}; } # return true if MIN_PERL_VERSION in $opts is < $ver, or no MIN_PERL_VERSION sub _min_perl_version_lt { my ($opts, $perlver) = @_; return (! defined $opts->{'MIN_PERL_VERSION'} || $opts->{'MIN_PERL_VERSION'} < $perlver); } sub _meta_merge_req_add { my $req = shift; ### MyMakeMakerExtras META_MERGE: @_ while (@_) { my $module = shift; my $version = shift; if (defined $req->{$module}) { if ($req->{$module} > $version) { $version = $req->{$module}; } } $req->{$module} = $version; } } #------------------------------------------------------------------------------ # postamble() sub postamble { my ($makemaker) = @_; ### MyMakeMakerExtras postamble(): $makemaker my $post = $my_options{'postamble_docs'}; my @exefiles_html; my @pmfiles_html; unless ($my_options{'MY_NO_HTML'}) { $post .= <<'HERE'; #------------------------------------------------------------------------------ # docs stuff -- from inc/MyMakeMakerExtras.pm MY_POD2HTML = $(PERL) inc/my_pod2html HERE my $munghtml_extra = $makemaker->{'MY_MUNGHTML_EXTRA'}; if ($munghtml_extra) { $post =~ s/apt-file!'/apt-file!'\\ $munghtml_extra/; } my @pmfiles = keys %{$makemaker->{'PM'}}; @pmfiles = grep {!/\.mo$/} @pmfiles; # not LocaleData .mo files my @exefiles = (defined $makemaker->{'EXE_FILES'} ? @{$makemaker->{'EXE_FILES'}} : ()); my %html_files; my $html_rule = sub { my ($pm) = @_; my $fullhtml = $pm; $fullhtml =~ s{lib/}{}; # remove lib/ $fullhtml =~ s{\.p[ml]$}{}; # remove .pm or .pl $fullhtml .= '.html'; my $parthtml = $fullhtml; $fullhtml =~ s{/}{-}g; # so Foo-Bar.html unless ($html_files{$fullhtml}++) { $post .= <<"HERE"; $fullhtml: $pm Makefile \$(MY_POD2HTML) $pm >$fullhtml HERE } $parthtml =~ s{.*/}{}; # remove any directory part, just Bar.html unless ($html_files{$parthtml}++) { $post .= <<"HERE"; $parthtml: $pm Makefile \$(MY_POD2HTML) $pm >$parthtml HERE } return $parthtml; }; foreach (@exefiles) { push @exefiles_html, &$html_rule ($_); } foreach (@pmfiles) { push @pmfiles_html, &$html_rule ($_); } $post .= "MY_HTML_FILES = " . join(' ', keys %html_files) . "\n"; $post .= <<'HERE'; html: $(MY_HTML_FILES) HERE } $post .= <<'HERE'; #------------------------------------------------------------------------------ # development stuff -- from inc/MyMakeMakerExtras.pm version: $(NOECHO)$(ECHO) $(VERSION) HERE my $lint_files = $my_options{'MyMakeMakerExtras_LINT_FILES'}; if (! defined $lint_files) { $lint_files = 'Makefile.PL $(EXE_FILES) $(TO_INST_PM)'; # would prefer not to lock down the 't' dir existance at ./Makefile.PL # time, but it's a bit hard without without GNU make extensions if (-d 't') { $lint_files .= ' t/*.t'; } if (-d 'xt') { $lint_files .= ' xt/*.t'; } foreach ('examples', 'devel') { my $dir = $_; my $pattern = "$dir/*.pl"; if (glob ($pattern)) { $lint_files .= " $pattern"; } } } my $podcoverage = ''; foreach (@{$my_options{'MyMakeMakerExtras_Pod_Coverage'}}) { my $class = $_; # the "." obscures it from MyExtractUse.pm $podcoverage .= "\t-\$(PERLRUNINST) -e 'use "."Pod::Coverage package=>$class'\n"; } $post .= "LINT_FILES = $lint_files\n" . <<'HERE'; lint: perl -MO=Lint $(LINT_FILES) pc: HERE # "podchecker -warnings -warnings" too much reporting every < and > $post .= $podcoverage . <<'HERE'; -podlinkcheck -I lib `ls $(LINT_FILES) | grep -v '\.bash$$|\.desktop$$\.png$$|\.xpm$$'` -podchecker `ls $(LINT_FILES) | grep -v '\.bash$$|\.desktop$$\.png$$|\.xpm$$'` perlcritic $(LINT_FILES) unused: for i in $(LINT_FILES); do perl -Mwarnings::unused -I lib -c $$i; done HERE $post .= <<'HERE'; myman: -mv MANIFEST MANIFEST.old touch SIGNATURE (make manifest 2>&1; diff -u MANIFEST.old MANIFEST) |less # find files in the dist with mod times this year, but without this year in # the copyright line check-copyright-years: year=`date +%Y`; \ tar tvfz $(DISTVNAME).tar.gz \ | egrep "$$year-|debian/copyright" \ | sed 's:^.*$(DISTVNAME)/::' \ | (result=0; \ while read i; do \ GREP=grep; \ case $$i in \ '' | */ \ | ppport.h \ | debian/changelog | debian/compat | debian/doc-base \ | debian/patches/*.diff | debian/source/format \ | COPYING | MANIFEST* | SIGNATURE | META.yml \ | version.texi | */version.texi \ | *utf16* | examples/rs''s2lea''fnode.conf \ | */MathI''mage/ln2.gz | */MathI''mage/pi.gz \ | *.mo | *.locatedb* | t/samp.*) \ continue ;; \ *.gz) GREP=zgrep ;; \ esac; \ if test -e "$(srcdir)/$$i"; then f="$(srcdir)/$$i"; \ else f="$$i"; fi; \ if ! $$GREP -q "Copyright.*$$year" $$f; then \ echo "$$i":"1: this file"; \ grep Copyright $$f; \ result=1; \ fi; \ done; \ exit $$result) # only a DEBUG non-zero number is bad, so an expression can copy a debug from # another package check-debug-constants: if egrep -nH 'DEBUG => [1-9]|^[ \t]*use Smart::Comments' $(EXE_FILES) $(TO_INST_PM) t/*.t xt/*.t; then exit 1; else exit 0; fi check-spelling: if find . -type f | egrep -v '(Makefile|dist-deb)' | xargs egrep --color=always -nHi '[c]usor|[r]efering|[w]riteable|[n]ineth|\b[o]mmitt?ed|[o]mited|[$$][rd]elf|[r]equrie|[n]oticable|[c]ontinous|[e]xistant|[e]xplict|[a]gument|[d]estionation|\b[t]he the\b|\b[n]ote sure\b'; \ then false; else true; fi HERE $post .= "\n"; $post .= ("MY_EXTRA_FILE_PART_OF = " . ($my_options{'MY_EXTRA_FILE_PART_OF'}||'') . "\n"); $post .= <<'HERE'; check-file-part-of: if grep --text 'This file is'' part of ' -r . | egrep -iv '$(DISTNAME)$(MY_EXTRA_FILE_PART_OF)'; then false; else true; fi diff-prev: rm -rf diff.tmp mkdir diff.tmp cd diff.tmp \ && tar xfz ../$(DISTNAME)-`expr $(VERSION) - 1`.tar.gz \ && tar xfz ../$(DISTNAME)-$(VERSION).tar.gz -cd diff.tmp; diff -ur $(DISTNAME)-`expr $(VERSION) - 1` \ $(DISTNAME)-$(VERSION) >tree.diff -$${PAGER:-less} diff.tmp/tree.diff rm -rf diff.tmp # in a hash-style multi-const this "use constant" pattern only picks up the # first constant, unfortunately, but it's better than nothing TAG_FILES = $(TO_INST_PM) TAGS: $(TAG_FILES) etags \ --regex='{perl}/use[ \t]+constant\(::defer\)?[ \t]+\({[ \t]*\)?\([A-Za-z_][^ \t=,;]+\)/\3/' \ $(TAG_FILES) HERE my $have_XS = scalar %{$makemaker->{'XS'}}; my $arch = ($have_XS ? `dpkg --print-architecture` : 'all'); chomp($arch); my $debname = (defined $makemaker->{'EXE_FILES'} ? '$(DISTNAME)' : "\Llib$makemaker->{'DISTNAME'}-perl"); $post .= "DEBNAME = $debname\n" . "DPKG_ARCH = $arch\n" . <<'HERE'; DEBVNAME = $(DEBNAME)_$(VERSION)-1 DEBFILE = $(DEBVNAME)_$(DPKG_ARCH).deb # ExtUtils::MakeMaker 6.42 of perl 5.10.0 makes "$(DISTVNAME).tar.gz" depend # on "$(DISTVNAME)" distdir directory, which is always non-existent after a # successful dist build, so the .tar.gz is always rebuilt. # # So although the .deb depends on the .tar.gz don't express that here or it # rebuilds the .tar.gz every time. # # The right rule for the .tar.gz would be to depend on the files which go # into it of course ... # # DISPLAY is unset for making a deb since under fakeroot gtk stuff may try # to read config files like ~/.pangorc from root's home dir /root/.pangorc, # and that dir will be unreadable by ordinary users (normally), provoking # warnings and possible failures from nowarnings(). # $(DEBFILE) deb: test -f $(DISTVNAME).tar.gz || $(MAKE) $(DISTVNAME).tar.gz debver="`dpkg-parsechangelog -c1 | sed -n -r -e 's/^Version: (.*)-[0-9.]+$$/\1/p'`"; \ echo "debver $$debver", want $(VERSION); \ test "$$debver" = "$(VERSION)" rm -rf $(DISTVNAME) tar xfz $(DISTVNAME).tar.gz unset DISPLAY; export DISPLAY; \ cd $(DISTVNAME) \ && dpkg-checkbuilddeps debian/control \ && fakeroot debian/rules binary rm -rf $(DISTVNAME) lintian-deb: $(DEBFILE) lintian -i -X new-package-should-close-itp-bug $(DEBFILE) lintian-source: rm -rf temp-lintian; \ mkdir temp-lintian; \ cd temp-lintian; \ cp ../$(DISTVNAME).tar.gz $(DEBNAME)_$(VERSION).orig.tar.gz; \ tar xfz $(DEBNAME)_$(VERSION).orig.tar.gz; \ echo 'empty-debian-diff' \ >$(DISTVNAME)/debian/source.lintian-overrides; \ mv -T $(DISTVNAME) $(DEBNAME)-$(VERSION); \ dpkg-source -b $(DEBNAME)-$(VERSION) \ $(DEBNAME)_$(VERSION).orig.tar.gz; \ lintian -i -X missing-debian-source-format *.dsc; \ cd ..; \ rm -rf temp-lintian HERE { my $list_html = join(' ',@exefiles_html); if (! $list_html && @pmfiles_html <= 3) { $list_html = join(' ',@pmfiles_html); } if (! -e 'inc/my_pod2html') { $list_html = ''; } my $make_list_html = ($list_html ? "\n\tmake $list_html" : ""); $post .= <<"HERE"; my-list:$make_list_html ls -l -U $list_html \$(EXE_FILES) *.tar.gz *.deb HERE $post .= <<'HERE'; @echo -n '$(DEBFILE) ' @dpkg-deb -f $(DEBFILE) | grep Installed-Size HERE if ($list_html) { $post .= "\trm -f $list_html\n"; } } return $post; } 1; __END__