Skip to content

fix(makemaker): mirror upstream prereq check (no false "have 0")#575

Merged
fglock merged 1 commit intomasterfrom
fix/makemaker-prereq-check-mirror-cpan
Apr 27, 2026
Merged

fix(makemaker): mirror upstream prereq check (no false "have 0")#575
fglock merged 1 commit intomasterfrom
fix/makemaker-prereq-check-mirror-cpan

Conversation

@fglock
Copy link
Copy Markdown
Owner

@fglock fglock commented Apr 27, 2026

Summary

Fixes a misleading dependency-check report in PerlOnJava's ExtUtils::MakeMaker shim and aligns the prereq logic with upstream MakeMaker (Perl 5.42 / MakeMaker 7.76).

Problem

jcpan -t ACME::Error::Coy was printing a self-contradictory configure block:

PerlOnJava MakeMaker: ACME::Error::Coy v0.01
============================================================

Missing dependencies:
  - Coy (>= 0.01, have 0)

Please install these modules first.
(PerlOnJava uses bundled modules or pure Perl CPAN modules)


Will install to: /Users/fglock/.perlonjava/lib
  Coy.pm -> /Users/fglock/.perlonjava/lib/ACME/Error/Coy.pm

============================================================
Configured! 1 files will be installed when 'make install' runs.

Root cause: _check_prereqs did eval "require Coy; 1" and then read $Coy::VERSION. CPAN.pm sets PERL_USE_UNSAFE_INC=1 so . is on @INC. The cwd at configure time is the ACME-Error-Coy build directory, which contains a file literally named Coy.pm — but it declares package ACME::Error::Coy. require Coy happily loads the wrong file, %INC records Coy.pm, but $Coy::VERSION stays undef, so the check reports have 0. Coy is in fact not installed at all.

What real Perl does

System Perl's ExtUtils::MakeMaker (5.42, MakeMaker 7.76, lines ~579-647) does not require prereqs. It uses:

  • MM->_installed_file_for_module($prereq) — file-path search of @INC for Foo/Bar.pm.
  • MM->parse_version($installed_file) — static parse of $VERSION = ... from the file.

Reporting:

  • File missing → warn "Warning: prerequisite Foo 1.0 not found.\n" and continue.
  • Version too low → warn "Warning: prerequisite Foo 1.0 not found. We have 0.5.\n" and continue.
  • MakeMaker FATAL: prerequisites not found.\n... Please install these modules first and rerun 'perl Makefile.PL'. — only on PREREQ_FATAL.

I confirmed system Perl on the same build dir is silent (parse_version returns 0.01 from the misnamed file, so the check looks satisfied; CPAN.pm independently catches the real missing dep via its own metadata).

Fix

src/main/perl/lib/ExtUtils/MakeMaker.pm:

  • Add _installed_file_for_module mirroring upstream (skipping @INC code/array/blessed hooks).
  • Rewrite _check_prereqs to use file-path search + MM->parse_version, never require.
  • Emit per-module Warning: prerequisite Foo X not found. / ... We have Y. to STDERR with the upstream wording.
  • Drop the unconditional Missing dependencies / Please install these modules first banner that contradicted the subsequent Configured! line.
  • Honor PREREQ_FATAL and die with the upstream message.
  • Aggregate BUILD_REQUIRES, CONFIGURE_REQUIRES, TEST_REQUIRES the same way upstream does.

After

$ jcpan -t ACME::Error::Coy
...
PerlOnJava MakeMaker: ACME::Error::Coy v0.01
Configured! 1 files will be installed when 'make install' runs.
PerlOnJava MakeMaker: Coy v0.06
Configured! 2 files will be installed when 'make install' runs.
...
Result: PASS

CPAN.pm's own dependency resolution (the ---- Unsatisfied dependencies detected ---- mechanism) still drives the actual Coy build.

Test plan

  • make (build + unit tests): green
  • jcpan -t ACME::Error::Coy end-to-end on a freshly cleaned ~/.cpan/build: configure clean, no false have 0, both modules tested, exit 0
  • Manual Makefile.PL with a non-existent prereq: prints Warning: prerequisite NoSuchModuleZZZ 1.0 not found. and continues
  • Same with PREREQ_FATAL => 1: prints the warning and dies with the upstream MakeMaker FATAL: ... Please install these modules first and rerun 'perl Makefile.PL'. message
  • Spot-checked behaviour against system perl Makefile.PL on the same tree — output now matches
  • make test-bundled-modules shows 2 pre-existing failures (Net-SSLeay/t/local/33_x509_create_cert.t, Text-CSV/t/55_combi.t) due to missing test helpers (./t/util.pl, Test::Net::SSLeay); unrelated to this change.

Generated with Devin

The PerlOnJava ExtUtils::MakeMaker stub used `eval "require $module"`
to verify PREREQ_PM, then read $Module::VERSION. That fails open in the
common CPAN scenario where PERL_USE_UNSAFE_INC=1 puts `.` on @inc and
the build directory contains a similarly-named .pm with a different
package (e.g. ACME-Error-Coy ships `Coy.pm` whose package is
`ACME::Error::Coy`). `require Coy` succeeds against that file, but
$Coy::VERSION is undef, so the check reported the misleading

  Missing dependencies:
    - Coy (>= 0.01, have 0)

  Please install these modules first.

even though the next line said "Configured! 1 files will be installed".

Real ExtUtils::MakeMaker (5.42 / 7.76, lines ~579-647 of the system
copy) uses `MM->_installed_file_for_module` (file-path search of @inc)
plus `MM->parse_version` (static parse of `$VERSION = ...`), never
`require`. With the same Makefile.PL system Perl silently considers
the prereq satisfied; CPAN.pm independently resolves the real Coy via
its own metadata.

This commit aligns _check_prereqs with upstream:
  - File-path search via _installed_file_for_module (skipping @inc
    code/array/blessed hooks).
  - parse_version on the found file instead of require + $VERSION.
  - Per-module `Warning: prerequisite Foo 1.0 not found.` /
    `... not found. We have X.` warnings via warn(), matching the
    upstream wording.
  - Drops the unconditional "Missing dependencies / Please install
    these modules first" banner that contradicted the subsequent
    "Configured!" message.
  - Adds PREREQ_FATAL handling that dies with the upstream message
    ("MakeMaker FATAL: prerequisites not found. ... Please install
    these modules first and rerun 'perl Makefile.PL'.").
  - Aggregates BUILD_REQUIRES / CONFIGURE_REQUIRES / TEST_REQUIRES the
    same way upstream does.

After: `jcpan -t ACME::Error::Coy` configures cleanly with no false
warning, tests still pass, and the CPAN.pm-driven Coy resolution is
unaffected.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@fglock fglock merged commit 56dddce into master Apr 27, 2026
2 checks passed
@fglock fglock deleted the fix/makemaker-prereq-check-mirror-cpan branch April 27, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant