The Main Problem With CPAN Modules On Github

....Or, this entry is better titled as "Use cpanfile, and make sure to add it to your repository"

UPDATE: read miyagawa's comment (note, this linked comment has the summary, but make sure to read the others), and his blog post please.


This is a tongue-in-cheek addendum to being able to do `cpanm $git_url` described in "Dont' release experiments to CPAN".

The truth is "no, I really don't think there's a problem with CPAN modules github", but I do think you could make life easier for people trying to do `cpanm $git_url`.

Namely: use cpanfile and cpanm 1.6, which supports

  1. build_requires / configure_requires equivalent, and
  2. version range specification, including exact version match, not "at least version X"

The reason I say this is because when you do `cpanm $git_url` on modules without META.yml or cpanfile, your installation process barfs if you don't have the modules required to run Makefile.PL / Build.PL. For example, I see a lot of github issues claiming that modules using Module::Install (and its plugins) failed to install via github. This works if you're downloading the complete tarball from CPAN because then you presumably included all the files in inc/, but you usually don't include this directory in your repository.

With cpanfile, you can declare this dependency in the `on configure` section:


... your other prerequisites ...
on configure => sub {
     requires 'Module::Install';
     requires 'Module::Install::Repository';
     requires 'Module::Install::ReadmeFromPod';
};

When this included, cpanm 1.6+ with "--installdeps" option will just pick it up and do the right thing.

Here I described a common problem with Module::Install, but this may happen if you use other pluggable mechanism. It also strikes me as odd that with perl the build process must be run to detect prerequisites for the build process... (what?! what am I saying?), thus I believe that prerequisites should be declared separately from the build process, and hence cpanfile.

Note: META.yml is fine, except you have zero dynamic configuration. cpanfile allows you to specify dependencies separately AND it can be dynamic.

So let's put cpanfile on all our repositories, and when you have dependencies on experimental stuff, why not just specify the repository url:


requires "MyExperimental::Module" => "git://github.com/lestrrat/p5-MyExperimental-Module.git";


And as a final note: Yes, I am guilty of not including cpanfile in all of my modules, but I'm getting to it one by one. Please file an issue if you encounter problems.


Happy cpanfiling, everybody.

15 Comments

It seems I am missing some background here.

Could you give a link where cpanfile is described? Where should one put it and what should be its content?

cpanfile is MIYAGAWA's file (format) for describing dependencies for Perl code, which is understood by cpanm and carton.

This slide deck is probably a better place to start since it gives a rationale for the format instead of a description of its details.

Perhaps I'm not following well enough, but the META.* file are where this information should be. Its annoying to maintain sometimes, but I always include those files in my git repo. Why? For this case, and so I can see the history of its evolution. Anyway, I don't see the need to add another meta file when the META.* files exist. Perhaps I'm wrong and someone will tell me.

Joel, I have the META files in .gitignore as the make dist generates them.


Seeing their history might be interesting but I think for that I could fetch the releases from CPAN.

About a year ago I was squawked at about this so I altered my dist.ini file to copy the generated Makefile.PL and put in it the repo, then I worked this approach into my release process.

The dist.ini file is here: https://github.com/alnewkirk/Validation-Class/blob/master/dist.ini

lestrrat: good article. One thing to note though, while adding Module::Install to configure dependencies would work *as a workaround*, i don't think it's right to have them once shipped to CPAN, because they'll be bundled in inc/ and not necessary.

This will be fixed once cpanm decides to pull in devel requires from cpanfile/META.yml if it tries to install "devel" environment i.e. git repo or local directory. I plan to fix it before the next major release of cpanm, 1.7.
https://gist.github.com/miyagawa/5028262
https://github.com/miyagawa/cpanminus/issues/205

Joel Burger: you don't *need to* maintain another cpanfile if you decide to commit META.yml for every update in the git, but cpanfile is specifically to address the need of a) managing your *app* dependencies without dealing with CPAN build tools b) installing a module from git without dumping META.yml every time.

It also comes with a nice Module::Install-like DSL, which is much easier to write than dealing with Makefile.PL/Build/PL directly, and also have the complete support for Meta spec, which isn't available in Module::Install for example.

I know dist.ini can do the same thing, but my point is again a) deps management for Perl *apps* (not dists) and b) the ability to bootstrap from git (without knowing specifically how to build dzil modules)

https://speakerdeck.com/miyagawa/cpanfile
https://gist.github.com/miyagawa/5028262

Just to be clear - there's nothing wrong with dumping META.yml in the repo and remembering to do so for every release. cpanm will understand that and it will pull in the required configure dependencies.

(But as I stated in the reply to lestrrat, having configure_deps for build tools like M::I/Dist::Zilla is wrong, because it's not necessary once shipped to CPAN)

cpanfile is a convenient format to have the canonical information about CPAN deps of your apps/modules that are not in CPAN-compat format (yet), and nothing else.

Everyone who gets it seems to like it :) I haven't promoted the format enough since i first announced at LPW 2011, particularly because my build tools (cpanm, carton) haven't had the full support for that yet. With cpanm 1.6 released and carton 1.0 in the pipeline, i will need to give a new talk in more conferences to promote that.

Once again, this is opt-in and not a requirement at all for CPAN authors. Using cpanfile (as a CPAN author) will still work with standard CPAN installers through the use of META->MYMETA compat layer such as Module::Install::CPANFile or Module::Build::Pluggable::CPANFile.

It's similar to how dzil users manage deps in dist.ini (or auto-extracted from scanner, which I'm not a big fan of), but dump META.yml when shipped to CPAN.

@lestrrat

While this is a good blog post, I don't think the use of cpanfile to stick git deps for your CPAN module is the primary purpose. cpanfile is for apps to pin CPAN deps without dealing with the MakeMaker or Build at all.

The ability to manage CPAN deps in the git (without committing META) is an accidental, secondary feature. Even yet, using `configure` phase for the build tools is wrong, and I hope we can switch to develop sooner.

Apologies for flooding comments.

I guess I'm in the dwindling minority of people who don't mind hand-crafting a Build.PL file. I should do well to remember that.

I really like the concept of cpanfile for non-CPAN projects, I agree that having a "fake" Makefile.PL just to be able to do cpanm --installdeps on it is unnecessary.

That said, for projects destined for CPAN, part of the reason that I still prefer a real Build.PL and associated vagaries, rather than dzil or other author-side build tools is that being close to the actual releasable dist allows others to jump in with less cognitive dissonance. The oddities of my dist.ini are not involved, there is no magic. My git repo is almost what you get from CPAN. I understand that's not for everyone, but I like it and I like when I go to contribute to some other project when I can jump in an work with no barrier. Then again, I'm sure other prefer cpanfile or dist.ini to Build.PL. Oh well.

Cheers

Joel Burger:
> rather than dzil or other author-side build tools is that being close to the actual releasable dist allows others to jump in with less cognitive dissonance.

That's exactly my point :)

> Then again, I'm sure other prefer cpanfile or dist.ini to Build.PL. Oh well.

It makes me giggle reading your comment, because you know what, my next target is to integrate LeonT's Module::Build::Tiny to work well with cpanfile, so that you have a real Build.PL in the repo that works transparently with cpanfile + MYMETA protocol, to get the best of both worlds :)

Above, you describe syntax for pointing a cpanfile to git. The end of the line is cut off, unfortunately:
requires "MyExperimental::Module" => "git://github.com/lestrrat/p5-MyExp

Do you know if this still works for cpanm and/or Carton, and what the proper syntax is for it? cpanm keeps trying to read the url as a version number, no matter how I enter it.

Leave a comment

About lestrrat

user-pic Japan Perl Association director; LINE, Inc; Tokyo, Japan