Search code examples
perlversioncpan

Do all my perl module .pm files need a `$VERSION` definition?


I just added a new file to the PDL::IO::Touchstone distribution and noticed that CPAN's indexer says version is undef since $VERSION is missing:

     module : PDL::IO::MDIF
     version: undef
     in file: PDL-IO-Touchstone-1.009/lib/PDL/IO/MDIF.pm
     status : indexed

So ::MDIF does not have $VERSION but really it is the same as the distribution version as noted in Makefile.PL:

my %WriteMakefileArgs = (
   VERSION_FROM     => 'lib/PDL/IO/Touchstone.pm',
   ...
);

Questions:

  • So does this module within the distribution need a version?
  • If so, should the new module's $VERSION be maintained separately from $VERSION provided by VERSION_FROM in Makefile.PL?
    • I could do $VERSION = $PDL::IO::Touchstone::VERSION but not sure if CPAN will figure that out. Will it?

I looked around and found lots of discussion of versioning practices, but nothing about versions of modules within the same Perl distribution package. Please share what the best practice here should be, I'm new to Perl modules and this is the first 2-file distribution that I've pushed out.

I'm sure I'll update the primary file when releasing a new dist, but not sure if I'll remember to bump the version of other modules in the dist when they change. It would be nice if there is a low-maintenance option here.

Update

I tried the suggestion in some answers below. Neither of these work:

  • $VERSION = do { use PDL::IO::Touchstone; $PDL::IO::Touchstone::VERSION };

  • use PDL::IO::Touchstone; our $VERSION = $PDL::IO::Touchstone::VERSION;

This is the MDIF.pm file at github: https://github.com/KJ7LNW/perl-PDL-IO-Touchstone/blob/master/lib/PDL/IO/MDIF.pm#L22

CPAN still shows version: undef:

Status: Version parsing problem
===============================

     module : PDL::IO::MDIF
     version: undef
...

Ok, so who gets the checkmark... any other ideas?


Solution

  • I like to give all of my modules versions. It's not a requirement, but consider the user experience while trying to upgrade when they don't know anything, or very little, about how CPAN works. ikegami already gave the tl;dr for this.

    When you want to update a module from CPAN, the tool looks at that module's $VERSION (well VERSION sub). If that module doesn't have a version, that's undef. When CPAN.pm (or other tools maybe) looks to see if there is a more recent version, it does not find one it thinks is more recent because the latest version is also undef.

    A concrete example is Mojo::UserAgent. Mojolicious only versions the main module. The other modules do not have versions. I typically do a lot of web client stuff, so my work product doesn't care about the web server side of Mojo. People using some of my stuff might not even know there is a different part of Mojo aside from the client stuff (they might even know Perl).

    If I run cpan Mojo::UserAgent, it compares my currently installed version (undef) to the latest on CPAN (undef). This means that CPAN.pm guesses that I do not have something earlier than the latest available.

    $ cpan -D Mojo::UserAgent
    Mojo::UserAgent
    -------------------------------------------------------------------------
        (no description)
        S/SR/SRI/Mojolicious-9.28.tar.gz
        /usr/local/perls/perl-5.36.0/lib/site_perl/5.36.0/Mojo/UserAgent.pm
        Installed: undef
        CPAN:      undef  up to date
        Sebastian Riedel (SRI)
        kraihx@googlemail.com
    

    Now, I have this special knowledge that this distro does this. But someone merely using something I wrote with Mojo::UserAgent probably doesn't. If they need Mojolicious 8 to get particular CSS selectors then, how do they know that?

    Normally, you can specify a minimum version of a module:

    use File::Glob 8.0;
    

    I can't require a minimum version of Mojo::UserAgent:

    use Mojo::Usergent 8.0;
    

    I get a weird error (there are other import issues and design decisions going along with this):

    Can't locate 8.pm in @INC (@INC contains: ...)
    

    This isn't a big deal because Mojolicious is mostly self-contained, so I can specify its minimum version:

    use Mojolicious 8.0;
    

    But, I have to know how all of this works, how that distro works, and how Perl works to do that. For the casual user of my stuff who just wants to get work down, including modifying what I've done, they have to discover some lore to know this. They have to know how CPAN.pm or PAUSE decides what the latest version is, and so on.

    Furthermore, this is a problem for modules in a distribution that don't change and have no logical reason for a version bump. Well, they do because they have an implicit dependency on the main module that does have a version, but we're not in the habit of declaring that version. Consider, for example, some module that works with an API that has changed, but the meat of the change is in another module it uses. The module you use directly has not changed its literal text, but it can't work as is because the world is different. But, since the literal text in that file hasn't changed so we typically don't bump the version.

    Maybe we should declare that main module dependency, but that's a lot of work. It adds some seemingly gratuitous churn to files, which is annoying in repo history. Ah hell, now that I've thought of that, I need to fix this in some distros. Some-not all. I don't know. Something to think about.

    Of course, I can document all of this in the distro, script, or whatever. But we know that I can say it and they can read it and still not appreciate the importance. And, by this time we're a far way away from "just working".