diff options
-rw-r--r-- | Build.PL | 4 | ||||
-rw-r--r-- | Changes | 150 | ||||
-rw-r--r-- | INSTALL | 44 | ||||
-rw-r--r-- | LICENSE | 379 | ||||
-rw-r--r-- | MANIFEST | 16 | ||||
-rw-r--r-- | META.json | 119 | ||||
-rw-r--r-- | META.yml | 79 | ||||
-rw-r--r-- | README | 15 | ||||
-rw-r--r-- | Todo | 1 | ||||
-rw-r--r-- | dist.ini | 21 | ||||
-rw-r--r-- | lib/Module/Build/Tiny.pm | 311 | ||||
-rw-r--r-- | t/00-compile.t | 50 | ||||
-rw-r--r-- | t/lib/DistGen.pm | 602 | ||||
-rw-r--r-- | t/release-pod-syntax.t | 14 | ||||
-rw-r--r-- | t/simple.t | 137 |
15 files changed, 1942 insertions, 0 deletions
diff --git a/Build.PL b/Build.PL new file mode 100644 index 0000000..1d4e61f --- /dev/null +++ b/Build.PL @@ -0,0 +1,4 @@ +use 5.006; +use lib 'lib'; +use Module::Build::Tiny; +Build_PL(@ARGV); @@ -0,0 +1,150 @@ +Revision history for Module::Build::Tiny + +0.039 2014-10-12 10:38:39+02:00 Europe/Amsterdam + Supply basename to *.PL files as its args + +0.038 2014-09-06 11:28:23+02:00 Europe/Amsterdam + Scrub PERL_MB_OPT in tests too + +0.037 2014-07-27 16:14:54+02:00 Europe/Amsterdam + Scrub environment variable in tests + +0.036 2014-05-02 14:51:02CEST+0200 Europe/Amsterdam + Add --jobs argument to MBT + Add xs directory to include list + +0.035 2014-02-17 23:18:54CET+0100 Europe/Amsterdam + Fix install test in absence of a compiler + +0.034 2014-01-22 03:40:21CET+0100 Europe/Amsterdam + Make install tests more platform independent + +0.033 2014-01-21 03:27:32CET+0100 Europe/Amsterdam + Require Getopt::Long 2.36 + Add install tests + +0.032 2014-01-20 20:07:13CET+0100 Europe/Amsterdam + Fix env options and Build.PL options being ignored (regression in 0.031) + +0.031 2014-01-20 16:24:58CET+0100 Europe/Amsterdam + Process argument sources separately + Use mod2fname appropriately + +0.030 2013-10-11 12:01:24 Europe/Amsterdam + Added workaround for #54606 + +0.029 2013-10-11 00:39:20 Europe/Amsterdam + Respect harness environmental variables + Add main dir to include path + +0.028 2013-09-29 19:58:39 Europe/Amsterdam + Revert "Removed clean and realclean actions" + Build .c and .o in temp/ instead of lib + Got rid of IO layers + Separate libdoc and bindoc checks + +0.027 2013-09-09 11:43:12 Europe/Amsterdam + Various documentation updates + +0.026 2013-08-19 22:09:00 Europe/Amsterdam + Safe PERL_MB_OPT during configuration stage + +0.025 2013-07-12 16:09:45 Europe/Amsterdam + Use local tempdir + +0.024 2013-06-29 21:57:13 Europe/Amsterdam + Generate man pages in the correct section + +0.023 2013-06-03 01:13:05 Europe/Amsterdam + Implement --pureperl-only + Skip compilation test when not having a compiler + +0.022 2013-06-01 03:31:05 Europe/Amsterdam + Fix dirname code for toplevel XS modules + +0.021 2013-05-27 14:35:05 Europe/Amsterdam + Add XS support + Only manify if really installable + +0.020 2013-05-20 14:29:59 Europe/Amsterdam + Accept a --create_packlist argument + +0.019 2013-04-30 01:20:54 Europe/Amsterdam + Accept --pureperl-only + +0.018 2013-04-24 16:22:44 Europe/Amsterdam + Lazily load Pod::Man and TAP::Harness + Don't manify unless necessary + +0.017 2013-04-13 09:13:22 Europe/London + Fix redefined warning for find + +0.016 2013-04-12 17:24:52 Europe/London + Fix loading of File::Find + +0.015 2013-04-12 15:58:14 Europe/London + Switched back from JSON to JSON::PP + Remove dependency on File::Find::Rule + Switched back to ExtUtils::Helpers for detildefy + Drop .modulebuildrc support per Lancaster consensus + +0.014 2013-04-04 15:58:50 Europe/Amsterdam + Added sharedir support + Fixed Synopsis [tokuhirom] + Make blib/arch, to satisfy blib.pm + Removed dependencies on Test::Exception, Capture::Tiny and File::Slurp + +0.013 2013-02-12 20:17:25 Europe/Amsterdam + Detildefy input + +0.012 2012-01-09 22:59:13 Europe/Amsterdam + Move manify from ExtUtils::Helpers to Module::Build::Tiny + Don't adapt too much to VMS's wiles (let EU::Helpers take care of the Build.com) + +0.011 2011-09-26 15:56:28 Europe/Amsterdam + Fix Module::Build::Tiny on Windows + +0.010 2011-08-23 19:46:29 Europe/Amsterdam + Don't let the test and install actions depend on build (was rather broken) + Add support for *.PL files + chmod more robustly (may fix bugs on Windows) + Various documentation updates + +0.009 2011-05-08 12:05:01 Europe/Amsterdam + Install packlists to the right location + +0.008 2011-05-07 11:25:39 Europe/Amsterdam + Removed clean and realclean commands + Fix writability for scripts and modules + +0.007 2011-05-01 22:36:17 Europe/Bucharest + Now with corrent configure-requires meta-information + +0.006 2011-04-29 11:56:37 Europe/Bucharest + Complete rewrite of Acme::Module::Build::Tiny into Module::Build::Tiny + * Now uses dependencies + * Either implements a feature correctly or not at all + +0.05 - Fri Oct 8 15:19:31 EDT 2010 + + - If $^X looks like a perl found in the path, use $Config{perlpath} + + - Avoid issuing a warning when Build is run with no arguments + +0.04 - Wed Mar 24 22:59:50 EDT 2010 + + - Fix test bug when running a versioned perl (e.g. perl5.10.1) + +0.03 - Wed Mar 24 09:48:55 EDT 2010 + + - Fix SYNOPSIS documentation + +0.02 - Tue Mar 23 15:20:19 EDT 2010 + + - Add support for .modulebuildrc and PERL_MB_OPT so it works + with local::lib + +0.01 - Tue Mar 23 14:21:29 EDT 2010 + + - First release + @@ -0,0 +1,44 @@ + +This is the Perl distribution Module-Build-Tiny. + +Installing Module-Build-Tiny is straightforward. + +## Installation with cpanm + +If you have cpanm, you only need one line: + + % cpanm Module::Build::Tiny + +If you are installing into a system-wide directory, you may need to pass the +"-S" flag to cpanm, which uses sudo to install the module: + + % cpanm -S Module::Build::Tiny + +## Installing with the CPAN shell + +Alternatively, if your CPAN shell is set up, you should just be able to do: + + % cpan Module::Build::Tiny + +## Manual installation + +As a last resort, you can manually install it. Download the tarball, untar it, +then build it: + + % perl Build.PL + % ./Build && ./Build test + +Then install it: + + % ./Build install + +If you are installing into a system-wide directory, you may need to run: + + % sudo ./Build install + +## Documentation + +Module-Build-Tiny documentation is available as POD. +You can run perldoc from a shell to read the documentation: + + % perldoc Module::Build::Tiny @@ -0,0 +1,379 @@ +This software is copyright (c) 2011 by Leon Timmermans, David Golden. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +Terms of the Perl programming language system itself + +a) the GNU General Public License as published by the Free + Software Foundation; either version 1, or (at your option) any + later version, or +b) the "Artistic License" + +--- The GNU General Public License, Version 1, February 1989 --- + +This software is Copyright (c) 2011 by Leon Timmermans, David Golden. + +This is free software, licensed under: + + The GNU General Public License, Version 1, February 1989 + + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 + + Copyright (C) 1989 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free +programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of a such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must tell them their rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any program or other work which +contains a notice placed by the copyright holder saying it may be +distributed under the terms of this General Public License. The +"Program", below, refers to any such program or work, and a "work based +on the Program" means either the Program or any work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + + 1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + + 2. You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating that + you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, that + in whole or in part contains the Program or any part thereof, either + with or without modifications, to be licensed at no charge to all + third parties under the terms of this General Public License (except + that you may choose to grant warranty protection to some or all + third parties, at your option). + + c) If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use + in the simplest and most usual way, to print or display an + announcement including an appropriate copyright notice and a notice + that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under these + conditions, and telling the user how to view a copy of this General + Public License. + + d) You may charge a fee for the physical act of transferring a + copy, and you may at your option offer warranty protection in + exchange for a fee. + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + + 3. You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal charge + for the cost of distribution) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + + 4. You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + + 5. By copying, distributing or modifying the Program (or any work based +on the Program) you indicate your acceptance of this license to do so, +and all its terms and conditions. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these +terms and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. + + 7. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of the license which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +the license, you may choose any version ever published by the Free Software +Foundation. + + 8. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to humanity, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19xx name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (a program to direct compilers to make passes + at assemblers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! + + +--- The Artistic License 1.0 --- + +This software is Copyright (c) 2011 by Leon Timmermans, David Golden. + +This is free software, licensed under: + + The Artistic License 1.0 + +The Artistic License + +Preamble + +The intent of this document is to state the conditions under which a Package +may be copied, such that the Copyright Holder maintains some semblance of +artistic control over the development of the package, while giving the users of +the package the right to use and distribute the Package in a more-or-less +customary fashion, plus the right to make reasonable modifications. + +Definitions: + + - "Package" refers to the collection of files distributed by the Copyright + Holder, and derivatives of that collection of files created through + textual modification. + - "Standard Version" refers to such a Package if it has not been modified, + or has been modified in accordance with the wishes of the Copyright + Holder. + - "Copyright Holder" is whoever is named in the copyright or copyrights for + the package. + - "You" is you, if you're thinking about copying or distributing this Package. + - "Reasonable copying fee" is whatever you can justify on the basis of media + cost, duplication charges, time of people involved, and so on. (You will + not be required to justify it to the Copyright Holder, but only to the + computing community at large as a market that must bear the fee.) + - "Freely Available" means that no fee is charged for the item itself, though + there may be fees involved in handling the item. It also means that + recipients of the item may redistribute it under the same conditions they + received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications derived +from the Public Domain or from the Copyright Holder. A Package modified in such +a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided that +you insert a prominent notice in each changed file stating how and when you +changed that file, and provided that you do at least ONE of the following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or an + equivalent medium, or placing the modifications on a major archive site + such as ftp.uu.net, or by allowing the Copyright Holder to include your + modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict with + standard executables, which must also be provided, and provide a separate + manual page for each non-standard executable that clearly documents how it + differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or executable +form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where to + get the Standard Version. + + b) accompany the distribution with the machine-readable source of the Package + with your modifications. + + c) accompany any non-standard executables with their corresponding Standard + Version executables, giving the non-standard executables non-standard + names, and clearly documenting the differences in manual pages (or + equivalent), together with instructions on where to get the Standard + Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this Package. You +may not charge a fee for this Package itself. However, you may distribute this +Package in aggregate with other (possibly commercial) programs as part of a +larger (possibly commercial) software distribution provided that you do not +advertise this Package as a product of your own. + +6. The scripts and library files supplied as input to or produced as output +from the programs of this Package do not automatically fall under the copyright +of this Package, but belong to whomever generated them, and may be sold +commercially, and may be aggregated with this Package. + +7. C or perl subroutines supplied by you and linked into this Package shall not +be considered part of this Package. + +8. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +The End + diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..82a22fb --- /dev/null +++ b/MANIFEST @@ -0,0 +1,16 @@ +# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.020. +Build.PL +Changes +INSTALL +LICENSE +MANIFEST +META.json +META.yml +README +Todo +dist.ini +lib/Module/Build/Tiny.pm +t/00-compile.t +t/lib/DistGen.pm +t/release-pod-syntax.t +t/simple.t diff --git a/META.json b/META.json new file mode 100644 index 0000000..c51a3da --- /dev/null +++ b/META.json @@ -0,0 +1,119 @@ +{ + "abstract" : "A tiny replacement for Module::Build", + "author" : [ + "Leon Timmermans <leont@cpan.org>", + "David Golden <dagolden@cpan.org>" + ], + "dynamic_config" : 0, + "generated_by" : "Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.142060", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "Module-Build-Tiny", + "prereqs" : { + "configure" : { + "requires" : { + "CPAN::Meta" : "0", + "DynaLoader" : "0", + "Exporter" : "5.57", + "ExtUtils::CBuilder" : "0", + "ExtUtils::Config" : "0.003", + "ExtUtils::Helpers" : "0.020", + "ExtUtils::Install" : "0", + "ExtUtils::InstallPaths" : "0.002", + "ExtUtils::ParseXS" : "0", + "File::Basename" : "0", + "File::Find" : "0", + "File::Path" : "0", + "File::Spec::Functions" : "0", + "Getopt::Long" : "2.36", + "JSON::PP" : "2", + "Pod::Man" : "0", + "TAP::Harness::Env" : "0", + "perl" : "5.006", + "strict" : "0", + "warnings" : "0" + } + }, + "develop" : { + "requires" : { + "Test::Pod" : "1.41" + } + }, + "runtime" : { + "conflicts" : { + "local::lib" : "< 1.006008" + }, + "requires" : { + "CPAN::Meta" : "0", + "DynaLoader" : "0", + "Exporter" : "5.57", + "ExtUtils::CBuilder" : "0", + "ExtUtils::Config" : "0.003", + "ExtUtils::Helpers" : "0.020", + "ExtUtils::Install" : "0", + "ExtUtils::InstallPaths" : "0.002", + "ExtUtils::ParseXS" : "0", + "File::Basename" : "0", + "File::Find" : "0", + "File::Path" : "0", + "File::Spec::Functions" : "0", + "Getopt::Long" : "2.36", + "JSON::PP" : "2", + "Pod::Man" : "0", + "TAP::Harness::Env" : "0", + "perl" : "5.006", + "strict" : "0", + "warnings" : "0" + }, + "suggests" : { + "constant" : "1.27" + } + }, + "test" : { + "requires" : { + "Carp" : "0", + "Cwd" : "0", + "Data::Dumper" : "0", + "File::Spec" : "0", + "File::Temp" : "0", + "IO::File" : "0", + "IO::Handle" : "0", + "IPC::Open2" : "0", + "IPC::Open3" : "0", + "Test::More" : "0.88", + "XSLoader" : "0", + "blib" : "0", + "lib" : "0", + "perl" : "5.006" + }, + "suggests" : { + "File::ShareDir" : "1.000" + } + } + }, + "provides" : { + "Module::Build::Tiny" : { + "file" : "lib/Module/Build/Tiny.pm", + "version" : "0.039" + } + }, + "release_status" : "stable", + "resources" : { + "bugtracker" : { + "mailto" : "bug-module-build-tiny at rt.cpan.org", + "web" : "http://rt.cpan.org/Public/Dist/Display.html?Name=Module-Build-Tiny" + }, + "repository" : { + "type" : "git", + "url" : "git://github.com/Leont/module-build-tiny.git", + "web" : "https://github.com/Leont/module-build-tiny" + } + }, + "version" : "0.039" +} + diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..ea4b68e --- /dev/null +++ b/META.yml @@ -0,0 +1,79 @@ +--- +abstract: 'A tiny replacement for Module::Build' +author: + - 'Leon Timmermans <leont@cpan.org>' + - 'David Golden <dagolden@cpan.org>' +build_requires: + Carp: '0' + Cwd: '0' + Data::Dumper: '0' + File::Spec: '0' + File::Temp: '0' + IO::File: '0' + IO::Handle: '0' + IPC::Open2: '0' + IPC::Open3: '0' + Test::More: '0.88' + XSLoader: '0' + blib: '0' + lib: '0' + perl: '5.006' +configure_requires: + CPAN::Meta: '0' + DynaLoader: '0' + Exporter: '5.57' + ExtUtils::CBuilder: '0' + ExtUtils::Config: '0.003' + ExtUtils::Helpers: '0.020' + ExtUtils::Install: '0' + ExtUtils::InstallPaths: '0.002' + ExtUtils::ParseXS: '0' + File::Basename: '0' + File::Find: '0' + File::Path: '0' + File::Spec::Functions: '0' + Getopt::Long: '2.36' + JSON::PP: '2' + Pod::Man: '0' + TAP::Harness::Env: '0' + perl: '5.006' + strict: '0' + warnings: '0' +conflicts: + local::lib: '< 1.006008' +dynamic_config: 0 +generated_by: 'Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.142060' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: '1.4' +name: Module-Build-Tiny +provides: + Module::Build::Tiny: + file: lib/Module/Build/Tiny.pm + version: '0.039' +requires: + CPAN::Meta: '0' + DynaLoader: '0' + Exporter: '5.57' + ExtUtils::CBuilder: '0' + ExtUtils::Config: '0.003' + ExtUtils::Helpers: '0.020' + ExtUtils::Install: '0' + ExtUtils::InstallPaths: '0.002' + ExtUtils::ParseXS: '0' + File::Basename: '0' + File::Find: '0' + File::Path: '0' + File::Spec::Functions: '0' + Getopt::Long: '2.36' + JSON::PP: '2' + Pod::Man: '0' + TAP::Harness::Env: '0' + perl: '5.006' + strict: '0' + warnings: '0' +resources: + bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=Module-Build-Tiny + repository: git://github.com/Leont/module-build-tiny.git +version: '0.039' @@ -0,0 +1,15 @@ + + +This archive contains the distribution Module-Build-Tiny, +version 0.039: + + A tiny replacement for Module::Build + +This software is copyright (c) 2011 by Leon Timmermans, David Golden. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + + +This README file was generated by Dist::Zilla::Plugin::Readme v5.020. + @@ -0,0 +1 @@ +* add HTML support diff --git a/dist.ini b/dist.ini new file mode 100644 index 0000000..a736b8f --- /dev/null +++ b/dist.ini @@ -0,0 +1,21 @@ +name = Module-Build-Tiny +author = Leon Timmermans <leont@cpan.org> +author = David Golden <dagolden@cpan.org> +license = Perl_5 +copyright_holder = Leon Timmermans, David Golden +copyright_year = 2011 + +;Building +[@LEONT] +; List explicitely for 'dzil authodeps' +;authordep Dist::Zilla::Plugin::BuildSelf +install_tool = self +BuildSelf.auto_configure_requires = 1 +AutoPrereqs.skip = File::ShareDir +-remove = PodCoverageTests +[Prereqs / RuntimeSuggests] +constant = 1.27 +[Prereqs / RuntimeConflicts] +local::lib = <1.006008 +[Prereqs / TestSuggests] +File::ShareDir = 1.000 diff --git a/lib/Module/Build/Tiny.pm b/lib/Module/Build/Tiny.pm new file mode 100644 index 0000000..fd89466 --- /dev/null +++ b/lib/Module/Build/Tiny.pm @@ -0,0 +1,311 @@ +package Module::Build::Tiny; +$Module::Build::Tiny::VERSION = '0.039'; +use strict; +use warnings; +use Exporter 5.57 'import'; +our @EXPORT = qw/Build Build_PL/; + +use CPAN::Meta; +use ExtUtils::Config 0.003; +use ExtUtils::Helpers 0.020 qw/make_executable split_like_shell man1_pagename man3_pagename detildefy/; +use ExtUtils::Install qw/pm_to_blib install/; +use ExtUtils::InstallPaths 0.002; +use File::Basename qw/basename dirname/; +use File::Find (); +use File::Path qw/mkpath rmtree/; +use File::Spec::Functions qw/catfile catdir rel2abs abs2rel splitdir curdir/; +use Getopt::Long 2.36 qw/GetOptionsFromArray/; +use JSON::PP 2 qw/encode_json decode_json/; + +sub write_file { + my ($filename, $content) = @_; + open my $fh, '>', $filename or die "Could not open $filename: $!\n"; + print $fh $content; +} +sub read_file { + my ($filename, $mode) = @_; + open my $fh, '<', $filename or die "Could not open $filename: $!\n"; + return do { local $/; <$fh> }; +} + +sub get_meta { + my ($metafile) = grep { -e $_ } qw/META.json META.yml/ or die "No META information provided\n"; + return CPAN::Meta->load_file($metafile); +} + +sub manify { + my ($input_file, $output_file, $section, $opts) = @_; + return if -e $output_file && -M $input_file <= -M $output_file; + my $dirname = dirname($output_file); + mkpath($dirname, $opts->{verbose}) if not -d $dirname; + require Pod::Man; + Pod::Man->new(section => $section)->parse_from_file($input_file, $output_file); + print "Manifying $output_file\n" if $opts->{verbose} && $opts->{verbose} > 0; + return; +} + +sub process_xs { + my ($source, $options) = @_; + + die "Can't build xs files under --pureperl-only\n" if $options->{'pureperl-only'}; + my (undef, @parts) = splitdir(dirname($source)); + push @parts, my $file_base = basename($source, '.xs'); + my $archdir = catdir(qw/blib arch auto/, @parts); + my $tempdir = 'temp'; + + my $c_file = catfile($tempdir, "$file_base.c"); + require ExtUtils::ParseXS; + mkpath($tempdir, $options->{verbose}, oct '755'); + ExtUtils::ParseXS::process_file(filename => $source, prototypes => 0, output => $c_file); + + my $version = $options->{meta}->version; + require ExtUtils::CBuilder; + my $builder = ExtUtils::CBuilder->new(config => $options->{config}->values_set); + my $ob_file = $builder->compile(source => $c_file, defines => { VERSION => qq/"$version"/, XS_VERSION => qq/"$version"/ }, include_dirs => [ curdir, dirname($source) ]); + + require DynaLoader; + my $mod2fname = defined &DynaLoader::mod2fname ? \&DynaLoader::mod2fname : sub { return $_[0][-1] }; + + mkpath($archdir, $options->{verbose}, oct '755') unless -d $archdir; + my $lib_file = catfile($archdir, $mod2fname->(\@parts) . '.' . $options->{config}->get('dlext')); + return $builder->link(objects => $ob_file, lib_file => $lib_file, module_name => join '::', @parts); +} + +sub find { + my ($pattern, $dir) = @_; + my @ret; + File::Find::find(sub { push @ret, $File::Find::name if /$pattern/ && -f }, $dir) if -d $dir; + return @ret; +} + +my %actions = ( + build => sub { + my %opt = @_; + for my $pl_file (find(qr/\.PL$/, 'lib')) { + (my $pm = $pl_file) =~ s/\.PL$//; + system $^X, $pl_file, $pm and die "$pl_file returned $?\n"; + } + my %modules = map { $_ => catfile('blib', $_) } find(qr/\.p(?:m|od)$/, 'lib'); + my %scripts = map { $_ => catfile('blib', $_) } find(qr//, 'script'); + my %shared = map { $_ => catfile(qw/blib lib auto share dist/, $opt{meta}->name, abs2rel($_, 'share')) } find(qr//, 'share'); + pm_to_blib({ %modules, %scripts, %shared }, catdir(qw/blib lib auto/)); + make_executable($_) for values %scripts; + mkpath(catdir(qw/blib arch/), $opt{verbose}); + process_xs($_, \%opt) for find(qr/.xs$/, 'lib'); + + if ($opt{install_paths}->install_destination('bindoc') && $opt{install_paths}->is_default_installable('bindoc')) { + manify($_, catfile('blib', 'bindoc', man1_pagename($_)), $opt{config}->get('man1ext'), \%opt) for keys %scripts; + } + if ($opt{install_paths}->install_destination('libdoc') && $opt{install_paths}->is_default_installable('libdoc')) { + manify($_, catfile('blib', 'libdoc', man3_pagename($_)), $opt{config}->get('man3ext'), \%opt) for keys %modules; + } + }, + test => sub { + my %opt = @_; + die "Must run `./Build build` first\n" if not -d 'blib'; + require TAP::Harness::Env; + my %test_args = ( + (verbosity => $opt{verbose}) x!! exists $opt{verbose}, + (jobs => $opt{jobs}) x!! exists $opt{jobs}, + (color => 1) x !!-t STDOUT, + lib => [ map { rel2abs(catdir(qw/blib/, $_)) } qw/arch lib/ ], + ); + my $tester = TAP::Harness::Env->create(\%test_args); + $tester->runtests(sort +find(qr/\.t$/, 't'))->has_errors and exit 1; + }, + install => sub { + my %opt = @_; + die "Must run `./Build build` first\n" if not -d 'blib'; + install($opt{install_paths}->install_map, @opt{qw/verbose dry_run uninst/}); + }, + clean => sub { + my %opt = @_; + rmtree($_, $opt{verbose}) for qw/blib temp/; + }, + realclean => sub { + my %opt = @_; + rmtree($_, $opt{verbose}) for qw/blib temp Build _build_params MYMETA.yml MYMETA.json/; + }, +); + +sub Build { + my $action = @ARGV && $ARGV[0] =~ /\A\w+\z/ ? shift @ARGV : 'build'; + die "No such action '$action'\n" if not $actions{$action}; + my($env, $bargv) = @{ decode_json(read_file('_build_params')) }; + my %opt; + GetOptionsFromArray($_, \%opt, qw/install_base=s install_path=s% installdirs=s destdir=s prefix=s config=s% uninst:1 verbose:1 dry_run:1 pureperl-only:1 create_packlist=i jobs=i/) for ($env, $bargv, \@ARGV); + $_ = detildefy($_) for grep { defined } @opt{qw/install_base destdir prefix/}, values %{ $opt{install_path} }; + @opt{ 'config', 'meta' } = (ExtUtils::Config->new($opt{config}), get_meta()); + $actions{$action}->(%opt, install_paths => ExtUtils::InstallPaths->new(%opt, dist_name => $opt{meta}->name)); +} + +sub Build_PL { + my $meta = get_meta(); + printf "Creating new 'Build' script for '%s' version '%s'\n", $meta->name, $meta->version; + my $dir = $meta->name eq 'Module-Build-Tiny' ? "use lib 'lib';" : ''; + write_file('Build', "#!perl\n$dir\nuse Module::Build::Tiny;\nBuild();\n"); + make_executable('Build'); + my @env = defined $ENV{PERL_MB_OPT} ? split_like_shell($ENV{PERL_MB_OPT}) : (); + write_file('_build_params', encode_json([ \@env, \@ARGV ])); + $meta->save(@$_) for ['MYMETA.json'], [ 'MYMETA.yml' => { version => 1.4 } ]; +} + +1; + +#ABSTRACT: A tiny replacement for Module::Build + + +# vi:et:sts=2:sw=2:ts=2 + +__END__ + +=pod + +=encoding UTF-8 + +=head1 NAME + +Module::Build::Tiny - A tiny replacement for Module::Build + +=head1 VERSION + +version 0.039 + +=head1 SYNOPSIS + + use Module::Build::Tiny; + Build_PL(); + +=head1 DESCRIPTION + +Many Perl distributions use a Build.PL file instead of a Makefile.PL file +to drive distribution configuration, build, test and installation. +Traditionally, Build.PL uses Module::Build as the underlying build system. +This module provides a simple, lightweight, drop-in replacement. + +Whereas Module::Build has over 6,700 lines of code; this module has less +than 120, yet supports the features needed by most distributions. + +=head2 Supported + +=over 4 + +=item * Pure Perl distributions + +=item * Building XS or C + +=item * Recursive test files + +=item * MYMETA + +=item * Man page generation + +=item * Generated code from PL files + +=back + +=head2 Not Supported + +=over 4 + +=item * Dynamic prerequisites + +=item * HTML documentation generation + +=item * Extending Module::Build::Tiny + +=item * Module sharedirs + +=back + +=head2 Directory structure + +Your .pm and .pod files must be in F<lib/>. Any executables must be in +F<script/>. Test files must be in F<t/>. Dist sharedirs must be in F<share/>. + +=head1 USAGE + +These all work pretty much like their Module::Build equivalents. + +=head2 perl Build.PL + +=head2 Build [ build ] + +=head2 Build test + +=head2 Build install + +This supports the following options: + +=over + +=item * verbose + +=item * install_base + +=item * installdirs + +=item * prefix + +=item * install_path + +=item * destdir + +=item * uninst + +=item * config + +=item * pure-perl + +=item * create_packlist + +=back + +=head1 AUTHORING + +This module doesn't support authoring. To develop modules using Module::Build::Tiny, usage of L<Dist::Zilla::Plugin::ModuleBuildTiny> or L<App::ModuleBuildTiny> is recommended. + +=head1 CONFIG FILE AND ENVIRONMENT + +Options can be provided in the C<PERL_MB_OPT> environment variable the same way they can with Module::Build. This should be done during the configuration stage. + +=head2 Incompatibilities + +=over 4 + +=item * Argument parsing + +Module::Build has an extremely permissive way of argument handling, Module::Build::Tiny only supports a (sane) subset of that. In particular, C<./Build destdir=/foo> does not work, you will need to pass it as C<./Build --destdir=/foo>. + +=item * .modulebuildrc + +Module::Build::Tiny does not support .modulebuildrc files. In particular, this means that versions of local::lib older than 1.006008 may break with C<ERROR: Can't create /usr/local/somepath>. If the output of C<perl -Mlocal::lib> contains C<MODULEBUILDRC> but not C<PERL_MB_OPT >, you will need to upgrade it to resolve this issue. + +=back + +=head1 SEE ALSO + +L<Module::Build> + +=head1 AUTHORS + +=over 4 + +=item * + +Leon Timmermans <leont@cpan.org> + +=item * + +David Golden <dagolden@cpan.org> + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 2011 by Leon Timmermans, David Golden. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut diff --git a/t/00-compile.t b/t/00-compile.t new file mode 100644 index 0000000..956ec06 --- /dev/null +++ b/t/00-compile.t @@ -0,0 +1,50 @@ +use 5.006; +use strict; +use warnings; + +# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.040 + +use Test::More tests => 1 + ($ENV{AUTHOR_TESTING} ? 1 : 0); + + + +my @module_files = ( + 'Module/Build/Tiny.pm' +); + + + +# no fake home requested + +my $inc_switch = -d 'blib' ? '-Mblib' : '-Ilib'; + +use File::Spec; +use IPC::Open3; +use IO::Handle; + +open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!"; + +my @warnings; +for my $lib (@module_files) +{ + # see L<perlfaq8/How can I capture STDERR from an external command?> + my $stderr = IO::Handle->new; + + my $pid = open3($stdin, '>&STDERR', $stderr, $^X, $inc_switch, '-e', "require q[$lib]"); + binmode $stderr, ':crlf' if $^O eq 'MSWin32'; + my @_warnings = <$stderr>; + waitpid($pid, 0); + is($?, 0, "$lib loaded ok"); + + if (@_warnings) + { + warn @_warnings; + push @warnings, @_warnings; + } +} + + + +is(scalar(@warnings), 0, 'no warnings found') if $ENV{AUTHOR_TESTING}; + + diff --git a/t/lib/DistGen.pm b/t/lib/DistGen.pm new file mode 100644 index 0000000..eee7375 --- /dev/null +++ b/t/lib/DistGen.pm @@ -0,0 +1,602 @@ +package DistGen; + +use strict; + +our $VERSION = '0.01'; +our $VERBOSE = 0; + +use Carp; + +use Cwd (); +use File::Basename (); +use File::Find (); +use File::Path (); +use File::Spec (); +use File::Temp (); +use IO::File (); +use Data::Dumper (); +use Exporter 5.57 'import'; + +our @EXPORT_OK = qw(undent); + +sub undent { + my ($string) = @_; + + my ($space) = $string =~ m/^(\s+)/; + $string =~ s/^$space//gm; + + return($string); +} + +sub chdir_all ($) { + # 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; +} + +######################################################################## + +my $orig_cwd = Cwd::cwd; +END { chdir_all($orig_cwd); } + +sub new { + my $self = bless {}, shift; + $self->reset(@_); +} + +sub reset { + my $self = shift; + my %options = @_; + + $options{name} ||= 'Simple'; + $options{dir} ||= File::Spec->rel2abs(File::Temp::tempdir( + DIR => File::Spec->curdir, CLEANUP => 1 + )); + + my %data = ( + %options, + ); + %$self = %data; + + $self->{filedata} = {}; + $self->{pending}{change} = {}; + + # start with a fresh, empty directory + if ( -d $self->dirname ) { + warn "Warning: Removing existing directory '@{[$self->dirname]}'\n"; + 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; + + # TODO maybe a public method like this (but with a better name?) + my $add_unless = sub { + my $self = shift; + my ($member, $data) = @_; + $self->add_file($member, $data) unless($self->{filedata}{$member}); + }; + + $self->$add_unless('Build.PL', undent(<<" ---")); + use lib 'inc'; use Module::Build::Tiny;Build_PL(\@ARGV); + --- + + my $module_filename = + join( '/', ('lib', split(/::/, $self->{name})) ) . '.pm'; + + my $module_name = $self->{name}; + (my $dist_name = $module_name) =~ s/::/-/g; + + $self->$add_unless($module_filename, undent(<<" ---")); + package $module_name; + + use vars qw( \$VERSION ); + \$VERSION = '0.01'; + + use strict; + + use Carp 0 (); + + 1; + + __END__ + + =head1 NAME + + $module_name - Perl extension for blah blah blah + + =head1 DESCRIPTION + + Stub documentation for $module_name. + + =head1 AUTHOR + + A. U. Thor, a.u.thor\@a.galaxy.far.far.away + + =cut + --- + + $self->$add_unless('t/basic.t', undent(<<" ---")); + use Test::More 0.23 tests => 1; + use strict; + + use $module_name; + ok 1; + --- + + $self->$add_unless('META.yml', undent(<<" ----")); + --- + name: $dist_name + version: 0.001 + author: + - 'David Golden <dagolden\@cpan.org>' + - 'Leon Timmermans <leont\@cpan.org>' + abstract: 'A testing dist' + license: perl + requires: + perl: 5.006 + Module::Build::Tiny: 0 + generated_by: Leon Timmermans + dynamic_config: 0 + meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 + ---- +} + +sub name { shift()->{name} } + +sub dirname { + my $self = shift; + my $dist = join( '-', split( /::/, $self->{name} ) ); + return File::Spec->catdir( $self->{dir}, $dist ); +} + +sub _real_filename { + my $self = shift; + my $filename = shift; + return File::Spec->catfile( split( /\//, $filename ) ); +} + +sub regen { + my $self = shift; + my %opts = @_; + + my $dist_dirname = $self->dirname; + + if ( $opts{clean} ) { + $self->clean() if -d $dist_dirname; + } else { + # TODO: This might leave dangling directories; e.g. if the removed file + # is 'lib/Simple/Simon.pm', the directory 'lib/Simple' will be left + # even if there are no files left in it. However, clean() will remove it. + my @files = keys %{$self->{pending}{remove}}; + foreach my $file ( @files ) { + my $real_filename = $self->_real_filename( $file ); + my $fullname = File::Spec->catfile( $dist_dirname, $real_filename ); + if ( -e $fullname ) { + 1 while File::Path::rmtree($fullname, 0, 0); + } + print "Unlinking pending file '$file'\n" if $VERBOSE; + delete( $self->{pending}{remove}{$file} ); + } + } + + foreach my $file ( keys( %{$self->{filedata}} ) ) { + my $real_filename = $self->_real_filename( $file ); + my $fullname = File::Spec->catfile( $dist_dirname, $real_filename ); + + if ( ! -e $fullname || + ( -e $fullname && $self->{pending}{change}{$file} ) ) { + + print "Changed file '$file'.\n" if $VERBOSE; + + my $dirname = File::Basename::dirname( $fullname ); + unless ( -d $dirname ) { + File::Path::mkpath( $dirname ) or do { + die "Can't create '$dirname'\n"; + }; + } + + if ( -e $fullname ) { + 1 while unlink( $fullname ); + } + + my $fh = IO::File->new(">$fullname") or do { + die "Can't write '$fullname'\n"; + }; + print $fh $self->{filedata}{$file}; + close( $fh ); + } + + delete( $self->{pending}{change}{$file} ); + } + + return $self; +} + +sub clean { + my $self = shift; + + my $here = Cwd::abs_path(); + my $there = File::Spec->rel2abs( $self->dirname() ); + + if ( -d $there ) { + chdir( $there ) or die "Can't change directory to '$there'\n"; + } else { + die "Distribution not found in '$there'\n"; + } + + my %names; + foreach my $file ( keys %{$self->{filedata}} ) { + my $filename = $self->_real_filename( $file ); + my $dirname = File::Basename::dirname( $filename ); + + $names{$filename} = 0; + + print "Splitting '$dirname'\n" if $VERBOSE; + my @dirs = File::Spec->splitdir( $dirname ); + while ( @dirs ) { + my $dir = ( scalar(@dirs) == 1 + ? $dirname + : File::Spec->catdir( @dirs ) ); + if (length $dir) { + print "Setting directory name '$dir' in \%names\n" if $VERBOSE; + $names{$dir} = 0; + } + pop( @dirs ); + } + } + + File::Find::finddepth( sub { + my $name = File::Spec->canonpath( $File::Find::name ); + + if ( not exists $names{$name} ) { + print "Removing '$name'\n" if $VERBOSE; + File::Path::rmtree( $_ ); + } + }, File::Spec->curdir ); + + + chdir_all( $here ); + return $self; +} + +sub add_file { + my $self = shift; + $self->change_file( @_ ); +} + +sub remove_file { + my $self = shift; + my $file = shift; + unless ( exists $self->{filedata}{$file} ) { + warn "Can't remove '$file': It does not exist.\n" if $VERBOSE; + } + delete( $self->{filedata}{$file} ); + $self->{pending}{remove}{$file} = 1; + return $self; +} + +sub change_file { + my $self = shift; + my $file = shift; + my $data = shift; + $self->{filedata}{$file} = $data; + $self->{pending}{change}{$file} = 1; + return $self; +} + +sub get_file { + my $self = shift; + my $file = shift; + exists($self->{filedata}{$file}) or croak("no such entry: '$file'"); + return $self->{filedata}{$file}; +} + +sub chdir_in { + my $self = shift; + $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 { exists shift()->{original_dir} } + +######################################################################## + +sub chdir_original { + my $self = shift; + + my $dir = delete $self->{original_dir}; + chdir_all($dir) or die "Can't chdir to '$dir': $!"; + return $self; +} +######################################################################## + +1; + +# vim:ts=2:sw=2:et:sta +__END__ + + +=head1 NAME + +DistGen - Creates simple distributions for testing. + +=head1 SYNOPSIS + + use DistGen; + + # create distribution and prepare to test + my $dist = DistGen->new(name => 'Foo::Bar'); + $dist->chdir_in; + + # change distribution files + $dist->add_file('t/some_test.t', $contents); + $dist->change_file('MANIFEST.SKIP', $new_contents); + $dist->remove_file('t/some_test.t'); + $dist->regen; + + # undo changes and clean up extraneous files + $dist->revert; + $dist->clean; + + # start over as a new distribution + $dist->reset( name => 'Foo::Bar' ); + $dist->chdir_in; + +=head1 USAGE + +A DistGen object manages a set of files in a distribution directory. + +The C<new()> constructor initializes the object and creates an empty +directory for the distribution. It does not create files or chdir into +the directory. The C<reset()> 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<not> +make any changes to the filesystem: + + add_file + change_file + change_build_pl + remove_file + revert + +Other methods then change the filesystem to match the target state of +the distribution: + + clean + regen + remove + +Other methods are provided for a convenience during testing. The +most important is the one to enter the distribution directory: + + chdir_in + +=head1 API + +=head2 Constructors + +=head3 new() + +Create a new object and an empty directory to hold the distribution's files. +If no C<dir> option is provided, it defaults to MBTest->tmpdir, which sets +a different temp directory for Perl core testing and CPAN testing. + +The C<new> method does not write any files -- see L</regen()> below. + + my $dist = DistGen->new( + name => 'Foo::Bar', + dir => MBTest->tmpdir, + ); + +The parameters are as follows. + +=over + +=item name + +The name of the module this distribution represents. The default is +'Simple'. This should be a "Foo::Bar" (module) name, not a "Foo-Bar" +dist name. + +=item dir + +The (parent) directory in which to create the distribution directory. The +distribution will be created under this according to the "dist" form of C<name> +(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 + +=back + +The following files are added as part of the default distribution: + + Build.PL + lib/Simple.pm # based on name parameter + t/basic.t + +The C<reset> method re-initializes the object as if it were generated +from a fresh call to C<new>. It takes the same optional parameters as C<new>. + + $dist->reset( name => 'Foo::Bar', xs => 0 ); + +=head2 Adding and editing files + +Note that C<$filename> should always be specified with unix-style paths, +and are relative to the distribution root directory, e.g. C<lib/Module.pm>. + +No changes are made to the filesystem until the distribution is regenerated. + +=head3 add_file() + +Add a $filename containing $content to the distribution. + + $dist->add_file( $filename, $content ); + +=head3 change_file() + +Changes the contents of $filename to $content. No action is performed +until the distribution is regenerated. + + $dist->change_file( $filename, $content ); + +=head3 change_build_pl() + +A wrapper around change_file specifically for setting Build.PL. Instead +of file C<$content>, it takes a hash-ref of Module::Build constructor +arguments: + + $dist->change_build_pl( + { + module_name => $dist->name, + dist_version => '3.14159265', + license => 'perl', + create_readme => 1, + } + ); + +=head3 get_file + +Retrieves the target contents of C<$filename>. + + $content = $dist->get_file( $filename ); + +=head3 remove_file() + +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. + +=head3 regen() + +Regenerate all missing or changed files. Also deletes any files +flagged for removal with remove_file(). + + $dist->regen(clean => 1); + +If the optional C<clean> argument is given, it also calls C<clean>. These +can also be chained like this, instead: + + $dist->clean->regen; + +=head3 clean() + +Removes any files that are not part of the distribution. + + $dist->clean; + +=head3 remove() + +Changes back to the original directory and removes the distribution +directory (but not the temporary directory set during C<new()>). + + $dist = DistGen->new->chdir->regen; + # ... do some testing ... + + $dist->remove->chdir_in->regen; + # ... do more testing ... + +This is like a more aggressive form of C<clean>. Generally, calling C<clean> +and C<regen> should be sufficient. + +=head2 Changing directories + +=head3 chdir_in + +Change directory into the dist root. + + $dist->chdir_in; + +=head3 chdir_original + +Returns to whatever directory you were in before chdir_in() (regardless +of the cwd.) + + $dist->chdir_original; + +=head2 Command-line helpers + +These use Module::Build->run_perl_script() to ensure that Build.PL or Build are +run in a separate process using the current perl interpreter. (Module::Build +is loaded on demand). They also ensure appropriate naming for operating +systems that require a suffix for Build. + +=head2 Properties + +=head3 name() + +Returns the name of the distribution. + + $dist->name: # e.g. Foo::Bar + +=head3 dirname() + +Returns the directory where the distribution is created. + + $dist->dirname; # e.g. t/_tmp/Simple + +=head2 Functions + +=head3 undent() + +Removes leading whitespace from a multi-line string according to the +amount of whitespace on the first line. + + my $string = undent(" foo(\n bar => 'baz'\n )"); + $string eq "foo( + bar => 'baz' + )"; + +=cut + diff --git a/t/release-pod-syntax.t b/t/release-pod-syntax.t new file mode 100644 index 0000000..cdd6a6c --- /dev/null +++ b/t/release-pod-syntax.t @@ -0,0 +1,14 @@ +#!perl + +BEGIN { + unless ($ENV{RELEASE_TESTING}) { + require Test::More; + Test::More::plan(skip_all => 'these tests are for release candidate testing'); + } +} + +# This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. +use Test::More; +use Test::Pod 1.41; + +all_pod_files_ok(); diff --git a/t/simple.t b/t/simple.t new file mode 100644 index 0000000..fe86c71 --- /dev/null +++ b/t/simple.t @@ -0,0 +1,137 @@ +#! perl +use strict; +use warnings; +use Config; +use ExtUtils::CBuilder; +use File::Spec::Functions 0 qw/catdir catfile/; +use IPC::Open2; +use Test::More 0.88; +use lib 't/lib'; +use DistGen qw/undent/; +use XSLoader; + +local $ENV{PERL_INSTALL_QUIET}; +local $ENV{PERL_MB_OPT}; + +#--------------------------------------------------------------------------# +# fixtures +#--------------------------------------------------------------------------# + +my $dist = DistGen->new(name => 'Foo::Bar'); +$dist->chdir_in; +$dist->add_file('share/file.txt', 'FooBarBaz'); +$dist->add_file('script/simple', undent(<<' ---')); + #!perl + use Foo::Bar; + print Simple->VERSION . "\n"; + --- +my $has_compiler = ExtUtils::CBuilder->new->have_compiler(); +$dist->add_file('lib/Simple.xs', undent(<<' ---')) if $has_compiler; + #define PERL_NO_GET_CONTEXT + #include "EXTERN.h" + #include "perl.h" + #include "XSUB.h" + + MODULE = Simple PACKAGE = Simple + + const char* + foo() + CODE: + RETVAL = "Hello World!\n"; + OUTPUT: + RETVAL + --- + +$dist->regen; + +my $interpreter = ($Config{startperl} eq $^X ) + ? qr/#!\Q$^X\E/ + : qr/(?:#!\Q$^X\E|\Q$Config{startperl}\E)/; +my ($guts, $ec); + +sub _mod2pm { (my $mod = shift) =~ s{::}{/}g; return "$mod.pm" } +sub _path2mod { (my $pm = shift) =~ s{/}{::}g; return substr $pm, 5, -3 } +sub _mod2dist { (my $mod = shift) =~ s{::}{-}g; return $mod; } +sub _slurp { do { local (@ARGV,$/)=$_[0]; <> } } + +#--------------------------------------------------------------------------# +# configure +#--------------------------------------------------------------------------# + +{ + is(system($^X, 'Build.PL', '--install_base=install'), 0, 'Ran Build.PL'); + ok( -f 'Build', "Build created" ); + if ($^O eq 'MSWin32') { + ok( -f 'Build.bat', 'Build is executable'); + } + else { + ok( -x 'Build', "Build is executable" ); + } + + open my $fh, "<", "Build"; + my $line = <$fh>; + + like( $line, qr{\A$interpreter}, "Build has shebang line with \$^X" ); + ok( -f '_build_params', "_build_params created" ); +} + +#--------------------------------------------------------------------------# +# build +#--------------------------------------------------------------------------# + +{ + ok( open2(my($in, $out), $^X, 'Build'), 'Could run Build' ); + my $output = do { local $/; <$in> }; + like( $output, qr{lib/Foo/Bar\.pm}, 'Build output looks correctly'); + ok( -d 'blib', "created blib" ); + ok( -d 'blib/lib', "created blib/lib" ); + ok( -d 'blib/script', "created blib/script" ); + + # check pm + my $pmfile = _mod2pm($dist->name); + ok( -f 'blib/lib/' . $pmfile, "$dist->{name} copied to blib" ); + is( _slurp("lib/$pmfile"), _slurp("blib/lib/$pmfile"), "pm contents are correct" ); + is((stat "blib/lib/$pmfile")[2] & 0222, 0, "pm file in blib is readonly" ); + + # check bin + ok( -f 'blib/script/simple', "bin/simple copied to blib" ); + like( _slurp("blib/script/simple"), '/' .quotemeta(_slurp("blib/script/simple")) . "/", "blib/script/simple contents are correct" ); + if ($^O eq 'MSWin32') { + ok( -f "blib/script/simple.bat", "blib/script/simple is executable"); + } + else { + ok( -x "blib/script/simple", "blib/script/simple is executable" ); + } + is((stat "blib/script/simple")[2] & 0222, 0, "script in blib is readonly" ); + if ($^O ne 'MSWin32') { + open my $fh, "<", "blib/script/simple"; + my $line = <$fh>; + like( $line, qr{\A$interpreter}, "blib/script/simple has shebang line with \$^X" ); + } + + require blib; + blib->import; + if (eval { require File::ShareDir }) { + ok( -d File::ShareDir::dist_dir('Foo-Bar'), 'sharedir has been made'); + ok( -f File::ShareDir::dist_file('Foo-Bar', 'file.txt'), 'sharedir file has been made'); + } + ok( -d catdir(qw/blib lib auto share dist Foo-Bar/), 'sharedir has been made'); + ok( -f catfile(qw/blib lib auto share dist Foo-Bar file.txt/), 'sharedir file has been made'); + + if ($has_compiler) { + XSLoader::load('Simple'); + is(Simple::foo(), "Hello World!\n", 'Can run XSub Simple::foo'); + } +} + +{ + ok( open2(my($in, $out), $^X, Build => 'install'), 'Could run Build install' ); + my $output = do { local $/; <$in> }; + my $filename = catfile(qw/install lib perl5/, ($has_compiler? $Config{archname} : () ), qw/Foo Bar.pm/); + like($output, qr/Installing \Q$filename/, 'Build install output looks correctly'); + + ok( -f $filename, 'Module is installed'); + ok( -f 'install/bin/simple', 'Script is installed'); +} + +done_testing; |