From: David Golden Date: Wed, 18 Nov 2009 05:52:18 +0000 (-0500) Subject: Updated Module::Build to 0.35_08 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=613f422f899872b39e45f0f48c3285ac4cece8c7;p=p5sagit%2Fp5-mst-13.2.git Updated Module::Build to 0.35_08 0.35_08 - Mon Nov 16 22:38:28 EST 2009 Bug fixes: - Multiple tests were failing due to dependency problems. Author dependencies have been largely removed from core 'requires' into optional features. Feature prereq detection and messaging have been expanded and bugs on older Perls have been removed. 0.35_07 - Sat Nov 14 17:14:39 EST 2009 Bug fixes: - Auto-detection of abstract and author fixed for mixed-case POD headers (RT#51117) [David Wheeler] - resume() was not restoring additions to @INC added in Build.PL (RT#50145) [David Golden] - When tarball paths are less than 100 characters, disables 'prefix' mode of Archive::Tar for maximum compatibility (RT#50571) [David Golden] 0.35_06 - Fri Nov 13 14:51:28 EST 2009 Enhancements: - Added experimental inc/ bundling; see Module::Build::Bundling for details. [David Golden and Eric Wilhelm] - Clarified that 'apache' in the license attribute indicates the Apache License 2.0 and added 'apache_1_1' for the older version of the license (RT#50614) [David Golden] Bug fixes: - Merging 'requires' and 'build_requires' in Module::Build::Compat could lead to duplicate PREREQ_PM entries; now the highest version is used for PREREQ_PM. (RT#50948) [David Golden] - Module::Build::Compat will now die with an error if advanced, non-numeric prerequisites are given, as these are not supported by ExtUtils::MakeMaker in PREREQ_PM [David Golden] - Made MYMETA generation non-fatal if fields required for META.yml are missing [David Golden] - Added Pod::Simple to requirements for manpage support; avoids problems if a user has a broken Pod::Man/Pod::Simple. (RT#50081) [David Golden] - Won't die if installed Pod::Readme is broken [David Golden] Other: - Fixed Module::Build::Notes POD [David Golden] - Some commands had become silent by default, so added a few short status messages so users know something actually happened [David Golden] - Cleaned up Changes file formatting [David Golden] - Removed most PERL_CORE customizations from test files due to reorganization of dual-life modules in core (RT#49522) [David Golden] 0.35_05 - Wed Oct 28 17:20:59 EDT 2009 Bug fixes: - Fix test failure in t/actions/installdeps.t when $^X is not the default perl [David Golden] - Work around $VERSION numbers in ActiveState with multiple underscores that prevent Module::Build from installing on Win32 [David Golden] - Fix bug cleaning compatibility Makefile when older ExtUtils::Manifest is installed [David Golden with help from David Cantrell] Other: - Suppressed more warnings from tests [David Golden] - Add provisional support for 'package NAME VERSION' syntax added in Perl 5.11.1 [David Golden] 0.35_04 - Fri Oct 23 11:20:41 EDT 2009 Bug fixes: - Fix test failure if IPC::Cmd isn't installed [David Golden] Other: - Suppressed warning messages from various tests [David Golden] 0.35_03 - Wed Oct 21 21:20:59 EDT 2009 *** API CHANGE *** - The prepare_metadata() method used to take a YAML::Node object as an argument for modification. The method now takes no arguments and just returns a hash reference of metadata. [David Golden] Enhancements - Command line options may be set via the PERL_MB_OPT environment variable (similar to PERL_MM_OPT in ExtUtils::MakeMaker) Bug fixes: - Updated PPM generation to PPM v4 (RT#49600) [Olivier Mengue] - When c_source is specified, the directory scan will include additional, less-common C++ extensions (RT49298) [David Golden] - When module_name is not supplied, no packlist was being written; fixed by guessing module_name from dist_version_from or the directory name (just like ExtUtils::Manifest does without NAME) [David Golden] - Bumped IO::File prereq to fix binmode failures in PPMMaker on Perl prior to 5.8.8 [David Golden] Other: - Replaced use of YAML.pm with YAML::Tiny; Module::Build::YAML is now based on YAML::Tiny as well [David Golden] - Reduced amount of console output under normal operation (use --verbose to see all output) [David Golden] 0.35_02 - Mon Sep 7 22:37:42 EDT 2009 Enhancements: - Added 'needs_compiler' property. Defaults to true if XS or c_source exist. If true, ExtUtils::CBuilder is also added to build_requires. [David Golden] - File::ShareDir automatically added to 'requires' if 'share_dir' is set [David Golden] - Added 'Build installdeps' action to install needed dependencies via a user-configurable command line program. (Defaults to 'cpan'.) [Eric Wilhelm] Bug fixes: - Failure to detect a compiler will now warn during Build.PL and be a fatal error when trying to compile during Build. (RT#48918) [David Golden] - Fixed directory sorting failure in share_dir.t [David Golden] - Property defaults that are data structures were being assigned as references to new objects. Changed so that defaults are cloned instead. (This mostly affects testing, which often creates multiple objects in the same process) [David Golden] - Simplified error message on exit under use_tap_harness [suggested by David Wheeler] - Fixed typemap search to use a dist-level typemap if a typemap is not found in the directory with the *.xs file; (was manifesting as warnings in Perl 5.6 tests) [David Golden] Other: - Replaced guts of new_from_context(). Build.PL is now executed in a separate process before resume() is called. (This is generally only of interest to Module::Build or toolchain developers) (RT#49350) [David Golden, Eric Wilhelm, Ken Williams] - Revised test helper classes to fix potential bugs and add new features to make writing tests simpler and easier. Changes incorporated into t/README.pod and t/sample.t as examples for new testing. [David Golden] 0.35_01 - Mon Aug 31 12:11:10 EDT 2009 Enhancements: - Generates MYMETA.yml during Build.PL (new standard protocol for communicating configuration results between toolchain components) [David Golden] - Added 'share_dir' property to provide File::ShareDir support; set automatically if a directory called 'share' exists [David Golden] Bug fixes: - Fix the t/destinations.t fix. [David Golden, with thanks to Eric Wilhelm] - Fix recursive test files in generated Makefile.PL (RT#49254) [Sawyer X] - Guard against trying :utf8 when :utf8 isn't available - The "test" action now dies when using the 'use_tap_harness' option and tests fail, matching the behavior under Test::Harness. (RT#49080) [initial patch from David Wheeler; revised by David Golden] Other: - Added t/README.pod and t/sample.t to guide developers writing new tests [David Golden, with some code from Eric Wilhelm] - Module::Build::Compat 'passthrough' style has been deprecated. Using 'passthrough' will issue warnings on Makefile.PL generation. See Module::Build::Compat documentation for rationale. --- diff --git a/.gitignore b/.gitignore index 74b65eb..a20fbf9 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,7 @@ ext.libs /uudmap.h /bitcount.h +lib/inc/ lib/Win32.pm lib/Win32API/ lib/Win32CORE.pm diff --git a/MANIFEST b/MANIFEST index b8073eb..2d76a3a 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1519,9 +1519,12 @@ cpan/MIME-Base64/t/quoted-print.t See whether MIME::QuotedPrint works cpan/MIME-Base64/t/unicode.t See whether MIME::Base64 works cpan/MIME-Base64/t/warn.t See whether MIME::Base64 works cpan/Module-Build/Changes Module::Build +cpan/Module-Build/lib/inc/latest.pm Module::Build +cpan/Module-Build/lib/inc/latest/private.pm Module::Build cpan/Module-Build/lib/Module/Build/API.pod Module::Build cpan/Module-Build/lib/Module/Build/Authoring.pod Module::Build cpan/Module-Build/lib/Module/Build/Base.pm Module::Build +cpan/Module-Build/lib/Module/Build/Bundling.pod Module::Build cpan/Module-Build/lib/Module/Build/Compat.pm Module::Build cpan/Module-Build/lib/Module/Build/Config.pm Module::Build cpan/Module-Build/lib/Module/Build/Cookbook.pm Module::Build @@ -1548,33 +1551,42 @@ cpan/Module-Build/lib/Module/Build/PPMMaker.pm Module::Build cpan/Module-Build/lib/Module/Build/Version.pm Module::Build cpan/Module-Build/lib/Module/Build/YAML.pm Module::Build cpan/Module-Build/scripts/config_data Module::Build +cpan/Module-Build/t/actions/installdeps.t Module::Build cpan/Module-Build/t/add_property.t Module::Build cpan/Module-Build/t/basic.t Module::Build -cpan/Module-Build/t/bundled/Tie/CPHash.pm Module::Build.pm +cpan/Module-Build/t/bundled/Tie/CPHash.pm Module::Build +cpan/Module-Build/t/bundle_inc.t Module::Build cpan/Module-Build/t/compat/exit.t Module::Build cpan/Module-Build/t/compat.t Module::Build -cpan/Module-Build/t/debug.t Module::Build tests +cpan/Module-Build/t/debug.t Module::Build cpan/Module-Build/t/destinations.t Module::Build cpan/Module-Build/t/extend.t Module::Build cpan/Module-Build/t/ext.t Module::Build cpan/Module-Build/t/files.t Module::Build cpan/Module-Build/t/help.t Module::Build -cpan/Module-Build/t/install_extra_target.t Module::Build tests +cpan/Module-Build/t/install_extra_target.t Module::Build cpan/Module-Build/t/install.t Module::Build cpan/Module-Build/t/lib/DistGen.pm Module::Build cpan/Module-Build/t/lib/MBTest.pm Module::Build cpan/Module-Build/t/manifypods.t Module::Build -cpan/Module-Build/t/mbyaml.t Module::Build cpan/Module-Build/t/metadata2.t Module::Build cpan/Module-Build/t/metadata.t Module::Build cpan/Module-Build/t/moduleinfo.t Module::Build +cpan/Module-Build/t/mymeta.t Module::Build cpan/Module-Build/t/new_from_context.t Module::Build cpan/Module-Build/t/notes.t Module::Build cpan/Module-Build/t/parents.t Module::Build -cpan/Module-Build/t/PL_files.t Module::Build tests +cpan/Module-Build/t/perl_mb_opt.t Module::Build +cpan/Module-Build/t/PL_files.t Module::Build cpan/Module-Build/t/pod_parser.t Module::Build cpan/Module-Build/t/ppm.t Module::Build +cpan/Module-Build/t/properties/module_name.t Module::Build +cpan/Module-Build/t/properties/needs_compiler.t Module::Build +cpan/Module-Build/t/properties/share_dir.t Module::Build +cpan/Module-Build/t/README.pod Module::Build +cpan/Module-Build/t/resume.t Module::Build cpan/Module-Build/t/runthrough.t Module::Build +cpan/Module-Build/t/sample.t Module::Build cpan/Module-Build/t/script_dist.t Module::Build cpan/Module-Build/t/test_file_exts.t Module::Build cpan/Module-Build/t/test_types.t Module::Build @@ -1582,7 +1594,7 @@ cpan/Module-Build/t/test_type.t Module::Build cpan/Module-Build/t/tilde.t Module::Build cpan/Module-Build/t/use_tap_harness.t Module::Build cpan/Module-Build/t/versions.t Module::Build -cpan/Module-Build/t/write_default_maniskip.t Module::Build tests +cpan/Module-Build/t/write_default_maniskip.t Module::Build cpan/Module-Build/t/xs.t Module::Build cpan/Module-Load-Conditional/lib/Module/Load/Conditional.pm Module::Conditional cpan/Module-Load-Conditional/t/01_Module_Load_Conditional.t Module::Conditional tests diff --git a/Porting/Maintainers.pl b/Porting/Maintainers.pl index e5db2eb..5ffa715 100755 --- a/Porting/Maintainers.pl +++ b/Porting/Maintainers.pl @@ -104,7 +104,7 @@ use File::Glob qw(:case); SIGNATURE THANKS TODO Todo VERSION WHATSNEW ); - + # Each entry in the %Modules hash roughly represents a distribution, # except in the case of CPAN=1, where it *exactly* represents a single # CPAN distribution. @@ -159,7 +159,7 @@ use File::Glob qw(:case); # Each key reprepresents a string prefix, with longest prefixes checked # first. The first match causes that prefix to be replaced with the # corresponding key. For example, with the following MAP: -# { +# { # 'lib/' => 'lib/', # '' => 'lib/Foo/', # }, @@ -167,7 +167,7 @@ use File::Glob qw(:case); # these files are mapped as shown: # # README becomes lib/Foo/README -# lib/Foo.pm becomes lib/Foo.pm +# lib/Foo.pm becomes lib/Foo.pm # # The default is dependent on the type of module. # For distributions which appear to be stored under ext/, it defaults to: @@ -176,7 +176,7 @@ use File::Glob qw(:case); # # otherwise, it's # -# { +# { # 'lib/' => 'lib/', # '' => 'lib/Foo/Bar/', # } @@ -1004,10 +1004,10 @@ use File::Glob qw(:case); 'Module::Build' => { 'MAINTAINER' => 'kwilliams', - 'DISTRIBUTION' => 'DAGOLDEN/Module-Build-0.35.tar.gz', + 'DISTRIBUTION' => 'DAGOLDEN/Module-Build-0.35_08.tar.gz', 'FILES' => q[cpan/Module-Build], - 'EXCLUDED' => [ qw{ t/par.t t/signature.t scripts/bundle.pl}, - qr!^contrib/! ], + 'EXCLUDED' => [ qw{ t/par.t t/signature.t }, + qr!^contrib/!, qr!^devtools! ], 'CPAN' => 1, 'UPSTREAM' => 'cpan', }, diff --git a/cpan/Module-Build/Changes b/cpan/Module-Build/Changes index df66502..f0f8d1b 100644 --- a/cpan/Module-Build/Changes +++ b/cpan/Module-Build/Changes @@ -1,24 +1,238 @@ Revision history for Perl extension Module::Build. +0.35_08 - Mon Nov 16 22:38:28 EST 2009 + + Bug fixes: + + - Multiple tests were failing due to dependency problems. Author + dependencies have been largely removed from core 'requires' into + optional features. Feature prereq detection and messaging have been + expanded and bugs on older Perls have been removed. + +0.35_07 - Sat Nov 14 17:14:39 EST 2009 + + Bug fixes: + + - Auto-detection of abstract and author fixed for mixed-case POD headers + (RT#51117) [David Wheeler] + + - resume() was not restoring additions to @INC added in Build.PL + (RT#50145) [David Golden] + + - When tarball paths are less than 100 characters, disables 'prefix' + mode of Archive::Tar for maximum compatibility (RT#50571) [David Golden] + +0.35_06 - Fri Nov 13 14:51:28 EST 2009 + + Enhancements: + + - Added experimental inc/ bundling; see Module::Build::Bundling for + details. [David Golden and Eric Wilhelm] + + - Clarified that 'apache' in the license attribute indicates the Apache + License 2.0 and added 'apache_1_1' for the older version of the license + (RT#50614) [David Golden] + + Bug fixes: + + - Merging 'requires' and 'build_requires' in Module::Build::Compat could + lead to duplicate PREREQ_PM entries; now the highest version is used + for PREREQ_PM. (RT#50948) [David Golden] + + - Module::Build::Compat will now die with an error if advanced, + non-numeric prerequisites are given, as these are not supported by + ExtUtils::MakeMaker in PREREQ_PM [David Golden] + + - Made MYMETA generation non-fatal if fields required for META.yml + are missing [David Golden] + + - Added Pod::Simple to requirements for manpage support; avoids + problems if a user has a broken Pod::Man/Pod::Simple. (RT#50081) + [David Golden] + + - Won't die if installed Pod::Readme is broken [David Golden] + + Other: + + - Fixed Module::Build::Notes POD [David Golden] + + - Some commands had become silent by default, so added a few short status + messages so users know something actually happened [David Golden] + + - Cleaned up Changes file formatting [David Golden] + + - Removed most PERL_CORE customizations from test files due to + reorganization of dual-life modules in core (RT#49522) [David Golden] + +0.35_05 - Wed Oct 28 17:20:59 EDT 2009 + + Bug fixes: + + - Fix test failure in t/actions/installdeps.t when $^X is not the default + perl [David Golden] + + - Work around $VERSION numbers in ActiveState with multiple underscores + that prevent Module::Build from installing on Win32 [David Golden] + + - Fix bug cleaning compatibility Makefile when older ExtUtils::Manifest is + installed [David Golden with help from David Cantrell] + + Other: + + - Suppressed more warnings from tests [David Golden] + + - Add provisional support for 'package NAME VERSION' syntax added in + Perl 5.11.1 [David Golden] + +0.35_04 - Fri Oct 23 11:20:41 EDT 2009 + + Bug fixes: + + - Fix test failure if IPC::Cmd isn't installed [David Golden] + + Other: + + - Suppressed warning messages from various tests [David Golden] + +0.35_03 - Wed Oct 21 21:20:59 EDT 2009 + + *** API CHANGE *** + + - The prepare_metadata() method used to take a YAML::Node object as an + argument for modification. The method now takes no arguments and just + returns a hash reference of metadata. [David Golden] + + Enhancements + + - Command line options may be set via the PERL_MB_OPT environment + variable (similar to PERL_MM_OPT in ExtUtils::MakeMaker) + + Bug fixes: + + - Updated PPM generation to PPM v4 (RT#49600) [Olivier Mengue] + + - When c_source is specified, the directory scan will include additional, + less-common C++ extensions (RT49298) [David Golden] + + - When module_name is not supplied, no packlist was being written; fixed + by guessing module_name from dist_version_from or the directory name + (just like ExtUtils::Manifest does without NAME) [David Golden] + + - Bumped IO::File prereq to fix binmode failures in PPMMaker on Perl + prior to 5.8.8 [David Golden] + + Other: + + - Replaced use of YAML.pm with YAML::Tiny; Module::Build::YAML is now + based on YAML::Tiny as well [David Golden] + + - Reduced amount of console output under normal operation (use --verbose + to see all output) [David Golden] + +0.35_02 - Mon Sep 7 22:37:42 EDT 2009 + + Enhancements: + + - Added 'needs_compiler' property. Defaults to true if XS or c_source + exist. If true, ExtUtils::CBuilder is also added to build_requires. + [David Golden] + + - File::ShareDir automatically added to 'requires' if 'share_dir' is set + [David Golden] + + - Added 'Build installdeps' action to install needed dependencies via + a user-configurable command line program. (Defaults to 'cpan'.) + [Eric Wilhelm] + + Bug fixes: + + - Failure to detect a compiler will now warn during Build.PL and be a + fatal error when trying to compile during Build. (RT#48918) [David + Golden] + + - Fixed directory sorting failure in share_dir.t [David Golden] + + - Property defaults that are data structures were being assigned as + references to new objects. Changed so that defaults are cloned instead. + (This mostly affects testing, which often creates multiple objects in the + same process) [David Golden] + + - Simplified error message on exit under use_tap_harness [suggested by + David Wheeler] + + - Fixed typemap search to use a dist-level typemap if a typemap is not + found in the directory with the *.xs file; (was manifesting as warnings + in Perl 5.6 tests) [David Golden] + + Other: + + - Replaced guts of new_from_context(). Build.PL is now executed in a + separate process before resume() is called. (This is generally only of + interest to Module::Build or toolchain developers) (RT#49350) [David + Golden, Eric Wilhelm, Ken Williams] + + - Revised test helper classes to fix potential bugs and add new features + to make writing tests simpler and easier. Changes incorporated into + t/README.pod and t/sample.t as examples for new testing. [David Golden] + +0.35_01 - Mon Aug 31 12:11:10 EDT 2009 + + Enhancements: + + - Generates MYMETA.yml during Build.PL (new standard protocol for + communicating configuration results between toolchain components) + [David Golden] + + - Added 'share_dir' property to provide File::ShareDir support; + set automatically if a directory called 'share' exists + [David Golden] + + Bug fixes: + + - Fix the t/destinations.t fix. [David Golden, with thanks to Eric Wilhelm] + + - Fix recursive test files in generated Makefile.PL (RT#49254) [Sawyer X] + + - Guard against trying :utf8 when :utf8 isn't available + + - The "test" action now dies when using the 'use_tap_harness' + option and tests fail, matching the behavior under Test::Harness. + (RT#49080) [initial patch from David Wheeler; revised by David Golden] + + Other: + + - Added t/README.pod and t/sample.t to guide developers writing new tests + [David Golden, with some code from Eric Wilhelm] + + - Module::Build::Compat 'passthrough' style has been deprecated. Using + 'passthrough' will issue warnings on Makefile.PL generation. See + Module::Build::Compat documentation for rationale. + 0.35 - Thu Aug 27 09:12:02 EDT 2009 Bug fixes: - - Fix t/destinations.t segfault on 5.6.2 + + - Fix t/destinations.t segfault on 5.6.2 [David Golden] 0.34_06 - Sat Aug 22 21:58:26 EDT 2009 Bug fixes: + - Multiple test fixes for OS2 [Ilya Zakharevich] + - Generated.ppd files use :utf8 if possible (RT#48827) [Olivier Mengue] + - Fixed preservation of custom install_paths on resume (RT#41166) [David Golden] + - Warn instead of crashing when Pod::Man tries to create files with colons on vfat partitions on unix (RT#45544) [David Golden] 0.34_05 - Sun Aug 9 22:31:37 EDT 2009 Bug fixes: - - When auto_configure_requires is true (the default), Module::Build will + + - When auto_configure_requires is true (the default), Module::Build will only add last 'major' version of Module:Build (e.g. 0.XX) to configure_requires to avoid specifying a minor development release not available on CPAN [David Golden] @@ -26,6 +240,7 @@ Revision history for Perl extension Module::Build. 0.34_04 - Sat Aug 8 11:02:24 EDT 2009 Other: + - Added documentation warning that 'get_options' should be capitalized to avoid conflicting with future Module::Build options and changed the examples accordingly. @@ -33,12 +248,17 @@ Revision history for Perl extension Module::Build. 0.34_03 - Sat Aug 8 07:39:16 EDT 2009 Bug fixes: + - Fixed failing xs.t if /tmp is mounted noexec (RT#47331) [David Golden] + - Fixed failing debug.t on VMS (RT#48362) [Craig Berry] + - Prevent par.t from dying on error in .zip extraction [David Golden] + - Fixed potential runthrough.t failure on 5.6.2 [David Golden] Other: + - Archive::Tar changed from 'requires' to 'recommends' so non-authors without IO::Zlib can still use Module::Build to install modules [reported by Matt Trout, fix by David Golden] @@ -46,22 +266,26 @@ Revision history for Perl extension Module::Build. 0.340201 - Sun Aug 9 22:11:04 EDT 2009 Other: + - Version bump for Perl core for 5.10.1 release; no other changes 0.34_02 - Sun Jul 26 22:50:40 EDT 2009 Bug-fixes: + - Bundled Module::Build::Version updated to bring into sync with CPAN version.pm 0.77 [John Peacock] 0.34_01 - Sat Jul 18 16:32:09 EDT 2009 Enhancements: + - Added --debug flag to trace Build action execution (RT#47933) [David Golden] Bug-fixes: - - Bundled Module::Build::Version version code updated to fix unsafe use + + - Bundled Module::Build::Version version code updated to fix unsafe use of $@ (RT#47980) [John Peacock] 0.34 - Tue Jul 7 16:56:47 EDT 2009 @@ -71,27 +295,33 @@ Revision history for Perl extension Module::Build. 0.33_06 - Sun Jul 5 10:11:40 EDT 2009 Bug-fixes: + - Bundled version code will use pure Perl on 5.10.0 to work around a corner case involving eval and locale [John Peacock] + - Reversed VMS patch from 0.33_03 [Craig Berry] + - PL_files in Build.PL that are in the bin/scripts directory should not be - installed as if they are scripts (fixed for case-tolerant systems). + installed as if they are scripts (fixed for case-tolerant systems). [David Golden, reported by Craig Berry] 0.33_05 - Sun Jun 28 22:06:49 EDT 2009 Enhancements: + - New 'auto_configure_requires' parameter (default 1) controls whether Module::Build should add itself to configure_requires in META.yml if not specified in Build.PL [David Golden] Bug-fixes: + - The default MANIFEST.SKIP created by the "manifest" action was out of date. It will now use the installed MANIFEST.SKIP and add some Module::Build and distribution specific items to it. [Michael Schwern] Other: + - configure_requires do not necessarily need to be in requires or build_requires; warning to that effect has been removed [David Golden] @@ -99,99 +329,141 @@ Revision history for Perl extension Module::Build. 0.33_04 - Fri Jun 26 07:09:06 EDT 2009 Bug-fixes: + - Don't try utf8 YAML I/O on Perl 5.6 [David Golden] Other: + - configure_requires added to prereq report (RT#47254) [Curtis Jewell] + - updated Module::Build::Version to match forthcoming version.pm 0.77 (RT#47256) [John Peacock] + - skips xs.t and ppm.t when perl was not compiled with dynamic loading - since Module::Buld does not support static linking (RT#46178) + since Module::Buld does not support static linking (RT#46178) [David Golden] + - skip failing test in par.t if Archive::Zip is broken [David Golden] + - Added YAML utf8 patch in 0.33_03 changes list + - Added attribution for patches in 0.33_03 changes list 0.33_03 - Mon Jun 22 17:22:56 EDT 2009 Bug-fixes: - - Removes Module::Build from its own configure/build_requires + + - Removes Module::Build from its own configure/build_requires [David Golden] + - ConfigData->feature() confirms that modules actually load successfully, not just that they are present. (RT#43557) [David Golden] - - Module::Build::Compat handling of INSTALL*LIB (RT#43827) + + - Module::Build::Compat handling of INSTALL*LIB (RT#43827) [Tony Payne, David Golden] + - Module::Build::Compat and recursive test files (RT#39171) [Dave Rolsky] + - Fixed bug linking non-standard XS names on Windows (RT#38065) ["snaury"] - - Run PL files that don't generate any file (RT#39365) + + - Run PL files that don't generate any file (RT#39365) [Matisse Enzer, David Golden] + - HTML generation failure no longer fatal (RT#36660) [David Golden] - - realclean might not delete Build.bat on Windows (RT#43863) + + - realclean might not delete Build.bat on Windows (RT#43863) [Roy Ivy, David Golden] + - include_dirs parameter now works correctly when given a single string argument (RT#40177) [David Wheeler] + - Lots of spelling fixes in the POD (RT#45528r) [Lars Dieckow] + - On Unix-like systems, tilde expansion is more liberal in username characters accepted (RT#33492) [Jon Jensen] Other + - On MSWin32, bumped File::Spec prereq to 3.30 for a variety of fixes + - Add support for VMS in Unix compatibility mode (RT#42157) [John E. Malmberg - - Added a can_action($name) method (RT#45172) [brian d foy] + + - Added a can_action($name) method (RT#45172) [brian d foy] + - Documented that subclass methods should not permanently change current directory (RT#46919) [David Wheeler] + - META.yml encoded in UTF-8 (RT#43765) [Olivier Mengue] 0.33_02 - Mon Jun 15 12:23:55 EDT 2009 Bug-fixes: + - Fixed tests for bleadperl 0.33_01 - Sat Jun 13 20:24:42 EDT 2009 Bug-fixes: + - Fixed RT#42724: consolidated VMS fixes [patch by Craig Berry] + - Fixed RT#46338: passthrough Makefile.PL cleans Makefile during distclean + - Fixed RT#45700: t/compat.t for HP/UX make Other: - - Adds current Module::Build to configure_requires (and build_requires) + + - Adds current Module::Build to configure_requires (and build_requires) if no configure_requires is specified + - Always normalizes version number tuples in META.yml (e.g. 'v1.2.0') - (Partially addresses RT#46150) - - Normalizes a generated dist_version (e.g. from a .pm file) -- + (Partially addresses RT#46150) + + - Normalizes a generated dist_version (e.g. from a .pm file) -- dist_version set manually in Build.PL is not normalized + - Documentation update for create_license + - Minor POD cleanup 0.33 - Sun May 3 20:16:34 PDT 2009 Bug-fixes: + - Fixed RT#45462: Compat.pm needs to reference 'Build.com' on VMS [patch from John Malmberg] + - Fixed RT#45461: ext.t on VMS [patch from John Malmberg] + - Fixed RT#43861: Module::Build::PPMMaker has broken PPD name versioning for v5.10+ 0.32_01 - Tue Apr 14 17:14:22 PDT 2009 Bug-fixes: + - Module::Build::Compat had stopped adding "PL_FILES => {}" when no PL_files property was set in Build.PL; restored old behavior and fixed tests and documentation related to this issue [David Golden] - - Caches ExtUtils::CBuilder object in a temporary stash instead of properties + + - Caches ExtUtils::CBuilder object in a temporary stash instead of properties + - Fixed undef resources->license in META.yml (RT #44453). + - Use $^X instead of 'perl' in t/ext.t [David Golden] (RT #43485) Other: + - Generated META.yml will indicate version 1.4 of the specification (RT #37478) [patch from Alexandr Ciornii] + - Archive::Tar now the default for generating tarballs on all platforms (avoids problems with incompatible tar binaries) + - dist_dir() now uses dist_name() and dist_version() accessors rather than using its properties directly. [brian d foy] (RT #45038) - + 0.32 - Wed Feb 25 17:40:02 PST 2009 No changes since 0.31_04. @@ -199,100 +471,129 @@ Revision history for Perl extension Module::Build. 0.31_04 - Fri Feb 20 11:04:59 PST 2009 Other - - Bumped Test::Harness prereq to 3.16 for latest PERL5LIB fixes (solves + +- Bumped Test::Harness prereq to 3.16 for latest PERL5LIB fixes (solves test failures when installing Module::Build using CPANPLUS::Dist::Build) [David Golden] 0.31_03 - Sun Feb 8 14:54:01 PST 2009 Enhancements + - added a "prereq_data" action that prints a Perl data structure of all prerequisites; can be loaded by external tools using eval() [David Golden] Bug-fixes + - 'fakeinstall' action warns and skips without ExtUtils::Install 1.32+ [David Golden, reported by Zefram] + - allows Module::Build version mismatch when installing self; works around limitations in CPANPLUS::Dist::Build [David Golden] 0.31_02 - Tue Jan 27 09:16:43 PST 2009 Other + - tests now use File::Temp (added to build_requires); appears to fix Win32 testing heisenbug on directory removal during high system loads + - use_tap_harness.t will skip unless a release version of TAP::Harness is installed + - improved diagnostics to ensure_blib() tests in t/lib/MBTest.pm Compat + - passthrough Makefile.PL will now play nice with cpantesters' on exit(0) (RT#32018) [Eric Wilhelm] Bug Fixes + - fix for doubling-up of --prefix (RT#19951) 0.31012 - Wed Jan 14 01:36:19 PST 2009 Bug Fixes + - t/tilde.t maybe actually fixed on MSWin32 now. 0.31011 - Mon Jan 12 21:57:04 PST 2009 Bug Fixes + - t/tilde.t had been failing on MSWin32 (RT#42349) 0.3101 - Mon Jan 12 13:52:36 PST 2009 Other + - added 'mirbsd' as a Unix-type OS [BinGOs] + - added 'haiku' as a Unix-type OS (backported from bleadperl) + - skips certain tests on VMS (backported from bleadperl) + - sets $^X to absolute path in tests (backported from bleadperl) 0.31 - Sat Dec 20 15:03:33 2008 Deprecations + - Use of attributes as class methods is deprecated (this was never a documented feature and appears to only have worked accidentally.) 0.30_02 - Mon Dec 15 12:23:55 PST 2008 Bug Fixes + - make Software::License dependency "softer". 0.30_01 - Thu Dec 11 18:25:53 PST 2008 New Docs + - Added a recipe for writing a new action to the Cookbook + - Added a recipe for bundling Module::Build to the Cookbook. Doc Fixes + - Clarified dist_abstract search procedure in API.pod (RT#41056) [Mario Domgoergen] Bug Fixes + - Workaround HARNESS_TIMER env issue in t/compat.t (RT#39635) + - Fix ~ expansion when $HOME is different from /etc/passwd as when running sudo. [rt.cpan.org 39662] + - Fixed a small POD error in the Cookbook. [Damyan Ivanov] + - Unset group/other write permission bits when using Archive::Tar to build the dist tarball. (RT#39804) [David Golden] Enhancements + - We now support a 'create_license' parameter to new() that will create a LICENSE file during the 'dist' phase with the full text of the license. This requires Software::License on the author's machine. + - Added lgpl2/lgpl3 entries to the supported licenses (RT#40532). + - Support for validating properties with a check subref. [David Wheeler] Test Fixes + - Defend against more stray environment variables interfering with the tests. Other + - Updated our embedded version.pm to 0.76, enhanced documentation on dist_version_from. [John Peacock] @@ -484,11 +785,11 @@ Revision history for Perl extension Module::Build. have stopped, but it didn't. Fixed. [Matthew Cast and David Golden] - - Module::Build::Compat adds "require 5.XXXXX" to Makefile.PL when + - Module::Build::Compat adds "require 5.XXXXX" to Makefile.PL when 'perl' is specified as a 'requires' prerequisite [David Golden] - - Refactored t/compat.t for modularity and transparency; added - labels for all tests; supressed subprocess output to + - Refactored t/compat.t for modularity and transparency; added + labels for all tests; supressed subprocess output to STDOUT and STDERR [David Golden] - Fixed bug in perl_version_to_float when version is already a float @@ -1015,7 +1316,7 @@ Revision history for Perl extension Module::Build. - The synonyms 'scripts' and 'prereq' for 'script_files' and 'requires' were broken in a previous version (0.27_01, probably), but now they're fixed. [David Golden] - + - Previously, we assumed that any custom subclass of Module::Build was located in _build/lib/. This is only true if the author used the subclass() method, though. We now use %INC to find where the @@ -2162,13 +2463,13 @@ Revision history for Perl extension Module::Build. - Added experimental code to build a .ppd file, in support of ActiveState's "Perl Package Manager". [original patch by Dave Rolsky] - + - For authors who use Module::Signature to sign their distributions, we now create the SIGNATURE file right in the distribution directory, rather than creating it in the top-level directory and copying it into place. This solves problems related to having files get out of date with respect to their signatures. - + - We now don't depend on Module::Info to scan for packages during the 'dist' action anymore, because it's way too aggressive about loading other modules that you may not want loaded. We now just @@ -2231,12 +2532,12 @@ Revision history for Perl extension Module::Build. - The distribution directory (e.g. Sample-Module-0.13/ ) will now be deleted during the 'clean' or 'realclean' actions. - + - During testing of modules, blib/lib and blib/arch are now added as absolute paths, not relative. This helps tests that load the modules at runtime and may change the current working directory (like Module::Build itself does during testing). - + - The $Config{cc} entry on some people's systems is something like 'ccache gcc', so we now split that string using split_like_shell(). [Richard Clamp] @@ -2266,7 +2567,7 @@ Revision history for Perl extension Module::Build. - When compiling C code, we now respect 'pollute' and 'inc' parameters. (XXX - needs docs) [Dave Rolsky] - + - Made the creation of the "install map" more generic. (XXX - needs documentation) @@ -2623,7 +2924,7 @@ Revision history for Perl extension Module::Build. - Renamed module_name_to_file() to find_module_by_name(), and added a parameter specifying the directories to search in. Previously we searched in 'lib' and @INC, which wasn't correct in all - situations. + situations. - Patched the docs to change "Build test" to "./Build test" [Elizabeth Mattijsen] @@ -2817,7 +3118,7 @@ Revision history for Perl extension Module::Build. - For the 'Build dist' action, we'll use the 'tar' and 'gzip' programs (as specified by Config.pm) on Unix platforms, otherwise we'll use Archive::Tar and Compress::Zlib. - + 0.02 Wed Sep 5 00:53:04 CDT 2001 - Added POD documentation. diff --git a/cpan/Module-Build/lib/Module/Build.pm b/cpan/Module-Build/lib/Module/Build.pm index be8c1f7..efae7f9 100644 --- a/cpan/Module-Build/lib/Module/Build.pm +++ b/cpan/Module-Build/lib/Module/Build.pm @@ -15,7 +15,7 @@ use Module::Build::Base; use vars qw($VERSION @ISA); @ISA = qw(Module::Build::Base); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; # Okay, this is the brute-force method of finding out what kind of @@ -167,24 +167,24 @@ This illustrates initial configuration and the running of three 'actions'. In this case the actions run are 'build' (the default action), 'test', and 'install'. Other actions defined so far include: - build manpages - clean pardist - code ppd - config_data ppmdist - diff prereq_data - dist prereq_report - distcheck pure_install - distclean realclean - distdir retest - distmeta skipcheck - distsign test - disttest testall - docs testcover - fakeinstall testdb - help testpod - html testpodcoverage - install versioninstall - manifest + build manifest + clean manpages + code pardist + config_data ppd + diff ppmdist + dist prereq_data + distcheck prereq_report + distclean pure_install + distdir realclean + distmeta retest + distsign skipcheck + disttest test + docs testall + fakeinstall testcover + help testdb + html testpod + install testpodcoverage + installdeps versioninstall You can run the 'help' action for a complete list of actions. @@ -318,7 +318,7 @@ tarball of the files listed in F and compress the tarball using GZIP compression. By default, this action will use the C module. However, you can -force it to use binary "tar" and "gzip" executables by supplying an explicit +force it to use binary "tar" and "gzip" executables by supplying an explicit C (and optional C) parameter: ./Build dist --tar C:\path\to\tar.exe --gzip C:\path\to\zip.exe @@ -355,8 +355,8 @@ F is a file containing various bits of I about the distribution. The metadata includes the distribution name, version, abstract, prerequisites, license, and various other data about the distribution. This file is created as F in YAML format. -It is recommended that the C module be installed to create it. -If the C module is not installed, an internal module supplied +It is recommended that the C module be installed to create it. +If the C module is not installed, an internal module supplied with Module::Build will be used to write the META.yml file, and this will most likely be fine. @@ -445,6 +445,24 @@ This can be a good idea, as it helps prevent multiple versions of a module from being present on your system, which can be a confusing situation indeed. +=item installdeps + +[version 0.36] + +This action will use the C parameter as a command to install +missing prerequisites. You will be prompted whether to install +optional dependencies. + +The C option defaults to 'cpan' but can be set as an option or in +F<.modulebuildrc>. It must be a shell command that takes a list of modules to +install as arguments (e.g. 'cpanp -i' for CPANPLUS). If the program part is a +relative path (e.g. 'cpan' or 'cpanp'), it will be located relative to the perl +program that executed Build.PL. + + /opt/perl/5.8.9/bin/perl Build.PL + ./Build installdeps --cpan_client 'cpanp -i' + # installs to 5.8.9 + =item manifest [version 0.05] @@ -541,7 +559,7 @@ for a bug report. [version 0.28] This action is identical to the C action. In the future, -though, when C starts writing to the file +though, when C starts writing to the file F<$(INSTALLARCHLIB)/perllocal.pod>, C won't, and that will be the only difference between them. @@ -666,7 +684,7 @@ argument. [version 0.25] -This checks all the files described in the C action and +This checks all the files described in the C action and produces C-style output. If you are a module author, this is useful to run before creating a new release. @@ -674,7 +692,7 @@ this is useful to run before creating a new release. [version 0.28] -This checks the pod coverage of the distribution and +This checks the pod coverage of the distribution and produces C-style output. If you are a module author, this is useful to run before creating a new release. @@ -731,15 +749,20 @@ C or C (e.g. C<--noverbose> or C<--no-verbose>). Suppress informative messages on output. +=item verbose + +Display extra information about the Build on output. + +=item cpan_client + +Sets the C command for use with the C action. +See C for more details. + =item use_rcfile Load the F<~/.modulebuildrc> option file. This option can be set to false to prevent the custom resource file from being loaded. -=item verbose - -Display extra information about the Build on output. - =item allow_mb_mismatch Suppresses the check upon startup that the version of Module::Build @@ -754,7 +777,6 @@ executed build actions. =back - =head2 Default Options File (F<.modulebuildrc>) [version 0.28] @@ -782,15 +804,35 @@ key C<*> (asterisk) denotes any global options that should be applied to all actions, and the key 'Build_PL' specifies options to be applied when you invoke C. - * verbose=1 # global options - diff flags=-u - install --install_base /home/ken - --install_path html=/home/ken/docs/html + * verbose=1 # global options + diff flags=-u + install --install_base /home/ken + --install_path html=/home/ken/docs/html + installdeps --cpan_client 'cpanp -i' If you wish to locate your resource file in a different location, you can set the environment variable C to the complete absolute path of the file containing your options. +=head2 Environment variables + +=over + +=item MODULEBUILDRC + +[version 0.28] + +Specifies an alternate location for a default options file as described above. + +=item PERL_MB_OPT + +[version 0.36] + +Command line options that are applied to Build.PL or any Build action. The +string is split as the shell would (e.g. whitespace) and the result is +prepended to any actual command-line arguments. + +=back =head1 INSTALL PATHS @@ -1091,7 +1133,7 @@ modify it under the same terms as Perl itself. =head1 SEE ALSO perl(1), L, L, -L, L, L +L, L, L F Specification: L diff --git a/cpan/Module-Build/lib/Module/Build/API.pod b/cpan/Module-Build/lib/Module/Build/API.pod index f4e4cea..1f5d51f 100644 --- a/cpan/Module-Build/lib/Module/Build/API.pod +++ b/cpan/Module-Build/lib/Module/Build/API.pod @@ -454,8 +454,13 @@ Specifies the licensing terms of your distribution. Valid options include: =item apache -The distribution is licensed under the Apache Software License -(L). +The distribution is licensed under the Apache License, Version 2.0 +(L). + +=item apache_1_1 + +The distribution is licensed under the Apache Software License, Version 1.1 +(L). =item artistic @@ -580,6 +585,18 @@ used to set C. Setting C won't override a C parameter you specify explicitly. +=item needs_compiler + +[version 0.36] + +The C parameter indicates whether a compiler is required to +build the distsribution. The default is false, unless XS files are found or +the C parameter is set, in which case it is true. If true, +L is automatically added to C if needed. + +For a distribution where a compiler is I, e.g. a dual XS/pure-Perl +distribution, C should explicitly be set to a false value. + =item PL_files [version 0.06] @@ -737,6 +754,35 @@ For backward compatibility, you may use the parameter C instead of C. Please consider this usage deprecated, though it will continue to exist for several version releases. +=item share_dir + +[version 0.36] + +An optional parameter specifying directories of static data files to +be installed as read-only files for use with L. The +C property supports both distribution-level and +module-level share files. + +The default when C is not set is for any files in a F +directory at the top level of the distribution to be installed in +distribution-level share directory. Alternatively, C can be set to +a directory name or an arrayref of directory names containing files to be +installed in the distribution-level share directory. + +If C is a hashref, it may have C or C keys +providing full flexibility in defining share directories to install. + + share_dir => { + dist => [ 'examples', 'more_examples' ], + module => { + Foo::Templates => ['share/html', 'share/text'], + Foo::Config => 'share/config', + } + } + +If C is set (manually or automatically), then File::ShareDir +will automatically be added to the C hash. + =item sign [version 0.16] @@ -802,25 +848,23 @@ files in your distribution. [version 0.28] -When called from a directory containing a F script and a -F file (in other words, the base directory of a -distribution), this method will run the F and return the -resulting C object to the caller. Any key-value -arguments given to C are essentially like -command line arguments given to the F script, so for example -you could pass C<< verbose => 1 >> to this method to turn on -verbosity. +When called from a directory containing a F script (in other words, +the base directory of a distribution), this method will run the F and +call C to return the resulting C object to the caller. +Any key-value arguments given to C are essentially like +command line arguments given to the F script, so for example you +could pass C<< verbose => 1 >> to this method to turn on verbosity. =item resume() [version 0.03] -You'll probably never call this method directly, it's only called from -the auto-generated C script. The C method is only -called once, when the user runs C. Thereafter, when -the user runs C or another action, the C -object is created using the C method to re-instantiate with -the settings given earlier to C. +You'll probably never call this method directly, it's only called from the +auto-generated C script (and the C method). The +C method is only called once, when the user runs C. +Thereafter, when the user runs C or another action, the +C object is created using the C method to +re-instantiate with the settings given earlier to C. =item subclass() @@ -1527,22 +1571,25 @@ Assigning the value C to an element causes it to be removed. =item prepare_metadata() -[version 0.28] +[version 0.36] -This method is provided for authors to override to customize the -fields of F. It is passed a YAML::Node node object which can -be modified as desired and then returned. E.g. +This method returns a hash reference of metadata that can be used to create a +YAML datastream. It is provided for authors to override or customize the fields +of F. E.g. package My::Builder; use base 'Module::Build'; sub prepare_metadata { my $self = shift; - my $node = $self->SUPER::prepare_metadata( shift ); - $node->{custom_field} = 'foo'; - return $node; + my $data = $self->SUPER::prepare_metadata(); + $data->{custom_field} = 'foo'; + return $data; } +Prior to version 0.36, this method took a YAML::Node as an argument to hold +assembled metadata. + =item prereq_failures() [version 0.11] @@ -1782,6 +1829,10 @@ accessor methods for the following properties: =item build_script() +=item bundle_inc() + +=item bundle_inc_preload() + =item c_source() =item config_dir() @@ -1790,6 +1841,8 @@ accessor methods for the following properties: =item conflicts() +=item cpan_client() + =item create_license() =item create_makefile_pl() @@ -1830,6 +1883,10 @@ accessor methods for the following properties: =item module_name() +=item mymetafile() + +=item needs_compiler() + =item orig_dir() =item perl() @@ -1920,7 +1977,7 @@ modify it under the same terms as Perl itself. =head1 SEE ALSO perl(1), L(3), L(3), -L(3), L(3), L(3) +L(3), L(3), L(3) F Specification: L diff --git a/cpan/Module-Build/lib/Module/Build/Base.pm b/cpan/Module-Build/lib/Module/Build/Base.pm index 531c354..abeea2e 100644 --- a/cpan/Module-Build/lib/Module/Build/Base.pm +++ b/cpan/Module-Build/lib/Module/Build/Base.pm @@ -4,7 +4,7 @@ package Module::Build::Base; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; BEGIN { require 5.00503 } @@ -23,6 +23,7 @@ use Text::ParseWords (); use Module::Build::ModuleInfo; use Module::Build::Notes; use Module::Build::Config; +use Module::Build::Version; #################### Constructors ########################### @@ -31,16 +32,37 @@ sub new { $self->{invoked_action} = $self->{action} ||= 'Build_PL'; $self->cull_args(@ARGV); - + die "Too early to specify a build action '$self->{action}'. Do 'Build $self->{action}' instead.\n" if $self->{action} && $self->{action} ne 'Build_PL'; $self->check_manifest; - $self->check_prereq; - $self->check_autofeatures; + $self->auto_require; + if ( $self->check_prereq + $self->check_autofeatures != 2) { + $self->log_warn(<dist_name eq 'Module-Build' || + $ENV{PERL5_CPANPLUS_IS_RUNNING} || $ENV{PERL5_CPAN_IS_RUNNING} + ) { + $self->log_warn( + "Run 'Build installdeps' to install missing prerequisites.\n\n" + ); + } + } + + # record for later use in resume; + $self->{properties}{_added_to_INC} = [ $self->_added_to_INC ]; + + $self->set_bundle_inc; $self->dist_name; $self->dist_version; + $self->_guess_module_name unless $self->module_name; $self->_find_nested_builds; @@ -52,6 +74,8 @@ sub resume { my $self = $package->_construct(@_); $self->read_config; + unshift @INC, @{ $self->{properties}{_added_to_INC} || [] }; + # If someone called Module::Build->current() or # Module::Build->new_from_context() and the correct class to use is # actually a *subclass* of Module::Build, we may need to load that @@ -72,7 +96,7 @@ sub resume { $self->log_warn(" * WARNING: Configuration was initially created with '$self->{properties}{perl}',\n". " but we are now using '$perl'.\n"); } - + $self->cull_args(@ARGV); unless ($self->allow_mb_mismatch) { @@ -82,7 +106,7 @@ sub resume { " or use --allow_mb_mismatch 1 to skip this version check.\n") if $mb_version ne $self->{properties}{mb_version}; } - + $self->{invoked_action} = $self->{action} ||= 'build'; return $self; @@ -90,18 +114,8 @@ sub resume { sub new_from_context { my ($package, %args) = @_; - - # XXX Read the META.yml and see whether we need to run the Build.PL? - - # Run the Build.PL. We use do() rather than run_perl_script() so - # that it runs in this process rather than a subprocess, because we - # need to make sure that the environment is the same during Build.PL - # as it is during resume() (and thereafter). - { - local @ARGV = $package->unparse_args(\%args); - do './Build.PL'; - die $@ if $@; - } + + $package->run_perl_script('Build.PL',[],[$package->unparse_args(\%args)]); return $package->resume; } @@ -497,6 +511,28 @@ sub _discover_perl_interpreter { "in (@paths)\n"; } +# Adapted from IPC::Cmd::can_run() +sub find_command { + my ($self, $command) = @_; + + if( File::Spec->file_name_is_absolute($command) ) { + return $self->_maybe_command($command); + + } else { + for my $dir ( File::Spec->path ) { + my $abs = File::Spec->catfile($dir, $command); + return $abs if $abs = $self->_maybe_command($abs); + } + } +} + +# Copied from ExtUtils::MM_Unix::maybe_command +sub _maybe_command { + my($self,$file) = @_; + return $file if -x $file && ! -d $file; + return; +} + sub _is_interactive { return -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)) ; # Pipe? } @@ -588,10 +624,18 @@ sub features { } if (my $info = $ph->{auto_features}->access($key)) { - my $failures = $self->prereq_failures($info); - my $disabled = grep( /^(?:\w+_)?(?:requires|conflicts)$/, - keys %$failures ) ? 1 : 0; - return !$disabled; + my $disabled; + for my $type ( @{$self->prereq_action_types} ) { + next if $type eq 'description' || $type eq 'recommends' || ! exists $info->{$type}; + my $prereqs = $info->{$type}; + for my $modname ( sort keys %$prereqs ) { + my $spec = $prereqs->{$modname}; + my $status = $self->check_installed_status($modname, $spec); + if ((!$status->{ok}) xor ($type =~ /conflicts$/)) { return 0; } + if ( ! eval "require $modname; 1" ) { return 0; } + } + } + return 1; } return $ph->{features}->access($key, @_); @@ -614,7 +658,7 @@ BEGIN { *feature = \&features } # Alias sub _mb_feature { my $self = shift; - + if (($self->module_name || '') eq 'Module::Build') { # We're building Module::Build itself, so ...::ConfigData isn't # valid, but $self->features() should be. @@ -625,6 +669,15 @@ sub _mb_feature { } } +sub _warn_mb_feature_deps { + my $self = shift; + my $name = shift; + $self->log_warn( + "The '$name' feature is not available. Please install missing\n" . + "feature dependencies and try again.\n". + $self->_feature_deps_msg($name) . "\n" + ); +} sub add_build_element { my ($self, $elem) = @_; @@ -635,7 +688,7 @@ sub add_build_element { sub ACTION_config_data { my $self = shift; return unless $self->has_config_data; - + my $module_name = $self->module_name or die "The config_data feature requires that 'module_name' be set"; my $notes_name = $module_name . '::ConfigData'; # TODO: Customize name ??? @@ -646,7 +699,7 @@ sub ACTION_config_data { $self->config_file('features') ], $notes_pm); - $self->log_info("Writing config notes to $notes_pm\n"); + $self->log_verbose("Writing config notes to $notes_pm\n"); File::Path::mkpath(File::Basename::dirname($notes_pm)); Module::Build::Notes->write_config_data @@ -661,7 +714,7 @@ sub ACTION_config_data { } ######################################################################## -{ # enclosing these lexicals -- TODO +{ # enclosing these lexicals -- TODO my %valid_properties = ( __PACKAGE__, {} ); my %additive_properties; @@ -681,10 +734,10 @@ sub ACTION_config_data { sub valid_properties_defaults { my %out; - for (reverse shift->_mb_classes) { - @out{ keys %{ $valid_properties{$_} } } = map { + for my $class (reverse shift->_mb_classes) { + @out{ keys %{ $valid_properties{$class} } } = map { $_->() - } values %{ $valid_properties{$_} }; + } values %{ $valid_properties{$class} }; } return \%out; } @@ -710,9 +763,11 @@ sub ACTION_config_data { my %p = @_ == 1 ? ( default => shift ) : @_; my $type = ref $p{default}; - $valid_properties{$class}{$property} = $type eq 'CODE' - ? $p{default} - : sub { $p{default} }; + $valid_properties{$class}{$property} = + $type eq 'CODE' ? $p{default} : + $type eq 'HASH' ? sub { return { %{ $p{default} } } } : + $type eq 'ARRAY'? sub { return [ @{ $p{default} } ] } : + sub { return $p{default} } ; push @{$additive_properties{$class}->{$type}}, $property if $type; @@ -831,12 +886,16 @@ sub _make_accessor { __PACKAGE__->add_property(auto_configure_requires => 1); __PACKAGE__->add_property(blib => 'blib'); __PACKAGE__->add_property(build_class => 'Module::Build'); -__PACKAGE__->add_property(build_elements => [qw(PL support pm xs pod script)]); +__PACKAGE__->add_property(build_elements => [qw(PL support pm xs share_dir pod script)]); __PACKAGE__->add_property(build_script => 'Build'); __PACKAGE__->add_property(build_bat => 0); +__PACKAGE__->add_property(bundle_inc => []); +__PACKAGE__->add_property(bundle_inc_preload => []); __PACKAGE__->add_property(config_dir => '_build'); __PACKAGE__->add_property(include_dirs => []); +__PACKAGE__->add_property(license => 'unknown'); __PACKAGE__->add_property(metafile => 'META.yml'); +__PACKAGE__->add_property(mymetafile => 'MYMETA.yml'); __PACKAGE__->add_property(recurse_into => []); __PACKAGE__->add_property(use_rcfile => 1); __PACKAGE__->add_property(create_packlist => 1); @@ -844,6 +903,7 @@ __PACKAGE__->add_property(allow_mb_mismatch => 0); __PACKAGE__->add_property(config => undef); __PACKAGE__->add_property(test_file_exts => ['.t']); __PACKAGE__->add_property(use_tap_harness => 0); +__PACKAGE__->add_property(cpan_client => 'cpan'); __PACKAGE__->add_property(tap_harness_args => {}); __PACKAGE__->add_property( 'installdirs', @@ -906,10 +966,10 @@ __PACKAGE__->add_property($_) for qw( has_config_data install_base libdoc_dirs - license magic_number mb_version module_name + needs_compiler orig_dir perl pm_files @@ -921,6 +981,7 @@ __PACKAGE__->add_property($_) for qw( recursive_test_files script_files scripts + share_dir sign test_files verbose @@ -993,14 +1054,14 @@ sub subclass { $opts{code} ||= ''; $opts{class} ||= 'MyModuleBuilder'; - + my $filename = File::Spec->catfile($build_dir, 'lib', split '::', $opts{class}) . '.pm'; my $filedir = File::Basename::dirname($filename); - $pack->log_info("Creating custom builder $filename in $filedir\n"); - + $pack->log_verbose("Creating custom builder $filename in $filedir\n"); + File::Path::mkpath($filedir); die "Can't create directory $filedir: $!" unless -d $filedir; - + my $fh = IO::File->new("> $filename") or die "Can't create $filename: $!"; print $fh <catdir(File::Spec->rel2abs($build_dir), 'lib'); eval "use $opts{class}"; die $@ if $@; @@ -1018,16 +1079,43 @@ EOF return $opts{class}; } +sub _guess_module_name { + my $self = shift; + my $p = $self->{properties}; + return if $p->{module_name}; + if ( $p->{dist_version_from} && -e $p->{dist_version_from} ) { + my $mi = Module::Build::ModuleInfo->new_from_file($self->dist_version_from); + $p->{module_name} = $mi->name; + } + else { + my $mod_path = my $mod_name = File::Basename::basename($self->base_dir); + $mod_name =~ s{-}{::}g; + $mod_path =~ s{-}{/}g; + $mod_path .= ".pm"; + if ( -e $mod_path || -e File::Spec->catfile('lib', $mod_path) ) { + $p->{module_name} = $mod_name; + } + else { + $self->log_warn( << 'END_WARN' ); +No 'module_name' was provided and it could not be inferred +from other properties. This will prevent a packlist from +being written for this file. Please set either 'module_name' +or 'dist_version_from' in Build.PL. +END_WARN + } + } +} + sub dist_name { my $self = shift; my $p = $self->{properties}; return $p->{dist_name} if defined $p->{dist_name}; - + die "Can't determine distribution name, must supply either 'dist_name' or 'module_name' parameter" unless $self->module_name; - + ($p->{dist_name} = $self->module_name) =~ s/::/-/g; - + return $p->{dist_name}; } @@ -1069,12 +1157,12 @@ sub _pod_parse { my $p = $self->{properties}; my $member = "dist_$part"; return $p->{$member} if defined $p->{$member}; - + my $docfile = $self->_main_docfile or return; my $fh = IO::File->new($docfile) or return; - + require Module::Build::PodParser; my $parser = Module::Build::PodParser->new(fh => $fh); my $method = "get_$part"; @@ -1109,7 +1197,7 @@ sub config_file { sub read_config { my ($self) = @_; - + my $file = $self->config_file('build_params') or die "Can't find 'build_params' in " . $self->config_dir; my $fh = IO::File->new($file) or die "Can't read '$file': $!"; @@ -1128,7 +1216,7 @@ sub has_config_data { sub _write_data { my ($self, $filename, $data) = @_; - + my $file = $self->config_file($filename); my $fh = IO::File->new("> $file") or die "Can't create '$file': $!"; unless (ref($data)) { # e.g. magicnum @@ -1141,10 +1229,10 @@ sub _write_data { sub write_config { my ($self) = @_; - + File::Path::mkpath($self->{properties}{config_dir}); -d $self->{properties}{config_dir} or die "Can't mkdir $self->{properties}{config_dir}: $!"; - + my @items = @{ $self->prereq_action_types }; $self->_write_data('prereqs', { map { $_, $self->$_() } @items }); $self->_write_data('build_params', [$self->{args}, $self->{config}->values_set, $self->{properties}]); @@ -1155,13 +1243,74 @@ sub write_config { $self->{phash}{$_}->write() foreach qw(notes cleanup features auto_features config_data runtime_params); } +{ + # packfile map -- keys are guts of regular expressions; If they match, + # values are module names corresponding to the packlist + my %packlist_map = ( + '^File::Spec' => 'Cwd', + '^Devel::AssertOS' => 'Devel::CheckOS', + ); + + sub _find_packlist { + my ($self, $inst, $mod) = @_; + my $lookup = $mod; + my $packlist = eval { $inst->packlist($lookup) }; + if ( ! $packlist ) { + # try from packlist_map + while ( my ($re, $new_mod) = each %packlist_map ) { + if ( $mod =~ qr/$re/ ) { + $lookup = $new_mod; + $packlist = eval { $inst->packlist($lookup) }; + last; + } + } + } + return $packlist ? $lookup : undef; + } + + sub set_bundle_inc { + my $self = shift; + + my $bundle_inc = $self->{properties}{bundle_inc}; + my $bundle_inc_preload = $self->{properties}{bundle_inc_preload}; + # We're in author mode if inc::latest is loaded, but not from cwd + return unless inc::latest->can('loaded_modules'); + require ExtUtils::Installed; + # ExtUtils::Installed is buggy about finding additions to default @INC + my $inst = ExtUtils::Installed->new(extra_libs => [@INC]); + my @bundle_list = map { [ $_, 0 ] } inc::latest->loaded_modules; + + # XXX TODO: Need to get ordering of prerequisites correct so they are + # are loaded in the right order. Use an actual tree?! + + while( @bundle_list ) { + my ($mod, $prereq) = @{ shift @bundle_list }; + + # XXX TODO: Append prereqs to list + # skip if core or already in bundle or preload lists + # push @bundle_list, [$_, 1] for prereqs() + + # Locate packlist for bundling + my $lookup = $self->_find_packlist($inst,$mod); + if ( ! $lookup ) { + # XXX Really needs a more helpful error message here + die << "NO_PACKLIST"; +Could not find a packlist for '$mod'. If it's a core module, try +force installing it from CPAN. +NO_PACKLIST + } + else { + push @{ $prereq ? $bundle_inc_preload : $bundle_inc }, $lookup; + } + } + } # sub check_bundling +} + sub check_autofeatures { my ($self) = @_; my $features = $self->auto_features; - - return unless %$features; - $self->log_info("Checking features:\n"); + return 1 unless %$features; # TODO refactor into ::Util my $longest = sub { @@ -1177,30 +1326,117 @@ sub check_autofeatures { }; my $max_name_len = length($longest->(keys %$features)); - while (my ($name, $info) = each %$features) { - $self->log_info(" $name" . '.' x ($max_name_len - length($name) + 4)); + my ($num_disabled, $log_text) = (0, "\nChecking optional features...\n"); + for my $name ( sort keys %$features ) { + $log_text .= $self->_feature_deps_msg($name, $max_name_len); + } + + $num_disabled = () = $log_text =~ /disabled/g; + + # warn user if features disabled + if ( $num_disabled ) { + $self->log_warn( $log_text ); + return 0; + } + else { + $self->log_verbose( $log_text ); + return 1; + } +} + +sub _feature_deps_msg { + my ($self, $name, $max_name_len) = @_; + $max_name_len ||= length $name; + my $features = $self->auto_features; + my $info = $features->{$name}; + my $feature_text = "$name" . '.' x ($max_name_len - length($name) + 4); + my ($log_text, $disabled) = ('',''); if ( my $failures = $self->prereq_failures($info) ) { - my $disabled = grep( /^(?:\w+_)?(?:requires|conflicts)$/, - keys %$failures ) ? 1 : 0; - $self->log_info( $disabled ? "disabled\n" : "enabled\n" ); - - my $log_text; - while (my ($type, $prereqs) = each %$failures) { - while (my ($module, $status) = each %$prereqs) { - my $required = - ($type =~ /^(?:\w+_)?(?:requires|conflicts)$/) ? 1 : 0; - my $prefix = ($required) ? '-' : '*'; - $log_text .= " $prefix $status->{message}\n"; - } + $disabled = grep( /^(?:\w+_)?(?:requires|conflicts)$/, + keys %$failures ) ? 1 : 0; + $feature_text .= $disabled ? "disabled\n" : "enabled\n"; + + for my $type ( @{ $self->prereq_action_types } ) { + next unless exists $failures->{$type}; + $feature_text .= " $type:\n"; + my $prereqs = $failures->{$type}; + for my $module ( sort keys %$prereqs ) { + my $status = $prereqs->{$module}; + my $required = + ($type =~ /^(?:\w+_)?(?:requires|conflicts)$/) ? 1 : 0; + my $prefix = ($required) ? '!' : '*'; + $feature_text .= " $prefix $status->{message}\n"; + } } - $self->log_warn("$log_text") unless $self->quiet; } else { - $self->log_info("enabled\n"); + $feature_text .= "enabled\n"; + } + $log_text .= $feature_text if $disabled || $self->verbose; + return $log_text; +} + +# Automatically detect and add prerequisites based on configuration +sub auto_require { + my ($self) = @_; + my $p = $self->{properties}; + + # add current Module::Build to configure_requires if there + # isn't one already specified (but not ourself, so we're not circular) + if ( $self->dist_name ne 'Module-Build' + && $self->auto_configure_requires + && ! exists $p->{configure_requires}{'Module::Build'} + ) { + (my $ver = $VERSION) =~ s/^(\d+\.\d\d).*$/$1/; # last major release only + $self->_add_prereq('configure_requires', 'Module::Build', $ver); + } + + # if we're in author mode, add inc::latest modules to + # configure_requires if not already set. If we're not in author mode + # then configure_requires will have been satisfied, or we'll just + # live with what we've bundled + if ( inc::latest->can('loaded_module') ) { + for my $mod ( inc::latest->loaded_modules ) { + next if exists $p->{configure_requires}{$mod}; + $self->_add_prereq('configure_requires', $mod, $mod->VERSION); } } - $self->log_warn("\n") unless $self->quiet; + # If needs_compiler is not explictly set, automatically set it + # If set, we need ExtUtils::CBuilder (and a compiler) + my $xs_files = $self->find_xs_files; + if ( ! defined $p->{needs_compiler} ) { + $self->needs_compiler( keys %$xs_files || defined $self->c_source ); + } + if ($self->needs_compiler) { + $self->_add_prereq('build_requires', 'ExtUtils::CBuilder', 0); + if ( ! $self->have_c_compiler ) { + $self->log_warn(<<'EOM'); +Warning: ExtUtils::CBuilder not installed or no compiler detected +Proceeding with configuration, but compilation may fail during Build + +EOM + } + } + + # If using share_dir, require File::ShareDir + if ( $self->share_dir ) { + $self->_add_prereq( 'requires', 'File::ShareDir', '1.00' ); + } + + return; +} + +sub _add_prereq { + my ($self, $type, $module, $version) = @_; + my $p = $self->{properties}; + $version = 0 unless defined $version; + if ( exists $p->{$type}{$module} ) { + return if $self->compare_versions( $version, '<=', $p->{$type}{$module} ); + } + $self->log_verbose("Adding to $type\: $module => $version\n"); + $p->{$type}{$module} = $version; + return 1; } sub prereq_failures { @@ -1213,7 +1449,8 @@ sub prereq_failures { foreach my $type (@types) { my $prereqs = $info->{$type}; - while ( my ($modname, $spec) = each %$prereqs ) { + for my $modname ( keys %$prereqs ) { + my $spec = $prereqs->{$modname}; my $status = $self->check_installed_status($modname, $spec); if ($type =~ /^(?:\w+_)?conflicts$/) { @@ -1224,7 +1461,7 @@ sub prereq_failures { } elsif ($type =~ /^(?:\w+_)?recommends$/) { next if $status->{ok}; $status->{message} = (!ref($status->{have}) && $status->{have} eq '' - ? "Optional prerequisite $modname is not installed" + ? "$modname is not installed" : "$modname ($status->{have}) is installed, but we prefer to have $spec"); } else { next if $status->{ok}; @@ -1253,44 +1490,29 @@ sub _enum_prereqs { sub check_prereq { my $self = shift; - # If we have XS files, make sure we can process them. - my $xs_files = $self->find_xs_files; - if (keys %$xs_files && !$self->_mb_feature('C_support')) { - $self->log_warn("Warning: this distribution contains XS files, ". - "but Module::Build is not configured with C_support. ". - "Please install ExtUtils::CBuilder to enable C_support.\n"); - } - # Check to see if there are any prereqs to check my $info = $self->_enum_prereqs; return 1 unless $info; - $self->log_info("Checking prerequisites...\n"); + my $log_text = "Checking prerequisites...\n"; my $failures = $self->prereq_failures($info); if ( $failures ) { - - while (my ($type, $prereqs) = each %$failures) { - while (my ($module, $status) = each %$prereqs) { - my $prefix = ($type =~ /^(?:\w+_)?recommends$/) ? '*' : '- ERROR:'; - $self->log_warn(" $prefix $status->{message}\n"); + $self->log_warn($log_text); + for my $type ( @{ $self->prereq_action_types } ) { + my $prereqs = $failures->{$type}; + $self->log_warn(" ${type}:\n") if keys %$prereqs; + for my $module ( sort keys %$prereqs ) { + my $status = $prereqs->{$module}; + my $prefix = ($type =~ /^(?:\w+_)?recommends$/) ? "* " : "! "; + $self->log_warn(" $prefix $status->{message}\n"); } } - - $self->log_warn(<log_info("Looks good\n\n"); + $self->log_verbose($log_text . "Looks good\n\n"); return 1; - } } @@ -1323,44 +1545,44 @@ sub _parse_conditions { sub check_installed_status { my ($self, $modname, $spec) = @_; my %status = (need => $spec); - + if ($modname eq 'perl') { $status{have} = $self->perl_version; - + } elsif (eval { no strict; $status{have} = ${"${modname}::VERSION"} }) { # Don't try to load if it's already loaded - + } else { my $pm_info = Module::Build::ModuleInfo->new_from_module( $modname ); unless (defined( $pm_info )) { @status{ qw(have message) } = ('', "$modname is not installed"); return \%status; } - + $status{have} = $pm_info->version(); if ($spec and !defined($status{have})) { @status{ qw(have message) } = (undef, "Couldn't find a \$VERSION in prerequisite $modname"); return \%status; } } - + my @conditions = $self->_parse_conditions($spec); - + foreach (@conditions) { my ($op, $version) = /^\s* (<=?|>=?|==|!=) \s* ([\w.]+) \s*$/x or die "Invalid prerequisite condition '$_' for $modname"; - + $version = $self->perl_version_to_float($version) if $modname eq 'perl'; - + next if $op eq '>=' and !$version; # Module doesn't have to actually define a $VERSION - + unless ($self->compare_versions( $status{have}, $op, $version )) { $status{message} = "$modname ($status{have}) is installed, but we need version $op $version"; return \%status; } } - + $status{ok} = 1; return \%status; } @@ -1368,7 +1590,7 @@ sub check_installed_status { sub compare_versions { my $self = shift; my ($v1, $op, $v2) = @_; - $v1 = Module::Build::Version->new($v1) + $v1 = Module::Build::Version->new($v1) unless UNIVERSAL::isa($v1,'Module::Build::Version'); my $eval_str = "\$v1 $op \$v2"; @@ -1381,14 +1603,14 @@ sub compare_versions { # I wish I could set $! to a string, but I can't, so I use $@ sub check_installed_version { my ($self, $modname, $spec) = @_; - + my $status = $self->check_installed_status($modname, $spec); - + if ($status->{ok}) { return $status->{have} if $status->{have} and "$status->{have}" ne ''; return '0 but true'; } - + $@ = $status->{message}; return 0; } @@ -1430,23 +1652,23 @@ sub _added_to_INC { sub _default_INC { my $self = shift; return @default_inc if @default_inc; - + local $ENV{PERL5LIB}; # this is not considered part of the default. - + my $perl = ref($self) ? $self->perl : $self->find_perl_interpreter; - + my @inc = $self->_backticks($perl, '-le', 'print for @INC'); chomp @inc; - + return @default_inc = @inc; } } sub print_build_script { my ($self, $fh) = @_; - + my $build_package = $self->build_class; - + my $closedata=""; my %q = map {$_, $self->$_()} qw(config_dir base_dir); @@ -1532,20 +1754,29 @@ EOF sub create_build_script { my ($self) = @_; $self->write_config; - + + # Create MYMETA.yml + my $mymetafile = $self->mymetafile; + if ( $self->delete_filetree($mymetafile) ) { + $self->log_verbose("Removed previous '$mymetafile'\n"); + } + $self->log_info("Creating new '$mymetafile' with configuration results\n"); + $self->write_metafile( $mymetafile, $self->prepare_metadata( fatal => 0 ) ); + + # Create Build my ($build_script, $dist_name, $dist_version) = map $self->$_(), qw(build_script dist_name dist_version); - + if ( $self->delete_filetree($build_script) ) { - $self->log_info("Removed previous script '$build_script'\n\n"); + $self->log_verbose("Removed previous script '$build_script'\n"); } $self->log_info("Creating new '$build_script' script for ", - "'$dist_name' version '$dist_version'\n"); + "'$dist_name' version '$dist_version'\n"); my $fh = IO::File->new(">$build_script") or die "Can't create '$build_script': $!"; $self->print_build_script($fh); close $fh; - + $self->make_executable($build_script); return 1; @@ -1554,20 +1785,20 @@ sub create_build_script { sub check_manifest { my $self = shift; return unless -e 'MANIFEST'; - + # Stolen nearly verbatim from MakeMaker. But ExtUtils::Manifest # could easily be re-written into a modern Perl dialect. require ExtUtils::Manifest; # ExtUtils::Manifest is not warnings clean. local ($^W, $ExtUtils::Manifest::Quiet) = (0,1); - - $self->log_info("Checking whether your kit is complete...\n"); + + $self->log_verbose("Checking whether your kit is complete...\n"); if (my @missed = ExtUtils::Manifest::manicheck()) { $self->log_warn("WARNING: the following files are missing in your kit:\n", "\t", join("\n\t", @missed), "\n", "Please inform the author.\n\n"); } else { - $self->log_info("Looks good\n\n"); + $self->log_verbose("Looks good\n\n"); } } @@ -1692,6 +1923,7 @@ sub _translate_option { use_rcfile use_tap_harness tap_harness_args + cpan_client ); # normalize only selected option names return $opt; @@ -1824,7 +2056,7 @@ sub read_args { require Module::Build::Compat; %args = (%args, Module::Build::Compat->makefile_to_build_macros); } - + return \%args, $action; } @@ -1977,7 +2209,10 @@ sub merge_args { sub cull_args { my $self = shift; - my ($args, $action) = $self->read_args(@_); + my @arg_list = @_; + unshift @arg_list, $self->split_like_shell($ENV{PERL_MB_OPT}) + if $ENV{PERL_MB_OPT}; + my ($args, $action) = $self->read_args(@arg_list); $self->merge_args($action, %$args); $self->merge_modulebuildrc( $action, %$args ); } @@ -1986,7 +2221,7 @@ sub super_classes { my ($self, $class, $seen) = @_; $class ||= ref($self) || $self; $seen ||= {}; - + no strict 'refs'; my @super = grep {not $seen->{$_}++} $class, @{ $class . '::ISA' }; return @super, map {$self->super_classes($_,$seen)} @super; @@ -1997,7 +2232,7 @@ sub known_actions { my %actions; no strict 'refs'; - + foreach my $class ($self->super_classes) { foreach ( keys %{ $class . '::' } ) { $actions{$1}++ if /^ACTION_(\w+)/; @@ -2073,7 +2308,7 @@ sub get_action_docs { $@ = "Couldn't find any docs for action '$action'"; return; } - + return join '', @docs; } @@ -2147,7 +2382,7 @@ sub prereq_report { sub ACTION_help { my ($self) = @_; my $actions = $self->known_actions; - + if (@{$self->{args}{ARGV}}) { my $msg = eval {$self->get_action_docs($self->{args}{ARGV}[0], $actions)}; print $@ ? "$@\n" : $msg; @@ -2158,10 +2393,10 @@ sub ACTION_help { Usage: $0 arg1=value arg2=value ... Example: $0 test verbose=1 - + Actions defined: EOF - + print $self->_action_listing($actions); print "\nRun `Build help ` for details on an individual action.\n"; @@ -2174,7 +2409,7 @@ sub _action_listing { # Flow down columns, not across rows my @actions = sort keys %$actions; @actions = map $actions[($_ + ($_ % 2) * @actions) / 2], 0..$#actions; - + my $out = ''; while (my ($one, $two) = splice @actions, 0, 2) { $out .= sprintf(" %-12s %-12s\n", $one, $two||''); @@ -2184,7 +2419,7 @@ sub _action_listing { sub ACTION_retest { my ($self) = @_; - + # Protect others against our @INC changes local @INC = @INC; @@ -2232,7 +2467,7 @@ sub generic_test { my $p = $self->{properties}; my @types = ( - (exists($args{type}) ? $args{type} : ()), + (exists($args{type}) ? $args{type} : ()), (exists($args{types}) ? @{$args{types}} : ()), ); @types or croak "need some types of tests to check"; @@ -2265,6 +2500,8 @@ sub generic_test { $self->do_tests; } +# Test::Harness dies on failure but TAP::Harness does not, so we must +# die if running under TAP::Harness sub do_tests { my $self = shift; @@ -2273,7 +2510,10 @@ sub do_tests { if(@$tests) { my $args = $self->tap_harness_args; if($self->use_tap_harness or ($args and %$args)) { - $self->run_tap_harness($tests); + my $aggregate = $self->run_tap_harness($tests); + if ( $aggregate->has_errors ) { + die "Errors in testing. Cannot continue.\n"; + } } else { $self->run_test_harness($tests); @@ -2293,12 +2533,14 @@ sub run_tap_harness { # TODO allow the test @INC to be set via our API? - TAP::Harness->new({ + my $aggregate = TAP::Harness->new({ lib => [@INC], verbosity => $self->{properties}{verbose}, switches => [ $self->harness_switches ], %{ $self->tap_harness_args }, })->runtests(@$tests); + + return $aggregate; } sub run_test_harness { @@ -2382,14 +2624,14 @@ sub ACTION_testcover { my $pm_files = $self->rscan_dir (File::Spec->catdir($self->blib, 'lib'), file_qr('\.pm$') ); my $cover_files = $self->rscan_dir('cover_db', sub {-f $_ and not /\.html$/}); - + $self->do_system(qw(cover -delete)) unless $self->up_to_date($pm_files, $cover_files) && $self->up_to_date($self->test_files, $cover_files); } - local $Test::Harness::switches = - local $Test::Harness::Switches = + local $Test::Harness::switches = + local $Test::Harness::Switches = local $ENV{HARNESS_PERL_SWITCHES} = "-MDevel::Cover"; $self->depends_on('test'); @@ -2398,17 +2640,17 @@ sub ACTION_testcover { sub ACTION_code { my ($self) = @_; - + # All installable stuff gets created in blib/ . # Create blib/arch to keep blib.pm happy my $blib = $self->blib; $self->add_to_cleanup($blib); File::Path::mkpath( File::Spec->catdir($blib, 'arch') ); - + if (my $split = $self->autosplit) { $self->autosplit_file($_, $blib) for ref($split) ? @$split : ($split); } - + foreach my $element (@{$self->build_elements}) { my $method = "process_${element}_files"; $method = "process_files_by_extension" unless $self->can($method); @@ -2420,16 +2662,17 @@ sub ACTION_code { sub ACTION_build { my $self = shift; + $self->log_info("Building " . $self->dist_name . "\n"); $self->depends_on('code'); $self->depends_on('docs'); } sub process_files_by_extension { my ($self, $ext) = @_; - + my $method = "find_${ext}_files"; my $files = $self->can($method) ? $self->$method() : $self->_find_file_by_type($ext, 'lib'); - + while (my ($file, $dest) = each %$files) { $self->copy_if_modified(from => $file, to => File::Spec->catfile($self->blib, $dest) ); } @@ -2439,19 +2682,70 @@ sub process_support_files { my $self = shift; my $p = $self->{properties}; return unless $p->{c_source}; - + push @{$p->{include_dirs}}, $p->{c_source}; - - my $files = $self->rscan_dir($p->{c_source}, file_qr('\.c(pp)?$')); + + my $files = $self->rscan_dir($p->{c_source}, file_qr('\.c(c|p|pp|xx|\+\+)?$')); foreach my $file (@$files) { push @{$p->{objects}}, $self->compile_c($file); } } +sub process_share_dir_files { + my $self = shift; + my $files = $self->_find_share_dir_files; + return unless $files; + + # root for all File::ShareDir paths + my $share_prefix = File::Spec->catdir($self->blib, qw/lib auto share/); + + # copy all share files to blib + while (my ($file, $dest) = each %$files) { + $self->copy_if_modified( + from => $file, to => File::Spec->catfile( $share_prefix, $dest ) + ); + } +} + +sub _find_share_dir_files { + my $self = shift; + my $share_dir = $self->share_dir; + return unless $share_dir; + + my @file_map; + if ( $share_dir->{dist} ) { + my $prefix = File::Spec->catdir( "dist", $self->dist_name ); + push @file_map, $self->_share_dir_map( $prefix, $share_dir->{dist} ); + } + + if ( $share_dir->{module} ) { + for my $mod ( keys %{ $share_dir->{module} } ) { + (my $altmod = $mod) =~ s{::}{-}g; + my $prefix = File::Spec->catdir("module", $altmod); + push @file_map, $self->_share_dir_map($prefix, $share_dir->{module}{$mod}); + } + } + + return { @file_map }; +} + +sub _share_dir_map { + my ($self, $prefix, $list) = @_; + my %files; + for my $dir ( @$list ) { + for my $f ( @{ $self->rscan_dir( $dir, sub {-f} )} ) { + $files{File::Spec->canonpath($f)} = File::Spec->catfile( + $prefix, File::Spec->abs2rel( $f, $dir ) + ); + } + } + return %files; +} + sub process_PL_files { my ($self) = @_; my $files = $self->find_PL_files; - + while (my ($file, $to) = each %$files) { unless ($self->up_to_date( $file, $to )) { $self->run_perl_script($file, [], [@$to]) or die "$file failed"; @@ -2482,7 +2776,7 @@ sub process_script_files { my $script_dir = File::Spec->catdir($self->blib, 'script'); File::Path::mkpath( $script_dir ); - + foreach my $file (keys %$files) { my $result = $self->copy_if_modified($file, $script_dir, 'flatten') or next; $self->fix_shebang_line($result) unless $self->is_vmsish; @@ -2494,7 +2788,7 @@ sub find_PL_files { my $self = shift; if (my $files = $self->{properties}{PL_files}) { # 'PL_files' is given as a Unix file spec, so we localize_file_path(). - + if (UNIVERSAL::isa($files, 'ARRAY')) { return { map {$_, [/^(.*)\.PL$/]} map $self->localize_file_path($_), @@ -2512,7 +2806,7 @@ sub find_PL_files { die "'PL_files' must be a hash reference or array reference"; } } - + return unless -d 'lib'; return { map {$_, [/^(.*)\.PL$/i ]} @{ $self->rscan_dir('lib', file_qr('\.PL$')) } }; @@ -2529,7 +2823,7 @@ sub find_script_files { # meaningless, but we preserve if present. return { map {$self->localize_file_path($_), $files->{$_}} keys %$files }; } - + # No default location for script files return {}; } @@ -2543,10 +2837,10 @@ sub find_test_files { $files = [map { -d $_ ? $self->expand_test_dir($_) : $_ } map glob, $self->split_like_shell($files)]; - + # Always given as a Unix file spec. return [ map $self->localize_file_path($_), @$files ]; - + } else { # Find all possible tests in t/ or test.pl my @tests; @@ -2558,12 +2852,12 @@ sub find_test_files { sub _find_file_by_type { my ($self, $type, $dir) = @_; - + if (my $files = $self->{properties}{"${type}_files"}) { # Always given as a Unix file spec return { map $self->localize_file_path($_), %$files }; } - + return {} unless -d $dir; return { map {$_, $_} map $self->localize_file_path($_), @@ -2584,48 +2878,48 @@ sub localize_dir_path { sub fix_shebang_line { # Adapted from fixin() in ExtUtils::MM_Unix 1.35 my ($self, @files) = @_; my $c = ref($self) ? $self->{config} : 'Module::Build::Config'; - + my ($does_shbang) = $c->get('sharpbang') =~ /^\s*\#\!/; for my $file (@files) { my $FIXIN = IO::File->new($file) or die "Can't process '$file': $!"; local $/ = "\n"; chomp(my $line = <$FIXIN>); next unless $line =~ s/^\s*\#!\s*//; # Not a shbang file. - + my ($cmd, $arg) = (split(' ', $line, 2), ''); next unless $cmd =~ /perl/i; my $interpreter = $self->{properties}{perl}; - + $self->log_verbose("Changing sharpbang in $file to $interpreter"); my $shb = ''; $shb .= $c->get('sharpbang')."$interpreter $arg\n" if $does_shbang; - + # I'm not smart enough to know the ramifications of changing the # embedded newlines here to \n, so I leave 'em in. $shb .= qq{ eval 'exec $interpreter $arg -S \$0 \${1+"\$\@"}' if 0; # not running under some shell } unless $self->is_windowsish; # this won't work on win32, so don't - + my $FIXOUT = IO::File->new(">$file.new") or die "Can't create new $file: $!\n"; - + # Print out the new #! line (or equivalent). local $\; undef $/; # Was localized above print $FIXOUT $shb, <$FIXIN>; close $FIXIN; close $FIXOUT; - + rename($file, "$file.bak") or die "Can't rename $file to $file.bak: $!"; - + rename("$file.new", $file) or die "Can't rename $file.new to $file: $!"; - + $self->delete_filetree("$file.bak") or $self->log_warn("Couldn't clean up $file.bak, leaving it there"); - + $self->do_system($c->get('eunicefix'), $file) if $c->get('eunicefix') ne ':'; } } @@ -2634,7 +2928,7 @@ eval 'exec $interpreter $arg -S \$0 \${1+"\$\@"}' sub ACTION_testpod { my $self = shift; $self->depends_on('docs'); - + eval q{use Test::Pod 0.95; 1} or die "The 'testpod' action requires Test::Pod version 0.95"; @@ -2655,7 +2949,7 @@ sub ACTION_testpodcoverage { my $self = shift; $self->depends_on('docs'); - + eval q{use Test::Pod::Coverage 1.00; 1} or die "The 'testpodcoverage' action requires ", "Test::Pod::Coverage version 1.00"; @@ -2738,9 +3032,9 @@ sub manify_bin_pods { $self->config( 'man1ext' ); my $outfile = File::Spec->catfile($mandir, $manpage); next if $self->up_to_date( $file, $outfile ); - $self->log_info("Manifying $file -> $outfile\n"); + $self->log_verbose("Manifying $file -> $outfile\n"); eval { $parser->parse_from_file( $file, $outfile ); 1 } - or $self->log_warn("Error creating '$outfile': $@\n"); + or $self->log_warn("Error creating '$outfile': $@\n"); $files->{$file} = $outfile; } } @@ -2763,9 +3057,9 @@ sub manify_lib_pods { $self->config( 'man3ext' ); my $outfile = File::Spec->catfile( $mandir, $manpage); next if $self->up_to_date( $file, $outfile ); - $self->log_info("Manifying $file -> $outfile\n"); + $self->log_verbose("Manifying $file -> $outfile\n"); eval { $parser->parse_from_file( $file, $outfile ); 1 } - or $self->log_warn("Error creating '$outfile': $@\n"); + or $self->log_warn("Error creating '$outfile': $@\n"); $files->{$file} = $outfile; } } @@ -2790,12 +3084,12 @@ sub _find_pods { sub contains_pod { my ($self, $file) = @_; return '' unless -T $file; # Only look at text files - + my $fh = IO::File->new( $file ) or die "Can't open $file: $!"; while (my $line = <$fh>) { return 1 if $line =~ /^\=(?:head|pod|item)/; } - + return ''; } @@ -2808,7 +3102,7 @@ sub ACTION_html { foreach my $type ( qw(bin lib) ) { my $files = $self->_find_pods( $self->{properties}{"${type}doc_dirs"}, - exclude => + exclude => [ file_qr('\.(?:bat|com|html)$') ] ); next unless %$files; @@ -2897,9 +3191,9 @@ sub htmlify_pods { push( @opts, "--css=$path2root/" . $self->html_css) if $self->html_css; } - $self->log_info("HTMLifying $infile -> $outfile\n"); + $self->log_verbose("HTMLifying $infile -> $outfile\n"); $self->log_verbose("pod2html @opts\n"); - eval { Pod::Html::pod2html(@opts); 1 } + eval { Pod::Html::pod2html(@opts); 1 } or $self->log_warn("pod2html @opts failed: $@"); } @@ -2919,10 +3213,10 @@ sub man3page_name { my $self = shift; my ($vol, $dirs, $file) = File::Spec->splitpath( shift ); my @dirs = File::Spec->splitdir( File::Spec->canonpath($dirs) ); - + # Remove known exts from the base name $file =~ s/\.p(?:od|m|l)\z//i; - + return join( $self->manpage_separator, @dirs, $file ); } @@ -2942,7 +3236,7 @@ sub ACTION_diff { my @flags = @{$self->{args}{ARGV}}; @flags = $self->split_like_shell($self->{args}{flags} || '') unless @flags; - + my $installmap = $self->install_map; delete $installmap->{read}; delete $installmap->{write}; @@ -2952,22 +3246,22 @@ sub ACTION_diff { while (my $localdir = each %$installmap) { my @localparts = File::Spec->splitdir($localdir); my $files = $self->rscan_dir($localdir, sub {-f}); - + foreach my $file (@$files) { my @parts = File::Spec->splitdir($file); @parts = @parts[@localparts .. $#parts]; # Get rid of blib/lib or similar - + my $installed = Module::Build::ModuleInfo->find_module_by_name( join('::', @parts), \@myINC ); if (not $installed) { print "Only in lib: $file\n"; next; } - + my $status = File::Compare::compare($installed, $file); next if $status == 0; # Files are the same die "Can't compare $installed and $file: $!" if $status == -1; - + if ($file =~ $text_suffix) { $self->do_system('diff', @flags, $installed, $file); } else { @@ -2985,7 +3279,7 @@ sub ACTION_install { my ($self) = @_; require ExtUtils::Install; $self->depends_on('build'); - ExtUtils::Install::install($self->install_map, !$self->quiet, 0, $self->{args}{uninst}||0); + ExtUtils::Install::install($self->install_map, $self->verbose, 0, $self->{args}{uninst}||0); } sub ACTION_fakeinstall { @@ -3005,19 +3299,74 @@ sub ACTION_fakeinstall { sub ACTION_versioninstall { my ($self) = @_; - + die "You must have only.pm 0.25 or greater installed for this operation: $@\n" unless eval { require only; 'only'->VERSION(0.25); 1 }; - + $self->depends_on('build'); - + my %onlyargs = map {exists($self->{args}{$_}) ? ($_ => $self->{args}{$_}) : ()} qw(version versionlib); only::install::install(%onlyargs); } +sub ACTION_installdeps { + my ($self) = @_; + + # XXX include feature prerequisites as optional prereqs? + + my $info = $self->_enum_prereqs; + if (! $info ) { + $self->log_info( "No prerequisites detected\n" ); + return; + } + + my $failures = $self->prereq_failures($info); + if ( ! $failures ) { + $self->log_info( "All prerequisites satisfied\n" ); + return; + } + + my @install; + while (my ($type, $prereqs) = each %$failures) { + if($type =~ m/^(?:\w+_)?requires$/) { + push(@install, keys %$prereqs); + next; + } + $self->log_info("Checking optional dependencies:\n"); + while (my ($module, $status) = each %$prereqs) { + push(@install, $module) if($self->y_n("Install $module?", 'y')); + } + } + + return unless @install; + + my ($command, @opts) = $self->split_like_shell($self->cpan_client); + + # relative command should be relative to our active Perl + # so we need to locate that command + if ( ! File::Spec->file_name_is_absolute( $command ) ) { + my @bindirs = File::Basename::dirname($self->perl); + push @bindirs, map {$self->config->{"install${_}bin"}} '','site','vendor'; + for my $d ( @bindirs ) { + my $abs_cmd = $self->find_command(File::Spec->catfile( $d, $command )); + if ( defined $abs_cmd ) { + $command = $abs_cmd; + last; + } + } + } + + if ( ! -x $command ) { + die "cpan_client '$command' is not executable\n"; + } + + $self->do_system($command, @opts, @install); +} + sub ACTION_clean { my ($self) = @_; + $self->log_info("Cleaning up build files\n"); foreach my $item (map glob($_), $self->cleanup) { $self->delete_filetree($item); } @@ -3026,11 +3375,15 @@ sub ACTION_clean { sub ACTION_realclean { my ($self) = @_; $self->depends_on('clean'); - $self->delete_filetree($self->config_dir, $self->build_script); + $self->log_info("Cleaning up configuration files\n"); + $self->delete_filetree( + $self->config_dir, $self->mymetafile, $self->build_script + ); } sub ACTION_ppd { my ($self) = @_; + require Module::Build::PPMMaker; my $ppd = Module::Build::PPMMaker->new(); my $file = $ppd->make_ppd(%{$self->{args}}, build => $self); @@ -3104,7 +3457,7 @@ sub ACTION_pardist { ); return(); } - + $self->depends_on( 'build' ); return PAR::Dist::blib_to_par( @@ -3115,11 +3468,11 @@ sub ACTION_pardist { sub ACTION_dist { my ($self) = @_; - + $self->depends_on('distdir'); - + my $dist_dir = $self->dist_dir; - + $self->make_tarball($dist_dir); $self->delete_filetree($dist_dir); } @@ -3127,6 +3480,8 @@ sub ACTION_dist { sub ACTION_distcheck { my ($self) = @_; + $self->_check_manifest_skip; + require ExtUtils::Manifest; local $^W; # ExtUtils::Manifest is not warnings clean. my ($missing, $extra) = ExtUtils::Manifest::fullcheck(); @@ -3141,6 +3496,25 @@ sub ACTION_distcheck { } } +sub _check_mymeta_skip { + my $self = shift; + my $maniskip = shift || 'MANIFEST.SKIP'; + + require ExtUtils::Manifest; + local $^W; # ExtUtils::Manifest is not warnings clean. + + # older ExtUtils::Manifest had a private _maniskip + my $skip_factory = ExtUtils::Manifest->can('maniskip') + || ExtUtils::Manifest->can('_maniskip'); + + my $mymetafile = $self->mymetafile; + # we can't check it, just add it anyway to be safe + unless ( $skip_factory && $skip_factory->($maniskip)->($mymetafile) ) { + $self->log_warn("File '$maniskip' does not include '$mymetafile'. Adding it now.\n"); + $self->_append_maniskip("^$mymetafile\$", $maniskip); + } +} + sub _add_to_manifest { my ($self, $manifest, $lines) = @_; $lines = [$lines] unless ref $lines; @@ -3153,7 +3527,7 @@ sub _add_to_manifest { my $mode = (stat $manifest)[2]; chmod($mode | oct(222), $manifest) or die "Can't make $manifest writable: $!"; - + my $fh = IO::File->new("< $manifest") or die "Can't read $manifest: $!"; my $last_line = (<$fh>)[-1] || "\n"; my $has_newline = $last_line =~ /\n$/; @@ -3165,7 +3539,7 @@ sub _add_to_manifest { close $fh; chmod($mode, $manifest); - $self->log_info(map "Added to $manifest: $_\n", @$lines); + $self->log_verbose(map "Added to $manifest: $_\n", @$lines); } sub _sign_dir { @@ -3175,16 +3549,16 @@ sub _sign_dir { $self->log_warn("Couldn't load Module::Signature for 'distsign' action:\n $@\n"); return; } - + # Add SIGNATURE to the MANIFEST { my $manifest = File::Spec->catfile($dir, 'MANIFEST'); die "Signing a distribution requires a MANIFEST file" unless -e $manifest; $self->_add_to_manifest($manifest, "SIGNATURE Added here by Module::Build"); } - + # Would be nice if Module::Signature took a directory argument. - + $self->_do_in_dir($dir, sub {local $Module::Signature::Quiet = 1; Module::Signature::sign()}); } @@ -3210,7 +3584,7 @@ sub ACTION_distsign { sub ACTION_skipcheck { my ($self) = @_; - + require ExtUtils::Manifest; local $^W; # ExtUtils::Manifest is not warnings clean. ExtUtils::Manifest::skipcheck(); @@ -3218,7 +3592,7 @@ sub ACTION_skipcheck { sub ACTION_distclean { my ($self) = @_; - + $self->depends_on('realclean'); $self->depends_on('distcheck'); } @@ -3235,6 +3609,11 @@ sub do_create_license { my $self = shift; $self->log_info("Creating LICENSE file\n"); + if ( ! $self->_mb_feature('license_creation') ) { + $self->_warn_mb_feature_deps('license_creation'); + die "Aborting.\n"; + } + my $l = $self->license or die "No license specified"; @@ -3243,7 +3622,7 @@ sub do_create_license { my $class = "Software::License::$key"; eval "use $class; 1" - or die "Can't load Software::License to create LICENSE file: $@"; + or die "Can't load Software::License::$key to create LICENSE file: $@"; $self->delete_filetree('LICENSE'); @@ -3270,7 +3649,9 @@ EOF return; } - if ( eval {require Pod::Readme; 1} ) { + # work around some odd Pod::Readme->new() failures in test reports by + # confirming that new() is available + if ( eval {require Pod::Readme; Pod::Readme->can('new') } ) { $self->log_info("Creating README using Pod::Readme\n"); my $parser = Pod::Readme->new; @@ -3326,29 +3707,48 @@ sub _main_docfile { } } +sub do_create_bundle_inc { + my $self = shift; + my $dist_inc = File::Spec->catdir( $self->dist_dir, 'inc' ); + require inc::latest; + inc::latest->write($dist_inc, @{$self->bundle_inc_preload}); + inc::latest->bundle_module($_, $dist_inc) for @{$self->bundle_inc}; + return 1; +} + sub ACTION_distdir { my ($self) = @_; + if ( @{$self->bundle_inc} && ! $self->_mb_feature('inc_bundling_support') ) { + $self->_warn_mb_feature_deps('inc_bundling_support'); + die "Aborting.\n"; + } + $self->depends_on('distmeta'); + # Must not include MYMETA + $self->_check_mymeta_skip('MANIFEST.SKIP'); + my $dist_files = $self->_read_manifest('MANIFEST') - or die "Can't create distdir without a MANIFEST file - run 'manifest' action first"; + or die "Can't create distdir without a MANIFEST file - run 'manifest' action first.\n"; delete $dist_files->{SIGNATURE}; # Don't copy, create a fresh one die "No files found in MANIFEST - try running 'manifest' action?\n" unless ($dist_files and keys %$dist_files); my $metafile = $self->metafile; $self->log_warn("*** Did you forget to add $metafile to the MANIFEST?\n") unless exists $dist_files->{$metafile}; - + my $dist_dir = $self->dist_dir; $self->delete_filetree($dist_dir); $self->log_info("Creating $dist_dir\n"); $self->add_to_cleanup($dist_dir); - + foreach my $file (keys %$dist_files) { my $new = $self->copy_if_modified(from => $file, to_dir => $dist_dir, verbose => 0); } - + + $self->do_create_bundle_inc if @{$self->bundle_inc}; + $self->_sign_dir($dist_dir) if $self->{properties}{sign}; } @@ -3388,8 +3788,7 @@ sub _eumanifest_has_include { my $self = shift; require ExtUtils::Manifest; - return ExtUtils::Manifest->VERSION >= 1.50 ? 1 : 0; - return 0; + return eval { ExtUtils::Manifest->VERSION(1.50); 1 }; } @@ -3436,6 +3835,19 @@ sub _slurp { } + +sub _append_maniskip { + my $self = shift; + my $skip = shift; + my $file = shift || 'MANIFEST.SKIP'; + return unless defined $skip && length $skip; + my $fh = IO::File->new(">> $file") + or die "Can't open $file: $!"; + + print $fh "$skip\n"; + $fh->close(); +} + sub _write_default_maniskip { my $self = shift; my $file = shift || 'MANIFEST.SKIP'; @@ -3446,6 +3858,8 @@ sub _write_default_maniskip { : $self->_slurp( $self->_default_maniskip ); $content .= <<'EOF'; +# Avoid configuration metadata file +^MYMETA\.$ # Avoid Module::Build generated and utility files. \bBuild$ @@ -3466,14 +3880,27 @@ EOF return; } -sub ACTION_manifest { +sub _check_manifest_skip { my ($self) = @_; my $maniskip = 'MANIFEST.SKIP'; - unless ( -e 'MANIFEST' || -e $maniskip ) { + + if ( ! -e $maniskip ) { $self->log_warn("File '$maniskip' does not exist: Creating a default '$maniskip'\n"); $self->_write_default_maniskip($maniskip); } + else { + # MYMETA must not be added to MANIFEST, so always confirm the skip + $self->_check_mymeta_skip( $maniskip ); + } + + return; +} + +sub ACTION_manifest { + my ($self) = @_; + + $self->_check_manifest_skip; require ExtUtils::Manifest; # ExtUtils::Manifest is not warnings clean. local ($^W, $ExtUtils::Manifest::Quiet) = (0,1); @@ -3511,6 +3938,63 @@ sub _files_in { return @files; } +sub share_dir { + my $self = shift; + my $p = $self->{properties}; + + $p->{share_dir} = shift if @_; + + # Always coerce to proper hash form + if ( ! defined $p->{share_dir} ) { + # not set -- use default 'share' dir if exists + $p->{share_dir} = { dist => [ 'share' ] } if -d 'share'; + } + elsif ( ! ref $p->{share_dir} ) { + # scalar -- treat as a single 'dist' directory + $p->{share_dir} = { dist => [ $p->{share_dir} ] }; + } + elsif ( ref $p->{share_dir} eq 'ARRAY' ) { + # array -- treat as a list of 'dist' directories + $p->{share_dir} = { dist => $p->{share_dir} }; + } + elsif ( ref $p->{share_dir} eq 'HASH' ) { + # hash -- check structure + my $share_dir = $p->{share_dir}; + # check dist key + if ( defined $share_dir->{dist} ) { + if ( ! ref $share_dir->{dist} ) { + # scalar, so upgrade to arrayref + $share_dir->{dist} = [ $share_dir->{dist} ]; + } + elsif ( ref $share_dir->{dist} ne 'ARRAY' ) { + die "'dist' key in 'share_dir' must be scalar or arrayref"; + } + } + # check module key + if ( defined $share_dir->{module} ) { + my $mod_hash = $share_dir->{module}; + if ( ref $mod_hash eq 'HASH' ) { + for my $k ( keys %$mod_hash ) { + if ( ! ref $mod_hash->{$k} ) { + $mod_hash->{$k} = [ $mod_hash->{$k} ]; + } + elsif( ref $mod_hash->{$k} ne 'ARRAY' ) { + die "modules in 'module' key of 'share_dir' must be scalar or arrayref"; + } + } + } + else { + die "'module' key in 'share_dir' must be hashref"; + } + } + } + else { + die "'share_dir' must be hashref, arrayref or string"; + } + + return $p->{share_dir}; +} + sub script_files { my $self = shift; @@ -3529,13 +4013,13 @@ sub script_files { } my %pl_files = map { - File::Spec->canonpath( File::Spec->case_tolerant ? uc $_ : $_ ) => 1 + File::Spec->canonpath( File::Spec->case_tolerant ? uc $_ : $_ ) => 1 } keys %{ $self->PL_files || {} }; my @bin_files = $self->_files_in('bin'); my %bin_map = map { - $_ => File::Spec->canonpath( File::Spec->case_tolerant ? uc $_ : $_ ) + $_ => File::Spec->canonpath( File::Spec->case_tolerant ? uc $_ : $_ ) } @bin_files; return $_ = { map {$_ => 1} grep !$pl_files{$bin_map{$_}}, @bin_files }; @@ -3546,6 +4030,7 @@ BEGIN { *scripts = \&script_files; } my %licenses = ( perl => 'Perl_5', apache => 'Apache_2_0', + apache_1_1 => 'Apache_1_1', artistic => 'Artistic_1_0', artistic_2 => 'Artistic_2_0', lgpl => 'LGPL_2_1', @@ -3568,6 +4053,7 @@ BEGIN { *scripts = \&script_files; } my %license_urls = ( perl => 'http://dev.perl.org/licenses/', apache => 'http://apache.org/licenses/LICENSE-2.0', + apache_1_1 => 'http://apache.org/licenses/LICENSE-1.1', artistic => 'http://opensource.org/licenses/artistic-license.php', artistic_2 => 'http://opensource.org/licenses/artistic-license-2.0.php', lgpl => 'http://opensource.org/licenses/lgpl-license.php', @@ -3615,10 +4101,10 @@ sub ACTION_distmeta { sub do_create_metafile { my $self = shift; return if $self->{wrote_metadata}; - + my $p = $self->{properties}; my $metafile = $self->metafile; - + unless ($p->{license}) { $self->log_warn("No license specified, setting license = 'unknown'\n"); $p->{license} = 'unknown'; @@ -3639,7 +4125,7 @@ sub do_create_metafile { push @INC, File::Spec->catdir($self->blib, 'lib'); } - if ( $self->write_metafile( $self->metafile, $self->generate_metadata ) ) { + if ( $self->write_metafile( $self->metafile, $self->prepare_metadata( fatal => 1 ) ) ) { $self->{wrote_metadata} = 1; $self->_add_to_manifest('MANIFEST', $metafile); } @@ -3647,42 +4133,22 @@ sub do_create_metafile { return 1; } -sub generate_metadata { - my $self = shift; - my $node = {}; - - if ($self->_mb_feature('YAML_support')) { - require YAML; - require YAML::Node; - # We use YAML::Node to get the order nice in the YAML file. - $self->prepare_metadata( $node = YAML::Node->new({}) ); - } else { - require Module::Build::YAML; - my @order_keys; - $self->prepare_metadata($node, \@order_keys); - $node->{_order} = \@order_keys; - } - return $node; -} - sub write_metafile { my $self = shift; my ($metafile, $node) = @_; + my $yaml; if ($self->_mb_feature('YAML_support')) { # XXX this is probably redundant, but stick with it - require YAML; - require YAML::Node; - delete $node->{_order}; # XXX also probably redundant, but for safety - # YAML API changed after version 0.30 - my $yaml_sub = $YAML::VERSION le '0.30' ? \&YAML::StoreFile : \&YAML::DumpFile; - $yaml_sub->( $metafile, $node ); + require YAML::Tiny; + $yaml = YAML::Tiny->new($node); } else { - # XXX probably redundant require Module::Build::YAML; - &Module::Build::YAML::DumpFile($metafile, $node); + $yaml = Module::Build::YAML->new($node); } - return 1; + my $result = $yaml->write($metafile) + or $self->log_warn( "Error writing '$metafile': " . $yaml->errstr . "\n"); + return $result; } sub normalize_version { @@ -3690,7 +4156,7 @@ sub normalize_version { if ( $version =~ /[=<>!,]/ ) { # logic, not just version # take as is without modification } - elsif ( ref $version eq 'version' || + elsif ( ref $version eq 'version' || ref $version eq 'Module::Build::Version' ) { # version objects $version = $version->is_qv ? $version->normal : $version->stringify; } @@ -3705,31 +4171,46 @@ sub normalize_version { } sub prepare_metadata { - my ($self, $node, $keys) = @_; + my ($self, %args) = @_; + my $fatal = $args{fatal} || 0; my $p = $self->{properties}; + my $node = {}; # A little helper sub my $add_node = sub { my ($name, $val) = @_; $node->{$name} = $val; - push @$keys, $name if $keys; }; foreach (qw(dist_name dist_version dist_author dist_abstract license)) { (my $name = $_) =~ s/^dist_//; $add_node->($name, $self->$_()); - die "ERROR: Missing required field '$_' for META.yml\n" - unless defined($node->{$name}) && length($node->{$name}); + unless ( defined($node->{$name}) && length($node->{$name}) ) { + my $err = "ERROR: Missing required field '$_' for metafile\n"; + if ( $fatal ) { + die $err; + } + else { + $self->log_warn($err); + } + } } - $node->{version} = $self->normalize_version($node->{version}); + $node->{version} = $self->normalize_version($node->{version}); if (defined( my $l = $self->license )) { - die "Unknown license string '$l'" - unless exists $self->valid_licenses->{ $l }; + unless ( exists $self->valid_licenses->{ $l } ) { + my $err = "Unknown license string '$l'"; + if ( $fatal ) { + die $err; + } + else { + $self->log_warn($err); + } + } if (my $key = $self->valid_licenses->{ $l }) { my $class = "Software::License::$key"; - if (eval "use $class; 1") { + if (eval "require Software::License; require $class; 1") { # S::L requires a 'holder' key $node->{resources}{license} = $class->new({holder=>"nobody"})->url; } @@ -3743,24 +4224,14 @@ sub prepare_metadata { # copy prereq data structures so we can modify them before writing to META my %prereq_types; for my $type ( 'configure_requires', @{$self->prereq_action_types} ) { - if (exists $p->{$type}) { + if (exists $p->{$type}) { for my $mod ( keys %{ $p->{$type} } ) { - $prereq_types{$type}{$mod} = + $prereq_types{$type}{$mod} = $self->normalize_version($p->{$type}{$mod}); } } } - # add current Module::Build to configure_requires if there - # isn't one already specified (but not ourself, so we're not circular) - if ( $self->dist_name ne 'Module-Build' - && $self->auto_configure_requires - && ! exists $prereq_types{'configure_requires'}{'Module::Build'} - ) { - (my $ver = $VERSION) =~ s/^(\d+\.\d\d).*$/$1/; # last major release only - $prereq_types{configure_requires}{'Module::Build'} = $ver; - } - for my $t ( keys %prereq_types ) { $add_node->($t, $prereq_types{$t}); } @@ -3771,7 +4242,7 @@ sub prepare_metadata { my $pkgs = eval { $self->find_dist_packages }; if ($@) { $self->log_warn("$@\nWARNING: Possible missing or corrupt 'MANIFEST' file.\n" . - "Nothing to enter for 'provides' field in META.yml\n"); + "Nothing to enter for 'provides' field in metafile.\n"); } else { $node->{provides} = $pkgs if %$pkgs; } @@ -3782,7 +4253,7 @@ sub prepare_metadata { $add_node->('generated_by', "Module::Build version $Module::Build::VERSION"); - $add_node->('meta-spec', + $add_node->('meta-spec', {version => '1.4', url => 'http://module-build.sourceforge.net/META-spec-v1.4.html', }); @@ -3815,21 +4286,28 @@ sub find_dist_packages { # private stock. my $manifest = $self->_read_manifest('MANIFEST') - or die "Can't find dist packages without a MANIFEST file - run 'manifest' action first"; + or die "Can't find dist packages without a MANIFEST file\nRun 'Build manifest' to generate one\n"; # Localize my %dist_files = map { $self->localize_file_path($_) => $_ } keys %$manifest; - my @pm_files = grep {exists $dist_files{$_}} keys %{ $self->find_pm_files }; + my @pm_files = grep { $_ !~ m{^t} } # skip things in t/ + grep {exists $dist_files{$_}} + keys %{ $self->find_pm_files }; + + return $self->find_packages_in_files(\@pm_files, \%dist_files); +} + +sub find_packages_in_files { + my ($self, $file_list, $filename_map) = @_; # First, we enumerate all packages & versions, # separating into primary & alternative candidates my( %prime, %alt ); - foreach my $file (@pm_files) { - next if $dist_files{$file} =~ m{^t/}; # Skip things in t/ - - my @path = split( /\//, $dist_files{$file} ); + foreach my $file (@{$file_list}) { + my $mapped_filename = $filename_map->{$file}; + my @path = split( /\//, $mapped_filename ); (my $prime_package = join( '::', @path[1..$#path] )) =~ s/\.pm$//; my $pm_info = Module::Build::ModuleInfo->new_from_file( $file ); @@ -3841,18 +4319,18 @@ sub find_dist_packages { my $version = $pm_info->version( $package ); if ( $package eq $prime_package ) { - if ( exists( $prime{$package} ) ) { - # M::B::ModuleInfo will handle this conflict - die "Unexpected conflict in '$package'; multiple versions found.\n"; - } else { - $prime{$package}{file} = $dist_files{$file}; + if ( exists( $prime{$package} ) ) { + # M::B::ModuleInfo will handle this conflict + die "Unexpected conflict in '$package'; multiple versions found.\n"; + } else { + $prime{$package}{file} = $mapped_filename; $prime{$package}{version} = $version if defined( $version ); } } else { - push( @{$alt{$package}}, { - file => $dist_files{$file}, - version => $version, - } ); + push( @{$alt{$package}}, { + file => $mapped_filename, + version => $version, + } ); } } } @@ -3972,24 +4450,29 @@ sub _resolve_module_versions { sub make_tarball { my ($self, $dir, $file) = @_; $file ||= $dir; - + $self->log_info("Creating $file.tar.gz\n"); - + if ($self->{args}{tar}) { my $tar_flags = $self->verbose ? 'cvf' : 'cf'; $self->do_system($self->split_like_shell($self->{args}{tar}), $tar_flags, "$file.tar", $dir); $self->do_system($self->split_like_shell($self->{args}{gzip}), "$file.tar") if $self->{args}{gzip}; } else { - eval { require Archive::Tar && Archive::Tar->VERSION(1.08); 1 } - or die "You must install Archive::Tar to make a distribution tarball\n". + eval { require Archive::Tar && Archive::Tar->VERSION(1.09); 1 } + or die "You must install Archive::Tar 1.09+ to make a distribution tarball\n". "or specify a binary tar program with the '--tar' option.\n". "See the documentation for the 'dist' action.\n"; + my $files = $self->rscan_dir($dir); + # Archive::Tar versions >= 1.09 use the following to enable a compatibility # hack so that the resulting archive is compatible with older clients. - $Archive::Tar::DO_NOT_USE_PREFIX = 0; + # If no file path is 100 chars or longer, we disable the prefix field + # for maximum compatibility. If there are any long file paths then we + # need the prefix field after all. + $Archive::Tar::DO_NOT_USE_PREFIX = + (grep { length($_) >= 100 } @$files) ? 0 : 1; - my $files = $self->rscan_dir($dir); my $tar = Archive::Tar->new; $tar->add_files(@$files); for my $f ($tar->get_files) { @@ -4055,7 +4538,7 @@ sub original_prefix { # or original_prefix('lib' => $value); my ($self, $key, $value) = @_; # update property before merging with defaults - if ( @_ == 3 && defined $key) { + if ( @_ == 3 && defined $key) { # $value can be undef; will mask default $self->{properties}{original_prefix}{$key} = $value; } @@ -4263,7 +4746,7 @@ sub install_map { } } } - + $map{read} = ''; # To keep ExtUtils::Install quiet return \%map; @@ -4284,7 +4767,7 @@ sub rscan_dir { !ref($pattern) || (ref $pattern eq 'Regexp') ? sub {push @result, $File::Find::name if /$pattern/} : ref($pattern) eq 'CODE' ? sub {push @result, $File::Find::name if $pattern->()} : die "Unknown pattern type"; - + File::Find::find({wanted => $subr, no_chdir => 1}, $dir); return \@result; } @@ -4294,7 +4777,7 @@ sub delete_filetree { my $deleted = 0; foreach (@_) { next unless -e $_; - $self->log_info("Deleting $_\n"); + $self->log_verbose("Deleting $_\n"); File::Path::rmtree($_, 0, 0); die "Couldn't remove '$_': $!\n" if -e $_; $deleted++; @@ -4327,21 +4810,25 @@ sub cbuilder { sub have_c_compiler { my ($self) = @_; - + my $p = $self->{properties}; - return $p->{have_compiler} if defined $p->{have_compiler}; - + return $p->{_have_c_compiler} if defined $p->{_have_c_compiler}; + $self->log_verbose("Checking if compiler tools configured... "); my $b = eval { $self->cbuilder }; - my $have = $b && $b->have_compiler; + my $have = $b && eval { $b->have_compiler }; $self->log_verbose($have ? "ok.\n" : "failed.\n"); - return $p->{have_compiler} = $have; + return $p->{_have_c_compiler} = $have; } sub compile_c { my ($self, $file, %args) = @_; - my $b = $self->cbuilder; + if ( ! $self->have_c_compiler ) { + die "Error: no compiler detected to compile '$file'. Aborting\n"; + } + + my $b = $self->cbuilder; my $obj_file = $b->object_file($file); $self->add_to_cleanup($obj_file); return $obj_file if $self->up_to_date($file, $obj_file); @@ -4381,11 +4868,11 @@ sub link_c { sub compile_xs { my ($self, $file, %args) = @_; - - $self->log_info("$file -> $args{outfile}\n"); + + $self->log_verbose("$file -> $args{outfile}\n"); if (eval {require ExtUtils::ParseXS; 1}) { - + ExtUtils::ParseXS::process_file( filename => $file, prototypes => 0, @@ -4393,26 +4880,26 @@ sub compile_xs { ); } else { # Ok, I give up. Just use backticks. - + my $xsubpp = Module::Build::ModuleInfo->find_module_by_name('ExtUtils::xsubpp') or die "Can't find ExtUtils::xsubpp in INC (@INC)"; - + my @typemaps; push @typemaps, Module::Build::ModuleInfo->find_module_by_name( 'ExtUtils::typemap', \@INC ); my $lib_typemap = Module::Build::ModuleInfo->find_module_by_name( - 'typemap', [File::Basename::dirname($file)] + 'typemap', [File::Basename::dirname($file), File::Spec->rel2abs('.')] ); push @typemaps, $lib_typemap if $lib_typemap; @typemaps = map {+'-typemap', $_} @typemaps; my $cf = $self->{config}; my $perl = $self->{properties}{perl}; - + my @command = ($perl, "-I".$cf->get('installarchlib'), "-I".$cf->get('installprivlib'), $xsubpp, '-noprototypes', @typemaps, $file); - + $self->log_info("@command\n"); my $fh = IO::File->new("> $args{outfile}") or die "Couldn't write $args{outfile}: $!"; print {$fh} $self->_backticks(@command); @@ -4422,12 +4909,12 @@ sub compile_xs { sub split_like_shell { my ($self, $string) = @_; - + return () unless defined($string); return @$string if UNIVERSAL::isa($string, 'ARRAY'); $string =~ s/^\s+|\s+$//g; return () unless length($string); - + return Text::ParseWords::shellwords($string); } @@ -4553,12 +5040,12 @@ sub process_xs { sub do_system { my ($self, @cmd) = @_; - $self->log_info("@cmd\n"); + $self->log_verbose("@cmd\n"); # Some systems proliferate huge PERL5LIBs, try to ameliorate: my %seen; my $sep = $self->config('path_sep'); - local $ENV{PERL5LIB} = + local $ENV{PERL5LIB} = ( !exists($ENV{PERL5LIB}) ? '' : length($ENV{PERL5LIB}) < 500 ? $ENV{PERL5LIB} @@ -4587,8 +5074,8 @@ sub copy_if_modified { unless (defined $file and length $file) { die "No 'from' parameter given to copy_if_modified"; } - - # makes no sense to replicate an absolute path, so assume flatten + + # makes no sense to replicate an absolute path, so assume flatten $args{flatten} = 1 if File::Spec->file_name_is_absolute( $file ); my $to_path; @@ -4601,7 +5088,7 @@ sub copy_if_modified { } else { die "No 'to' or 'to_dir' parameter given to copy_if_modified"; } - + return if $self->up_to_date($file, $to_path); # Already fresh { @@ -4611,9 +5098,9 @@ sub copy_if_modified { # Create parent directories File::Path::mkpath(File::Basename::dirname($to_path), 0, oct(777)); - - $self->log_info("Copying $file -> $to_path\n") if $args{verbose}; - + + $self->log_verbose("Copying $file -> $to_path\n"); + if ($^O eq 'os2') {# copy will not overwrite; 0x1 = overwrite chmod 0666, $to_path; File::Copy::syscopy($file, $to_path, 0x1) or die "Can't copy('$file', '$to_path'): $!"; @@ -4644,7 +5131,7 @@ sub up_to_date { } $most_recent_source = -M _ if -M _ < $most_recent_source; } - + foreach my $derived (@$derived) { return 0 if -M $derived > $most_recent_source; } @@ -4655,21 +5142,21 @@ sub dir_contains { my ($self, $first, $second) = @_; # File::Spec doesn't have an easy way to check whether one directory # is inside another, unfortunately. - + ($first, $second) = map File::Spec->canonpath($_), ($first, $second); my @first_dirs = File::Spec->splitdir($first); my @second_dirs = File::Spec->splitdir($second); return 0 if @second_dirs < @first_dirs; - + my $is_same = ( File::Spec->case_tolerant ? sub {lc(shift()) eq lc(shift())} : sub {shift() eq shift()} ); - + while (@first_dirs) { return 0 unless $is_same->(shift @first_dirs, shift @second_dirs); } - + return 1; } diff --git a/cpan/Module-Build/lib/Module/Build/Bundling.pod b/cpan/Module-Build/lib/Module/Build/Bundling.pod new file mode 100644 index 0000000..0a60d8f --- /dev/null +++ b/cpan/Module-Build/lib/Module/Build/Bundling.pod @@ -0,0 +1,154 @@ +=head1 NAME + +Module::Build::Bundling - How to bundle Module::Build with a distribution + +=head1 SYNOPSIS + + # Build.PL + use lib '.'; + use inc::latest 'Module::Build'; + + Module::Build->new( + module_name => 'Foo::Bar', + license => 'perl', + )->create_build_script; + +=head1 DESCRIPTION + +B + +In order to install a distribution using Module::Build, users must +have Module::Build available on their systems. There are two ways +to do this. The first way is to include Module::Build in the +C metadata field. This field is supported by +recent versions L and L and is a standard feature +in the Perl core as of Perl 5.10.1. Module::Build now adds itself +to C by default. + +The second way supports older Perls that have not upgraded CPAN or +CPANPLUS and involves bundling an entire copy of Module::Build +into the distribution's C directory. This is the same approach +used by L, a modern wrapper around ExtUtils::MakeMaker +for Makefile.PL based distributions. + +The "trick" to making this work for Module::Build is making sure the +highest version Module::Build is used, whether this is in C or +already installed on the user's system. This ensures that all necessary +features are available as well as any new bug fixes. This is done using +the new L module. + +A "normal" Build.PL looks like this (with only the minimum required +fields): + + use Module::Build; + + Module::Build->new( + module_name => 'Foo::Bar', + license => 'perl', + )->create_build_script; + +A "bundling" Build.PL replaces the initial "use" line with a nearly +transparent replacement: + + use lib '.'; + use inc::latest 'Module::Build'; + + Module::Build->new( + module_name => 'Foo::Bar', + license => 'perl', + )->create_build_script; + +The inital C line ensures that the top-level distribution directory is +added to C<@INC> so that C loads from C<./inc/latest.pm>. You +SHOULD NOT add 'inc' to C<@INC> (unless you have other special reasons for +doing so) -- that's not how C works. + +For I, when "Build dist" is run, Module::Build will be +automatically bundled into C according to the rules for +L. + +For I, inc::latest will load the latest Module::Build, whether +installed or bundled in C. + +=head1 BUNDLING OTHER CONFIGURATION DEPENDENCIES + +The same approach works for other configuration dependencies -- modules +that I be available for Build.PL to run. All other dependencies can +be specified as usual in the Build.PL and CPAN or CPANPLUS will install +them after Build.PL finishes. + +For example, to bundle the L module (which ensures a +"Unix-like" operating system), one could do this: + + use inc::latest 'Devel::AssertOS::Unix'; + use inc::latest 'Module::Build'; + + Module::Build->new( + module_name => 'Foo::Bar', + license => 'perl', + )->create_build_script; + +The C module creates bundled directories based on the packlist +file of an installed distribution. Even though C takes module +name arguments, it is better to think of it as bundling and making +available entire I. When a module is loaded through +C, it looks in all bundled distributions in C for a +newer module than can be found in the existing C<@INC> array. + +Thus, the module-name provided should usually be the "top-level" module +name of a distribution, though this is not strictly required. For example, +L has a number of heuristics to map module names to +packlists, allowing users to do things like this: + + use inc::latest 'Devel::AssertOS::Unix'; + +even though Devel::AssertOS::Unix is contained within the Devel-CheckOS +distribution. + +At the current time, packlists are required. Thus, bundling dual-core +modules, I, may require a 'forced install' over +versions in the latest version of perl in order to create the necessary +packlist for bundling. This limitation will hopefully be addressed in a +future version of Module::Build. + +=head2 WARNING -- How to Manage Dependency Chains + +Before bundling a distribution you must ensure that all prerequisites are +also bundled and load in the correct order. For Module::Build itself, this +should not be necessary, but it is necessary for any other distribution. +(A future release of Module::Build will hopefully address this deficiency.) + +For example, if you need C, but C depends on C, +your Build.PL might look like this: + + use inc::latest 'Wobble'; + use inc::latest 'Wibble'; + use inc::latest 'Module::Build'; + + Module::Build->new( + module_name => 'Foo::Bar', + license => 'perl', + )->create_build_script; + +Authors are strongly suggested to limit the bundling of additional +dependencies if at all possible and to carefully test their distribution +tarballs on older versions of Perl before uploading to CPAN. + +=head1 AUTHOR + +David Golden + +Development questions, bug reports, and patches should be sent to the +Module-Build mailing list at . + +Bug reports are also welcome at +. + +=head1 SEE ALSO + +perl(1), L, L(3), L(3), +L(3), + +=cut + +# vim: tw=75 diff --git a/cpan/Module-Build/lib/Module/Build/Compat.pm b/cpan/Module-Build/lib/Module/Build/Compat.pm index dfe75d5..ebe1b12 100644 --- a/cpan/Module-Build/lib/Module/Build/Compat.pm +++ b/cpan/Module-Build/lib/Module/Build/Compat.pm @@ -2,7 +2,7 @@ package Module::Build::Compat; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; use File::Basename (); use File::Spec; @@ -18,7 +18,7 @@ my %convert_installdirs = ( VENDOR => 'vendor', ); -my %makefile_to_build = +my %makefile_to_build = ( TEST_VERBOSE => 'verbose', VERBINST => 'verbose', @@ -64,13 +64,50 @@ my %macro_to_build = %makefile_to_build; # "LIB=foo make" is not the same as "perl Makefile.PL LIB=foo" delete $macro_to_build{LIB}; +sub _simple_prereq { + return $_[0] =~ /^[0-9_]+\.?[0-9_]*$/; # crudly, a decimal literal +} + +sub _merge_prereq { + my ($req, $breq) = @_; + $req ||= {}; + $breq ||= {}; + + # validate formats + for my $p ( $req, $breq ) { + for my $k (keys %$p) { + die "Prereq '$p->{$k}' for '$k' is not supported by Module::Build::Compat\n" + unless _simple_prereq($p->{$k}); + } + } + # merge + my $merge = { %$req }; + for my $k ( keys %$breq ) { + my $v1 = $merge->{$k} || 0; + my $v2 = $breq->{$k}; + $merge->{$k} = $v1 > $v2 ? $v1 : $v2; + } + return %$merge; +} + sub create_makefile_pl { my ($package, $type, $build, %args) = @_; - + die "Don't know how to build Makefile.PL of type '$type'" unless $type =~ /^(small|passthrough|traditional)$/; + if ($type eq 'passthrough') { + $build->log_warn(<<"HERE"); + +IMPORTANT NOTE: The '$type' style of Makefile.PL is deprecated and +may be removed in a future version of Module::Build in favor of the +'configure_requires' property. See Module::Build::Compat +documentation for details. + +HERE + } + my $fh; if ($args{fh}) { $fh = $args{fh}; @@ -83,7 +120,7 @@ sub create_makefile_pl { print {$fh} "# Note: this file was auto-generated by ", __PACKAGE__, " version $VERSION\n"; - # Minimum perl version should be specified as "require 5.XXXXXX" in + # Minimum perl version should be specified as "require 5.XXXXXX" in # Makefile.PL my $requires = $build->requires; if ( my $minimum_perl = $requires->{perl} ) { @@ -123,41 +160,41 @@ EOF } elsif ($type eq 'passthrough') { printf {$fh} <<'EOF', $subclass_load, ref($build), ref($build); - + unless (eval "use Module::Build::Compat 0.02; 1" ) { print "This module requires Module::Build to install itself.\n"; - + require ExtUtils::MakeMaker; my $yn = ExtUtils::MakeMaker::prompt (' Install Module::Build now from CPAN?', 'y'); - + unless ($yn =~ /^y/i) { die " *** Cannot install without Module::Build. Exiting ...\n"; } - + require Cwd; require File::Spec; require CPAN; - + # Save this 'cause CPAN will chdir all over the place. my $cwd = Cwd::cwd(); - + CPAN::Shell->install('Module::Build::Compat'); CPAN::Shell->expand("Module", "Module::Build::Compat")->uptodate or die "Couldn't install Module::Build, giving up.\n"; - + chdir $cwd or die "Cannot chdir() back to $cwd: $!"; } eval "use Module::Build::Compat 0.02; 1" or die $@; %s Module::Build::Compat->run_build_pl(args => \@ARGV); - my $build_script = 'Build'; + my $build_script = 'Build'; $build_script .= '.com' if $^O eq 'VMS'; exit(0) unless(-e $build_script); # cpantesters convention require %s; Module::Build::Compat->write_makefile(build_class => '%s'); EOF - + } elsif ($type eq 'traditional') { my (%MM_Args, %prereq); @@ -165,37 +202,37 @@ EOF tie %MM_Args, 'Tie::IxHash'; # Don't care if it fails here tie %prereq, 'Tie::IxHash'; # Don't care if it fails here } - + my %name = ($build->module_name ? (NAME => $build->module_name) : (DISTNAME => $build->dist_name)); - + my %version = ($build->dist_version_from ? (VERSION_FROM => $build->dist_version_from) : (VERSION => $build->dist_version) ); %MM_Args = (%name, %version); - - %prereq = ( %{$build->requires}, %{$build->build_requires} ); + + %prereq = _merge_prereq( $build->requires, $build->build_requires ); %prereq = map {$_, $prereq{$_}} sort keys %prereq; - + delete $prereq{perl}; $MM_Args{PREREQ_PM} = \%prereq; - + $MM_Args{INSTALLDIRS} = $build->installdirs eq 'core' ? 'perl' : $build->installdirs; - + $MM_Args{EXE_FILES} = [ sort keys %{$build->script_files} ] if $build->script_files; - + $MM_Args{PL_FILES} = $build->PL_files || {}; if ($build->recursive_test_files) { - $MM_Args{TESTS} = join q{ }, $package->_test_globs($build); + $MM_Args{test} = { TESTS => join q{ }, $package->_test_globs($build) }; } local $Data::Dumper::Terse = 1; my $args = Data::Dumper::Dumper(\%MM_Args); $args =~ s/\{(.*)\}/($1)/s; - + print $fh <<"EOF"; use ExtUtils::MakeMaker; WriteMakefile @@ -213,7 +250,7 @@ sub _test_globs { sub subclass_dir { my ($self, $build) = @_; - + return (Module::Build::ModuleInfo->find_module_dir_by_name(ref $build) || File::Spec->catdir($build->config_dir, 'lib')); } @@ -228,7 +265,7 @@ sub makefile_to_build_args { my @out; foreach my $arg (@_) { next if $arg eq ''; - + my ($key, $val) = ($arg =~ /^(\w+)=(.+)/ ? ($1, $2) : die "Malformed argument '$arg'"); @@ -283,7 +320,7 @@ sub makefile_to_build_macros { } } } - push @out, (config => \%config) if %config; + push @out, (config => \%config) if %config; return @out; } @@ -342,19 +379,19 @@ $action : force_do_it $perl $Build $action EOF } - + if ($self->_is_vms_mms) { # Roll our own .EXPORT as MMS/MMK don't honor that directive. - $maketext .= "\n.FIRST\n\t\@ $noop\n"; + $maketext .= "\n.FIRST\n\t\@ $noop\n"; for my $macro (keys %macro_to_build) { $maketext .= ".IFDEF $macro\n\tDEFINE $macro \"\$($macro)\"\n.ENDIF\n"; } - $maketext .= "\n"; + $maketext .= "\n"; } else { $maketext .= "\n.EXPORT : " . join(' ', keys %macro_to_build) . "\n\n"; } - + return $maketext; } @@ -363,15 +400,13 @@ sub fake_prereqs { my $fh = IO::File->new("< $file") or die "Can't read $file: $!"; my $prereqs = eval do {local $/; <$fh>}; close $fh; - + + my %merged = _merge_prereq( $prereqs->{requires}, $prereqs->{build_requires} ); my @prereq; - foreach my $section (qw/build_requires requires/) { - foreach (keys %{$prereqs->{$section}}) { - next if $_ eq 'perl'; - push @prereq, "$_=>q[$prereqs->{$section}{$_}]"; - } + foreach (sort keys %merged) { + next if $_ eq 'perl'; + push @prereq, "$_=>q[$merged{$_}]"; } - return unless @prereq; return "# PREREQ_PM => { " . join(", ", @prereq) . " }\n\n"; } @@ -414,7 +449,7 @@ Module::Build::Compat - Compatibility with ExtUtils::MakeMaker my $build = Module::Build->new ( module_name => 'Foo::Bar', license => 'perl', - create_makefile_pl => 'passthrough' ); + create_makefile_pl => 'traditional' ); ... @@ -448,6 +483,18 @@ The currently supported styles are: =over 4 +=item traditional + +A F will be created in the "traditional" style, i.e. it will +use C and won't rely on C at all. +In order to create the F, we'll include the C and +C dependencies as the C parameter. + +You don't want to use this style if during the C stage +you ask the user questions, or do some auto-sensing about the user's +environment, or if you subclass C to do some +customization, because the vanilla F won't do any of that. + =item small A small F will be created that passes all functionality @@ -455,24 +502,22 @@ through to the F script in the same directory. The user must already have C installed in order to use this, or else they'll get a module-not-found error. -=item passthrough +=item passthrough (DEPRECATED) This is just like the C option above, but if C is not already installed on the user's system, the script will offer to use C to download it and install it before continuing with the build. -=item traditional - -A F will be created in the "traditional" style, i.e. it will -use C and won't rely on C at all. -In order to create the F, we'll include the C and -C dependencies as the C parameter. +This option has been deprecated and may be removed in a future version +of Module::Build. Modern CPAN.pm and CPANPLUS will recognize the +C metadata property and install Module::Build before +running Build.PL if Module::Build is listed and Module::Build now +adds itself to configure_requires by default. -You don't want to use this style if during the C stage -you ask the user questions, or do some auto-sensing about the user's -environment, or if you subclass C to do some -customization, because the vanilla F won't do any of that. +Perl 5.10.1 includes C support. In the future, when +C support is deemed sufficiently widespread, the +C style will be removed. =back diff --git a/cpan/Module-Build/lib/Module/Build/Config.pm b/cpan/Module-Build/lib/Module/Build/Config.pm index de8b44d..b833e2b 100644 --- a/cpan/Module-Build/lib/Module/Build/Config.pm +++ b/cpan/Module-Build/lib/Module/Build/Config.pm @@ -2,7 +2,7 @@ package Module::Build::Config; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Config; diff --git a/cpan/Module-Build/lib/Module/Build/Cookbook.pm b/cpan/Module-Build/lib/Module/Build/Cookbook.pm index 82c8e01..42054d1 100644 --- a/cpan/Module-Build/lib/Module/Build/Cookbook.pm +++ b/cpan/Module-Build/lib/Module/Build/Cookbook.pm @@ -1,7 +1,7 @@ package Module::Build::Cookbook; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; =head1 NAME @@ -487,7 +487,7 @@ Next, add this to the top of your F. # Find out what version of Module::Build is installed or fail quietly. # This should be cross-platform. - my $Installed_MB = + my $Installed_MB = `$^X -e "eval q{require Module::Build; print Module::Build->VERSION} or exit 1"; # some operating systems put a newline at the end of every print. diff --git a/cpan/Module-Build/lib/Module/Build/Dumper.pm b/cpan/Module-Build/lib/Module/Build/Dumper.pm index 1cd8cd0..6f8ff7a 100644 --- a/cpan/Module-Build/lib/Module/Build/Dumper.pm +++ b/cpan/Module-Build/lib/Module/Build/Dumper.pm @@ -1,7 +1,7 @@ package Module::Build::Dumper; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; # This is just a split-out of a wrapper function to do Data::Dumper # stuff "the right way". See: diff --git a/cpan/Module-Build/lib/Module/Build/ModuleInfo.pm b/cpan/Module-Build/lib/Module/Build/ModuleInfo.pm index 4de09b4..12ffa1d 100644 --- a/cpan/Module-Build/lib/Module/Build/ModuleInfo.pm +++ b/cpan/Module-Build/lib/Module/Build/ModuleInfo.pm @@ -8,13 +8,14 @@ package Module::Build::ModuleInfo; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use File::Spec; use IO::File; use Module::Build::Version; +my $V_NUM_REGEXP = qr{v?[0-9._]+}; # crudely, a v-string or decimal my $PKG_REGEXP = qr{ # match a package declaration ^[\s\{;]* # intro chars on a line @@ -22,6 +23,8 @@ my $PKG_REGEXP = qr{ # match a package declaration \s+ # whitespace ([\w:]+) # a package name \s* # optional whitespace + ($V_NUM_REGEXP)? # optional version number + \s* # optional whitesapce ; # semicolon line terminator }x; @@ -221,10 +224,10 @@ sub _parse_fh { $self->_parse_version_expression( $line ); if ( $line =~ $PKG_REGEXP ) { - $pkg = $1; - push( @pkgs, $pkg ) unless grep( $pkg eq $_, @pkgs ); - $vers{$pkg} = undef unless exists( $vers{$pkg} ); - $need_vers = 1; + $pkg = $1; + push( @pkgs, $pkg ) unless grep( $pkg eq $_, @pkgs ); + $vers{$pkg} = (defined $2 ? $2 : undef) unless exists( $vers{$pkg} ); + $need_vers = defined $2 ? 0 : 1; # VERSION defined with full package spec, i.e. $Module::VERSION } elsif ( $vers_fullname && $vers_pkg ) { @@ -232,7 +235,7 @@ sub _parse_fh { $need_vers = 0 if $vers_pkg eq $pkg; unless ( defined $vers{$vers_pkg} && length $vers{$vers_pkg} ) { - $vers{$vers_pkg} = + $vers{$vers_pkg} = $self->_evaluate_version_line( $vers_sig, $vers_fullname, $line ); } else { # Warn unless the user is using the "$VERSION = eval @@ -323,11 +326,22 @@ sub _evaluate_version_line { (ref($vsub) eq 'CODE') or die "failed to build version sub for $self->{filename}"; my $result = eval { $vsub->() }; + die "Could not get version from $self->{filename} by executing:\n$eval\n\nThe fatal error was: $@\n" + if $@; - die "Could not get version from $self->{filename} by executing:\n$eval\n\nThe fatal error was: $@\n" if $@; + # Activestate apparently creates custom versions like '1.23_45_01', which + # cause M::B::Version to think it's an invalid alpha. So check for that + # and strip them + my $num_dots = () = $result =~ m{\.}g; + my $num_unders = () = $result =~ m{_}g; + if ( substr($result,0,1) ne 'v' && $num_dots < 2 && $num_unders > 1 ) { + $result =~ s{_}{}g; + } # Bless it into our own version class - $result = Module::Build::Version->new($result); + eval { $result = Module::Build::Version->new($result) }; + die "Version '$result' from $self->{filename} does not appear to be valid:\n$eval\n\nThe fatal error was: $@\n" + if $@; return $result; } diff --git a/cpan/Module-Build/lib/Module/Build/Notes.pm b/cpan/Module-Build/lib/Module/Build/Notes.pm index fe98419..a0506c6 100644 --- a/cpan/Module-Build/lib/Module/Build/Notes.pm +++ b/cpan/Module-Build/lib/Module/Build/Notes.pm @@ -4,7 +4,7 @@ package Module::Build::Notes; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Data::Dumper; use IO::File; @@ -33,10 +33,10 @@ sub restore { sub access { my $self = shift; return $self->read() unless @_; - + my $key = shift; return $self->read($key) unless @_; - + my $value = shift; $self->write({ $key => $value }); return $self->read($key); @@ -61,7 +61,7 @@ sub read { return $self->{new}{$key} if exists $self->{new}{$key}; return $self->{disk}{$key}; } - + # Return all data my $out = (keys %{$self->{new}} ? {%{$self->{disk}}, %{$self->{new}}} @@ -79,7 +79,7 @@ sub _same { sub write { my ($self, $href) = @_; $href ||= {}; - + @{$self->{new}}{ keys %$href } = values %$href; # Merge # Do some optimization to avoid unnecessary writes @@ -88,17 +88,17 @@ sub write { next if ref $self->{disk}{$key} or !exists $self->{disk}{$key}; delete $self->{new}{$key} if $self->_same($self->{new}{$key}, $self->{disk}{$key}); } - + if (my $file = $self->{file}) { my ($vol, $dir, $base) = File::Spec->splitpath($file); $dir = File::Spec->catpath($vol, $dir, ''); return unless -e $dir && -d $dir; # The user needs to arrange for this return if -e $file and !keys %{ $self->{new} }; # Nothing to do - - @{$self->{disk}}{ keys %{$self->{new}} } = values %{$self->{new}}; # Merge + + @{$self->{disk}}{ keys %{$self->{new}} } = values %{$self->{new}}; # Merge $self->_dump($file, $self->{disk}); - + $self->{new} = {}; } return $self->read; @@ -106,18 +106,66 @@ sub write { sub _dump { my ($self, $file, $data) = @_; - + my $fh = IO::File->new("> $file") or die "Can't create '$file': $!"; print {$fh} Module::Build::Dumper->_data_dump($data); } +my $orig_template = do { local $/; }; +close DATA; + sub write_config_data { my ($self, %args) = @_; + my $template = $orig_template; + $template =~ s/NOTES_NAME/$args{config_module}/g; + $template =~ s/MODULE_NAME/$args{module}/g; + $template =~ s/=begin private\n//; + $template =~ s/=end private/=cut/; + + # strip out private POD markers we use to keep pod from being + # recognized for *this* source file + $template =~ s{$_\n}{} for '=begin private', '=end private'; + my $fh = IO::File->new("> $args{file}") or die "Can't create '$args{file}': $!"; + print {$fh} $template; + print {$fh} "\n__DATA__\n"; + print {$fh} Module::Build::Dumper->_data_dump([$args{config_data}, $args{feature}, $args{auto_features}]); + +} + +1; + + +=head1 NAME + +Module::Build::Notes - Create persistent distribution configuration modules + +=head1 DESCRIPTION + +This module is used internally by Module::Build to create persistent +configuration files that can be installed with a distribution. See +L for an example. + +=head1 AUTHOR - printf $fh <<'EOF', $args{config_module}; -package %s; +Ken Williams + +=head1 COPYRIGHT + +Copyright (c) 2001-2006 Ken Williams. All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +=head1 SEE ALSO + +perl(1), L(3) + +=cut + +__DATA__ +package NOTES_NAME; use strict; my $arrayref = eval do {local $/; } or die "Couldn't load ConfigData data: $@"; @@ -129,14 +177,14 @@ sub config { $config->{$_[1]} } sub set_config { $config->{$_[1]} = $_[2] } sub set_feature { $features->{$_[1]} = 0+!!$_[2] } # Constrain to 1 or 0 -sub auto_feature_names { grep !exists $features->{$_}, keys %%$auto_features } +sub auto_feature_names { grep !exists $features->{$_}, keys %$auto_features } sub feature_names { - my @features = (keys %%$features, auto_feature_names()); + my @features = (keys %$features, auto_feature_names()); @features; } -sub config_names { keys %%$config } +sub config_names { keys %$config } sub write { my $me = __FILE__; @@ -170,20 +218,20 @@ sub write { sub feature { my ($package, $key) = @_; return $features->{$key} if exists $features->{$key}; - + my $info = $auto_features->{$key} or return 0; - - # Under perl 5.005, each(%%$foo) isn't working correctly when $foo + + # Under perl 5.005, each(%$foo) isn't working correctly when $foo # was reanimated with Data::Dumper and eval(). Not sure why, but # copying to a new hash seems to solve it. - my %%info = %%$info; - + my %info = %$info; + require Module::Build; # XXX should get rid of this - while (my ($type, $prereqs) = each %%info) { + while (my ($type, $prereqs) = each %info) { next if $type eq 'description' || $type eq 'recommends'; - - my %%p = %%$prereqs; # Ditto here. - while (my ($modname, $spec) = each %%p) { + + my %p = %$prereqs; # Ditto here. + while (my ($modname, $spec) = each %p) { my $status = Module::Build->check_installed_status($modname, $spec); if ((!$status->{ok}) xor ($type =~ /conflicts$/)) { return 0; } if ( ! eval "require $modname; 1" ) { return 0; } @@ -192,36 +240,32 @@ sub feature { return 1; } -EOF - - my ($module_name, $notes_name) = ($args{module}, $args{config_module}); - printf $fh <<"EOF", $notes_name, $module_name; +=begin private =head1 NAME -$notes_name - Configuration for $module_name - +NOTES_NAME - Configuration for MODULE_NAME =head1 SYNOPSIS - use $notes_name; - \$value = $notes_name->config('foo'); - \$value = $notes_name->feature('bar'); - - \@names = $notes_name->config_names; - \@names = $notes_name->feature_names; - - $notes_name->set_config(foo => \$new_value); - $notes_name->set_feature(bar => \$new_value); - $notes_name->write; # Save changes + use NOTES_NAME; + $value = NOTES_NAME->config('foo'); + $value = NOTES_NAME->feature('bar'); + + @names = NOTES_NAME->config_names; + @names = NOTES_NAME->feature_names; + + NOTES_NAME->set_config(foo => $new_value); + NOTES_NAME->set_feature(bar => $new_value); + NOTES_NAME->write; # Save changes =head1 DESCRIPTION -This module holds the configuration data for the C<$module_name> +This module holds the configuration data for the C module. It also provides a programmatic interface for getting or setting that configuration data. Note that in order to actually make -changes, you'll have to have write access to the C<$notes_name> +changes, you'll have to have write access to the C module, and you should attempt to understand the repercussions of your actions. @@ -230,17 +274,17 @@ actions. =over 4 -=item config(\$name) +=item config($name) Given a string argument, returns the value of the configuration item by that name, or C if no such item exists. -=item feature(\$name) +=item feature($name) Given a string argument, returns the value of the feature by that name, or C if no such feature exists. -=item set_config(\$name, \$value) +=item set_config($name, $value) Sets the configuration item with the given name to the given value. The value may be any Perl scalar that will serialize correctly using @@ -248,7 +292,7 @@ C. This includes references, objects (usually), and complex data structures. It probably does not include transient things like filehandles or sockets. -=item set_feature(\$name, \$value) +=item set_feature($name, $value) Sets the feature with the given name to the given boolean value. The value will be converted to 0 or 1 automatically. @@ -256,12 +300,12 @@ value will be converted to 0 or 1 automatically. =item config_names() Returns a list of all the names of config items currently defined in -C<$notes_name>, or in scalar context the number of items. +C, or in scalar context the number of items. =item feature_names() Returns a list of all the names of features currently defined in -C<$notes_name>, or in scalar context the number of features. +C, or in scalar context the number of features. =item auto_feature_names() @@ -273,24 +317,16 @@ a fixed value. =item write() Commits any changes from C and C to disk. -Requires write access to the C<$notes_name> module. +Requires write access to the C module. =back =head1 AUTHOR -C<$notes_name> was automatically created using C. +C was automatically created using C. C was written by Ken Williams, but he holds no -authorship claim or copyright claim to the contents of C<$notes_name>. - -=cut +authorship claim or copyright claim to the contents of C. -__DATA__ - -EOF - - print {$fh} Module::Build::Dumper->_data_dump([$args{config_data}, $args{feature}, $args{auto_features}]); -} +=end private -1; diff --git a/cpan/Module-Build/lib/Module/Build/PPMMaker.pm b/cpan/Module-Build/lib/Module/Build/PPMMaker.pm index 35b5a75..74a5a73 100644 --- a/cpan/Module-Build/lib/Module/Build/PPMMaker.pm +++ b/cpan/Module-Build/lib/Module/Build/PPMMaker.pm @@ -1,8 +1,9 @@ package Module::Build::PPMMaker; use strict; +use Config; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; # This code is mostly borrowed from ExtUtils::MM_Unix 6.10_03, with a @@ -34,7 +35,6 @@ sub make_ppd { my $method = "dist_$info"; $dist{$info} = $build->$method() or die "Can't determine distribution's $info\n"; } - $dist{version} = $self->_ppd_version($dist{version}); $self->_simple_xml_escape($_) foreach $dist{abstract}, @{$dist{author}}; @@ -42,21 +42,17 @@ sub make_ppd { # various licenses my $ppd = <<"PPD"; - $dist{name} $dist{abstract} @{[ join "\n", map " $_", @{$dist{author}} ]} PPD - # TODO: We could set or maybe - # ??? - # We don't include recommended dependencies because PPD has no way # to distinguish them from normal dependencies. We don't include # build_requires dependencies because the PPM installer doesn't # build or test before installing. And obviously we don't include # conflicts either. - + foreach my $type (qw(requires)) { my $prereq = $build->$type(); while (my ($modname, $spec) = each %$prereq) { @@ -73,27 +69,18 @@ PPD } } - # Another hack - dependencies are on modules, but PPD expects - # them to be on distributions (I think). - $modname =~ s/::/-/g; - - $ppd .= sprintf(<<'EOF', $modname, $self->_ppd_version($min_version)); - -EOF + # PPM4 spec requires a '::' for top level modules + $modname .= '::' unless $modname =~ /::/; + $ppd .= qq! \n!; } } # We only include these tags if this module involves XS, on the - # assumption that pure Perl modules will work on any OS. PERLCORE, - # unfortunately, seems to indicate that a module works with _only_ - # that version of Perl, and so is only appropriate when a module - # uses XS. + # assumption that pure Perl modules will work on any OS. if (keys %{$build->find_xs_files}) { my $perl_version = $self->_ppd_version($build->perl_version); - $ppd .= sprintf(<<'EOF', $perl_version, $^O, $self->_varchname($build->config) ); - - + $ppd .= sprintf(<<'EOF', $self->_varchname($build->config) ); EOF } @@ -113,7 +100,9 @@ EOF my $ppd_file = "$dist{name}.ppd"; my $fh = IO::File->new(">$ppd_file") or die "Cannot write to $ppd_file: $!"; - $fh->binmode(":utf8") if $fh->can("binmode"); + + $fh->binmode(":utf8") + if $fh->can('binmode') && $] >= 5.008 && $Config{useperlio}; print $fh $ppd; close $fh; @@ -148,7 +137,7 @@ sub _varchname { # Copied from PPM.pm '<' => '<', ); my $rx = join '|', keys %escapes; - + sub _simple_xml_escape { $_[1] =~ s/($rx)/$escapes{$1}/go; } diff --git a/cpan/Module-Build/lib/Module/Build/Platform/Amiga.pm b/cpan/Module-Build/lib/Module/Build/Platform/Amiga.pm index 5ce8cf5..b31a963 100644 --- a/cpan/Module-Build/lib/Module/Build/Platform/Amiga.pm +++ b/cpan/Module-Build/lib/Module/Build/Platform/Amiga.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::Amiga; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Module::Build::Base; diff --git a/cpan/Module-Build/lib/Module/Build/Platform/Default.pm b/cpan/Module-Build/lib/Module/Build/Platform/Default.pm index df29af5..b0e83a3 100644 --- a/cpan/Module-Build/lib/Module/Build/Platform/Default.pm +++ b/cpan/Module-Build/lib/Module/Build/Platform/Default.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::Default; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Module::Build::Base; diff --git a/cpan/Module-Build/lib/Module/Build/Platform/EBCDIC.pm b/cpan/Module-Build/lib/Module/Build/Platform/EBCDIC.pm index d68836c..4365b12 100644 --- a/cpan/Module-Build/lib/Module/Build/Platform/EBCDIC.pm +++ b/cpan/Module-Build/lib/Module/Build/Platform/EBCDIC.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::EBCDIC; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Module::Build::Base; diff --git a/cpan/Module-Build/lib/Module/Build/Platform/MPEiX.pm b/cpan/Module-Build/lib/Module/Build/Platform/MPEiX.pm index a835c30..c735378 100644 --- a/cpan/Module-Build/lib/Module/Build/Platform/MPEiX.pm +++ b/cpan/Module-Build/lib/Module/Build/Platform/MPEiX.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::MPEiX; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Module::Build::Base; diff --git a/cpan/Module-Build/lib/Module/Build/Platform/MacOS.pm b/cpan/Module-Build/lib/Module/Build/Platform/MacOS.pm index 9c9281a..2c74942 100644 --- a/cpan/Module-Build/lib/Module/Build/Platform/MacOS.pm +++ b/cpan/Module-Build/lib/Module/Build/Platform/MacOS.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::MacOS; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Module::Build::Base; use vars qw(@ISA); @@ -15,17 +15,17 @@ sub have_forkpipe { 0 } sub new { my $class = shift; my $self = $class->SUPER::new(@_); - + # $Config{sitelib} and $Config{sitearch} are, unfortunately, missing. foreach ('sitelib', 'sitearch') { $self->config($_ => $self->config("install$_")) unless $self->config($_); } - + # For some reason $Config{startperl} is filled with a bunch of crap. (my $sp = $self->config('startperl')) =~ s/.*Exit \{Status\}\s//; $self->config(startperl => $sp); - + return $self; } @@ -42,7 +42,7 @@ sub dispatch { if( !@_ and !@ARGV ) { require MacPerl; - + # What comes first in the action list. my @action_list = qw(build test install); my %actions = map {+($_, 1)} $self->known_actions; @@ -53,17 +53,17 @@ sub dispatch { foreach (@action_list) { $_ .= ' *' if $toolserver{$_}; } - + my $cmd = MacPerl::Pick("What build command? ('*' requires ToolServer)", @action_list); return unless defined $cmd; $cmd =~ s/ \*$//; $ARGV[0] = ($cmd); - + my $args = MacPerl::Ask('Any extra arguments? (ie. verbose=1)', ''); return unless defined $args; push @ARGV, $self->split_like_shell($args); } - + $self->SUPER::dispatch(@_); } @@ -82,10 +82,10 @@ sub ACTION_realclean { sub ACTION_install { my $self = shift; - + return $self->SUPER::ACTION_install(@_) if eval {ExtUtils::Install->VERSION('1.30'); 1}; - + local $^W = 0; # Avoid a 'redefine' warning local *ExtUtils::Install::find = sub { my ($code, @dirs) = @_; @@ -94,7 +94,7 @@ sub ACTION_install { return File::Find::find($code, @dirs); }; - + return $self->SUPER::ACTION_install(@_); } diff --git a/cpan/Module-Build/lib/Module/Build/Platform/RiscOS.pm b/cpan/Module-Build/lib/Module/Build/Platform/RiscOS.pm index c240750..9deb097 100644 --- a/cpan/Module-Build/lib/Module/Build/Platform/RiscOS.pm +++ b/cpan/Module-Build/lib/Module/Build/Platform/RiscOS.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::RiscOS; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Module::Build::Base; diff --git a/cpan/Module-Build/lib/Module/Build/Platform/Unix.pm b/cpan/Module-Build/lib/Module/Build/Platform/Unix.pm index 879ca3a..43f585f 100644 --- a/cpan/Module-Build/lib/Module/Build/Platform/Unix.pm +++ b/cpan/Module-Build/lib/Module/Build/Platform/Unix.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::Unix; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Module::Build::Base; diff --git a/cpan/Module-Build/lib/Module/Build/Platform/VMS.pm b/cpan/Module-Build/lib/Module/Build/Platform/VMS.pm index 3305154..13d350d 100644 --- a/cpan/Module-Build/lib/Module/Build/Platform/VMS.pm +++ b/cpan/Module-Build/lib/Module/Build/Platform/VMS.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::VMS; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Module::Build::Base; @@ -131,22 +131,22 @@ sub _quote_args { # or if we get a single arg that is an array reference, quote the # elements of it and return the reference. my ($self, @args) = @_; - my $got_arrayref = (scalar(@args) == 1 - && UNIVERSAL::isa($args[0], 'ARRAY')) - ? 1 + my $got_arrayref = (scalar(@args) == 1 + && UNIVERSAL::isa($args[0], 'ARRAY')) + ? 1 : 0; # Do not quote qualifiers that begin with '/'. - map { if (!/^\//) { + map { if (!/^\//) { $_ =~ s/\"/""/g; # escape C<"> by doubling $_ = q(").$_.q("); } } - ($got_arrayref ? @{$args[0]} + ($got_arrayref ? @{$args[0]} : @args ); - return $got_arrayref ? $args[0] + return $got_arrayref ? $args[0] : join(' ', @args); } @@ -173,6 +173,62 @@ sub _backticks { return `$cmd $args`; } +=item find_command + +Local an executable program + +=cut + +sub find_command { + my ($self, $command) = @_; + + # a lot of VMS executables have a symbol defined + # check those first + if ( $^O eq 'VMS' ) { + require VMS::DCLsym; + my $syms = VMS::DCLsym->new; + return $command if scalar $syms->getsym( uc $command ); + } + + $self->SUPER::find_command($command); +} + +# _maybe_command copied from ExtUtils::MM_VMS::maybe_command + +=item _maybe_command (override) + +Follows VMS naming conventions for executable files. +If the name passed in doesn't exactly match an executable file, +appends F<.Exe> (or equivalent) to check for executable image, and F<.Com> +to check for DCL procedure. If this fails, checks directories in DCL$PATH +and finally F for an executable file having the name specified, +with or without the F<.Exe>-equivalent suffix. + +=cut + +sub _maybe_command { + my($self,$file) = @_; + return $file if -x $file && ! -d _; + my(@dirs) = (''); + my(@exts) = ('',$Config{'exe_ext'},'.exe','.com'); + + if ($file !~ m![/:>\]]!) { + for (my $i = 0; defined $ENV{"DCL\$PATH;$i"}; $i++) { + my $dir = $ENV{"DCL\$PATH;$i"}; + $dir .= ':' unless $dir =~ m%[\]:]$%; + push(@dirs,$dir); + } + push(@dirs,'Sys$System:'); + foreach my $dir (@dirs) { + my $sysfile = "$dir$file"; + foreach my $ext (@exts) { + return $file if -x "$sysfile$ext" && ! -d _; + } + } + } + return; +} + =item do_system Override to ensure that we quote the arguments but not the command. @@ -182,7 +238,7 @@ Override to ensure that we quote the arguments but not the command. sub do_system { # The command must not be quoted but the arguments to it must be. my ($self, @cmd) = @_; - $self->log_info("@cmd\n"); + $self->log_verbose("@cmd\n"); my $cmd = shift @cmd; my $args = $self->_quote_args(@cmd); return !system("$cmd $args"); @@ -205,7 +261,7 @@ sub oneliner { =item _infer_xs_spec -Inherit the standard version but tweak the library file name to be +Inherit the standard version but tweak the library file name to be something Dynaloader can find. =cut @@ -250,7 +306,7 @@ sub rscan_dir { =item dist_dir -Inherit the standard version but replace embedded dots with underscores because +Inherit the standard version but replace embedded dots with underscores because a dot is the directory delimiter on VMS. =cut @@ -265,7 +321,7 @@ sub dist_dir { =item man3page_name -Inherit the standard version but chop the extra manpage delimiter off the front if +Inherit the standard version but chop the extra manpage delimiter off the front if there is one. The VMS version of splitdir('[.foo]') returns '', 'foo'. =cut @@ -367,7 +423,7 @@ sub _detildefy { $newdirs = File::Spec::Unix->catdir(@hdirs, @backup, @dirs); } - + # Now put the two cases back together $arg = File::Spec::Unix->catpath($hvol, $newdirs, $file); @@ -446,7 +502,7 @@ sub _unix_rpt { $unix_rpt = VMS::Feature::current("filename_unix_report"); } else { my $env_unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || ''; - $unix_rpt = $env_unix_rpt =~ /^[ET1]/i; + $unix_rpt = $env_unix_rpt =~ /^[ET1]/i; } return $unix_rpt; } @@ -459,7 +515,7 @@ sub _efs { $efs = VMS::Feature::current("efs_charset"); } else { my $env_efs = $ENV{'DECC$EFS_CHARSET'} || ''; - $efs = $env_efs =~ /^[ET1]/i; + $efs = $env_efs =~ /^[ET1]/i; } return $efs; } diff --git a/cpan/Module-Build/lib/Module/Build/Platform/VOS.pm b/cpan/Module-Build/lib/Module/Build/Platform/VOS.pm index be46a80..2061b2c 100644 --- a/cpan/Module-Build/lib/Module/Build/Platform/VOS.pm +++ b/cpan/Module-Build/lib/Module/Build/Platform/VOS.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::VOS; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Module::Build::Base; diff --git a/cpan/Module-Build/lib/Module/Build/Platform/Windows.pm b/cpan/Module-Build/lib/Module/Build/Platform/Windows.pm index 6cf9da9..fcaef5a 100644 --- a/cpan/Module-Build/lib/Module/Build/Platform/Windows.pm +++ b/cpan/Module-Build/lib/Module/Build/Platform/Windows.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::Windows; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Config; @@ -39,7 +39,7 @@ sub ACTION_realclean { if ( lc $basename eq lc $self->build_script ) { if ( $self->build_bat ) { - $self->log_info("Deleting $basename.bat\n"); + $self->log_verbose("Deleting $basename.bat\n"); my $full_progname = $0; $full_progname =~ s/(?:\.bat)?$/.bat/i; @@ -207,22 +207,22 @@ sub split_like_shell { # into words. The algorithm below was bashed out by Randy and Ken # (mostly Randy), and there are a lot of regression tests, so we # should feel free to adjust if desired. - + (my $self, local $_) = @_; - + return @$_ if defined() && UNIVERSAL::isa($_, 'ARRAY'); - + my @argv; return @argv unless defined() && length(); - + my $arg = ''; my( $i, $quote_mode ) = ( 0, 0 ); - + while ( $i < length() ) { - + my $ch = substr( $_, $i , 1 ); my $next_ch = substr( $_, $i+1, 1 ); - + if ( $ch eq '\\' && $next_ch eq '"' ) { $arg .= '"'; $i++; @@ -249,10 +249,10 @@ sub split_like_shell { } else { $arg .= $ch; } - + $i++; } - + push( @argv, $arg ) if defined( $arg ) && length( $arg ); return @argv; } @@ -273,6 +273,27 @@ sub do_system { return !$status; } +# Copied from ExtUtils::MM_Win32 +sub _maybe_command { + my($self,$file) = @_; + my @e = exists($ENV{'PATHEXT'}) + ? split(/;/, $ENV{PATHEXT}) + : qw(.com .exe .bat .cmd); + my $e = ''; + for (@e) { $e .= "\Q$_\E|" } + chop $e; + # see if file ends in one of the known extensions + if ($file =~ /($e)$/i) { + return $file if -e $file; + } + else { + for (@e) { + return "$file$_" if -e "$file$_"; + } + } + return; +} + 1; diff --git a/cpan/Module-Build/lib/Module/Build/Platform/aix.pm b/cpan/Module-Build/lib/Module/Build/Platform/aix.pm index 45feb3c..7ba3c32 100644 --- a/cpan/Module-Build/lib/Module/Build/Platform/aix.pm +++ b/cpan/Module-Build/lib/Module/Build/Platform/aix.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::aix; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Module::Build::Platform::Unix; diff --git a/cpan/Module-Build/lib/Module/Build/Platform/cygwin.pm b/cpan/Module-Build/lib/Module/Build/Platform/cygwin.pm index 62a6461..8b882ed 100644 --- a/cpan/Module-Build/lib/Module/Build/Platform/cygwin.pm +++ b/cpan/Module-Build/lib/Module/Build/Platform/cygwin.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::cygwin; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Module::Build::Platform::Unix; @@ -13,6 +13,22 @@ sub manpage_separator { '.' } +# Copied from ExtUtils::MM_Cygwin::maybe_command() +# If our path begins with F then we use C +# to determine if it may be a command. Otherwise we use the tests +# from C. + +sub _maybe_command { + my ($self, $file) = @_; + + if ($file =~ m{^/cygdrive/}i) { + require Module::Build::Platform::Win32; + return Module::Build::Platform::Win32->_maybe_command($file); + } + + return $self->SUPER::_maybe_command($file); +} + 1; __END__ diff --git a/cpan/Module-Build/lib/Module/Build/Platform/darwin.pm b/cpan/Module-Build/lib/Module/Build/Platform/darwin.pm index 39e9e36..145933d 100644 --- a/cpan/Module-Build/lib/Module/Build/Platform/darwin.pm +++ b/cpan/Module-Build/lib/Module/Build/Platform/darwin.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::darwin; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Module::Build::Platform::Unix; diff --git a/cpan/Module-Build/lib/Module/Build/Platform/os2.pm b/cpan/Module-Build/lib/Module/Build/Platform/os2.pm index ace01a3..b6615c8 100644 --- a/cpan/Module-Build/lib/Module/Build/Platform/os2.pm +++ b/cpan/Module-Build/lib/Module/Build/Platform/os2.pm @@ -2,7 +2,7 @@ package Module::Build::Platform::os2; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use Module::Build::Platform::Unix; @@ -13,6 +13,16 @@ sub manpage_separator { '.' } sub have_forkpipe { 0 } +# Copied from ExtUtils::MM_OS2::maybe_command +sub _maybe_command { + my($self,$file) = @_; + $file =~ s,[/\\]+,/,g; + return $file if -x $file && ! -d _; + return "$file.exe" if -x "$file.exe" && ! -d _; + return "$file.cmd" if -x "$file.cmd" && ! -d _; + return; +} + 1; __END__ diff --git a/cpan/Module-Build/lib/Module/Build/PodParser.pm b/cpan/Module-Build/lib/Module/Build/PodParser.pm index b17b80b..7a94e77 100644 --- a/cpan/Module-Build/lib/Module/Build/PodParser.pm +++ b/cpan/Module-Build/lib/Module/Build/PodParser.pm @@ -2,7 +2,7 @@ package Module::Build::PodParser; use strict; use vars qw($VERSION); -$VERSION = '0.35'; +$VERSION = '0.35_08'; $VERSION = eval $VERSION; use vars qw(@ISA); @@ -33,31 +33,31 @@ sub new { sub _myparse_from_filehandle { my ($self, $fh) = @_; - + local $_; while (<$fh>) { next unless /^=(?!cut)/ .. /^=cut/; # in POD last if ($self->{abstract}) = /^ (?: [a-z:]+ \s+ - \s+ ) (.*\S) /ix; } - + my @author; while (<$fh>) { - next unless /^=head1\s+AUTHORS?/ ... /^=/; + next unless /^=head1\s+AUTHORS?/i ... /^=/; next if /^=/; push @author, $_ if /\@/; } return unless @author; s/^\s+|\s+$//g foreach @author; - + $self->{author} = \@author; - + return; } sub get_abstract { my $self = shift; return $self->{abstract} if defined $self->{abstract}; - + $self->parse_from_filehandle($self->{fh}); return $self->{abstract}; @@ -66,7 +66,7 @@ sub get_abstract { sub get_author { my $self = shift; return $self->{author} if defined $self->{author}; - + $self->parse_from_filehandle($self->{fh}); return $self->{author} || []; @@ -92,10 +92,10 @@ sub textblock { my ($self, $text) = @_; $text =~ s/^\s+//; $text =~ s/\s+$//; - if ($self->{_head} eq 'NAME') { + if (uc $self->{_head} eq 'NAME') { my ($name, $abstract) = split( /\s+-\s+/, $text, 2 ); $self->{abstract} = $abstract; - } elsif ($self->{_head} =~ /^AUTHORS?$/) { + } elsif ($self->{_head} =~ /^AUTHORS?$/i) { push @{$self->{author}}, $text if $text =~ /\@/; } } diff --git a/cpan/Module-Build/lib/Module/Build/Version.pm b/cpan/Module-Build/lib/Module/Build/Version.pm index 0664d43..4a1b961 100644 --- a/cpan/Module-Build/lib/Module/Build/Version.pm +++ b/cpan/Module-Build/lib/Module/Build/Version.pm @@ -81,7 +81,7 @@ sub import { map { $args{$_} = 1 } @_ } else { # no parameters at all on use line - %args = + args = ( qv => 1, 'UNIVERSAL::VERSION' => 1, @@ -89,9 +89,9 @@ sub import { } my $callpkg = caller(); - + if (exists($args{declare})) { - *{$callpkg."::declare"} = + *{$callpkg."::declare"} = sub {return $class->declare(shift) } unless defined(&{$callpkg.'::declare'}); } @@ -155,7 +155,7 @@ sub new { my ($class, $value) = @_; my $self = bless ({}, ref ($class) || $class); - + if ( ref($value) && eval('$value->isa("version")') ) { # Can copy the elements directly $self->{version} = [ @{$value->{version} } ]; @@ -193,7 +193,7 @@ sub new $value = sprintf("%.9f",$value); $value =~ s/(0+)$//; # trim trailing zeros } - + # This is not very efficient, but it is morally equivalent # to the XS code (as that is the reference implementation). # See vutil/vutil.c for details @@ -215,7 +215,7 @@ sub new } $start = $last = $pos = $s; - + # pre-scan the input string to check for decimals/underbars while ( substr($value,$pos,1) =~ /[._\d,]/ ) { if ( substr($value,$pos,1) eq '.' ) { @@ -300,7 +300,7 @@ sub new $orev = $rev; $rev += substr($value,$s,1) * $mult; $mult /= 10; - if ( abs($orev) > abs($rev) + if ( abs($orev) > abs($rev) || abs($rev) > abs($VERSION_MAX) ) { if ( warnings::enabled("overflow") ) { require Carp; @@ -320,7 +320,7 @@ sub new $orev = $rev; $rev += substr($value,$end,1) * $mult; $mult *= 10; - if ( abs($orev) > abs($rev) + if ( abs($orev) > abs($rev) || abs($rev) > abs($VERSION_MAX) ) { if ( warnings::enabled("overflow") ) { require Carp; @@ -335,15 +335,15 @@ sub new # Append revision push @{$self->{version}}, $rev; - if ( substr($value,$pos,1) eq '.' + if ( substr($value,$pos,1) eq '.' && substr($value,$pos+1,1) =~ /\d/ ) { $s = ++$pos; } - elsif ( substr($value,$pos,1) eq '_' + elsif ( substr($value,$pos,1) eq '_' && substr($value,$pos+1,1) =~ /\d/ ) { $s = ++$pos; } - elsif ( substr($value,$pos,1) eq ',' + elsif ( substr($value,$pos,1) eq ',' && substr($value,$pos+1,1) =~ /\d/ ) { $s = ++$pos; } @@ -400,7 +400,7 @@ sub new *parse = \&new; -sub numify +sub numify { my ($self) = @_; unless (_verify($self)) { @@ -441,7 +441,7 @@ sub numify return $string; } -sub normal +sub normal { my ($self) = @_; unless (_verify($self)) { @@ -484,9 +484,9 @@ sub stringify require Carp; Carp::croak("Invalid version object"); } - return exists $self->{original} - ? $self->{original} - : exists $self->{qv} + return exists $self->{original} + ? $self->{original} + : exists $self->{qv} ? $self->normal : $self->numify; } @@ -524,8 +524,8 @@ sub vcmp } # tiebreaker for alpha with identical terms - if ( $retval == 0 - && $l == $r + if ( $retval == 0 + && $l == $r && $left->{version}[$m] == $right->{version}[$m] && ( $lalpha || $ralpha ) ) { @@ -557,7 +557,7 @@ sub vcmp } } - return $retval; + return $retval; } sub vbool { @@ -565,8 +565,8 @@ sub vbool { return vcmp($self,$self->new("0"),1); } -sub vnoop { - require Carp; +sub vnoop { + require Carp; Carp::croak("operation not supported with version object"); } @@ -644,7 +644,7 @@ sub _VERSION { if ( defined $req ) { unless ( defined $version ) { require Carp; - my $msg = $] < 5.006 + my $msg = $] < 5.006 ? "$class version $req required--this is only version " : "$class does not define \$$class\::VERSION" ."--version check failed"; @@ -662,14 +662,14 @@ sub _VERSION { if ( $req > $version ) { require Carp; if ( $req->is_qv ) { - Carp::croak( + Carp::croak( sprintf ("%s version %s required--". "this is only version %s", $class, $req->normal, $version->normal) ); } else { - Carp::croak( + Carp::croak( sprintf ("%s version %s required--". "this is only version %s", $class, $req->stringify, $version->stringify) diff --git a/cpan/Module-Build/lib/Module/Build/YAML.pm b/cpan/Module-Build/lib/Module/Build/YAML.pm index 4a181ad..2da91f2 100644 --- a/cpan/Module-Build/lib/Module/Build/YAML.pm +++ b/cpan/Module-Build/lib/Module/Build/YAML.pm @@ -1,161 +1,600 @@ +# Adapted from YAML::Tiny 1.40 package Module::Build::YAML; use strict; -use vars qw($VERSION @EXPORT @EXPORT_OK); -$VERSION = "0.50"; -@EXPORT = (); -@EXPORT_OK = qw(Dump Load DumpFile LoadFile); +use Carp 'croak'; +# UTF Support? +sub HAVE_UTF8 () { $] >= 5.007003 } +BEGIN { + if ( HAVE_UTF8 ) { + # The string eval helps hide this from Test::MinimumVersion + eval "require utf8;"; + die "Failed to load UTF-8 support" if $@; + } + + # Class structure + require 5.004; + + $Module::Build::YAML::VERSION = '1.40'; + + # Error storage + $Module::Build::YAML::errstr = ''; +} + +# The character class of all characters we need to escape +# NOTE: Inlined, since it's only used once +# my $RE_ESCAPE = '[\\x00-\\x08\\x0b-\\x0d\\x0e-\\x1f\"\n]'; + +# Printed form of the unprintable characters in the lowest range +# of ASCII characters, listed by ASCII ordinal position. +my @UNPRINTABLE = qw( + z x01 x02 x03 x04 x05 x06 a + x08 t n v f r x0e x0f + x10 x11 x12 x13 x14 x15 x16 x17 + x18 x19 x1a e x1c x1d x1e x1f +); + +# Printable characters for escapes +my %UNESCAPES = ( + z => "\x00", a => "\x07", t => "\x09", + n => "\x0a", v => "\x0b", f => "\x0c", + r => "\x0d", e => "\x1b", '\\' => '\\', +); + +# Special magic boolean words +my %QUOTE = map { $_ => 1 } qw{ + null Null NULL + y Y yes Yes YES n N no No NO + true True TRUE false False FALSE + on On ON off Off OFF +}; + +##################################################################### +# Implementation + +# Create an empty Module::Build::YAML object sub new { - my $this = shift; - my $class = ref($this) || $this; - my $self = {}; - bless $self, $class; - return($self); + my $class = shift; + bless [ @_ ], $class; } -sub Dump { - shift if ($_[0] eq __PACKAGE__ || ref($_[0]) eq __PACKAGE__); - my $yaml = ""; - foreach my $item (@_) { - $yaml .= "---\n"; - $yaml .= &_yaml_chunk("", $item); - } - return $yaml; +# Create an object from a file +sub read { + my $class = ref $_[0] ? ref shift : shift; + + # Check the file + my $file = shift or return $class->_error( 'You did not specify a file name' ); + return $class->_error( "File '$file' does not exist" ) unless -e $file; + return $class->_error( "'$file' is a directory, not a file" ) unless -f _; + return $class->_error( "Insufficient permissions to read '$file'" ) unless -r _; + + # Slurp in the file + local $/ = undef; + local *CFG; + unless ( open(CFG, $file) ) { + return $class->_error("Failed to open file '$file': $!"); + } + my $contents = ; + unless ( close(CFG) ) { + return $class->_error("Failed to close file '$file': $!"); + } + + $class->read_string( $contents ); } -sub Load { - shift if ($_[0] eq __PACKAGE__ || ref($_[0]) eq __PACKAGE__); - die "not yet implemented"; +# Create an object from a string +sub read_string { + my $class = ref $_[0] ? ref shift : shift; + my $self = bless [], $class; + my $string = $_[0]; + unless ( defined $string ) { + return $self->_error("Did not provide a string to load"); + } + + # Byte order marks + # NOTE: Keeping this here to educate maintainers + # my %BOM = ( + # "\357\273\277" => 'UTF-8', + # "\376\377" => 'UTF-16BE', + # "\377\376" => 'UTF-16LE', + # "\377\376\0\0" => 'UTF-32LE' + # "\0\0\376\377" => 'UTF-32BE', + # ); + if ( $string =~ /^(?:\376\377|\377\376|\377\376\0\0|\0\0\376\377)/ ) { + return $self->_error("Stream has a non UTF-8 BOM"); + } else { + # Strip UTF-8 bom if found, we'll just ignore it + $string =~ s/^\357\273\277//; + } + + # Try to decode as utf8 + utf8::decode($string) if HAVE_UTF8; + + # Check for some special cases + return $self unless length $string; + unless ( $string =~ /[\012\015]+\z/ ) { + return $self->_error("Stream does not end with newline character"); + } + + # Split the file into lines + my @lines = grep { ! /^\s*(?:\#.*)?\z/ } + split /(?:\015{1,2}\012|\015|\012)/, $string; + + # Strip the initial YAML header + @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines; + + # A nibbling parser + while ( @lines ) { + # Do we have a document header? + if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) { + # Handle scalar documents + shift @lines; + if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) { + push @$self, $self->_read_scalar( "$1", [ undef ], \@lines ); + next; + } + } + + if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) { + # A naked document + push @$self, undef; + while ( @lines and $lines[0] !~ /^---/ ) { + shift @lines; + } + + } elsif ( $lines[0] =~ /^\s*\-/ ) { + # An array at the root + my $document = [ ]; + push @$self, $document; + $self->_read_array( $document, [ 0 ], \@lines ); + + } elsif ( $lines[0] =~ /^(\s*)\S/ ) { + # A hash at the root + my $document = { }; + push @$self, $document; + $self->_read_hash( $document, [ length($1) ], \@lines ); + + } else { + croak("Module::Build::YAML failed to classify the line '$lines[0]'"); + } + } + + $self; } -# This is basically copied out of YAML.pm and simplified a little. -sub DumpFile { - shift if ($_[0] eq __PACKAGE__ || ref($_[0]) eq __PACKAGE__); - my $filename = shift; - local $/ = "\n"; # reset special to "sane" - my $mode = '>'; - if ($filename =~ /^\s*(>{1,2})\s*(.*)$/) { - ($mode, $filename) = ($1, $2); - } - open my $OUT, "$mode $filename" - or die "Can't open $filename for writing: $!"; - binmode($OUT, ':utf8') if $] >= 5.008; - print $OUT Dump(@_); - close $OUT; -} - -# This is basically copied out of YAML.pm and simplified a little. -sub LoadFile { - shift if ($_[0] eq __PACKAGE__ || ref($_[0]) eq __PACKAGE__); - my $filename = shift; - open my $IN, $filename - or die "Can't open $filename for reading: $!"; - binmode($IN, ':utf8') if $] >= 5.008; - return Load(do { local $/; <$IN> }); - close $IN; -} - -sub _yaml_chunk { - my ($indent, $values) = @_; - my $yaml_chunk = ""; - my $ref = ref($values); - my ($value, @allkeys, %keyseen); - if (!$ref) { # a scalar - $yaml_chunk .= &_yaml_value($values) . "\n"; - } - elsif ($ref eq "ARRAY") { - foreach $value (@$values) { - $yaml_chunk .= "$indent-"; - $ref = ref($value); - if (!$ref) { - $yaml_chunk .= " " . &_yaml_value($value) . "\n"; - } - else { - $yaml_chunk .= "\n"; - $yaml_chunk .= &_yaml_chunk("$indent ", $value); - } - } - } - else { # assume "HASH" - if ($values->{_order} && ref($values->{_order}) eq "ARRAY") { - @allkeys = @{$values->{_order}}; - $values = { %$values }; - delete $values->{_order}; - } - push(@allkeys, sort keys %$values); - foreach my $key (@allkeys) { - next if (!defined $key || $key eq "" || $keyseen{$key}); - $keyseen{$key} = 1; - $yaml_chunk .= "$indent$key:"; - $value = $values->{$key}; - $ref = ref($value); - if (!$ref) { - $yaml_chunk .= " " . &_yaml_value($value) . "\n"; - } - else { - $yaml_chunk .= "\n"; - $yaml_chunk .= &_yaml_chunk("$indent ", $value); - } - } - } - return($yaml_chunk); -} - -sub _yaml_value { - my ($value) = @_; - # undefs become ~ - return '~' if not defined $value; - - # empty strings will become empty strings - return '""' if $value eq ''; - - # allow simple scalars (without embedded quote chars) to be unquoted - # (includes $%_+=-\;:,./) - return $value if $value !~ /["'`~\n!\@\#^\&\*\(\)\{\}\[\]\|<>\?]/; - - # quote and escape strings with special values - return "'$value'" - if $value !~ /['`~\n!\#^\&\*\(\)\{\}\[\]\|\?]/; # nothing but " or @ or < or > (email addresses) - - $value =~ s/\n/\\n/g; # handle embedded newlines - $value =~ s/"/\\"/g; # handle embedded quotes - return qq{"$value"}; +# Deparse a scalar string to the actual scalar +sub _read_scalar { + my ($self, $string, $indent, $lines) = @_; + + # Trim trailing whitespace + $string =~ s/\s*\z//; + + # Explitic null/undef + return undef if $string eq '~'; + + # Quotes + if ( $string =~ /^\'(.*?)\'\z/ ) { + return '' unless defined $1; + $string = $1; + $string =~ s/\'\'/\'/g; + return $string; + } + if ( $string =~ /^\"((?:\\.|[^\"])*)\"\z/ ) { + # Reusing the variable is a little ugly, + # but avoids a new variable and a string copy. + $string = $1; + $string =~ s/\\"/"/g; + $string =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex; + return $string; + } + + # Special cases + if ( $string =~ /^[\'\"!&]/ ) { + croak("Module::Build::YAML does not support a feature in line '$lines->[0]'"); + } + return {} if $string eq '{}'; + return [] if $string eq '[]'; + + # Regular unquoted string + return $string unless $string =~ /^[>|]/; + + # Error + croak("Module::Build::YAML failed to find multi-line scalar content") unless @$lines; + + # Check the indent depth + $lines->[0] =~ /^(\s*)/; + $indent->[-1] = length("$1"); + if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) { + croak("Module::Build::YAML found bad indenting in line '$lines->[0]'"); + } + + # Pull the lines + my @multiline = (); + while ( @$lines ) { + $lines->[0] =~ /^(\s*)/; + last unless length($1) >= $indent->[-1]; + push @multiline, substr(shift(@$lines), length($1)); + } + + my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n"; + my $t = (substr($string, 1, 1) eq '-') ? '' : "\n"; + return join( $j, @multiline ) . $t; } -1; +# Parse an array +sub _read_array { + my ($self, $array, $indent, $lines) = @_; -__END__ + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("Module::Build::YAML found bad indenting in line '$lines->[0]'"); + } + + if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) { + # Inline nested hash + my $indent2 = length("$1"); + $lines->[0] =~ s/-/ /; + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, $indent2 ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) { + # Array entry with a value + shift @$lines; + push @$array, $self->_read_scalar( "$2", [ @$indent, undef ], $lines ); -=head1 NAME + } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) { + shift @$lines; + unless ( @$lines ) { + push @$array, undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)\-/ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] == $indent2 ) { + # Null array entry + push @$array, undef; + } else { + # Naked indenter + push @$array, [ ]; + $self->_read_array( $array->[-1], [ @$indent, $indent2 ], $lines ); + } -Module::Build::YAML - Provides just enough YAML support so that Module::Build works even if YAML.pm is not installed + } elsif ( $lines->[0] =~ /^(\s*)\S/ ) { + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, length("$1") ], $lines ); -=head1 SYNOPSIS + } else { + croak("Module::Build::YAML failed to classify line '$lines->[0]'"); + } - use Module::Build::YAML; + } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) { + # This is probably a structure like the following... + # --- + # foo: + # - list + # bar: value + # + # ... so lets return and let the hash parser handle it + return 1; - ... + } else { + croak("Module::Build::YAML failed to classify line '$lines->[0]'"); + } + } -=head1 DESCRIPTION + return 1; +} + +# Parse an array +sub _read_hash { + my ($self, $hash, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } -Provides just enough YAML support so that Module::Build works even if YAML.pm is not installed. + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("Module::Build::YAML found bad indenting in line '$lines->[0]'"); + } -Currently, this amounts to the ability to write META.yml files when C -is executed via the Dump() and DumpFile() functions/methods. + # Get the key + unless ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) { + if ( $lines->[0] =~ /^\s*[?\'\"]/ ) { + croak("Module::Build::YAML does not support a feature in line '$lines->[0]'"); + } + croak("Module::Build::YAML failed to classify line '$lines->[0]'"); + } + my $key = $1; -=head1 AUTHOR + # Do we have a value? + if ( length $lines->[0] ) { + # Yes + $hash->{$key} = $self->_read_scalar( shift(@$lines), [ @$indent, undef ], $lines ); + } else { + # An indent + shift @$lines; + unless ( @$lines ) { + $hash->{$key} = undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)-/ ) { + $hash->{$key} = []; + $self->_read_array( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } elsif ( $lines->[0] =~ /^(\s*)./ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] >= $indent2 ) { + # Null hash entry + $hash->{$key} = undef; + } else { + $hash->{$key} = {}; + $self->_read_hash( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } + } + } + } -Stephen Adkins + return 1; +} + +# Save an object to a file +sub write { + my $self = shift; + my $file = shift or return $self->_error('No file name provided'); -=head1 COPYRIGHT + # Write it to the file + open( CFG, '>' . $file ) or return $self->_error( + "Failed to open file '$file' for writing: $!" + ); + print CFG $self->write_string; + close CFG; -Copyright (c) 2006. Stephen Adkins. All rights reserved. + return 1; +} -This program is free software; you can redistribute it and/or modify it -under the same terms as Perl itself. +# Save an object to a string +sub write_string { + my $self = shift; + return '' unless @$self; -See L + # Iterate over the documents + my $indent = 0; + my @lines = (); + foreach my $cursor ( @$self ) { + push @lines, '---'; -=cut + # An empty document + if ( ! defined $cursor ) { + # Do nothing + + # A scalar document + } elsif ( ! ref $cursor ) { + $lines[-1] .= ' ' . $self->_write_scalar( $cursor, $indent ); + + # A list at the root + } elsif ( ref $cursor eq 'ARRAY' ) { + unless ( @$cursor ) { + $lines[-1] .= ' []'; + next; + } + push @lines, $self->_write_array( $cursor, $indent, {} ); + + # A hash at the root + } elsif ( ref $cursor eq 'HASH' ) { + unless ( %$cursor ) { + $lines[-1] .= ' {}'; + next; + } + push @lines, $self->_write_hash( $cursor, $indent, {} ); + + } else { + croak("Cannot serialize " . ref($cursor)); + } + } + + join '', map { "$_\n" } @lines; +} + +sub _write_scalar { + my $string = $_[1]; + return '~' unless defined $string; + return "''" unless length $string; + if ( $string =~ /[\x00-\x08\x0b-\x0d\x0e-\x1f\"\'\n]/ ) { + $string =~ s/\\/\\\\/g; + $string =~ s/"/\\"/g; + $string =~ s/\n/\\n/g; + $string =~ s/([\x00-\x1f])/\\$UNPRINTABLE[ord($1)]/g; + return qq|"$string"|; + } + if ( $string =~ /(?:^\W|\s)/ or $QUOTE{$string} ) { + return "'$string'"; + } + return $string; +} + +sub _write_array { + my ($self, $array, $indent, $seen) = @_; + if ( $seen->{refaddr($array)}++ ) { + die "Module::Build::YAML does not support circular references"; + } + my @lines = (); + foreach my $el ( @$array ) { + my $line = (' ' x $indent) . '-'; + my $type = ref $el; + if ( ! $type ) { + $line .= ' ' . $self->_write_scalar( $el, $indent + 1 ); + push @lines, $line; + + } elsif ( $type eq 'ARRAY' ) { + if ( @$el ) { + push @lines, $line; + push @lines, $self->_write_array( $el, $indent + 1, $seen ); + } else { + $line .= ' []'; + push @lines, $line; + } + + } elsif ( $type eq 'HASH' ) { + if ( keys %$el ) { + push @lines, $line; + push @lines, $self->_write_hash( $el, $indent + 1, $seen ); + } else { + $line .= ' {}'; + push @lines, $line; + } + + } else { + die "Module::Build::YAML does not support $type references"; + } + } + + @lines; +} + +sub _write_hash { + my ($self, $hash, $indent, $seen) = @_; + if ( $seen->{refaddr($hash)}++ ) { + die "Module::Build::YAML does not support circular references"; + } + my @lines = (); + foreach my $name ( sort keys %$hash ) { + my $el = $hash->{$name}; + my $line = (' ' x $indent) . "$name:"; + my $type = ref $el; + if ( ! $type ) { + $line .= ' ' . $self->_write_scalar( $el, $indent + 1 ); + push @lines, $line; + + } elsif ( $type eq 'ARRAY' ) { + if ( @$el ) { + push @lines, $line; + push @lines, $self->_write_array( $el, $indent + 1, $seen ); + } else { + $line .= ' []'; + push @lines, $line; + } + + } elsif ( $type eq 'HASH' ) { + if ( keys %$el ) { + push @lines, $line; + push @lines, $self->_write_hash( $el, $indent + 1, $seen ); + } else { + $line .= ' {}'; + push @lines, $line; + } + + } else { + die "Module::Build::YAML does not support $type references"; + } + } + + @lines; +} + +# Set error +sub _error { + $Module::Build::YAML::errstr = $_[1]; + undef; +} + +# Retrieve error +sub errstr { + $Module::Build::YAML::errstr; +} + +##################################################################### +# YAML Compatibility + +sub Dump { + Module::Build::YAML->new(@_)->write_string; +} + +sub Load { + my $self = Module::Build::YAML->read_string(@_); + unless ( $self ) { + croak("Failed to load YAML document from string"); + } + if ( wantarray ) { + return @$self; + } else { + # To match YAML.pm, return the last document + return $self->[-1]; + } +} + +BEGIN { + *freeze = *Dump; + *thaw = *Load; +} + +sub DumpFile { + my $file = shift; + Module::Build::YAML->new(@_)->write($file); +} + +sub LoadFile { + my $self = Module::Build::YAML->read($_[0]); + unless ( $self ) { + croak("Failed to load YAML document from '" . ($_[0] || '') . "'"); + } + if ( wantarray ) { + return @$self; + } else { + # Return only the last document to match YAML.pm, + return $self->[-1]; + } +} + +##################################################################### +# Use Scalar::Util if possible, otherwise emulate it + +BEGIN { + eval { + require Scalar::Util; + }; + if ( $@ ) { + # Failed to load Scalar::Util + eval <<'END_PERL'; +sub refaddr { + my $pkg = ref($_[0]) or return undef; + if (!!UNIVERSAL::can($_[0], 'can')) { + bless $_[0], 'Scalar::Util::Fake'; + } else { + $pkg = undef; + } + "$_[0]" =~ /0x(\w+)/; + my $i = do { local $^W; hex $1 }; + bless $_[0], $pkg if defined $pkg; + $i; +} +END_PERL + } else { + Scalar::Util->import('refaddr'); + } +} + +1; + +__END__ diff --git a/cpan/Module-Build/lib/inc/latest.pm b/cpan/Module-Build/lib/inc/latest.pm new file mode 100644 index 0000000..9d4a380 --- /dev/null +++ b/cpan/Module-Build/lib/inc/latest.pm @@ -0,0 +1,250 @@ +package inc::latest; +use strict; +use vars qw($VERSION); +$VERSION = '0.35_08'; +$VERSION = eval $VERSION; + +use Carp; +use File::Basename (); +use File::Spec (); +use File::Path (); +use IO::File (); +use File::Copy (); + +# track and return modules loaded by inc::latest +my @loaded_modules; +sub loaded_modules {@loaded_modules} + +# must ultimately "goto" the import routine of the module to be loaded +# so that the calling package is correct when $mod->import() runs. +sub import { + my ($package, $mod, @args) = @_; + return unless(defined $mod); + + my $inc_path = './inc/latest.pm'; + my $private_path = './inc/latest/private.pm'; + if(-e $inc_path) { + # delete our methods + delete $inc::latest::{$_} for(keys %inc::latest::); + # load the bundled module + require $inc_path; + require $private_path; + my $import = inc::latest->can('import'); + goto $import; + } + + # author mode - just record and load the modules + push(@loaded_modules, $mod); + require inc::latest::private; + goto \&inc::latest::private::_load_module; +} + +sub write { + my $package = shift; + my ($where, @preload) = @_; + + warn "should really be writing in inc/" unless $where =~ /inc$/; + + # write inc/latest.pm + File::Path::mkpath( $where ); + my $fh = IO::File->new( File::Spec->catfile($where,'latest.pm'), "w" ); + print {$fh} "# This stub created by inc::latest $VERSION\n"; + print {$fh} <<'HERE'; +package inc::latest; +use strict; +use vars '@ISA'; +require inc::latest::private; +@ISA = qw/inc::latest::private/; +HERE + if (@preload) { + print {$fh} "\npackage inc::latest::preload;\n"; + for my $mod (@preload) { + print {$fh} "inc::latest->import('$mod');\n"; + } + } + print {$fh} "\n1;\n"; + close $fh; + + # write inc/latest/private; + require inc::latest::private; + File::Path::mkpath( File::Spec->catdir( $where, 'latest' ) ); + my $from = $INC{'inc/latest/private.pm'}; + my $to = File::Spec->catfile($where,'latest','private.pm'); + File::Copy::copy( $from, $to ) or die "Couldn't copy '$from' to '$to': $!"; + + return 1; +} + +sub bundle_module { + my ($package, $module, $where) = @_; + + # create inc/inc_$foo + (my $dist = $module) =~ s{::}{-}g; + my $inc_lib = File::Spec->catdir($where,"inc_$dist"); + File::Path::mkpath $inc_lib; + + # get list of files to copy + require ExtUtils::Installed; + # workaround buggy EU::Installed check of @INC + my $inst = ExtUtils::Installed->new(extra_libs => [@INC]); + my $packlist = $inst->packlist( $module ) or die "Couldn't find packlist"; + my @files = grep { /\.pm$/ } keys %$packlist; + + + # figure out prefix + my $mod_path = quotemeta $package->_mod2path( $module ); + my ($prefix) = grep { /$mod_path$/ } @files; + $prefix =~ s{$mod_path$}{}; + + # copy files + for my $from ( @files ) { + next unless $from =~ /\.pm$/; + (my $mod_path = $from) =~ s{^\Q$prefix\E}{}; + my $to = File::Spec->catfile( $inc_lib, $mod_path ); + File::Path::mkpath(File::Basename::dirname($to)); + File::Copy::copy( $from, $to ) or die "Couldn't copy '$from' to '$to': $!"; + } + return 1; +} + +# Translate a module name into a directory/file.pm to search for in @INC +sub _mod2path { + my ($self, $mod) = @_; + my @parts = split /::/, $mod; + $parts[-1] .= '.pm'; + return $parts[0] if @parts == 1; + return File::Spec->catfile(@parts); +} + +1; + + +=head1 NAME + +inc::latest - use modules bundled in inc/ if they are newer than installed ones + +=head1 SYNOPSIS + + # in Build.PL + use inc::latest 'Module::Build'; + +=head1 DESCRIPTION + +The C module helps bootstrap configure-time dependencies for CPAN +distributions. These dependencies get bundled into the C directory within +a distribution and are used by Build.PL (or Makefile.PL). + +Arguments to C are module names that are checked against both the +current C<@INC> array and against specially-named directories in C. If +the bundled verison is newer than the installed one (or the module isn't +installed, then, the bundled directory is added to the start of <@INC> and the +module is loaded from there. + +There are actually two variations of C -- one for authors and one +for the C directory. For distribution authors, the C +installed in the system will record modules loaded via C and can +be used to create the bundled files in C, including writing the second +variation as C. + +This second C is the one that is loaded in a distribution being +installed (e.g. from Build.PL). This bundled C is the one +that determines which module to load. + +=head2 Special notes on bundling + +The C module creates bundled directories based on the packlist +file of an installed distribution. Even though C takes module +name arguments, it is better to think of it as bundling and making available +entire I. When a module is loaded through C, +it looks in all bundled distributions in C for a newer module than +can be found in the existing C<@INC> array. + +Thus, the module-name provided should usually be the "top-level" module name of +a distribution, though this is not strictly required. For example, +L has a number of heuristics to map module names to packlists, +allowing users to do things like this: + + use inc::latest 'Devel::AssertOS::Unix'; + +even though Devel::AssertOS::Unix is contained within the Devel-CheckOS +distribution. + +At the current time, packlists are required. Thus, bundling dual-core modules +may require a 'forced install' over versions in the latest version of perl +in order to create the necessary packlist for bundling. + +=head1 USAGE + +When calling C, the bundled C takes a single module name and +optional arguments to pass to that module's own import method. + + use 'inc::latest' 'Foo::Bar' qw/foo bar baz/; + +=head2 Author-mode + +You are in author-mode inc::latest if any of the Author-mode methods are +available. For example: + + if ( inc::latest->can('write') ) { + inc::latest->write('inc'); + } + +=over 4 + +=item loaded_modules() + + my @list = inc::latest->loaded_modules; + +This takes no arguments and always returns a list of module names requested for +loading via "use inc::latest 'MODULE'", regardless of wether the load was +successful or not. + +=item write() + + inc::latest->write( 'inc' ); + +This writes the bundled version of inc::latest to the directory name given as an +argument. It almost all cases, it should be 'C'. + +=item bundle_module() + + for my $mod ( inc::latest->loaded_modules ) { + inc::latest->bundle_module($mod, $dir); + } + +If $mod corresponds to a packlist, then this function creates a specially-named +directory in $dir and copies all .pm files from the modlist to the new +directory (which almost always should just be 'inc'). For example, if Foo::Bar +is the name of the module, and $dir is 'inc', then the directory would be +'inc/inc_Foo-Bar' and contain files like this: + + inc/inc_Foo-Bar/Foo/Bar.pm + +Currently, $mod B have a packlist. If this is not the case (e.g. for a +dual-core module), then the bundling will fail. You may be able to create a +packlist by forced installing the module on top of the version that came with +core Perl. + +=back + +=head2 As bundled in inc/ + +All methods are private. Only the C method is public. + +=head1 AUTHOR + +Eric Wilhelm , David Golden + +=head1 COPYRIGHT + +Copyright (c) 2009 by Eric Wilhelm and David Golden + +This library is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +=head1 SEE ALSO + +L + +=cut + diff --git a/cpan/Module-Build/lib/inc/latest/private.pm b/cpan/Module-Build/lib/inc/latest/private.pm new file mode 100644 index 0000000..285514b --- /dev/null +++ b/cpan/Module-Build/lib/inc/latest/private.pm @@ -0,0 +1,101 @@ +package inc::latest::private; +use strict; +use vars qw($VERSION); +$VERSION = '0.35_08'; +$VERSION = eval $VERSION; + +use File::Spec; +use IO::File; + +# must ultimately "goto" the import routine of the module to be loaded +# so that the calling package is correct when $mod->import() runs. +sub import { + my ($package, $mod, @args) = @_; + my $file = $package->_mod2path($mod); + + if ($INC{$file}) { + # Already loaded, but let _load_module handle import args + goto \&_load_module; + } + + # A bundled copy must be present + my ($bundled, $bundled_dir) = $package->_search_bundled($file) + or die "No bundled copy of $mod found"; + + my $from_inc = $package->_search_INC($file); + unless ($from_inc) { + # Only bundled is available + unshift(@INC, $bundled_dir); + goto \&_load_module; + } + + if (_version($from_inc) >= _version($bundled)) { + # Ignore the bundled copy + goto \&_load_module; + } + + # Load the bundled copy + unshift(@INC, $bundled_dir); + goto \&_load_module; +} + +sub _version { + require ExtUtils::MakeMaker; + return ExtUtils::MM->parse_version(shift); +} + +# use "goto" for import to preserve caller +sub _load_module { + my $package = shift; # remaining @_ is ready for goto + my ($mod, @args) = @_; + eval "require $mod; 1" or die $@; + if ( my $import = $mod->can('import') ) { + goto $import; + } + return 1; +} + +sub _search_bundled { + my ($self, $file) = @_; + + my $mypath = 'inc'; + + local *DH; # Maintain 5.005 compatibility + opendir DH, $mypath or die "Can't open directory $mypath: $!"; + + while (defined(my $e = readdir DH)) { + next unless $e =~ /^inc_/; + my $try = File::Spec->catfile($mypath, $e, $file); + + return($try, File::Spec->catdir($mypath, $e)) if -e $try; + } + return; +} + +# Look for the given path in @INC. +sub _search_INC { + # TODO: doesn't handle coderefs or arrayrefs or objects in @INC, but + # it probably should + my ($self, $file) = @_; + + foreach my $dir (@INC) { + next if ref $dir; + my $try = File::Spec->catfile($dir, $file); + return $try if -e $try; + } + + return; +} + +# Translate a module name into a directory/file.pm to search for in @INC +sub _mod2path { + my ($self, $mod) = @_; + my @parts = split /::/, $mod; + $parts[-1] .= '.pm'; + return $parts[0] if @parts == 1; + return File::Spec->catfile(@parts); +} + +1; + + diff --git a/cpan/Module-Build/t/PL_files.t b/cpan/Module-Build/t/PL_files.t index a221714..68614c8 100644 --- a/cpan/Module-Build/t/PL_files.t +++ b/cpan/Module-Build/t/PL_files.t @@ -4,7 +4,7 @@ use strict; use lib 't/lib'; use MBTest tests => 8; use DistGen; -use Module::Build; +blib_load('Module::Build'); my $dist; diff --git a/cpan/Module-Build/t/README.pod b/cpan/Module-Build/t/README.pod new file mode 100644 index 0000000..b2d0579 --- /dev/null +++ b/cpan/Module-Build/t/README.pod @@ -0,0 +1,94 @@ +=head1 A GUIDE TO WRITING TESTS FOR MODULE::BUILD + +This document provides tips on writing new tests for Module::Build. Please +note that many existing tests were written prior to these guidelines and +have many different styles. Please don't copy/paste old tests by rote without +considering better ways to test. See C for a starter test file. + +=head1 TEST FILE PREAMBLE + +Every Module::Build test should begin with the same preamble to ensure that the +test library is set properly and that the correct version of Module::Build is +being tested. + + use strict; + use lib 't/lib'; + use MBTest tests => 2; # or 'no_plan' + + blib_load('Module::Build'); + +The C module is in C and subclasses Test::More. When loaded +it cleans up several environment variables that could cause problems, +tweaks C<@INC> and exports several helper functions. See that module for +details. + +=head1 CREATING A TEST DISTRIBUTION + +The C module in C should be used to create sample +distributions for testing. It provides numerous helpful methods to +create a skeleton distribution, add files, change files, and so on. +Run C on C to see the documentation. + + # CREATE A TEST DISTRIBUTION + + use DistGen; + + # create dist object in a temp directory + my $dist = DistGen->new; + + # enter the test distribution directory before further testing + $dist->chdir_in; + + # generate the skeleton files + $dist->regen; + + +=head1 GETTING A MODULE::BUILD OBJECT + +From inside the test distribution, you can get the Module::Build object +configured in Build.PL using the C method on the +dist object. This is just like Module::Build's C except +it passes C<< quiet => 1 >> to avoid sending output to the terminal. +Use the Module::Build object to test the programmatic API. + + my $mb = $dist->new_from_context( quiet => 1 ); + isa_ok( $mb, "Module::Build" ); + is( $mb->dist_name, "Simple", "dist_name is 'Simple'" ); + +=head1 TESTING THE COMMAND LINE API + +The command line API is tested by running subprocesses, not via a Module::Build +object. The C object has helper methods for running C and +C and passing arguments on the command line. + + $dist->run_build_pl( '--quiet' ); + $dist->run_build( 'test' ); + +=head1 TYPICAL TESTING CYCLE + +The typical testing cycle is to generate or modify a test distribution, either +through the C object or directly in the filesystem, then regenerate +the distribution and test it (or run command line tests and observe the +result.) + + # Modify the distribution + + $dist->change_build_pl( + { + module_name => $dist->name, + license => 'artistic', + } + ); + $dist->regen; + + # Get a new build object and test it + + $mb = $dist->new_from_context; + is( $mb->license, "artistic", "saw 'artistic' license" ); + + +=head1 COPYRIGHT + +This documentation is Copyright (C) 2009 by David Golden. You can redistribute +it and/or modify it under the same terms as Perl 5.10.0. + diff --git a/cpan/Module-Build/t/actions/installdeps.t b/cpan/Module-Build/t/actions/installdeps.t new file mode 100644 index 0000000..95e221d --- /dev/null +++ b/cpan/Module-Build/t/actions/installdeps.t @@ -0,0 +1,48 @@ +use strict; +use lib 't/lib'; +use MBTest; +use DistGen; + +plan tests => 7; + +# Ensure any Module::Build modules are loaded from correct directory +blib_load('Module::Build'); + +# create dist object in a temp directory +# enter the directory and generate the skeleton files +my $dist = DistGen->new->chdir_in; + +$dist->change_build_pl( + module_name => $dist->name, + requires => { + 'File::Spec' => 9999, + }, + build_requires => { + 'Getopt::Long' => 9998, + }, + cpan_client => $^X . ' -le print($_)for($^X,@ARGV)', +)->regen; + +# get a Module::Build object and test with it +my $mb; +stdout_stderr_of( sub { $mb = $dist->new_from_context('verbose' => 1) } ); +isa_ok( $mb, "Module::Build" ); +like( $mb->cpan_client, qr/^\Q$^X\E/, "cpan_client is mocked with perl" ); + +my $out = stdout_of( sub { + $dist->run_build('installdeps') +}); +ok( length($out), "ran mocked Build installdeps"); +my $expected = quotemeta(Module::Build->find_command($^X)); +like( $out, qr/$expected/i, "relative cpan_client resolved relative to \$^X" ); +like( $out, qr/File::Spec/, "saw File::Spec prereq" ); +like( $out, qr/Getopt::Long/, "saw Getopt::Long prereq" ); + +$out = stdout_stderr_of( sub { + $dist->run_build('installdeps', '--cpan_client', 'ADLKASJDFLASDJ') +}); +like( $out, qr/cpan_client .* is not executable/, + "Build installdeps with bad cpan_client dies" +); + +# vim:ts=2:sw=2:et:sta:sts=2 diff --git a/cpan/Module-Build/t/add_property.t b/cpan/Module-Build/t/add_property.t index 6032b09..e0b25ae 100644 --- a/cpan/Module-Build/t/add_property.t +++ b/cpan/Module-Build/t/add_property.t @@ -2,12 +2,11 @@ use strict; use lib 't/lib'; -use MBTest tests => 29; +use MBTest tests => 27; #use MBTest 'no_plan'; use DistGen; -BEGIN { use_ok 'Module::Build' or die; } -ensure_blib 'Module::Build'; +blib_load 'Module::Build'; my $tmp = MBTest->tmpdir; my $dist = DistGen->new( dir => $tmp ); diff --git a/cpan/Module-Build/t/basic.t b/cpan/Module-Build/t/basic.t index f46be0a..74c50b6 100644 --- a/cpan/Module-Build/t/basic.t +++ b/cpan/Module-Build/t/basic.t @@ -2,10 +2,9 @@ use strict; use lib 't/lib'; -use MBTest tests => 60; +use MBTest tests => 58; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); my $tmp = MBTest->tmpdir; @@ -28,7 +27,7 @@ $dist->chdir_in; $mb = Module::Build->new( dist_name => $dist->name, dist_version => 7 ); ok $mb; - ok ! $mb->module_name; # Make sure it's defined + ok $mb->module_name; # Set via heuristics is $mb->dist_name, $dist->name; } @@ -163,10 +162,7 @@ $dist->chdir_in; is $args{foo}, 1; # revert test distribution to pristine state because we modified a file - $dist->remove; - $dist = DistGen->new( dir => $tmp ); - $dist->regen; - $dist->chdir_in; + $dist->regen( clean => 1 ); } # Test author stuff @@ -236,5 +232,3 @@ $dist->chdir_in; is_deeply $mb->include_dirs, ['/foo'], 'Should have single include dir'; } -# cleanup -$dist->remove; diff --git a/cpan/Module-Build/t/bundle_inc.t b/cpan/Module-Build/t/bundle_inc.t new file mode 100644 index 0000000..edb1aa9 --- /dev/null +++ b/cpan/Module-Build/t/bundle_inc.t @@ -0,0 +1,194 @@ +# sample.t -- a sample test file for Module::Build + +use strict; +use lib 't/lib'; +use MBTest; # or 'no_plan' +use DistGen; +use Config; +use IO::File; +use File::Spec; +use ExtUtils::Packlist; +use File::Path; + +# Ensure any Module::Build modules are loaded from correct directory +blib_load('Module::Build'); +blib_load('Module::Build::ConfigData'); + +if ( Module::Build::ConfigData->feature('inc_bundling_support') ) { + plan tests => 18; +} else { + plan skip_all => 'inc_bundling_support feature is not enabled'; +} + +# need to do a temp install of M::B being tested to ensure a packlist +# is available for bundling + +my $current_mb = Module::Build->resume(); +my $temp_install = MBTest->tmpdir(); +my $arch = $Config{archname}; +my $lib_path = File::Spec->catdir($temp_install,qw/lib perl5/); +my $arch_path = File::Spec->catdir( $lib_path, $arch ); +mkpath ( $arch_path ); +ok( -d $arch_path, "created temporary M::B pseudo-install directory"); + +unshift @INC, $lib_path, $arch_path; +local $ENV{PERL5LIB} = join( $Config{path_sep}, + $lib_path, $arch_path, ($ENV{PERL5LIB} ? $ENV{PERL5LIB} : () ) +); + +stdout_of( sub { $current_mb->dispatch('install', install_base => $temp_install) } ); + +# create dist object in a temp directory +# enter the directory and generate the skeleton files +my $dist = DistGen->new( inc => 1 )->chdir_in->regen; + +# get a Module::Build object and test with it +my $mb = $dist->new_from_context(); # quiet by default +isa_ok( $mb, "Module::Build" ); +is( $mb->dist_name, "Simple", "dist_name is 'Simple'" ); +is_deeply( $mb->bundle_inc, [ 'Module::Build' ], + "Module::Build is flagged for bundling" +); + +# see what gets bundled +stdout_stderr_of( sub { $mb->dispatch('distdir') } ); + +my $dist_inc = File::Spec->catdir($mb->dist_dir, 'inc'); +ok( -e File::Spec->catfile( $dist_inc, 'latest.pm' ), + "./inc/latest.pm created" +); + +ok( -d File::Spec->catdir( $dist_inc, 'inc_Module-Build' ), + "dist_dir/inc/inc_Module_Build created" +); + +my $mb_file = + File::Spec->catfile( $dist_inc, qw/inc_Module-Build Module Build.pm/ ); + +ok( -e $mb_file, + "dist_dir/inc/inc_Module_Build/Module/Build.pm created" +); + +ok( -e File::Spec->catfile( $dist_inc, qw/inc_Module-Build Module Build Base.pm/ ), + "dist_dir/inc/inc_Module_Build/Module/Build/Base.pm created" +); + +# Force bundled M::B to a higher version so it gets loaded + +my $fh = IO::File->new($mb_file, "+<") or die "Could not open $mb_file: $!"; +my $mb_code = do { local $/; <$fh> }; +$mb_code =~ s{\$VERSION\s+=\s+\S+}{\$VERSION = 9999;}; +$fh->seek(0,0); +print {$fh} $mb_code; +$fh->close; + +# test the bundling in dist_dir +chdir $mb->dist_dir; + +stdout_of( sub { Module::Build->run_perl_script('Build.PL',[],[]) } ); + +my $meta = IO::File->new('MYMETA.yml'); +ok( $meta, "found MYMETA.yml" ); +ok( scalar( grep { /generated_by:.*9999/ } <$meta> ), + "dist_dir Build.PL loaded bundled Module::Build" +); + +#--------------------------------------------------------------------------# +# test identification of dependencies +#--------------------------------------------------------------------------# + +$dist->chdir_in; + +$dist->add_file( 'mylib/Foo.pm', << 'HERE' ); +package Foo; +our $VERSION = 1; +1; +HERE + +$dist->add_file( 'mylib/Bar.pm', << 'HERE' ); +package Bar; +use Foo; +our $VERSION = 42; +1; +HERE + +$dist->change_file( 'Build.PL', << "HERE" ); +use inc::latest 'Module::Build'; +use inc::latest 'Foo'; + +Module::Build->new( + module_name => '$dist->{name}', + license => 'perl', +)->create_build_script; +HERE + +$dist->regen( clean => 1 ); + +make_packlist($_,'mylib') for qw/Foo Bar/; + +# get a Module::Build object and test with it +my $abs_mylib = File::Spec->rel2abs('mylib'); + + +unshift @INC, $abs_mylib; +$mb = $dist->new_from_context(); # quiet by default +isa_ok( $mb, "Module::Build" ); +is_deeply( [sort @{$mb->bundle_inc}], [ 'Foo', 'Module::Build' ], + "Module::Build and Foo are flagged for bundling" +); + +my $output = stdout_stderr_of( sub { $mb->dispatch('distdir') } ); + +ok( -e File::Spec->catfile( $dist_inc, 'latest.pm' ), + "./inc/latest.pm created" +); + +ok( -d File::Spec->catdir( $dist_inc, 'inc_Foo' ), + "dist_dir/inc/inc_Foo created" +); + +$dist->change_file( 'Build.PL', << "HERE" ); +use inc::latest 'Module::Build'; +use inc::latest 'Bar'; + +Module::Build->new( + module_name => '$dist->{name}', + license => 'perl', +)->create_build_script; +HERE + +$dist->regen( clean => 1 ); +make_packlist($_,'mylib') for qw/Foo Bar/; + +$mb = $dist->new_from_context(); # quiet by default +isa_ok( $mb, "Module::Build" ); +is_deeply( [sort @{$mb->bundle_inc}], [ 'Bar', 'Module::Build' ], + "Module::Build and Bar are flagged for bundling" +); + +$output = stdout_stderr_of( sub { $mb->dispatch('distdir') } ); + +ok( -e File::Spec->catfile( $dist_inc, 'latest.pm' ), + "./inc/latest.pm created" +); + +ok( -d File::Spec->catdir( $dist_inc, 'inc_Bar' ), + "dist_dir/inc/inc_Bar created" +); + + + +sub make_packlist { + my ($mod, $lib) = @_; + my $arch = $Config{archname}; + (my $mod_path = $mod) =~ s{::}{/}g; + my $mod_file = File::Spec->catfile( $lib, "$mod_path\.pm" ); + my $abs = File::Spec->rel2abs($mod_file); + my $packlist_path = File::Spec->catdir($lib, $arch, 'auto', $mod_path); + mkpath $packlist_path; + my $packlist = ExtUtils::Packlist->new; + $packlist->{$abs}++; + $packlist->write( File::Spec->catfile( $packlist_path, '.packlist' )); +} + +# vim:ts=2:sw=2:et:sta:sts=2 diff --git a/cpan/Module-Build/t/compat.t b/cpan/Module-Build/t/compat.t index 88e5953..f84b79b 100644 --- a/cpan/Module-Build/t/compat.t +++ b/cpan/Module-Build/t/compat.t @@ -25,8 +25,8 @@ if ( $Config{make} && $^O ne 'VMS' ? find_in_path($Config{make}) : 1 ) { my $is_vms_mms = ($^O eq 'VMS') && ($Config{make} =~ /MM[SK]/i); -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); +blib_load('Module::Build::Version'); ######################### @@ -43,8 +43,8 @@ $dist->chdir_in; ######################### -use Module::Build; -use Module::Build::Compat; +blib_load('Module::Build'); +blib_load('Module::Build::Compat'); use Carp; $SIG{__WARN__} = \&Carp::cluck; @@ -72,10 +72,11 @@ $dist->change_build_pl({ license => 'perl', requires => { 'perl' => $], - 'File::Spec' => 0, + 'File::Spec' => 0.2, }, - build_requires => { - 'Test::More' => 0, + build_requires => { + 'Test::More' => 0, + 'File::Spec' => 0, }, PL_files => { 'foo.PL' => 'foo' }, }); @@ -90,8 +91,11 @@ $dist->regen; test_makefile_types( requires => { 'perl' => $], - 'File::Spec' => 0, + 'File::Spec' => 0.2, + }, + build_requires => { 'Test::More' => 0, + 'File::Spec' => 0, }, PL_files => { 'foo.PL' => 'foo', @@ -108,7 +112,7 @@ $dist->regen; # Create M::B instance but don't pollute STDOUT my $mb; -stdout_of( sub { +stdout_stderr_of( sub { $mb = Module::Build->new_from_context; }); ok $mb, "Module::Build->new_from_context"; @@ -131,7 +135,7 @@ ok $mb, "Module::Build->new_from_context"; # Makefile.PL - make sure it fails in the right way here. local @Foo::Builder::ISA = qw(Module::Build); my $foo_builder; - stdout_of( sub { + stdout_stderr_of( sub { $foo_builder = Foo::Builder->new_from_context; }); foreach my $style ('passthrough', 'small') { @@ -148,13 +152,13 @@ ok $mb, "Module::Build->new_from_context"; # Now make sure it can actually work. my $bar_builder; - stdout_of( sub { + stdout_stderr_of( sub { $bar_builder = Module::Build->subclass( class => 'Bar::Builder' )->new_from_context; }); foreach my $style ('passthrough', 'small') { create_makefile_pl($style, $bar_builder); my $result; - stdout_of( sub { + stdout_stderr_of( sub { $result = $mb->run_perl_script('Makefile.PL'); }); ok $result, "Makefile.PL ran without error"; @@ -167,7 +171,7 @@ ok $mb, "Module::Build->new_from_context"; my $libdir = File::Spec->catdir( $tmp, 'libdir' ); my $result; - stdout_of( sub { + stdout_stderr_of( sub { $result = $mb->run_perl_script('Makefile.PL', [], [ "LIB=$libdir", @@ -188,7 +192,7 @@ ok $mb, "Module::Build->new_from_context"; # Make sure those switches actually had an effect my ($ran_ok, $output); - $output = stdout_of( sub { $ran_ok = $new_build->do_system(@make, 'test') } ); + $output = stdout_stderr_of( sub { $ran_ok = $new_build->do_system(@make, 'test') } ); ok $ran_ok, "make test ran without error"; $output =~ s/^/# /gm; # Don't confuse our own test output like $output, qr/(?:# ok \d+\s+)+/, 'Should be verbose'; @@ -201,7 +205,7 @@ ok $mb, "Module::Build->new_from_context"; $make_macro = '/macro=("' . $make_macro . '")'; } - $output = stdout_of( sub { + $output = stdout_stderr_of( sub { local $ENV{HARNESS_TIMER}; # RT#39635 - timer messes with output $ran_ok = $mb->do_system(@make, 'test', $make_macro) } ); @@ -258,7 +262,7 @@ ok $mb, "Module::Build->new_from_context"; } } - stdout_of( sub { $mb->do_system(@make, 'realclean'); } ); + stdout_stderr_of( sub { $mb->do_system(@make, 'realclean'); } ); ok ! -e $makefile, "$makefile shouldn't exist"; 1 while unlink 'Makefile.PL'; @@ -274,14 +278,14 @@ ok $mb, "Module::Build->new_from_context"; create_makefile_pl('passthrough', $mb); - stdout_of( sub { + stdout_stderr_of( sub { $mb->run_perl_script('Makefile.PL', [], ['INSTALL_BASE=~/foo']); }); my $b2 = Module::Build->current; ok $b2->install_base, "install_base set"; unlike $b2->install_base, qr/^~/, "Tildes should be expanded"; - stdout_of( sub { $mb->do_system(@make, 'realclean'); } ); + stdout_stderr_of( sub { $mb->do_system(@make, 'realclean'); } ); ok ! -e $makefile, "$makefile shouldn't exist"; 1 while unlink 'Makefile.PL'; @@ -293,34 +297,53 @@ ok $mb, "Module::Build->new_from_context"; $dist->regen; my $mb; - stdout_of( sub { + stdout_stderr_of( sub { $mb = Module::Build->new_from_context( recursive_test_files => 1 ); }); create_makefile_pl('traditional', $mb); my $args = extract_writemakefile_args() || {}; - is $args->{TESTS}, - join( q{ }, - File::Spec->catfile(qw(t *.t)), - File::Spec->catfile(qw(t deep *.t)) - ), - 'Makefile.PL has correct TESTS line for recursive test files'; -} -# cleanup -$dist->remove; + if ( exists $args->{test}->{TESTS} ) { + is $args->{test}->{TESTS}, + join( q{ }, + File::Spec->catfile(qw(t *.t)), + File::Spec->catfile(qw(t deep *.t)) + ), + 'Makefile.PL has correct TESTS line for recursive test files'; + } else { + ok( ! exists $args->{TESTS}, 'Not using incorrect recursive tests key' ); + } + +} ######################################################### +sub _merge_prereqs { + my ($first, $second) = @_; + my $new = { %$first }; + for my $k (keys %$second) { + if ( exists $new->{$k} ) { + my ($v1,$v2) = ($new->{$k},$second->{$k}); + $new->{$k} = ($v1 > $v2 ? $v1 : $v2); + } + else { + $new->{$k} = $second->{$k}; + } + } + return $new; +} + sub test_makefile_types { my %opts = @_; $opts{requires} ||= {}; + $opts{build_requires} ||= {}; $opts{PL_files} ||= {}; foreach my $type (@makefile_types) { # Create M::B instance my $mb; - stdout_of( sub { + stdout_stderr_of( sub { $mb = Module::Build->new_from_context; }); ok $mb, "Module::Build->new_from_context"; @@ -330,12 +353,12 @@ sub test_makefile_types { test_makefile_pl_requires_perl( $opts{requires}{perl} ); test_makefile_creation($mb); - test_makefile_prereq_pm( $opts{requires} ); + test_makefile_prereq_pm( _merge_prereqs($opts{requires}, $opts{build_requires}) ); test_makefile_pl_files( $opts{PL_files} ) if $type eq 'traditional'; my ($output,$success); # Capture output to keep our STDOUT clean - $output = stdout_of( sub { + $output = stdout_stderr_of( sub { $success = $mb->do_system(@make); }); ok $success, "make ran without error"; @@ -345,13 +368,13 @@ sub test_makefile_types { } # Can't let 'test' STDOUT go to our STDOUT, or it'll confuse Test::Harness. - $output = stdout_of( sub { + $output = stdout_stderr_of( sub { $success = $mb->do_system(@make, 'test'); }); ok $success, "make test ran without error"; like uc $output, qr{DONE\.|SUCCESS}, "make test output indicated success"; - $output = stdout_of( sub { + $output = stdout_stderr_of( sub { $success = $mb->do_system(@make, 'realclean'); }); ok $success, "make realclean ran without error"; @@ -372,7 +395,7 @@ sub test_makefile_creation { my ($output, $result); # capture output to avoid polluting our test output - $output = stdout_of( sub { + $output = stdout_stderr_of( sub { $result = $build->run_perl_script('Makefile.PL', $preargs, $postargs); }); my $label = "Makefile.PL ran without error"; @@ -472,7 +495,8 @@ sub extract_writemakefile_args { } sub create_makefile_pl { - Module::Build::Compat->create_makefile_pl(@_); + my @args = @_; + stdout_stderr_of( sub { Module::Build::Compat->create_makefile_pl(@args) } ); my $ok = ok -e 'Makefile.PL', "$_[0] Makefile.PL created"; # Some really conservative make's, like HP/UX, assume files with the same diff --git a/cpan/Module-Build/t/compat/exit.t b/cpan/Module-Build/t/compat/exit.t old mode 100644 new mode 100755 index 78269a9..3672c93 --- a/cpan/Module-Build/t/compat/exit.t +++ b/cpan/Module-Build/t/compat/exit.t @@ -3,10 +3,9 @@ use strict; use lib 't/lib'; -use MBTest tests => 5; +use MBTest tests => 3; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); ######################### @@ -24,11 +23,13 @@ $dist->chdir_in; my $mb; stdout_of(sub{ $mb = Module::Build->new_from_context}); -use Module::Build::Compat; +blib_load('Module::Build::Compat'); $dist->regen; -Module::Build::Compat->create_makefile_pl('passthrough', $mb); +stdout_stderr_of( + sub{ Module::Build::Compat->create_makefile_pl('passthrough', $mb); } +); # as silly as all of this exit(0) business is, that is what the cpan # testers have instructed everybody to do so... diff --git a/cpan/Module-Build/t/debug.t b/cpan/Module-Build/t/debug.t index c9b4fa5..e0b8f60 100644 --- a/cpan/Module-Build/t/debug.t +++ b/cpan/Module-Build/t/debug.t @@ -2,18 +2,15 @@ use strict; use lib 't/lib'; -use MBTest tests => 3; +use MBTest tests => 1; -require_ok('Module::Build'); -ensure_blib('Module::Build'); +blib_load('Module::Build'); my $tmp = MBTest->tmpdir; use DistGen; my $dist = DistGen->new( dir => $tmp ); $dist->regen; -END{ $dist->remove } - $dist->chdir_in; ######################### @@ -28,6 +25,3 @@ $dist->chdir_in; ); } -######################### - -# cleanup diff --git a/cpan/Module-Build/t/destinations.t b/cpan/Module-Build/t/destinations.t index 4af99d0..07247a3 100644 --- a/cpan/Module-Build/t/destinations.t +++ b/cpan/Module-Build/t/destinations.t @@ -2,10 +2,9 @@ use strict; use lib 't/lib'; -use MBTest tests => 115; +use MBTest tests => 113; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); my $tmp = MBTest->tmpdir; @@ -248,7 +247,8 @@ $mb->prefix(undef); } # Poke at the innards of MB to change the default install locations. - my $old = $mb->install_sets->{site} = \%test_config; + my $old = $mb->install_sets->{site}; + $mb->install_sets->{site} = \%test_config; $mb->config(siteprefixexp => catdir(File::Spec->rootdir, 'wierd', 'prefix')); @@ -321,5 +321,3 @@ sub test_install_destinations { } } - -$dist->remove; diff --git a/cpan/Module-Build/t/ext.t b/cpan/Module-Build/t/ext.t index 8045761..6101bcc 100644 --- a/cpan/Module-Build/t/ext.t +++ b/cpan/Module-Build/t/ext.t @@ -4,8 +4,6 @@ use strict; use lib 't/lib'; use MBTest; -use Module::Build; - my @unix_splits = ( { q{one t'wo th'ree f"o\"ur " "five" } => [ 'one', 'two three', 'fo"ur ', 'five' ] }, @@ -58,9 +56,11 @@ my @win_splits = { 'a " b " c' => [ 'a', ' b ', 'c' ] }, ); -plan tests => 10 + 4*@unix_splits + 4*@win_splits; +plan tests => 9 + 4*@unix_splits + 4*@win_splits; -ensure_blib('Module::Build'); +blib_load('Module::Build'); +blib_load('Module::Build::Platform::Unix'); +blib_load('Module::Build::Platform::Windows'); ######################### @@ -74,7 +74,6 @@ foreach my $platform ('', '::Platform::Unix', '::Platform::Windows') { # I think 3.24 isn't actually the majik version, my 3.23 seems to pass... my $low_TPW_version = Text::ParseWords->VERSION < 3.24; -use Module::Build::Platform::Unix; foreach my $test (@unix_splits) { # Text::ParseWords bug: local $TODO = $low_TPW_version && ((keys %$test)[0] =~ m{\\\n}); @@ -82,7 +81,6 @@ foreach my $test (@unix_splits) { do_split_tests('Module::Build::Platform::Unix', $test); } -use Module::Build::Platform::Windows; foreach my $test (@win_splits) { do_split_tests('Module::Build::Platform::Windows', $test); } diff --git a/cpan/Module-Build/t/extend.t b/cpan/Module-Build/t/extend.t index db99eec..36ff4b6 100644 --- a/cpan/Module-Build/t/extend.t +++ b/cpan/Module-Build/t/extend.t @@ -2,10 +2,9 @@ use strict; use lib 't/lib'; -use MBTest tests => 66; +use MBTest tests => 64; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); my $tmp = MBTest->tmpdir; @@ -79,7 +78,7 @@ print "Hello, World!\n"; $mb->add_build_element('foo'); $mb->add_build_element('foo'); - is_deeply $mb->build_elements, [qw(PL support pm xs pod script foo)], + is_deeply $mb->build_elements, [qw(PL support pm xs share_dir pod script foo)], 'The foo element should be in build_elements only once'; $mb->dispatch('build'); @@ -187,21 +186,20 @@ print "Hello, World!\n"; meta_add => {foo => 'bar'}, conflicts => {'Foo::Barxx' => 0}, ); - my %data; - $mb->prepare_metadata( \%data ); - is $data{foo}, 'bar'; + my $data = $mb->prepare_metadata; + is $data->{foo}, 'bar'; $mb->meta_merge(foo => 'baz'); - $mb->prepare_metadata( \%data ); - is $data{foo}, 'baz'; + $data = $mb->prepare_metadata; + is $data->{foo}, 'baz'; $mb->meta_merge(conflicts => {'Foo::Fooxx' => 0}); - $mb->prepare_metadata( \%data ); - is_deeply $data{conflicts}, {'Foo::Barxx' => 0, 'Foo::Fooxx' => 0}; + $data = $mb->prepare_metadata; + is_deeply $data->{conflicts}, {'Foo::Barxx' => 0, 'Foo::Fooxx' => 0}; $mb->meta_add(conflicts => {'Foo::Bazxx' => 0}); - $mb->prepare_metadata( \%data ); - is_deeply $data{conflicts}, {'Foo::Bazxx' => 0, 'Foo::Fooxx' => 0}; + $data = $mb->prepare_metadata; + is_deeply $data->{conflicts}, {'Foo::Bazxx' => 0, 'Foo::Fooxx' => 0}; } { @@ -275,5 +273,3 @@ print "Hello, World!\n"; } -# cleanup -$dist->remove; diff --git a/cpan/Module-Build/t/files.t b/cpan/Module-Build/t/files.t index 87b192e..cf822fb 100644 --- a/cpan/Module-Build/t/files.t +++ b/cpan/Module-Build/t/files.t @@ -2,10 +2,9 @@ use strict; use lib 't/lib'; -use MBTest tests => 6; +use MBTest tests => 4; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); use IO::File; my $tmp = MBTest->tmpdir; @@ -46,5 +45,3 @@ my $mb = Module::Build->new_from_context; ok( Module::Build->dir_contains($first, $second) ); } -# cleanup -$dist->remove; diff --git a/cpan/Module-Build/t/help.t b/cpan/Module-Build/t/help.t index 8408315..2bf34c8 100644 --- a/cpan/Module-Build/t/help.t +++ b/cpan/Module-Build/t/help.t @@ -2,38 +2,23 @@ use strict; use lib 't/lib'; -use MBTest tests => 25; +use MBTest tests => 23; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); - -use Cwd (); -use File::Path (); - -my $cwd = Cwd::cwd(); -my $tmp = MBTest->tmpdir; +blib_load('Module::Build'); use DistGen; -my $dist = DistGen->new(dir => $tmp); - - +my $dist = DistGen->new; $dist->regen; +$dist->chdir_in; my $restart = sub { - $dist->clean(); - DistGen::chdir_all( $cwd ); - File::Path::rmtree( $tmp ); # we're redefining the same package as we go, so... delete($::{'MyModuleBuilder::'}); delete($INC{'MyModuleBuilder.pm'}); - $dist->regen; - chdir($dist->dirname) or - die "Can't chdir to '@{[$dist->dirname]}': $!"; + $dist->regen( clean => 1 ); }; -chdir($dist->dirname) or die "Can't chdir to '@{[$dist->dirname]}': $!"; - ######################################################################## { # check the =item style my $mb = Module::Build->subclass( @@ -274,7 +259,5 @@ is($mb->get_action_docs('batz'), undef, 'nothing after uplevel'); # cleanup $dist->clean(); -DistGen::chdir_all($cwd); -File::Path::rmtree( $tmp ); # vim:ts=2:sw=2:et:sta diff --git a/cpan/Module-Build/t/install.t b/cpan/Module-Build/t/install.t index 2cadaa3..66cdd5c 100644 --- a/cpan/Module-Build/t/install.t +++ b/cpan/Module-Build/t/install.t @@ -2,10 +2,9 @@ use strict; use lib 't/lib'; -use MBTest tests => 36; +use MBTest tests => 34; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); use Config; use Cwd (); @@ -225,10 +224,7 @@ Simple Man is keys %$pms, 0; # revert to pristine state - $dist->remove; - $dist = DistGen->new( dir => $tmp ); - $dist->regen; - $dist->chdir_in; + $dist->regen( clean => 1 ); } sub strip_volume { @@ -243,6 +239,3 @@ sub file_exists { ok -e $file or diag("Expected $file to exist, but it doesn't"); } - -# cleanup -$dist->remove; diff --git a/cpan/Module-Build/t/install_extra_target.t b/cpan/Module-Build/t/install_extra_target.t index c717ce5..21d0c27 100644 --- a/cpan/Module-Build/t/install_extra_target.t +++ b/cpan/Module-Build/t/install_extra_target.t @@ -3,10 +3,9 @@ use strict; use lib 't/lib'; -use MBTest tests => 8; +use MBTest tests => 6; -require_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); use File::Spec::Functions qw( catdir ); @@ -46,11 +45,11 @@ sub process_etc_files } #Copy share files to blib -sub process_share_files +sub process_shared_files { my $self = shift; - $self->copy_files("share"); + $self->copy_files("shared"); } 1; @@ -62,23 +61,23 @@ my $build = $subclass->new( ); $build->add_build_element('etc'); -$build->add_build_element('share'); +$build->add_build_element('shared'); my $distdir = lc $build->dist_name(); foreach my $id ('core', 'site', 'vendor') { #Where to install these build types when using prefix symantics - $build->prefix_relpaths($id, 'share' => "share/$distdir"); + $build->prefix_relpaths($id, 'shared' => "shared/$distdir"); $build->prefix_relpaths($id, 'etc' => "etc/$distdir"); #Where to install these build types when using default symantics my $set = $build->install_sets($id); - $set->{'share'} = '/usr/'.($id eq 'site' ? 'local/':'')."share/$distdir"; + $set->{'shared'} = '/usr/'.($id eq 'site' ? 'local/':'')."shared/$distdir"; $set->{'etc'} = ($id eq 'site' ? '/usr/local/etc/':'/etc/').$distdir; } #Where to install these types when using install_base symantics -$build->install_base_relpaths('share' => "share/$distdir"); +$build->install_base_relpaths('shared' => "shared/$distdir"); $build->install_base_relpaths('etc' => "etc/$distdir"); $build->create_build_script(); @@ -97,12 +96,12 @@ stardate = 1234344 ===EOF=== -$dist->add_file("share/data", <<'===EOF==='); +$dist->add_file("shared/data", <<'===EOF==='); 7 * 9 = 42? ===EOF=== -$dist->add_file("share/html/index.html", <<'===EOF==='); +$dist->add_file("shared/html/index.html", <<'===EOF===');

Hello World!

@@ -122,16 +121,15 @@ $output .= stdout_of sub { $dist->run_build }; my $error; $error++ unless ok(-e "blib/etc/config", "Built etc/config"); -$error++ unless ok(-e "blib/share/data", "Built share/data"); -$error++ unless ok(-e "blib/share/html/index.html", "Built share/html"); +$error++ unless ok(-e "blib/shared/data", "Built shared/data"); +$error++ unless ok(-e "blib/shared/html/index.html", "Built shared/html"); diag "OUTPUT:\n$output" if $error; $output = stdout_of sub { $dist->run_build('install') }; $error = 0; $error++ unless ok(-e "$installdest/etc/simple/config", "installed etc/config"); -$error++ unless ok(-e "$installdest/share/simple/data", "installed share/data"); -$error++ unless ok(-e "$installdest/share/simple/html/index.html", "installed share/html"); +$error++ unless ok(-e "$installdest/shared/simple/data", "installed shared/data"); +$error++ unless ok(-e "$installdest/shared/simple/html/index.html", "installed shared/html"); diag "OUTPUT:\n$output" if $error; -$dist->remove(); diff --git a/cpan/Module-Build/t/lib/DistGen.pm b/cpan/Module-Build/t/lib/DistGen.pm index 86ee794..d1fb260 100644 --- a/cpan/Module-Build/t/lib/DistGen.pm +++ b/cpan/Module-Build/t/lib/DistGen.pm @@ -7,9 +7,9 @@ use vars qw( $VERSION $VERBOSE @EXPORT_OK); $VERSION = '0.01'; $VERBOSE = 0; - use Carp; +use MBTest (); use Cwd (); use File::Basename (); use File::Find (); @@ -38,7 +38,7 @@ BEGIN { $vms_efs_case = VMS::Feature::current("efs_case_preserve"); } else { my $env_unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || ''; - $unix_rpt = $env_unix_rpt =~ /^[ET1]/i; + $unix_rpt = $env_unix_rpt =~ /^[ET1]/i; my $efs_case = $ENV{'DECC$EFS_CASE_PRESERVE'} || ''; $vms_efs_case = $efs_case =~ /^[ET1]/i; } @@ -64,44 +64,76 @@ sub undent { } sub chdir_all ($) { - # OS/2 has "current directory per disk", undeletable; + # OS/2 has "current directory per disk", undeletable; # doing chdir() to another disk won't change cur-dir of initial disk... chdir('/') if $^O eq 'os2'; chdir shift; } + ######################################################################## +END { chdir_all(MBTest->original_cwd); } + sub new { - my $package = shift; + my $self = bless {}, shift; + $self->reset(@_); +} + +sub reset { + my $self = shift; my %options = @_; $options{name} ||= 'Simple'; - $options{dir} ||= Cwd::cwd(); + $options{dir} = File::Spec->rel2abs( + defined $options{dir} ? $options{dir} : MBTest->tmpdir + ); my %data = ( no_manifest => 0, xs => 0, + inc => 0, %options, ); - my $self = bless( \%data, $package ); - - # So we can clean up later even if the caller chdir()s - $self->{dir} = File::Spec->rel2abs($self->{dir}); + %$self = %data; tie %{$self->{filedata}}, 'Tie::CPHash'; tie %{$self->{pending}{change}}, 'Tie::CPHash'; + # start with a fresh, empty directory if ( -d $self->dirname ) { warn "Warning: Removing existing directory '@{[$self->dirname]}'\n"; - $self->remove; + File::Path::rmtree( $self->dirname ); } + File::Path::mkpath( $self->dirname ); $self->_gen_default_filedata(); return $self; } +sub remove { + my $self = shift; + $self->chdir_original if($self->did_chdir); + File::Path::rmtree( $self->dirname ); + return $self; +} + +sub revert { + my ($self, $file) = @_; + if ( defined $file ) { + delete $self->{filedata}{$file}; + delete $self->{pending}{$_}{$file} for qw/change remove/; + } + else { + delete $self->{filedata}{$_} for keys %{ $self->{filedata} }; + for my $pend ( qw/change remove/ ) { + delete $self->{pending}{$pend}{$_} for keys %{ $self->{pending}{$pend} }; + } + } + $self->_gen_default_filedata; +} + sub _gen_default_filedata { my $self = shift; @@ -112,17 +144,32 @@ sub _gen_default_filedata { $self->add_file($member, $data) unless($self->{filedata}{$member}); }; - $self->$add_unless('Build.PL', undent(<<" ---")); - use strict; - use Module::Build; + if ( ! $self->{inc} ) { + $self->$add_unless('Build.PL', undent(<<" ---")); + use strict; + use Module::Build; - my \$builder = Module::Build->new( - module_name => '$self->{name}', - license => 'perl', - ); + my \$builder = Module::Build->new( + module_name => '$self->{name}', + license => 'perl', + ); - \$builder->create_build_script(); - --- + \$builder->create_build_script(); + --- + } + else { + $self->$add_unless('Build.PL', undent(<<" ---")); + use strict; + use inc::latest 'Module::Build'; + + my \$builder = Module::Build->new( + module_name => '$self->{name}', + license => 'perl', + ); + + \$builder->create_build_script(); + --- + } my $module_filename = join( '/', ('lib', split(/::/, $self->{name})) ) . '.pm'; @@ -229,7 +276,7 @@ sub _gen_default_filedata { # 5.6 is missing const char * in its typemap $self->$add_unless('typemap', undent(<<" ---")); - const char * T_PV + const char *\tT_PV --- $self->$add_unless('t/basic.t', undent(<<" ---")); @@ -249,7 +296,6 @@ sub _gen_manifest { my $manifest = shift; my $fh = IO::File->new( ">$manifest" ) or do { - $self->remove(); die "Can't write '$manifest'\n"; }; @@ -312,7 +358,6 @@ sub regen { my $dirname = File::Basename::dirname( $fullname ); unless ( -d $dirname ) { File::Path::mkpath( $dirname ) or do { - $self->remove(); die "Can't create '$dirname'\n"; }; } @@ -322,7 +367,6 @@ sub regen { } my $fh = IO::File->new(">$fullname") or do { - $self->remove(); die "Can't write '$fullname'\n"; }; print $fh $self->{filedata}{$file}; @@ -339,6 +383,7 @@ sub regen { } $self->_gen_manifest( $manifest ); } + return $self; } sub clean { @@ -396,20 +441,7 @@ sub clean { }, ($^O eq 'VMS' ? './' : File::Spec->curdir) ); chdir_all( $here ); -} - -sub remove { - my $self = shift; - croak("invalid usage -- remove()") if(@_); - $self->chdir_original if($self->did_chdir); - File::Path::rmtree( $self->dirname ); - # might as well check - croak("\nthis test should have used chdir_in()") unless(Cwd::getcwd); -} - -sub revert { - my $self = shift; - die "Unimplemented.\n"; + return $self; } sub add_file { @@ -425,10 +457,13 @@ sub remove_file { } delete( $self->{filedata}{$file} ); $self->{pending}{remove}{$file} = 1; + return $self; } sub change_build_pl { - my ($self, $opts) = @_; + my ($self, @opts) = @_; + + my $opts = ref $opts[0] eq 'HASH' ? $opts[0] : { @opts }; local $Data::Dumper::Terse = 1; (my $args = Dumper($opts)) =~ s/^\s*\{|\}\s*$//g; @@ -437,16 +472,17 @@ sub change_build_pl { use strict; use Module::Build; my \$b = Module::Build->new( - # Some CPANPLUS::Dist::Build versions need to allow mismatches + # Some CPANPLUS::Dist::Build versions need to allow mismatches # On logic: thanks to Module::Install, CPAN.pm must set both keys, but # CPANPLUS sets only the one - allow_mb_mismatch => ( + allow_mb_mismatch => ( \$ENV{PERL5_CPANPLUS_IS_RUNNING} && ! \$ENV{PERL5_CPAN_IS_RUNNING} ? 1 : 0 ), $args ); \$b->create_build_script(); --- + return $self; } sub change_file { @@ -455,6 +491,7 @@ sub change_file { my $data = shift; $self->{filedata}{$file} = $data; $self->{pending}{change}{$file} = 1; + return $self; } sub get_file { @@ -466,40 +503,43 @@ sub get_file { sub chdir_in { my $self = shift; - - $self->{original_dir} ||= Cwd::cwd; # only once + $self->{original_dir} ||= Cwd::cwd; # only once! my $dir = $self->dirname; chdir($dir) or die "Can't chdir to '$dir': $!"; + return $self; } ######################################################################## -sub did_chdir { - my $self = shift; +sub did_chdir { exists shift()->{original_dir} } - return exists($self->{original_dir}); -} ######################################################################## sub chdir_original { my $self = shift; - croak("never called chdir_in()") unless($self->{original_dir}); - my $dir = $self->{original_dir}; + my $dir = delete $self->{original_dir}; chdir_all($dir) or die "Can't chdir to '$dir': $!"; + return $self; } ######################################################################## +sub new_from_context { + my ($self, @args) = @_; + require Module::Build; + return Module::Build->new_from_context( quiet => 1, @args ); +} + sub run_build_pl { my ($self, @args) = @_; require Module::Build; - Module::Build->run_perl_script('Build.PL', [], [@args]) + return Module::Build->run_perl_script('Build.PL', [], [@args]) } sub run_build { my ($self, @args) = @_; require Module::Build; my $build_script = $^O eq 'VMS' ? 'Build.com' : 'Build'; - Module::Build->run_perl_script($build_script, [], [@args]) + return Module::Build->run_perl_script($build_script, [], [@args]) } 1; @@ -516,8 +556,7 @@ DistGen - Creates simple distributions for testing. use DistGen; # create distribution and prepare to test - my $dist = DistGen->new(name => 'Foo::Bar', dir => $tmp); - $dist->regen; + my $dist = DistGen->new(name => 'Foo::Bar'); $dist->chdir_in; # change distribution files @@ -526,42 +565,48 @@ DistGen - Creates simple distributions for testing. $dist->remove_file('t/some_test.t'); $dist->regen; - # clean up extraneous files + # undo changes and clean up extraneous files + $dist->revert; $dist->clean; # exercise the command-line interface $dist->run_build_pl(); $dist->run_build('test'); - # finish testing and clean up - $dist->chdir_original; - $dist->remove; + # start over as a new distribution + $dist->reset( name => 'Foo::Bar', xs => 1 ); + $dist->chdir_in; =head1 USAGE A DistGen object manages a set of files in a distribution directory. -The constructor and some methods only define the target state of the -distribution. They do B make any changes to the filesystem: +The C constructor initializes the object and creates an empty +directory for the distribution. It does not create files or chdir into +the directory. The C method re-initializes the object in a +new directory with new parameters. It also does not create files or change +the current directory. + +Some methods only define the target state of the distribution. They do B +make any changes to the filesystem: - new add_file change_file change_build_pl remove_file + revert Other methods then change the filesystem to match the target state of -the distribution (or to remove it entirely): +the distribution: - regen clean + regen remove Other methods are provided for a convenience during testing. The -most important are ones that manage the current directory: +most important is the one to enter the distribution directory: chdir_in - chdir_original Additional methods portably encapsulate running Build.PL and Build: @@ -570,16 +615,19 @@ Additional methods portably encapsulate running Build.PL and Build: =head1 API -=head2 Constructor +=head2 Constructors =head3 new() -Create a new object. Does not write its contents (see L.) +Create a new object and an empty directory to hold the distribution's files. +If no C option is provided, it defaults to MBTest->tmpdir, which sets +a different temp directory for Perl core testing and CPAN testing. + +The C method does not write any files -- see L below. - my $tmp = MBTest->tmpdir; my $dist = DistGen->new( name => 'Foo::Bar', - dir => $tmp, + dir => MBTest->tmpdir, xs => 1, no_manifest => 0, ); @@ -596,9 +644,14 @@ dist name. =item dir -The (parent) directory in which to create the distribution directory. -The default is File::Spec->curdir. The distribution will be created -under this according to the "dist" form of C (e.g. "Foo-Bar".) +The (parent) directory in which to create the distribution directory. The +distribution will be created under this according to the "dist" form of C +(e.g. "Foo-Bar".) Defaults to a temporary directory. + + $dist = DistGen->new( dir => '/tmp/MB-test' ); + $dist->regen; + + # distribution files have been created in /tmp/MB-test/Simple =item xs @@ -622,6 +675,13 @@ the following files are also added: typemap lib/Simple.xs # based on name parameter +=head3 reset() + +The C method re-initializes the object as if it were generated +from a fresh call to C. It takes the same optional parameters as C. + + $dist->reset( name => 'Foo::Bar', xs => 0 ); + =head2 Adding and editing files Note that C<$filename> should always be specified with unix-style paths, @@ -669,6 +729,14 @@ Removes C<$filename> from the distribution. $dist->remove_file( $filename ); +=head3 revert() + +Returns the object to its initial state, or given a $filename it returns that +file to its initial state if it is one of the built-in files. + + $dist->revert; + $dist->revert($filename); + =head2 Changing the distribution directory These methods immediately affect the filesystem. @@ -680,8 +748,10 @@ flagged for removal with remove_file(). $dist->regen(clean => 1); -If the optional C argument is given, it also removes any -extraneous files that do not belong to the distribution. +If the optional C argument is given, it also calls C. These +can also be chained like this, instead: + + $dist->clean->regen; =head3 clean() @@ -689,22 +759,19 @@ Removes any files that are not part of the distribution. $dist->clean; -=begin TODO - -=head3 revert() - -[Unimplemented] Returns the object to its initial state, or given a -$filename it returns that file to it's initial state if it is one of -the built-in files. +=head3 remove() - $dist->revert; - $dist->revert($filename); +Changes back to the original directory and removes the distribution +directory (but not the temporary directory set during C). -=end TODO + $dist = DistGen->new->chdir->regen; + # ... do some testing ... -=head3 remove() + $dist->remove->chdir_in->regen; + # ... do more testing ... -Removes the entire distribution directory. +This is like a more aggressive form of C. Generally, calling C +and C should be sufficient. =head2 Changing directories diff --git a/cpan/Module-Build/t/lib/MBTest.pm b/cpan/Module-Build/t/lib/MBTest.pm index dc2410b..8a5acd2 100644 --- a/cpan/Module-Build/t/lib/MBTest.pm +++ b/cpan/Module-Build/t/lib/MBTest.pm @@ -13,6 +13,7 @@ BEGIN { my @delete_env_keys = qw( DEVEL_COVER_OPTIONS MODULEBUILDRC + PERL_MB_OPT HARNESS_TIMER HARNESS_OPTIONS HARNESS_VERBOSE @@ -49,7 +50,15 @@ BEGIN { # In case the test wants to use our other bundled # modules, make sure they can be loaded. - push @INC, File::Spec->catdir('t', 'bundled'); + my $t_lib = File::Spec->catdir('t', 'bundled'); + push @INC, $t_lib; # Let user's installed version override + + if ($ENV{PERL_CORE}) { + # We change directories, so expand @INC and $^X to absolute paths + # Also add . + @INC = (map(File::Spec->rel2abs($_), @INC), "."); + $^X = File::Spec->rel2abs($^X); + } } use Exporter; @@ -74,7 +83,7 @@ my @extra_exports = qw( find_in_path check_compiler have_module - ensure_blib + blib_load ); push @EXPORT, @extra_exports; __PACKAGE__->export(scalar caller, @extra_exports); @@ -85,7 +94,9 @@ __PACKAGE__->export(scalar caller, @extra_exports); # always return to the current directory { - my $cwd = Cwd::cwd; + my $cwd = File::Spec->rel2abs(Cwd::cwd); + + sub original_cwd { return $cwd } END { # Go back to where you came from! @@ -103,13 +114,11 @@ __PACKAGE__->export(scalar caller, @extra_exports); } ######################################################################## -# Setup a temp directory -sub tmpdir { - my ($self, $usr_tmp) = @_; - return File::Temp::tempdir( 'MB-XXXXXXXX', - CLEANUP => 1, DIR => $ENV{PERL_CORE} ? Cwd::cwd : - $usr_tmp ? $usr_tmp : File::Spec->tmpdir - ); +# Setup a temp directory +sub tmpdir { + my ($self, @args) = @_; + my $dir = $ENV{PERL_CORE} ? MBTest->original_cwd : File::Spec->tmpdir; + return File::Temp::tempdir('MB-XXXXXXXX', CLEANUP => 1, DIR => $dir, @args); } sub save_handle { @@ -137,7 +146,7 @@ sub stdout_stderr_of { $stdout = stdout_of ( sub { $stderr = stderr_of( $subr ) }); - return ($stdout, $stderr); + return wantarray ? ($stdout, $stderr) : $stdout . $stderr; } sub slurp { @@ -160,13 +169,20 @@ sub exe_exts { sub find_in_path { my $thing = shift; - - my @path = split $Config{path_sep}, $ENV{PATH}; + my @exe_ext = exe_exts(); - foreach (@path) { - my $fullpath = File::Spec->catfile($_, $thing); + if ( File::Spec->file_name_is_absolute( $thing ) ) { foreach my $ext ( '', @exe_ext ) { - return "$fullpath$ext" if -e "$fullpath$ext"; + return "$thing$ext" if -e "$thing$ext"; + } + } + else { + my @path = split $Config{path_sep}, $ENV{PATH}; + foreach (@path) { + my $fullpath = File::Spec->catfile($_, $thing); + foreach my $ext ( '', @exe_ext ) { + return "$fullpath$ext" if -e "$fullpath$ext"; + } } } return; @@ -178,6 +194,7 @@ sub check_compiler { local $SIG{__WARN__} = sub {}; + blib_load('Module::Build'); my $mb = Module::Build->current; $mb->verbose( 0 ); @@ -202,21 +219,23 @@ sub check_compiler { sub have_module { my $module = shift; - return eval "use $module; 1"; + return eval "require $module; 1"; } -sub ensure_blib { - # Make sure the given module was loaded from blib/, not the larger system +sub blib_load { + # Load the given module and ensure it came from blib/, not the larger system my $mod = shift; + have_module($mod) or die "Error loading $mod\: $@\n"; + (my $path = $mod) =~ s{::}{/}g; - - local $Test::Builder::Level = $Test::Builder::Level + 1; - SKIP: { - skip "no blib in core", 1 if $ENV{PERL_CORE}; - like $INC{"$path.pm"}, qr/\bblib\b/, "Make sure $mod was loaded from blib/" - or diag "PERL5LIB: " . ($ENV{PERL5LIB} || '') . "\n" . - "PERL5OPT: " . ($ENV{PERL5OPT} || '') . "\n" . - "\@INC contains:\n " . join("\n ", @INC) . "\n"; + $path .= ".pm"; + my ($pkg, $file, $line) = caller; + unless($ENV{PERL_CORE}) { + unless($INC{$path} =~ m/\bblib\b/) { + (my $load_from = $INC{$path}) =~ s{$path$}{}; + die "$mod loaded from '$load_from'\nIt should have been loaded from blib. \@INC contains:\n ", + join("\n ", @INC) . "\nFatal error occured in blib_load() at $file, line $line.\n"; + } } } diff --git a/cpan/Module-Build/t/manifypods.t b/cpan/Module-Build/t/manifypods.t index 31c9e8e..5947646 100644 --- a/cpan/Module-Build/t/manifypods.t +++ b/cpan/Module-Build/t/manifypods.t @@ -3,15 +3,14 @@ use strict; use lib 't/lib'; use MBTest; -use Module::Build; -use Module::Build::ConfigData; +blib_load('Module::Build'); +blib_load('Module::Build::ConfigData'); if ( Module::Build::ConfigData->feature('manpage_support') ) { - plan tests => 22; + plan tests => 21; } else { plan skip_all => 'manpage_support feature is not enabled'; } -ensure_blib('Module::Build'); ######################### @@ -139,11 +138,7 @@ $mb->dispatch('realclean'); # revert to a pristine state -$dist->remove; -$dist = DistGen->new( dir => $tmp ); -$dist->regen; -$dist->chdir_in; - +$dist->regen( clean => 1 ); my $mb2 = Module::Build->new( module_name => $dist->name, @@ -163,6 +158,3 @@ foreach ('testcover', 'disttest') { unlike $docs, qr/\n=/, $docs; } - -# cleanup -$dist->remove; diff --git a/cpan/Module-Build/t/mbyaml.t b/cpan/Module-Build/t/mbyaml.t deleted file mode 100644 index d2cb0d5..0000000 --- a/cpan/Module-Build/t/mbyaml.t +++ /dev/null @@ -1,262 +0,0 @@ -#!/usr/local/bin/perl -w - -use strict; -use lib 't/lib'; -use MBTest 'no_plan'; - -use_ok 'Module::Build::YAML'; -ensure_blib('Module::Build::YAML'); - -my ($dir); -$dir = "."; -$dir = "t" if (-d "t"); - -{ - my ($expected, $got, $var); - ########################################################## - # Test a typical-looking Module::Build structure (alphabetized) - ########################################################## - $var = { - 'resources' => { - 'license' => 'http://opensource.org/licenses/artistic-license.php' - }, - 'meta-spec' => { - 'version' => '1.2', - 'url' => 'http://module-build.sourceforge.net/META-spec-v1.2.html' - }, - 'generated_by' => 'Module::Build version 0.2709', - 'version' => '0.13', - 'name' => 'js-app', - 'dynamic_config' => '1', - 'author' => [ - '"Stephen Adkins" ' - ], - 'license' => 'lgpl', - 'build_requires' => { - 'App::Build' => '0', - 'File::Spec' => '0', - 'Module::Build' => '0' - }, - 'provides' => { - 'JavaScript::App' => { - 'version' => '0', - 'file' => 'lib/JavaScript/App.pm' - } - }, - 'requires' => { - 'App::Options' => '0' - }, - 'abstract' => 'A framework for building dynamic widgets or full applications in Javascript' - }; - $expected = <<'EOF'; ---- -abstract: A framework for building dynamic widgets or full applications in Javascript -author: - - '"Stephen Adkins" ' -build_requires: - App::Build: 0 - File::Spec: 0 - Module::Build: 0 -dynamic_config: 1 -generated_by: Module::Build version 0.2709 -license: lgpl -meta-spec: - url: http://module-build.sourceforge.net/META-spec-v1.2.html - version: 1.2 -name: js-app -provides: - JavaScript::App: - file: lib/JavaScript/App.pm - version: 0 -requires: - App::Options: 0 -resources: - license: http://opensource.org/licenses/artistic-license.php -version: 0.13 -EOF - $got = &Module::Build::YAML::Dump($var); - is($got, $expected, "Dump(): single deep hash"); - - ########################################################## - # Test a typical-looking Module::Build structure (ordered) - ########################################################## - $expected = <<'EOF'; ---- -name: js-app -version: 0.13 -author: - - '"Stephen Adkins" ' -abstract: A framework for building dynamic widgets or full applications in Javascript -license: lgpl -resources: - license: http://opensource.org/licenses/artistic-license.php -requires: - App::Options: 0 -build_requires: - App::Build: 0 - File::Spec: 0 - Module::Build: 0 -dynamic_config: 1 -provides: - JavaScript::App: - file: lib/JavaScript/App.pm - version: 0 -generated_by: Module::Build version 0.2709 -meta-spec: - url: http://module-build.sourceforge.net/META-spec-v1.2.html - version: 1.2 -EOF - $var->{_order} = [qw(name version author abstract license resources requires build_requires dynamic_config provides)]; - $got = &Module::Build::YAML::Dump($var); - is($got, $expected, "Dump(): single deep hash, ordered"); - - ########################################################## - # Test that an array turns into multiple documents - ########################################################## - $var = [ - "e", - 2.71828, - [ "pi", "is", 3.1416 ], - { fun => "under_sun", 6 => undef, "more", undef }, - ]; - $expected = <<'EOF'; ---- -e ---- -2.71828 ---- -- pi -- is -- 3.1416 ---- -6: ~ -fun: under_sun -more: ~ -EOF - $got = &Module::Build::YAML::Dump(@$var); - is($got, $expected, "Dump(): multiple, various"); - - ########################################################## - # Test that a single array ref turns into one document - ########################################################## - $expected = <<'EOF'; ---- -- e -- 2.71828 -- - - pi - - is - - 3.1416 -- - 6: ~ - fun: under_sun - more: ~ -EOF - $got = &Module::Build::YAML::Dump($var); - is($got, $expected, "Dump(): single array of various"); - - ########################################################## - # Test Object-Oriented Flavor of the API - ########################################################## - my $y = Module::Build::YAML->new(); - $got = $y->Dump($var); - is($got, $expected, "Dump(): single array of various (OO)"); - - ########################################################## - # Test Quoting Conditions (newlines, quotes, tildas, undefs) - ########################################################## - $var = { - 'foo01' => '`~!@#$%^&*()_+-={}|[]\\;\':",./?<> -', - 'foo02' => '~!@#$%^&*()_+-={}|[]\\;:,./<>?', - 'foo03' => undef, - 'foo04' => '~', - }; - $expected = <<'EOF'; ---- -foo01: "`~!@#$%^&*()_+-={}|[]\;':\",./?<>\n" -foo02: "~!@#$%^&*()_+-={}|[]\;:,./<>?" -foo03: ~ -foo04: "~" -EOF - $got = &Module::Build::YAML::Dump($var); - is($got, $expected, "Dump(): tricky embedded characters"); - - $var = { - 'foo10' => undef, - 'foo40' => '!', - 'foo41' => '@', - 'foo42' => '#', - 'foo43' => '$', - 'foo44' => '%', - 'foo45' => '^', - 'foo47' => '&', - 'foo48' => '*', - 'foo49' => '(', - 'foo50' => ')', - 'foo51' => '_', - 'foo52' => '+', - 'foo53' => '-', - 'foo54' => '=', - 'foo55' => '{', - 'foo56' => '}', - 'foo57' => '|', - 'foo58' => '[', - 'foo59' => ']', - 'foo60' => '\\', - 'foo61' => ';', - 'foo62' => ':', - 'foo63' => ',', - 'foo64' => '.', - 'foo65' => '/', - 'foo66' => '<', - 'foo67' => '>', - 'foo68' => '?', - 'foo69' => '\'', - 'foo70' => '"', - 'foo71' => '`', - 'foo72' => ' -', - }; - $expected = <<'EOF'; ---- -foo10: ~ -foo40: "!" -foo41: '@' -foo42: "#" -foo43: $ -foo44: % -foo45: "^" -foo47: "&" -foo48: "*" -foo49: "(" -foo50: ")" -foo51: _ -foo52: + -foo53: - -foo54: = -foo55: "{" -foo56: "}" -foo57: "|" -foo58: "[" -foo59: "]" -foo60: \ -foo61: ; -foo62: : -foo63: , -foo64: . -foo65: / -foo66: '<' -foo67: '>' -foo68: "?" -foo69: "'" -foo70: '"' -foo71: "`" -foo72: "\n" -EOF - $got = &Module::Build::YAML::Dump($var); - is($got, $expected, "Dump(): tricky embedded characters (singles)"); - -} - - diff --git a/cpan/Module-Build/t/metadata.t b/cpan/Module-Build/t/metadata.t index 6f53c1d..2850bea 100644 --- a/cpan/Module-Build/t/metadata.t +++ b/cpan/Module-Build/t/metadata.t @@ -2,15 +2,13 @@ use strict; use lib 't/lib'; -use MBTest tests => 53; +use MBTest tests => 51; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); +blib_load('Module::Build::ConfigData'); my $tmp = MBTest->tmpdir; -use Module::Build::ConfigData; - my %metadata = ( module_name => 'Simple', @@ -56,7 +54,6 @@ my $simple2_file = 'lib/Simple2.pm'; $dist->chdir_in; -use Module::Build; my $mb = Module::Build->new_from_context; ################################################## @@ -68,7 +65,7 @@ my $mb = Module::Build->new_from_context; my $mb_config_req = { 'Module::Build' => int($Module::Build::VERSION * 100)/100 }; - my $node = $mb->prepare_metadata( {} ); + my $node = $mb->prepare_metadata( ); # exists() doesn't seem to work here is $node->{name}, $metadata{module_name}; @@ -89,7 +86,7 @@ my $mb = Module::Build->new_from_context; { my $mb_prereq = { 'Module::Build' => 0 }; $mb->configure_requires( $mb_prereq ); - my $node = $mb->prepare_metadata( {} ); + my $node = $mb->prepare_metadata( ); # exists() doesn't seem to work here @@ -366,7 +363,7 @@ package Simple; $VERSION = '2.34'; --- $dist->regen( clean => 1 ); -$mb = new_build(); +stderr_of( sub { $mb = new_build(); } ); $err = stderr_of( sub { $provides = $mb->find_dist_packages } ); is_deeply($provides, {'Simple' => { file => $simple_file, @@ -470,7 +467,7 @@ package Foo; $VERSION = '2.34'; --- $dist->regen( clean => 1 ); -$mb = new_build(); +stderr_of( sub { $mb = new_build(); } ); $err = stderr_of( sub { $provides = $mb->find_dist_packages } ); # XXX Should 'Foo' exist ??? Can't predict values for file & version ok( exists( $provides->{Foo} ) ); @@ -604,6 +601,3 @@ $dist->regen( clean => 1 ); $mb = new_build(); is_deeply($mb->find_dist_packages, {}); -############################################################ -# cleanup -$dist->remove; diff --git a/cpan/Module-Build/t/metadata2.t b/cpan/Module-Build/t/metadata2.t index a5af034..954b658 100644 --- a/cpan/Module-Build/t/metadata2.t +++ b/cpan/Module-Build/t/metadata2.t @@ -2,14 +2,11 @@ use strict; use lib 't/lib'; -use MBTest tests => 20; +use MBTest tests => 18; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); +blib_load('Module::Build::ConfigData'); -my $tmp = MBTest->tmpdir; - -use Module::Build::ConfigData; use DistGen; @@ -19,14 +16,12 @@ SKIP: { skip( 'YAML_support feature is not enabled', 4 ) unless Module::Build::ConfigData->feature('YAML_support'); - my $dist = DistGen->new( dir => $tmp, no_manifest => 1 ); - $dist->regen; - - $dist->chdir_in; + my $dist = DistGen->new( no_manifest => 1 )->chdir_in->regen; ok ! -e 'MANIFEST'; - my $mb = Module::Build->new_from_context; + my $mb; + stderr_of( sub { $mb = Module::Build->new_from_context } ); my $out; $out = eval { stderr_of(sub{$mb->dispatch('distmeta')}) }; @@ -36,7 +31,6 @@ SKIP: { ok -e 'META.yml'; - $dist->remove; } @@ -62,7 +56,7 @@ Simple Simon =cut --- -my $dist = DistGen->new( dir => $tmp ); +my $dist = DistGen->new->chdir_in; $dist->change_build_pl ({ @@ -71,10 +65,6 @@ $dist->change_build_pl license => 'perl', create_readme => 1, }); -$dist->regen; - -$dist->chdir_in; - # .pm File with pod # @@ -139,7 +129,3 @@ is( $mb->dist_author->[0], 'Simple Simon ', is( $mb->dist_abstract, "A simple module", "Extracting abstract from .pod over .pm"); - -############################################################ -# cleanup -$dist->remove; diff --git a/cpan/Module-Build/t/moduleinfo.t b/cpan/Module-Build/t/moduleinfo.t index ca7eb04..e28726d 100644 --- a/cpan/Module-Build/t/moduleinfo.t +++ b/cpan/Module-Build/t/moduleinfo.t @@ -4,99 +4,58 @@ use strict; use lib 't/lib'; -use MBTest tests => 82; - -use_ok 'Module::Build::ModuleInfo'; -ensure_blib('Module::Build::ModuleInfo'); - -my $tmp = MBTest->tmpdir; - -use DistGen; -my $dist = DistGen->new( dir => $tmp ); -$dist->regen; - -$dist->chdir_in; - -######################### - -# class method C -my $module = Module::Build::ModuleInfo->find_module_by_name( - 'Module::Build::ModuleInfo' ); -ok( -e $module, 'find_module_by_name() succeeds' ); - - -# fail on invalid module name -my $pm_info = Module::Build::ModuleInfo->new_from_module( - 'Foo::Bar', inc => [] ); -ok( !defined( $pm_info ), 'fail if can\'t find module by module name' ); - - -# fail on invalid filename -my $file = File::Spec->catfile( 'Foo', 'Bar.pm' ); -$pm_info = Module::Build::ModuleInfo->new_from_file( $file, inc => [] ); -ok( !defined( $pm_info ), 'fail if can\'t find module by file name' ); - - -# construct from module filename -$file = File::Spec->catfile( 'lib', split( /::/, $dist->name ) ) . '.pm'; -$pm_info = Module::Build::ModuleInfo->new_from_file( $file ); -ok( defined( $pm_info ), 'new_from_file() succeeds' ); - -# construct from module name, using custom include path -$pm_info = Module::Build::ModuleInfo->new_from_module( - $dist->name, inc => [ 'lib', @INC ] ); -ok( defined( $pm_info ), 'new_from_module() succeeds' ); - +use MBTest; # parse various module $VERSION lines +# these will be reversed later to create %modules my @modules = ( - <<'---', # declared & defined on same line with 'our' + '1.23' => <<'---', # declared & defined on same line with 'our' package Simple; our $VERSION = '1.23'; --- - <<'---', # declared & defined on separate lines with 'our' + '1.23' => <<'---', # declared & defined on separate lines with 'our' package Simple; our $VERSION; $VERSION = '1.23'; --- - <<'---', # use vars + '1.23' => <<'---', # use vars package Simple; use vars qw( $VERSION ); $VERSION = '1.23'; --- - <<'---', # choose the right default package based on package/file name + '1.23' => <<'---', # choose the right default package based on package/file name package Simple::_private; $VERSION = '0'; package Simple; $VERSION = '1.23'; # this should be chosen for version --- - <<'---', # just read the first $VERSION line + '1.23' => <<'---', # just read the first $VERSION line package Simple; $VERSION = '1.23'; # we should see this line $VERSION = eval $VERSION; # and ignore this one --- - <<'---', # just read the first $VERSION line in reopened package (1) + '1.23' => <<'---', # just read the first $VERSION line in reopened package (1) package Simple; $VERSION = '1.23'; package Error::Simple; $VERSION = '2.34'; package Simple; --- - <<'---', # just read the first $VERSION line in reopened package (2) + '1.23' => <<'---', # just read the first $VERSION line in reopened package (2) package Simple; package Error::Simple; $VERSION = '2.34'; package Simple; $VERSION = '1.23'; --- - <<'---', # mentions another module's $VERSION + '1.23' => <<'---', # mentions another module's $VERSION package Simple; $VERSION = '1.23'; if ( $Other::VERSION ) { # whatever } --- - <<'---', # mentions another module's $VERSION in a different package + '1.23' => <<'---', # mentions another module's $VERSION in a different package package Simple; $VERSION = '1.23'; package Simple2; @@ -104,21 +63,21 @@ if ( $Simple::VERSION ) { # whatever } --- - <<'---', # $VERSION checked only in assignments, not regexp ops + '1.23' => <<'---', # $VERSION checked only in assignments, not regexp ops package Simple; $VERSION = '1.23'; if ( $VERSION =~ /1\.23/ ) { # whatever } --- - <<'---', # $VERSION checked only in assignments, not relational ops + '1.23' => <<'---', # $VERSION checked only in assignments, not relational ops package Simple; $VERSION = '1.23'; if ( $VERSION == 3.45 ) { # whatever } --- - <<'---', # $VERSION checked only in assignments, not relational ops + '1.23' => <<'---', # $VERSION checked only in assignments, not relational ops package Simple; $VERSION = '1.23'; package Simple2; @@ -126,36 +85,36 @@ if ( $Simple::VERSION == 3.45 ) { # whatever } --- - <<'---', # Fully qualified $VERSION declared in package + '1.23' => <<'---', # Fully qualified $VERSION declared in package package Simple; $Simple::VERSION = 1.23; --- - <<'---', # Differentiate fully qualified $VERSION in a package + '1.23' => <<'---', # Differentiate fully qualified $VERSION in a package package Simple; $Simple2::VERSION = '999'; $Simple::VERSION = 1.23; --- - <<'---', # Differentiate fully qualified $VERSION and unqualified + '1.23' => <<'---', # Differentiate fully qualified $VERSION and unqualified package Simple; $Simple2::VERSION = '999'; $VERSION = 1.23; --- - <<'---', # $VERSION declared as package variable from within 'main' package + '1.23' => <<'---', # $VERSION declared as package variable from within 'main' package $Simple::VERSION = '1.23'; { package Simple; $x = $y, $cats = $dogs; } --- - <<'---', # $VERSION wrapped in parens - space inside + '1.23' => <<'---', # $VERSION wrapped in parens - space inside package Simple; ( $VERSION ) = '1.23'; --- - <<'---', # $VERSION wrapped in parens - no space inside + '1.23' => <<'---', # $VERSION wrapped in parens - no space inside package Simple; ($VERSION) = '1.23'; --- - <<'---', # $VERSION follows a spurious 'package' in a quoted construct + '1.23' => <<'---', # $VERSION follows a spurious 'package' in a quoted construct package Simple; __PACKAGE__->mk_accessors(qw( program socket proc @@ -163,25 +122,87 @@ __PACKAGE__->mk_accessors(qw( our $VERSION = "1.23"; --- - <<'---', # $VERSION using version.pm + '1.23' => <<'---', # $VERSION using version.pm package Simple; use version; our $VERSION = version->new('1.23'); --- - <<'---', # $VERSION using version.pm and qv() + '1.23' => <<'---', # $VERSION using version.pm and qv() package Simple; use version; our $VERSION = qv('1.230'); --- - <<'---', # Two version assignments, should ignore second one + '1.23' => <<'---', # Two version assignments, should ignore second one $Simple::VERSION = '1.230'; $Simple::VERSION = eval $Simple::VERSION; --- + '1.23' => <<'---', # declared & defined on same line with 'our' +package Simple; +our $VERSION = '1.23_00_00'; +--- + '1.23' => <<'---', # package NAME VERSION + package Simple 1.23; +--- + '1.23_01' => <<'---', # package NAME VERSION + package Simple 1.23_01; +--- + 'v1.2.3' => <<'---', # package NAME VERSION + package Simple v1.2.3; +--- + 'v1.2_3' => <<'---', # package NAME VERSION + package Simple v1.2_3; +--- ); +my %modules = reverse @modules; + +plan tests => 36 + 2 * keys( %modules ); -my( $i, $n ) = ( 1, scalar( @modules ) ); -foreach my $module ( @modules ) { +blib_load('Module::Build::ModuleInfo'); + +my $tmp = MBTest->tmpdir; + +use DistGen; +my $dist = DistGen->new( dir => $tmp ); +$dist->regen; + +$dist->chdir_in; + +######################### + +# class method C +my $module = Module::Build::ModuleInfo->find_module_by_name( + 'Module::Build::ModuleInfo' ); +ok( -e $module, 'find_module_by_name() succeeds' ); + + +# fail on invalid module name +my $pm_info = Module::Build::ModuleInfo->new_from_module( + 'Foo::Bar', inc => [] ); +ok( !defined( $pm_info ), 'fail if can\'t find module by module name' ); + + +# fail on invalid filename +my $file = File::Spec->catfile( 'Foo', 'Bar.pm' ); +$pm_info = Module::Build::ModuleInfo->new_from_file( $file, inc => [] ); +ok( !defined( $pm_info ), 'fail if can\'t find module by file name' ); + + +# construct from module filename +$file = File::Spec->catfile( 'lib', split( /::/, $dist->name ) ) . '.pm'; +$pm_info = Module::Build::ModuleInfo->new_from_file( $file ); +ok( defined( $pm_info ), 'new_from_file() succeeds' ); + +# construct from module name, using custom include path +$pm_info = Module::Build::ModuleInfo->new_from_module( + $dist->name, inc => [ 'lib', @INC ] ); +ok( defined( $pm_info ), 'new_from_module() succeeds' ); + + +foreach my $module ( sort keys %modules ) { + my $expected = $modules{$module}; SKIP: { skip( "No our() support until perl 5.6", 2 ) - if $] < 5.006 && $module =~ /\bour\b/; + if $] < 5.006 && $module =~ /\bour\b/; + skip( "No package NAME VERSION support until perl 5.11.1", 2 ) + if $] < 5.011001 && $module =~ /package\s+[\w\:\']+\s+v?[0-9._]+/; $dist->change_file( 'lib/Simple.pm', $module ); $dist->regen; @@ -191,19 +212,17 @@ foreach my $module ( @modules ) { my $pm_info = Module::Build::ModuleInfo->new_from_file( $file ); # Test::Builder will prematurely numify objects, so use this form - ok( $pm_info->version eq '1.23', - "correct module version ($i of $n)" ); - is( $warnings, '', 'no warnings from parsing' ); - $i++; + my $errs; + ok( $pm_info->version eq $expected, + "correct module version (expected '$expected')" ) + or $errs++; + is( $warnings, '', 'no warnings from parsing' ) or $errs++; + diag "Got: '@{[$pm_info->version]}'\nModule contents:\n$module" if $errs; } } # revert to pristine state -$dist->remove; -$dist = DistGen->new( dir => $tmp ); -$dist->regen; -$dist->chdir_in; - +$dist->regen( clean => 1 ); # Find each package only once $dist->change_file( 'lib/Simple.pm', <<'---' ); @@ -249,19 +268,15 @@ $pm_info = Module::Build::ModuleInfo->new_from_file( $file ); is( $pm_info->version, '1.23_01', 'alpha version reported'); # NOTE the following test has be done this way because Test::Builder is -# too smart for our own good and tries to see if the version object is a +# too smart for our own good and tries to see if the version object is a # dual-var, which breaks with alpha versions: # Argument "1.23_0100" isn't numeric in addition (+) at -# /usr/lib/perl5/5.8.7/Test/Builder.pm line 505. +# /usr/lib/perl5/5.8.7/Test/Builder.pm line 505. ok( $pm_info->version > 1.23, 'alpha version greater than non'); # revert to pristine state -$dist->remove; -$dist = DistGen->new( dir => $tmp ); -$dist->regen; -$dist->chdir_in; - +$dist->regen( clean => 1 ); # parse $VERSION lines scripts for package main my @scripts = ( @@ -313,7 +328,7 @@ $::VERSION = 0.01; --- ); -( $i, $n ) = ( 1, scalar( @scripts ) ); +my ( $i, $n ) = ( 1, scalar( @scripts ) ); foreach my $script ( @scripts ) { $dist->change_file( 'bin/simple.plx', $script ); $dist->regen; @@ -402,7 +417,7 @@ __DATA__ is( $pm_info->name, 'Simple', 'found default package' ); is( $pm_info->version, '0.01', 'version for default package' ); my @packages = $pm_info->packages_inside; - is_deeply(\@packages, ['Simple']); + is_deeply(\@packages, ['Simple'], 'packages inside'); } { @@ -419,10 +434,7 @@ $VERSION = version->new('0.61.' . (qw$Revision: 129 $)[1]); is( $pm_info->name, 'Simple', 'found default package' ); is( $pm_info->version, '0.60.128', 'version for default package' ); my @packages = $pm_info->packages_inside; - is_deeply([sort @packages], ['Simple', 'Simple::Simon']); + is_deeply([sort @packages], ['Simple', 'Simple::Simon'], 'packages inside'); is( $pm_info->version('Simple::Simon'), '0.61.129', 'version for embedded package' ); } - -# cleanup -$dist->remove; diff --git a/cpan/Module-Build/t/mymeta.t b/cpan/Module-Build/t/mymeta.t new file mode 100644 index 0000000..c60a5b2 --- /dev/null +++ b/cpan/Module-Build/t/mymeta.t @@ -0,0 +1,30 @@ +#!/usr/bin/perl -w + +use strict; +use lib 't/lib'; +use MBTest tests => 3; + +blib_load('Module::Build'); + +my $tmp = MBTest->tmpdir; + +use DistGen; +my $dist = DistGen->new( dir => $tmp ); +$dist->regen; +$dist->chdir_in; + +######################### + +# Test MYMETA generation +{ + ok( ! -e "MYMETA.yml", "MYMETA.yml doesn't exist before Build.PL runs" ); + my $output; + $output = stdout_of sub { $dist->run_build_pl }; + like($output, qr/Creating new 'MYMETA.yml' with configuration results/, + "Saw MYMETA.yml creation message" + ); + ok( -e "MYMETA.yml", "MYMETA.yml exists" ); +} + +######################### + diff --git a/cpan/Module-Build/t/new_from_context.t b/cpan/Module-Build/t/new_from_context.t index ee34f07..f45a176 100644 --- a/cpan/Module-Build/t/new_from_context.t +++ b/cpan/Module-Build/t/new_from_context.t @@ -2,10 +2,9 @@ use strict; use lib 't/lib'; -use MBTest tests => 4; +use MBTest tests => 2; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); use IO::File; my $tmp = MBTest->tmpdir; @@ -25,7 +24,4 @@ my $mb = eval { Module::Build->new_from_context}; ok(! $@, 'dodged the bullet') or die; ok($mb); -# cleanup -$dist->remove; - # vim:ts=2:sw=2:et:sta diff --git a/cpan/Module-Build/t/notes.t b/cpan/Module-Build/t/notes.t index 29f1fc3..4568e7c 100644 --- a/cpan/Module-Build/t/notes.t +++ b/cpan/Module-Build/t/notes.t @@ -2,10 +2,9 @@ use strict; use lib 't/lib'; -use MBTest tests => 13; +use MBTest tests => 11; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); my $tmp = MBTest->tmpdir; @@ -65,6 +64,3 @@ $mb = Module::Build->resume; ok $mb; is $mb->notes('foo'), 'bar'; - -# cleanup -$dist->remove; diff --git a/cpan/Module-Build/t/parents.t b/cpan/Module-Build/t/parents.t index 666fb05..825f79a 100644 --- a/cpan/Module-Build/t/parents.t +++ b/cpan/Module-Build/t/parents.t @@ -2,10 +2,9 @@ use strict; use lib 't/lib'; -use MBTest tests => 28; +use MBTest tests => 26; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); ######################### diff --git a/cpan/Module-Build/t/perl_mb_opt.t b/cpan/Module-Build/t/perl_mb_opt.t new file mode 100644 index 0000000..70089ee --- /dev/null +++ b/cpan/Module-Build/t/perl_mb_opt.t @@ -0,0 +1,62 @@ +# sample.t -- a sample test file for Module::Build + +use strict; +use lib 't/lib'; +use MBTest; +use DistGen; + +plan tests => 8; # or 'no_plan' + +# Ensure any Module::Build modules are loaded from correct directory +blib_load('Module::Build'); + +# create dist object in a temp directory +# enter the directory and generate the skeleton files +my $dist = DistGen->new->chdir_in->regen; + +$dist->add_file('t/subtest/foo.t', <<'END_T'); +use strict; +use Test::More tests => 1; +ok(1, "this is a recursive test"); +END_T + +$dist->regen; + +# get a Module::Build object and test with it +my $mb = $dist->new_from_context(); # quiet by default +isa_ok( $mb, "Module::Build" ); +is( $mb->dist_name, "Simple", "dist_name is 'Simple'" ); +ok( ! $mb->recursive_test_files, "set for no recursive testing" ); + +# set for recursive testing using PERL_MB_OPT +{ + local $ENV{PERL_MB_OPT} = "--verbose --recursive_test_files 1"; + + my $out = stdout_stderr_of( sub { + $dist->run_build('test'); + }); + like( $out, qr/this is a recursive test/, + "recursive tests run via PERL_MB_OPT" + ); +} + +# set Build.PL opts using PERL_MB_OPT +{ + local $ENV{PERL_MB_OPT} = "--verbose --recursive_test_files 1"; + my $mb = $dist->new_from_context(); # quiet by default + ok( $mb->recursive_test_files, "PERL_MB_OPT set recusive tests in Build.PL" ); + ok( $mb->verbose, "PERL_MB_OPT set verbose in Build.PL" ); +} + +# verify settings preserved during 'Build test' +{ + ok( !$ENV{PERL_MB_OPT}, "PERL_MB_OPT cleared" ); + my $out = stdout_stderr_of( sub { + $dist->run_build('test'); + }); + like( $out, qr/this is a recursive test/, + "recursive tests run via Build object" + ); +} + +# vim:ts=2:sw=2:et:sta:sts=2 diff --git a/cpan/Module-Build/t/pod_parser.t b/cpan/Module-Build/t/pod_parser.t index 42a7820..64d4c75 100644 --- a/cpan/Module-Build/t/pod_parser.t +++ b/cpan/Module-Build/t/pod_parser.t @@ -2,10 +2,9 @@ use strict; use lib 't/lib'; -use MBTest tests => 8; +use MBTest tests => 9; -use_ok 'Module::Build::PodParser'; -ensure_blib('Module::Build::PodParser'); +blib_load('Module::Build::PodParser'); ######################### @@ -66,3 +65,26 @@ EOF } +{ + # Try again with mixed-case =head1s. + untie *FH; + tie *FH, 'IO::StringBased', <<'EOF'; +=head1 Name + +Foo::Bar - Perl extension for blah blah blah + +=head1 Author + +C was written by Engelbert Humperdinck Ieh@example.comE> in 2004. + +Home page: http://example.com/~eh/ + +=cut +EOF + + my $pp = Module::Build::PodParser->new(fh => \*FH); + ok $pp, 'object created'; + + is $pp->get_author->[0], 'C was written by Engelbert Humperdinck Ieh@example.comE> in 2004.', 'author'; + is $pp->get_abstract, 'Perl extension for blah blah blah', 'abstract'; +} diff --git a/cpan/Module-Build/t/ppm.t b/cpan/Module-Build/t/ppm.t index 7fb6450..4d69c97 100644 --- a/cpan/Module-Build/t/ppm.t +++ b/cpan/Module-Build/t/ppm.t @@ -3,11 +3,10 @@ use strict; use lib 't/lib'; use MBTest; - -use Module::Build; -use Module::Build::ConfigData; use Config; +blib_load('Module::Build'); +blib_load('Module::Build::ConfigData'); my $manpage_support = Module::Build::ConfigData->feature('manpage_support'); my $HTML_support = Module::Build::ConfigData->feature('HTML_support'); @@ -26,15 +25,13 @@ my $HTML_support = Module::Build::ConfigData->feature('HTML_support'); } elsif ( $^O eq 'VMS' ) { plan skip_all => "Needs porting work on VMS"; } else { - plan tests => 13; + plan tests => 12; } } -ensure_blib('Module::Build'); my $tmp = MBTest->tmpdir; - use DistGen; my $dist = DistGen->new( dir => $tmp, xs => 1 ); $dist->add_file( 'hello', <<'---' ); @@ -66,7 +63,6 @@ $dist->chdir_in; use File::Spec::Functions qw(catdir); -use Module::Build; my @installstyle = qw(lib perl5); my $mb = Module::Build->new_from_context( verbose => 0, @@ -98,13 +94,10 @@ my $varchname = Module::Build::PPMMaker->_varchname($mb->config); # do a strict string comparison, but absent an XML parser it's the # best we can do. is $ppd, <<"---"; - - @{[$dist->name]} + Perl extension for blah blah blah A. U. Thor, a.u.thor\@a.galaxy.far.far.away - - @@ -185,9 +178,6 @@ SKIP: { } -$dist->remove; - - ######################################## sub exists_ok { diff --git a/cpan/Module-Build/t/properties/module_name.t b/cpan/Module-Build/t/properties/module_name.t new file mode 100644 index 0000000..c266b41 --- /dev/null +++ b/cpan/Module-Build/t/properties/module_name.t @@ -0,0 +1,53 @@ +# sample.t -- a sample test file for Module::Build + +use strict; +use lib 't/lib'; +use MBTest; +use DistGen; + +plan tests => 4; + +# Ensure any Module::Build modules are loaded from correct directory +blib_load('Module::Build'); + +# enter the directory and generate the skeleton files +my $dist = DistGen->new( name => "Not::So::Simple" )->chdir_in; + +#--------------------------------------------------------------------------# +# try getting module_name from dist directory name +#--------------------------------------------------------------------------# + +$dist->change_build_pl( + dist_name => 'Random-Name', + dist_version => 1, +)->regen; + +my $mb = $dist->new_from_context(); +isa_ok( $mb, "Module::Build" ); +is( $mb->module_name, "Not::So::Simple", + "module_name guessed from directory name" +); + +#--------------------------------------------------------------------------# +# Try getting module_name from dist_version_from +#--------------------------------------------------------------------------# + +$dist->add_file( 'lib/Simple/Name.pm', << 'END_PACKAGE' ); +package Simple::Name; +our $VERSION = 1.23; +1; +END_PACKAGE + +$dist->change_build_pl( + dist_name => 'Random-Name', + dist_version_from => 'lib/Simple/Name.pm', + dist_abstract => "Don't complain about missing abstract", +)->regen( clean => 1 ); + +$mb = $dist->new_from_context(); +isa_ok( $mb, "Module::Build" ); +is( $mb->module_name, "Simple::Name", + "module_name guessed from dist_version_from" +); + +# vim:ts=2:sw=2:et:sta:sts=2 diff --git a/cpan/Module-Build/t/properties/needs_compiler.t b/cpan/Module-Build/t/properties/needs_compiler.t new file mode 100644 index 0000000..f298e82 --- /dev/null +++ b/cpan/Module-Build/t/properties/needs_compiler.t @@ -0,0 +1,122 @@ +# sample.t -- a sample test file for Module::Build + +use strict; +use lib 't/lib'; +use MBTest; +use DistGen; + +plan tests => 19; + +# Ensure any Module::Build modules are loaded from correct directory +blib_load('Module::Build'); + +my $dist = DistGen->new->regen->chdir_in; + +# get a Module::Build object and test with it +my $mb; +stderr_of(sub { + ok( $mb = $dist->new_from_context, "Default Build.PL" ); +}); + +ok( ! $mb->needs_compiler, "needs_compiler is false" ); +ok( ! exists $mb->{properties}{build_requires}{'ExtUtils::CBuilder'}, + "ExtUtils::CBuilder is not in build_requires" +); + +#--------------------------------------------------------------------------# +# try with c_source +#--------------------------------------------------------------------------# +$dist->change_build_pl({ + module_name => $dist->name, + license => 'perl', + c_source => 'src', +}); +$dist->regen; +stderr_of(sub { + ok( $mb = $dist->new_from_context, + "Build.PL with c_source" + ); +}); +is( $mb->c_source, 'src', "c_source is set" ); +ok( $mb->needs_compiler, "needs_compiler is true" ); +ok( exists $mb->{properties}{build_requires}{'ExtUtils::CBuilder'}, + "ExtUtils::CBuilder was added to build_requires" +); + +#--------------------------------------------------------------------------# +# try with xs files +#--------------------------------------------------------------------------# +$dist = DistGen->new(dir => 'MBTest', xs => 1); +$dist->regen; +$dist->chdir_in; + +stderr_of(sub { + ok( $mb = $dist->new_from_context, + "Build.PL with xs files" + ); +}); +ok( $mb->needs_compiler, "needs_compiler is true" ); +ok( exists $mb->{properties}{build_requires}{'ExtUtils::CBuilder'}, + "ExtUtils::CBuilder was added to build_requires" +); + +#--------------------------------------------------------------------------# +# force needs_compiler off, despite xs modules +#--------------------------------------------------------------------------# + +$dist->change_build_pl({ + module_name => $dist->name, + license => 'perl', + needs_compiler => 0, +}); +$dist->regen; + +stderr_of(sub { + ok( $mb = $dist->new_from_context , + "Build.PL with xs files, but needs_compiler => 0" + ); +}); +is( $mb->needs_compiler, 0, "needs_compiler is false" ); +ok( ! exists $mb->{properties}{build_requires}{'ExtUtils::CBuilder'}, + "ExtUtils::CBuilder is not in build_requires" +); + +#--------------------------------------------------------------------------# +# don't override specific EU::CBuilder build_requires +#--------------------------------------------------------------------------# + +$dist->change_build_pl({ + module_name => $dist->name, + license => 'perl', + build_requires => { 'ExtUtils::CBuilder' => 0.2 }, +}); +$dist->regen; + +stderr_of(sub { + ok( $mb = $dist->new_from_context , + "Build.PL with xs files, build_requires EU::CB 0.2" + ); +}); +ok( $mb->needs_compiler, "needs_compiler is true" ); +is( $mb->build_requires->{'ExtUtils::CBuilder'}, 0.2, + "build_requires for ExtUtils::CBuilder is correct version" +); + +#--------------------------------------------------------------------------# +# falsify compiler and test error handling +#--------------------------------------------------------------------------# + +my $err = stderr_of( sub { + $mb = $dist->new_from_context( config => { cc => "adfasdfadjdjk" } ) +}); +ok( $mb, "Build.PL while hiding compiler" ); +like( $err, qr/no compiler detected/, + "hidden compiler resulted in warning message during Build.PL" +); +eval { $mb->dispatch('build') }; +like( $@, qr/no compiler detected/, + "hidden compiler resulted in fatal message during Build" +); + + +# vim:ts=2:sw=2:et:sta:sts=2 diff --git a/cpan/Module-Build/t/properties/share_dir.t b/cpan/Module-Build/t/properties/share_dir.t new file mode 100644 index 0000000..f781a8a --- /dev/null +++ b/cpan/Module-Build/t/properties/share_dir.t @@ -0,0 +1,228 @@ +#!/usr/bin/perl -w + +use strict; +use lib 't/lib'; +use MBTest; +use File::Spec::Functions qw/catdir catfile/; + +#--------------------------------------------------------------------------# +# Begin testing +#--------------------------------------------------------------------------# + +plan tests => 21; + +blib_load('Module::Build'); + +#--------------------------------------------------------------------------# +# Create test distribution +#--------------------------------------------------------------------------# + +my $tmp = MBTest->tmpdir; + +use DistGen; +my $dist = DistGen->new( dir => $tmp, name => 'Simple::Share' ); +$dist->regen; +$dist->chdir_in; + +#--------------------------------------------------------------------------# +# Test setting 'share_dir' +#--------------------------------------------------------------------------# + +my $mb = $dist->new_from_context; + +# Test without a 'share' dir +ok( $mb, "Created Module::Build object" ); +is( $mb->share_dir, undef, + "default share undef if no 'share' dir exists" +); +ok( ! exists $mb->{properties}{requires}{'File::ShareDir'}, + "File::ShareDir not added to 'requires'" +); + +# Add 'share' dir and an 'other' dir and content +$dist->add_file('share/foo.txt',<< '---'); +This is foo.txt +--- +$dist->add_file('other/share/bar.txt',<< '---'); +This is bar.txt +--- +$dist->regen; +ok( -e catfile(qw/share foo.txt/), "Created 'share' directory" ); +ok( -e catfile(qw/other share bar.txt/), "Created 'other/share' directory" ); + +# Check default when share_dir is not given +stdout_stderr_of( sub { $mb = $dist->new_from_context }); +is_deeply( $mb->share_dir, { dist => [ 'share' ] }, + "Default share_dir set as dist-type share" +); +is( $mb->{properties}{requires}{'File::ShareDir'}, '1.00', + "File::ShareDir 1.00 added to 'requires'" +); + +# share_dir set to scalar +$dist->change_build_pl( + { + module_name => $dist->name, + license => 'perl', + share_dir => 'share', + } +); +$dist->regen; +stdout_stderr_of( sub { $mb = $dist->new_from_context }); +is_deeply( $mb->share_dir, { dist => [ 'share' ] }, + "Scalar share_dir set as dist-type share" +); + +# share_dir set to arrayref +$dist->change_build_pl( + { + module_name => $dist->name, + license => 'perl', + share_dir => [ 'share' ], + } +); +$dist->regen; +stdout_stderr_of( sub { $mb = $dist->new_from_context }); +is_deeply( $mb->share_dir, { dist => [ 'share' ] }, + "Arrayref share_dir set as dist-type share" +); + +# share_dir set to hashref w scalar +$dist->change_build_pl( + { + module_name => $dist->name, + license => 'perl', + share_dir => { dist => 'share' }, + } +); +$dist->regen; +stdout_stderr_of( sub { $mb = $dist->new_from_context }); +is_deeply( $mb->share_dir, { dist => [ 'share' ] }, + "Hashref share_dir w/ scalar dist set as dist-type share" +); + +# share_dir set to hashref w array +$dist->change_build_pl( + { + module_name => $dist->name, + license => 'perl', + share_dir => { dist => [ 'share' ] }, + } +); +$dist->regen; +stdout_stderr_of( sub { $mb = $dist->new_from_context }); +is_deeply( $mb->share_dir, { dist => [ 'share' ] }, + "Hashref share_dir w/ arrayref dist set as dist-type share" +); + +# Generate a module sharedir (scalar) +$dist->change_build_pl( + { + module_name => $dist->name, + license => 'perl', + share_dir => { + dist => 'share', + module => { $dist->name => 'other/share' }, + }, + } +); +$dist->regen; +stdout_stderr_of( sub { $mb = $dist->new_from_context }); +is_deeply( $mb->share_dir, + { dist => [ 'share' ], + module => { $dist->name => ['other/share'] }, + }, + "Hashref share_dir w/ both dist and module shares (scalar-form)" +); + +# Generate a module sharedir (array) +$dist->change_build_pl( + { + module_name => $dist->name, + license => 'perl', + share_dir => { + dist => [ 'share' ], + module => { $dist->name => ['other/share'] }, + }, + } +); +$dist->regen; +stdout_stderr_of( sub { $mb = $dist->new_from_context }); +is_deeply( $mb->share_dir, + { dist => [ 'share' ], + module => { $dist->name => ['other/share'] }, + }, + "Hashref share_dir w/ both dist and module shares (array-form)" +); + +#--------------------------------------------------------------------------# +# test constructing to/from mapping +#--------------------------------------------------------------------------# + +is_deeply( $mb->_find_share_dir_files, + { + catfile(qw/share foo.txt/) => catfile(qw/dist Simple-Share foo.txt/), + catfile(qw/other share bar.txt/) => catfile(qw/module Simple-Share bar.txt/), + }, + "share_dir filemap for copying to lib complete" +); + +#--------------------------------------------------------------------------# +# test moving files to blib +#--------------------------------------------------------------------------# + +$mb->dispatch('build'); + +ok( -d 'blib', "Build ran and blib exists" ); +ok( -d 'blib/lib/auto/share', "blib/lib/auto/share exists" ); + +my $share_list = Module::Build->rscan_dir('blib/lib/auto/share', sub {-f}); + +is_deeply( + [ sort @$share_list ], [ + 'blib/lib/auto/share/dist/Simple-Share/foo.txt', + 'blib/lib/auto/share/module/Simple-Share/bar.txt', + ], + "share_dir files copied to blib" +); + +#--------------------------------------------------------------------------# +# test installing +#--------------------------------------------------------------------------# + +my $temp_install = 'temp_install'; +mkdir $temp_install; +ok( -d $temp_install, "temp install dir created" ); + +$mb->install_base($temp_install); +stdout_of( sub { $mb->dispatch('install') } ); + +$share_list = Module::Build->rscan_dir( + "$temp_install/lib/perl5/auto/share", sub {-f} +); + +is_deeply( + [ sort @$share_list ], [ + "$temp_install/lib/perl5/auto/share/dist/Simple-Share/foo.txt", + "$temp_install/lib/perl5/auto/share/module/Simple-Share/bar.txt", + ], + "share_dir files correctly installed" +); + +#--------------------------------------------------------------------------# +# test with File::ShareDir +#--------------------------------------------------------------------------# + +SKIP: { + eval { require File::ShareDir; File::ShareDir->VERSION(1.00) }; + skip "needs File::ShareDir 1.00", 2 if $@; + + unshift @INC, File::Spec->catdir($temp_install, qw/lib perl5/); + require Simple::Share; + + eval {File::ShareDir::dist_file('Simple-Share','foo.txt') }; + is( $@, q{}, "Found shared dist file" ); + + eval {File::ShareDir::module_file('Simple::Share','bar.txt') }; + is( $@, q{}, "Found shared module file" ); +} diff --git a/cpan/Module-Build/t/resume.t b/cpan/Module-Build/t/resume.t new file mode 100644 index 0000000..add123d --- /dev/null +++ b/cpan/Module-Build/t/resume.t @@ -0,0 +1,43 @@ +use strict; +use lib 't/lib'; +use MBTest; +plan tests => 3; # or 'no_plan' +use DistGen; + +# Ensure any Module::Build modules are loaded from correct directory +blib_load('Module::Build'); + +# create dist object in a temp directory +# enter the directory and generate the skeleton files +my $dist = DistGen->new->chdir_in; +$dist->add_file('mylib/MBUtil.pm', << "---"); +package MBUtil; +sub foo { 42 } +1; +--- + +$dist->add_file('Build.PL', << "---"); +use strict; +use lib 'mylib'; +use MBUtil; +use Module::Build; + +die unless MBUtil::foo() == 42; + +my \$builder = Module::Build->new( +module_name => '$dist->{name}', +license => 'perl', +); + +\$builder->create_build_script(); +--- + +$dist->regen; + +# get a Module::Build object and test with it +my $mb = $dist->new_from_context(); # quiet by default +isa_ok( $mb, "Module::Build" ); +is( $mb->dist_name, "Simple", "dist_name is 'Simple'" ); +ok( ( grep { /mylib/ } @INC ), "resume added \@INC addition to \@INC"); + +# vim:ts=2:sw=2:et:sta:sts=2 diff --git a/cpan/Module-Build/t/runthrough.t b/cpan/Module-Build/t/runthrough.t index 21d3d1c..741755c 100644 --- a/cpan/Module-Build/t/runthrough.t +++ b/cpan/Module-Build/t/runthrough.t @@ -2,12 +2,10 @@ use strict; use lib 't/lib'; -use MBTest tests => 32; +use MBTest tests => 30; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); - -use Module::Build::ConfigData; +blib_load('Module::Build'); +blib_load('Module::Build::ConfigData'); my $have_yaml = Module::Build::ConfigData->feature('YAML_support'); ######################### @@ -24,6 +22,9 @@ $dist->change_build_pl requires => { 'File::Spec' => 0 }, }); +$dist->add_file( 'MANIFEST.SKIP', <<'---' ); +^MYMETA.yml$ +--- $dist->add_file( 'script', <<'---' ); #!perl -w print "Hello, World!\n"; @@ -169,12 +170,11 @@ SKIP: { # do a strict string comparison, but absent an XML parser it's the # best we can do. is $ppd, <<'EOF'; - - Simple + Perl extension for blah blah blah A. U. Thor, a.u.thor@a.galaxy.far.far.away - + @@ -189,8 +189,6 @@ ok ! -e $mb->build_script; ok ! -e $mb->config_dir; ok ! -e $mb->dist_dir; -$dist->remove; - SKIP: { skip( 'Windows-only test', 4 ) unless $^O =~ /^MSWin/; @@ -223,8 +221,5 @@ echo Hello, World! my $out = slurp( $script_file ); is $out, $script_data, ' unmodified by pl2bat'; - $dist->remove; } -# cleanup -$dist->remove; diff --git a/cpan/Module-Build/t/sample.t b/cpan/Module-Build/t/sample.t new file mode 100644 index 0000000..d83bc56 --- /dev/null +++ b/cpan/Module-Build/t/sample.t @@ -0,0 +1,20 @@ +# sample.t -- a sample test file for Module::Build + +use strict; +use lib 't/lib'; +use MBTest tests => 2; # or 'no_plan' +use DistGen; + +# Ensure any Module::Build modules are loaded from correct directory +blib_load('Module::Build'); + +# create dist object in a temp directory +# enter the directory and generate the skeleton files +my $dist = DistGen->new->chdir_in->regen; + +# get a Module::Build object and test with it +my $mb = $dist->new_from_context(); # quiet by default +isa_ok( $mb, "Module::Build" ); +is( $mb->dist_name, "Simple", "dist_name is 'Simple'" ); + +# vim:ts=2:sw=2:et:sta:sts=2 diff --git a/cpan/Module-Build/t/script_dist.t b/cpan/Module-Build/t/script_dist.t index e6b7fd8..02faca0 100644 --- a/cpan/Module-Build/t/script_dist.t +++ b/cpan/Module-Build/t/script_dist.t @@ -8,7 +8,8 @@ use MBTest 'no_plan'; use DistGen qw(undent); -use Module::Build; +blib_load('Module::Build'); +blib_load('Module::Build::ConfigData'); # XXX DistGen shouldn't be assuming module-ness? my $dist = DistGen->new(dir => MBTest->tmpdir); @@ -69,12 +70,11 @@ is_deeply($mb->dist_author, ['A. U. Thor, a.u.thor@a.galaxy.far.far.away']); ok $mb->dispatch('distmeta'); -use Module::Build::ConfigData; SKIP: { skip( 'YAML_support feature is not enabled', 1 ) unless Module::Build::ConfigData->feature('YAML_support'); - require YAML; - my $yml = YAML::LoadFile('META.yml'); + require YAML::Tiny; + my $yml = YAML::Tiny::LoadFile('META.yml'); is_deeply($yml->{provides}, \%meta_provides); } $dist->chdir_original if $dist->did_chdir; diff --git a/cpan/Module-Build/t/test_file_exts.t b/cpan/Module-Build/t/test_file_exts.t index 9dbf73e..5bb803c 100644 --- a/cpan/Module-Build/t/test_file_exts.t +++ b/cpan/Module-Build/t/test_file_exts.t @@ -2,11 +2,10 @@ use strict; use lib 't/lib'; -use MBTest tests => 5; +use MBTest tests => 3; use DistGen; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); my $tmp = MBTest->tmpdir; my $dist = DistGen->new( dir => $tmp ); @@ -39,7 +38,4 @@ my $out = uc(stdout_of( like $out, qr/^OK 1 - FIRST MYTEST[.]S/m, 'Should see first test output'; like $out, qr/^OK 2 - SECOND MYTEST[.]S/m, 'Should see second test output'; -# Cleanup. -$dist->remove; - # vim:ts=4:sw=4:et:sta diff --git a/cpan/Module-Build/t/test_type.t b/cpan/Module-Build/t/test_type.t index 3c6cfb6..fe4d599 100644 --- a/cpan/Module-Build/t/test_type.t +++ b/cpan/Module-Build/t/test_type.t @@ -9,10 +9,9 @@ BEGIN { use strict; use lib 't/lib'; -use MBTest tests => 9; +use MBTest tests => 7; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); my $tmp = MBTest->tmpdir; @@ -72,6 +71,4 @@ like($output, qr/\.\. ?OK/); is($::x, 3, "called a third time"); -$dist->remove; - # vim:ts=4:sw=4:et:sta diff --git a/cpan/Module-Build/t/test_types.t b/cpan/Module-Build/t/test_types.t index 5f3f5cf..d88e215 100644 --- a/cpan/Module-Build/t/test_types.t +++ b/cpan/Module-Build/t/test_types.t @@ -2,16 +2,13 @@ use strict; use lib 't/lib'; -use MBTest tests => 15 + 12; +use MBTest tests => 25; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); - -my $tmp = MBTest->tmpdir; +blib_load('Module::Build'); use DistGen; -my $dist = DistGen->new(dir => $tmp); +my $dist = DistGen->new()->chdir_in; $dist->add_file('t/special_ext.st', <<'---'); #!perl @@ -34,7 +31,6 @@ die "don't run this non-test file"; --- $dist->regen; -$dist->chdir_in; ######################### my $mb = Module::Build->subclass( @@ -98,10 +94,10 @@ is(scalar(@{[$all_output =~ m/OK 1/mg]}), 3 ); is(scalar(@{[$all_output =~ m/OK/mg]}), 8 ); is(scalar(@{[$all_output =~ m/ALL TESTS SUCCESSFUL\./mg]}), 1); -$dist->remove; - { # once-again +$dist->revert; + $dist->add_file('t/foo/special.st', <<'---'); #!perl use Test::More tests => 2; @@ -114,7 +110,6 @@ use strict; use Simple; ok 1; --- $dist->regen; -$dist->chdir_in; my $mb = Module::Build->subclass( code => q# @@ -174,7 +169,6 @@ like($all_output, qr/^OK 2 - SECOND TEST IN ANOTHER_EXT/m); is(scalar(@{[$all_output =~ m/(OK 1)/mg]}), 5 ); is(scalar(@{[$all_output =~ m/(OK)/mg]}), 13 ); -$dist->remove; } # end once-again # vim:ts=4:sw=4:et:sta diff --git a/cpan/Module-Build/t/tilde.t b/cpan/Module-Build/t/tilde.t index 5b39204..692ade0 100644 --- a/cpan/Module-Build/t/tilde.t +++ b/cpan/Module-Build/t/tilde.t @@ -4,10 +4,9 @@ use strict; use lib 't/lib'; -use MBTest tests => 18; +use MBTest tests => 16; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); my $tmp = MBTest->tmpdir; @@ -111,6 +110,3 @@ SKIP: { like( run_sample( $p => "~$me/foo")->$p(), qr($expected)i ); } - -# cleanup -$dist->remove; diff --git a/cpan/Module-Build/t/use_tap_harness.t b/cpan/Module-Build/t/use_tap_harness.t index d14cb05..f6e7e50 100644 --- a/cpan/Module-Build/t/use_tap_harness.t +++ b/cpan/Module-Build/t/use_tap_harness.t @@ -4,7 +4,7 @@ use strict; use Test::More; use lib 't/lib'; if (eval { require TAP::Harness } && TAP::Harness->VERSION >= 3) { - plan tests => 8; + plan tests => 9; } else { plan skip_all => 'TAP::Harness 3+ not installed' } @@ -12,21 +12,24 @@ if (eval { require TAP::Harness } && TAP::Harness->VERSION >= 3) { use MBTest; use DistGen; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); my $tmp = MBTest->tmpdir; my $dist = DistGen->new( dir => $tmp ); $dist->regen; - $dist->chdir_in; + ######################### # Make sure that TAP::Harness properly does its thing. -ok my $mb = Module::Build->new( +$dist->change_build_pl( module_name => $dist->name, use_tap_harness => 1, quiet => 1, -), 'Construct build object with test_file_exts parameter'; +); +$dist->regen; + +ok my $mb = $dist->new_from_context, + 'Construct build object with test_file_exts parameter'; $mb->add_to_cleanup('save_out'); # Use uc() so we don't confuse the current test output @@ -40,12 +43,16 @@ like $out, qr/^ALL TESTS SUCCESSFUL/m, 'Should see test success message'; ######################### # Make sure that arguments are passed through to TAP::Harness. -ok $mb = Module::Build->new( +$dist->change_build_pl( module_name => $dist->name, use_tap_harness => 1, tap_harness_args => { verbosity => 0 }, quiet => 1, -), 'Construct build object with test_file_exts parameter'; +); +$dist->regen; + +ok $mb = $dist->new_from_context, + 'Construct build object with test_file_exts parameter'; $mb->add_to_cleanup('save_out'); # Use uc() so we don't confuse the current test output @@ -56,6 +63,32 @@ $out = uc(stdout_of( unlike $out, qr/^OK 1/m, 'Should not see first test output'; like $out, qr/^ALL TESTS SUCCESSFUL/m, 'Should see test success message'; -$dist->remove; +#--------------------------------------------------------------------------# +# test that a failing test dies +#--------------------------------------------------------------------------# + +$dist->change_build_pl( + module_name => $dist->name, + use_tap_harness => 1, + tap_harness_args => { verbosity => 1 }, + quiet => 1, +); +$dist->change_file('t/basic.t',<<"---"); +use Test::More tests => 1; +use strict; + +use $dist->{name}; +ok 0; +--- +$dist->regen; + +ok $mb = $dist->new_from_context, + 'Construct build object after setting tests to fail'; +# Use uc() so we don't confuse the current test output +$out = stdout_stderr_of( sub { $dist->run_build('test')} ); +ok( $?, "'Build test' had non-zero exit code" ); +like( $out, qr{Errors in testing\. Cannot continue\.}, + "Saw emulated Test::Harness die() message" +); # vim:ts=4:sw=4:et:sta diff --git a/cpan/Module-Build/t/versions.t b/cpan/Module-Build/t/versions.t index 7f511e5..5eafbac 100644 --- a/cpan/Module-Build/t/versions.t +++ b/cpan/Module-Build/t/versions.t @@ -2,10 +2,9 @@ use strict; use lib 't/lib'; -use MBTest tests => 4; +use MBTest tests => 2; -use_ok 'Module::Build'; -ensure_blib('Module::Build'); +blib_load('Module::Build'); my $tmp = MBTest->tmpdir; @@ -20,7 +19,3 @@ my $file = File::Spec->catfile( $dist->dirname, 'lib', @mod ) . '.pm'; is( Module::Build->version_from_file( $file ), '0.01', 'version_from_file' ); ok( Module::Build->compare_versions( '1.01_01', '>', '1.01' ), 'compare: 1.0_01 > 1.0' ); - - -# cleanup -$dist->remove; diff --git a/cpan/Module-Build/t/write_default_maniskip.t b/cpan/Module-Build/t/write_default_maniskip.t index 084d81e..40389f2 100644 --- a/cpan/Module-Build/t/write_default_maniskip.t +++ b/cpan/Module-Build/t/write_default_maniskip.t @@ -8,14 +8,14 @@ use MBTest 'no_plan'; use DistGen; use Cwd; -use_ok 'Module::Build'; -ensure_blib 'Module::Build'; +blib_load('Module::Build'); { my $cwd = Cwd::cwd; chdir MBTest->tmpdir(); my $build = Module::Build->new( + module_name => "Foo::Bar", dist_name => "Foo-Bar", dist_version => '1.23', ); diff --git a/cpan/Module-Build/t/xs.t b/cpan/Module-Build/t/xs.t index e3f1ed7..6d167c8 100644 --- a/cpan/Module-Build/t/xs.t +++ b/cpan/Module-Build/t/xs.t @@ -3,11 +3,12 @@ use strict; use lib 't/lib'; use MBTest; -use Module::Build; use Config; my $tmp; +blib_load('Module::Build'); + { my ($have_c_compiler, $C_support_feature, $tmp_exec) = check_compiler(); @@ -20,24 +21,20 @@ my $tmp; } elsif ( !$Config{usedl} ) { plan skip_all => 'Perl not compiled for dynamic loading' } else { - plan tests => 23; + plan tests => 20; } require Cwd; $tmp = MBTest->tmpdir( $tmp_exec ? undef : Cwd::cwd ); } -ensure_blib('Module::Build'); ######################### use DistGen; -my $dist = DistGen->new( dir => $tmp, xs => 1 ); -$dist->regen; - -$dist->chdir_in; -my $mb = Module::Build->new_from_context; +my $dist = DistGen->new( dir => $tmp, xs => 1 )->chdir_in->regen; +my $mb = $dist->new_from_context; eval {$mb->dispatch('clean')}; is $@, ''; @@ -83,7 +80,7 @@ is $@, ''; # We can't be verbose in the sub-test, because Test::Harness will # think that the output is for the top-level test. -eval {$mb->dispatch('test')}; +stdout_stderr_of( sub { eval {$mb->dispatch('test')} }); is $@, ''; eval {$mb->dispatch('clean')}; @@ -106,42 +103,31 @@ is $@, ''; # Make sure blib/ is gone after 'realclean' ok ! -e 'blib'; - -# cleanup -$dist->remove; - - ######################################## # Try a XS distro with a deep namespace -$dist = DistGen->new( name => 'Simple::With::Deep::Name', - dir => $tmp, xs => 1 ); -$dist->regen; -$dist->chdir_in; -$mb = Module::Build->new_from_context; -is $@, ''; +$dist->reset( name => 'Simple::With::Deep::Name', dir => $tmp, xs => 1 ); +$dist->chdir_in->regen; -$mb->dispatch('build'); -is $@, ''; +$mb = $dist->new_from_context; -$mb->dispatch('test'); +eval { $mb->dispatch('build') }; is $@, ''; -$mb->dispatch('realclean'); +stdout_stderr_of( sub { eval { $mb->dispatch('test') } } ); is $@, ''; -# cleanup -$dist->remove; - +eval { $mb->dispatch('realclean') }; +is $@, ''; ######################################## # Try a XS distro using a flat directory structure # and a 'dist_name' instead of a 'module_name' -$dist = DistGen->new( name => 'Dist-Name', dir => $tmp, xs => 1 ); +$dist->reset( name => 'Dist-Name', dir => $tmp, xs => 1 )->chdir_in; $dist->remove_file('lib/Dist-Name.pm'); $dist->remove_file('lib/Dist-Name.xs'); @@ -211,20 +197,15 @@ ok( Simple::okay() eq 'ok' ); --- $dist->regen; -$dist->chdir_in; - -$mb = Module::Build->new_from_context; -is $@, ''; +$mb = $dist->new_from_context; -$mb->dispatch('build'); +eval { $mb->dispatch('build') }; is $@, ''; -$mb->dispatch('test'); +stdout_of( sub { eval { $mb->dispatch('test') } } ); is $@, ''; -$mb->dispatch('realclean'); +eval { $mb->dispatch('realclean') }; is $@, ''; -# cleanup -$dist->remove;