Selasa, 10 November 2009

Dist::Zilla for Module::Starter Users: A 2-Minute Guide

So you're a module author. You typically do this when starting a new distribution:

$ module-starter --module=Foo::Bar --author="Your Name" --email="you@example.com"

and then hack away under the resulting Foo-Bar directory. Easy enough right?

Problems are:

  • too much generated boilerplate code and text;
  • lack of automation for the building and release process.


I'm sure you have experienced one or more of these:

  • Having to search+replace copyright year in every file;
  • Forgetting to "make clean" or remove backup files before creating tarball;
  • Forgetting to update MANIFEST;
  • Feeling tired and bored of all the tedious and laborious tasks;
  • Wondering if there is a better way.


You need a distribution builder like Dist::Zilla. It helps:

  • eliminate a lot of duplicate text;
  • automate updating MANIFEST;
  • automate generating README;
  • build tarball;
  • automate a lot of other stuffs;
  • upload to CPAN;
  • and more.


Dist::Zilla is flexible and has a lot of plugin/plugin bundles, but it can be less straightforward to use it. Here's a simple step-by-step guide you can follow.



  1. Install these modules from CPAN:


    • Dist::Zilla
    • Dist::Zilla::Plugin::PodWeaver
    • Dist::Zilla::Plugin::ReadmeFromPod


  2. Create ~/.dzil/config.ini, containing:

    [!new]
    author = Your Name
    copyright_holder = Your Name
    initial_version = 0.01

    [!release]
    user = YOUR-PAUSE-ID
    password = YOUR-PAUSE-PASSWORD


  3. Now, instead of using module-starter, you run dzil new to start your new distribution:

    $ dzil new Foo-Bar

    Instead of a bunch of files under Foo-Bar/, there's now just one file, dist.ini:

    name = Foo-Bar
    version = 0.01
    author = youruser
    license = Perl_5
    copyright_holder = youruser

    [@Classic]


    There's currently a small bug in Dist::Zilla not supplying the correct author/copyright_holder, so edit dist.ini, as well as for adding some lines:

    name = Foo-Bar
    version = 0.01
    author = Your Name <you@example.com>
    license = Perl_5
    copyright_holder = Your Name

    [@Classic]
    [PodWeaver]
    [ReadmeFromPod]


  4. Create the most basic distribution structure:

    $ mkdir -p lib/Foo t

    Put some test files into t/. Default tests generated from module-starter like 00-load.t might be a good start.

    Create Changes file. You can copy paste from the one generated by module-starter:

    0.01    2009-11-11
    First version, released on an unsuspecting world.


    As for lib/Foo/Bar.pm, here's what I use for template. You can just fill out the [[...]] parts:

    package Foo::Bar;
    # ABSTRACT: [[Abstract of module]]

    use strict;
    use warnings;

    [[YOUR CODE]]

    1;
    __END__
    =head1 SYNOPSIS

    [[YOUR SYNOPSIS]]
    =head1 DESCRIPTION

    [[YOUR DESCRIPTION]]

    =cut


    It's much simpler and shorter than what module-starter generates. Some POD sections like VERSION, NAME, AUTHOR, LICENSE AND COPYRIGHT are deliberately omitted. They will be generated by Dist::Zilla later when building the distro.

  5. Hack away. Write your code in lib/Foo/Bar.pm. Add some tests in t/. Add other files when needed.

  6. To test the distribution, run dzil test.

  7. To build the distribution, run dzil build. This will create Foo-Bar-0.01.tar.gz which contains all the necessary goodies of a standard classic distribution, like README, LICENSE, MANIFEST, META.yml, etc.

  8. To release the distribution, run dzil release. This will upload your module to CPAN. Sweet!

  9. To release a new distribution, just update version number in dist.ini and $VERSION in your main module file. Don't forget to add an entry to Changes. Repeat dzil test, build, release.


In the future "dzil new" might allow creating a more complete skeleton.

There are lots of other nice things Dist::Zilla can do for you, like checking Changes file, do automatic version numbering, etc. Welcome to the nice world of Dist::Zilla!

Comments/corrections are welcome.

7 komentar:

  1. You could skip our $VERSION from your code... dzil build will fill that in later and make sure they are consistent.

    As a second bonus, it also helps with source control systems, if you need to merge branches with different versions, one less conflict.

    BalasHapus
  2. When the "more complete skeleton" is added it will be no-brainer to switch.

    BalasHapus
  3. Currently I use my Makefile.PL to manage project dependencies. For example, if I need a new project dependency, I add it to the Makefile.PL and then from the command prompt I do:

    perl Makefile.PL
    make installdeps
    make veryclean

    and all that works well with Module::Install and local::lib to help isolate and validate that my project dependencies are correct. How could I do similar with Dist::Zilla?

    BalasHapus
  4. @evZh.8gAt5qa1xDbY_dE.iSYdbI-: Dist::Zilla will create your Makefile.PL for you. To add a dependency, put this in dist.ini:

    [Prereq]
    Module::Name = 0.1
    Other::Module::Name = 0

    BalasHapus
  5. Hey, I didn't know there was a bug in 'dzil new'!

    I just fixed it.

    Also, you can use ! to mean "a command" in your config, so:

    [!new]
    default_license = GPL3

    BalasHapus
  6. Thanks for fixing the bug, Ricardo. Post updated.

    BalasHapus