Adam Kennedy wrote:
>Modules don't declare dependencies on distributions, and never have.

True.  But it's distributions that have the optional_features.

>They declare dependencies on APIs, described as namespace/version pairs.

So to fit in with this system, we could arrange for each optional feature
of a distribution to be reified as a module.  Consider the case I ran
into, where I want to declare a dependency on the C language support
aspects of Module::Build.  We can name this "Module::Build::C_support",
or something similar.  There'd be a Module-Build-C_support distribution,
with a META.yml containing

    name: Module-Build-C_support
    version: 0.01
    requires:
      Module::Build: 0
      ExtUtils::CBuilder: 0.15
    provides:
      Module::Build::C_support:
        file: C_support.pm
        version: 0.01

C_support.pm could almost be an empty file.  It would only ever be
"use"d or "require"d in order to check its existence and version number.
It would contain roughly

    package Module::Build::C_support;
    our $VERSION = "0.01";
    1;

It could also have some POD to explain the arrangement, of course.
It could additionally load the prerequisite modules, to act as a (minimal)
runtime dependency test:

    package Module::Build::C_support;
    use Module::Build;
    use ExtUtils::CBuilder 0.15;
    our $VERSION = "0.01";
    1;

Then the Crypt-MySQL distribution can declare, perhaps automagically:

    build_requires:
      Module::Build: 0
      Module::Build::C_support: 0

This would express all the dependency relationships correctly,
without Crypt-MySQL needing to know the internals of Module::Build.
The dependencies would also be understood and correctly processed
by today's CPAN.pm.  The (only?) downside is having an extra, small,
distribution on CPAN for each optional feature.

>                          (because configure_requires isn't quite ready for
>prime time yet).

I think you're referring here to something else I was wondering about
dependencies.  build_requires declares things that are required at the
time of running ./Build; is there any way to declare things that must
be installed before running ./Build.PL?  Is that what configure_requires
is for?

I have a module, Time::UTC::Now, that needs to experimentally compile
some C code in order to determine which interfaces are available for the
main XS code to use.  Currently it does this probing in Makefile.PL.
Translating into Module::Build, I'd need ExtUtils::CBuilder present
before Build.PL could run successfully.

Incidentally, on reflection I think the `optional features' of
my numeric modules are actually best handled as a "conflicts".
That is, Date::ISO8601 does not really depend on Math::BigInt>=1.64
(as it currently declares), but it conflicts with Math::BigInt<1.64.
META.yml solves a problem for me there.

I noticed a problem in the definition of the "conflicts" section of
META.yml.  Hypothetically, suppose that my Date::ISO8601 module could
work with any Math::BigInt from 1.64 on *except* for 1.70.  In reality
there is no such exception, but the version syntax of META.yml allows
for such, because I can declare the positive dependency thus:

    requires:
      Math::BigInt: >=1.64, !=1.70

But how would I declare this in the negative form?  I essentially want
to do

    conflicts:
      Math::BigInt: <1.64
      Math::BigInt: ==1.70

but of course I can't duplicate the "Math::BigInt" key.  I would need
a logical-OR syntax:

    conflicts:
      Math::BigInt: <1.64 or ==1.70

-zefram

Reply via email to