How to add 'provides' metadata via Makefile.PL

Reading time: 3 minutes

My last post about PAUSE permission problems suggested to manually add a ‘provides’ field to your metadata files if PAUSE can’t determine what packages are in your distribution. I realized that people might not know how to do that, so this is a quick tutorial.

One reason PAUSE might not be able to find your package names is if you generate your .pm files for some reason. I’m going to use a super-simplified example distribution to show what to do.

Consider a distribution for a hypothetical “Acme::Provides” with these four files:

  • Makefile.PL — our distribution build tool
  • Provides.pm.PL — our module generator
  • t/00-load.t — a test that the built module can be loaded
  • MANIFEST — a listing of these four files

The Provides.pm.PL generates Acme/Provides.pm directly into the blib directory when make runs, so there is no .pm file hanging out in lib for PAUSE to examine.

When we run the Makefile.PL we get a Makefile that will generate the .pm file we need. We can see that it does so by running make and make test:

$ perl Makefile.PL
Checking if your kit is complete...
Looks good
Generating a Unix-style Makefile
Writing Makefile for Acme::Provides
Writing MYMETA.yml and MYMETA.json

$ make
"/Users/david/.plenv/versions/20.2t/bin/perl5.20.2" "-Iblib/arch" "-Iblib/lib" Provides.pm.PL blib/lib/Acme/Provides.pm

$ make test
PERL_DL_NONLAZY=1 "/Users/david/.plenv/versions/20.2t/bin/perl5.20.2" "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib/lib', 'blib/arch')" t/*.t
t/00-load.t .. ok
All tests successful.
Files=1, Tests=1,  0 wallclock secs ( 0.02 usr  0.01 sys +  0.01 cusr  0.00 csys =  0.04 CPU)
Result: PASS

We can build the distribution directory with make distdir:

$ make distdir
rm -rf Acme-Provides-0.01
"/Users/david/.plenv/versions/20.2t/bin/perl5.20.2" "-MExtUtils::Manifest=manicopy,maniread" \
                -e "manicopy(maniread(),'Acme-Provides-0.01', 'best');"
mkdir Acme-Provides-0.01
mkdir Acme-Provides-0.01/t
Generating META.yml
Generating META.json

Here is the generated Acme-Provides-0.01/META.json file (omitting ‘no_index’ and ‘prereqs’ fields for brevity):

{
   "abstract" : "Demonstration of adding provides metadata",
   "author" : [
      "David Golden <dagolden@cpan.org>"
   ],
   "dynamic_config" : 1,
   "generated_by" : "ExtUtils::MakeMaker version 7.04, CPAN::Meta::Converter version 2.150001",
   "license" : [
      "artistic_1"
   ],
   "meta-spec" : {
      "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
      "version" : "2"
   },
   "name" : "Acme-Provides",
   "release_status" : "stable",
   "version" : "0.01"
}

That doesn’t tell PAUSE about our generated module, so if we uploaded this distribution, it wouldn’t get indexed because we wouldn’t be claiming the package name “Acme::Provides” to match the distribution tarball name “Acme-Provides-0.01.tar.gz”.

However, we can use the META_ADD directive in the the Makefile.PL to add that information ourselves:

META_ADD => {
        provides => {
            'Acme::Provides' => {
                file => 'Provides.pm.PL',
                version => '0.01',
            },
        },
    },

Check out the revised file here: Makefile.PL.

Now, if we re-run Makefile.PL and regenerate the distribution directory with make distdir, we can see our ‘provides’ data added to the generated Acme-Provides-0.01/META.json file (again omitting ‘no_index’ and ‘prereqs’ fields for brevity):

{
   "abstract" : "Demonstration of adding provides metadata",
   "author" : [
      "David Golden <dagolden@cpan.org>"
   ],
   "dynamic_config" : 1,
   "generated_by" : "ExtUtils::MakeMaker version 7.04, CPAN::Meta::Converter version 2.150001",
   "license" : [
      "artistic_1"
   ],
   "meta-spec" : {
      "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
      "version" : "2"
   },
   "name" : "Acme-Provides",
   "provides" : {
      "Acme::Provides" : {
         "file" : "Provides.pm.PL",
         "version" : "0.01"
      }
   },
   "release_status" : "stable",
   "version" : "0.01"
}

Now, if we upload this distribution, PAUSE will see us claiming “Acme::Provides” and all should be well.

•      •      •

If you enjoyed this or have feedback, please let me know by or