miyagawa / cpanminus

cpanminus - get, unpack, build and install modules from CPAN
http://cpanmin.us
746 stars 213 forks source link

Order of dependency installation #649

Open rlauer6 opened 1 year ago

rlauer6 commented 1 year ago

The order of dependency installation is random and can lead to problems when a specific version of a module is required. Example:

suppose I require version 0.04 of some module Foo, the latest version of Foo being > 0.04 ...now suppose another one of my dependencies Bar requires ANY version of Foo ...if Bar is installed before my explicit callout of the required Foo, then Bar's requirement of Foo will be satisfied by installing the latest version of Foo, not the one I specified in my manifest.

To correct this would it not be possible to:

...or maybe there is some other way to handle this situation?

miyagawa commented 1 year ago

then Bar's requirement of Foo will be satisfied by installing the latest version of Foo, not the one I specified in my manifest.

What do you mean by "I specified in my manifest" and how do you specify it?

In general, cpanminus supports pinning to a specific version of a module in cpanfile using ==, and the dependency resolver should consider what's specified in the top level cpanfile.

# cpanfile
requires 'Foo', '== 0.04';
requires 'Bar';

if a dependency requires a specific version of a module AND a different version of that module is specified in the manifest, error out with a conflict

again, I believe cpanminus does support this if you specify them in cpanfile. If that's not the case you might want to try Carmel instead.

rlauer6 commented 1 year ago

then Bar's requirement of Foo will be satisfied by installing the latest version of Foo, not the one I specified in my manifest.

What do you mean by "I specified in my manifest" and how do you specify it?

In general, cpanminus supports pinning to a specific version of a module in cpanfile using ==, and the dependency resolver should consider what's specified in the top level cpanfile.

# cpanfile
requires 'Foo', '== 0.04';
requires 'Bar';

if a dependency requires a specific version of a module AND a different version of that module is specified in the manifest, error out with a conflict

again, I believe cpanminus does support this if you specify them in cpanfile. If that's not the case you might want to try Carmel instead.

I should have specified that the version is specified in the PREREQ_PM hash in Makefile.PL (which is why they are being installed in a random order). I was using cpanm against a CPAN distribution.

miyagawa commented 1 year ago

I should have specified that the version is specified in the PREREQ_PM hash in Makefile.PL (which is why they are being installed in a random order).

The installation order is also random if you specify them in cpanfile, but the requirements specified in there is kept as a global context, to start walking down the requirements.

I was using cpanm against a CPAN distribution.

Right, stable version pinning is only supported if they're specified from the root level using cpanfile - they might be specified as part of the dependency chain, but as you describe, that depends on the order of dependency resolution tree. Otherwise, cpanm would need to do a two-pass of requirement resolution, by first examining all the configuration + requirements scanning, before actually building and installing the modules, which is not supported.

I recommend extracting these pinned requirements to a cpanfile so that cpanm can know which version of the module you need before the resolution even begins.

Also, Carmel has a nice way to handle all this in a version controlled manner and is definitely worth a look.

rlauer6 commented 1 year ago

I should have specified that the version is specified in the PREREQ_PM hash in Makefile.PL (which is why they are being installed in a random order).

The installation order is also random if you specify them in cpanfile, but the requirements specified in there is kept as a global context, to start walking down the requirements.

I was using cpanm against a CPAN distribution.

Right, stable version pinning is only supported if they're specified from the root level using cpanfile - they might be specified as part of the dependency chain, but as you describe, that depends on the order of dependency resolution tree. Otherwise, cpanm would need to do a two-pass of requirement resolution, by first examining all the configuration + requirements scanning, before actually building and installing the modules, which is not supported.

I recommend extracting these pinned requirements to a cpanfile so that cpanm can know which version of the module you need before the resolution even begins.

Also, Carmel has a nice way to handle all this in a version controlled manner and is definitely worth a look.

Thank you so much for your insight and suggestions...and thank you for such a useful tool.

P.S. As a CPAN author we don't always know how our modules will be installed...so users wishing to use CPAN modules will need to be aware of various these types of issues I would imagine.