jordansissel/fpm · error · FPM::InvalidPackageConfiguration
I don't know how to build #{name}. No Makefile.PL nor Build.
Error message
I don't know how to build #{name}. No Makefile.PL nor Build.PL found What it means
fpm's cpan source package only knows two Perl build systems: Module::Build (Build.PL) and ExtUtils::MakeMaker (Makefile.PL). After downloading and extracting the distribution tarball from CPAN/metacpan, it checks for those two files in the extracted root; if neither exists it raises FPM::InvalidPackageConfiguration with this message. The package name in the message is the CPAN distribution being built.
Source
Thrown at lib/fpm/package/cpan.rb:262
"-Mlocal::lib=#{build_path("cpan")}",
"Makefile.PL", "PREFIX=#{prefix}", "LIB=#{perl_lib_path}",
# Empty install_base to avoid local::lib being used.
"INSTALL_BASE=")
else
safesystem(attributes[:cpan_perl_bin],
"-Mlocal::lib=#{build_path("cpan")}",
"Makefile.PL", "PREFIX=#{prefix}",
# Empty install_base to avoid local::lib being used.
"INSTALL_BASE=")
end
make = [ "env", "PERL5LIB=#{build_path("cpan/lib/perl5")}", "make" ]
safesystem(*make)
safesystem(*(make + ["test"])) if attributes[:cpan_test?]
safesystem(*(make + ["DESTDIR=#{staging_path}", "install"]))
else
raise FPM::InvalidPackageConfiguration,
"I don't know how to build #{name}. No Makefile.PL nor " \
"Build.PL found"
end
# Fix any files likely to cause conflicts that are duplicated
# across packages.
# https://github.com/jordansissel/fpm/issues/443
# https://github.com/jordansissel/fpm/issues/510
glob_prefix = attributes[:cpan_perl_lib_path] || prefix
::Dir.glob(File.join(staging_path, glob_prefix, "**/perllocal.pod")).each do |path|
logger.debug("Removing useless file.",
:path => path.gsub(staging_path, ""))
File.unlink(path)
end
# Remove useless .packlist files and their empty parent folders
# https://github.com/jordansissel/fpm/issues/1179
::Dir.glob(File.join(staging_path, glob_prefix, "**/.packlist")).each do |path|View on GitHub (pinned to b6d77ba72a)
Solutions
- Download the tarball manually and inspect it (tar tzf Foo-1.00.tar.gz) to confirm whether Build.PL or Makefile.PL actually exists at the root
- Retry without --version (or with a different --version) so metacpan resolves a normal, complete release
- If the module has no supported build script, build/install it yourself (perl Makefile.PL && make install DESTDIR=...) and package the result with fpm -s dir -t deb
- Point --cpan-mirror at a complete mirror such as http://www.cpan.org/ to rule out a truncated download
Example fix
# before fpm -s cpan -t deb Some::Module --version 0.01 # 0.01 tarball lacks build scripts # after fpm -s cpan -t deb Some::Module # let metacpan pick a complete release # or package a manual install: # perl Makefile.PL && make && make install DESTDIR=/tmp/root fpm -s dir -t deb -n some-module -v 1.00 /tmp/root
Defensive patterns
Strategy: validation
Validate before calling
# Pre-check the release tarball fpm will fetch, before invoking the CPAN source
require 'net/http'
require 'json'
url = URI('https://fastapi.metacpan.org/v1/release/_search?_source=download_url')
body = { query: { term: { name: "#{dist}-#{version}" } } }.to_json
resp = Net::HTTP.post(url, body, 'Content-Type' => 'application/json')
raise 'metacpan unreachable' unless resp.code == '200'
dl = JSON.parse(resp.body)['hits']['hits'][0]['_source']['download_url']
# fpm extracts the tarball and needs Build.PL or Makefile.PL at the root;
# inspecting the tarball member list locally requires downloading it first:
system("curl -sL http://www.cpan.org/#{dl} -o /tmp/pkg.tar.gz")
files = `tar tzf /tmp/pkg.tar.gz`.split("\n")
has_build = files.any? { |f| f =~ /(Build\.PL|Makefile\.PL)$/ }
abort 'no Build.PL/Makefile.PL: package manually with -s dir' unless has_build Try / catch
begin
FPM::Package::CPAN.new.input(module_name)
rescue FPM::InvalidPackageConfiguration => e
# message matches /No Makefile.PL nor Build.PL/
warn "#{module_name} has no supported build script; falling back to -s dir"
build_and_package_manually(module_name)
end Prevention
- Pre-download the tarball and run tar tzf to confirm Build.PL or Makefile.PL exists at the root before scripting fpm cpan builds
- Let metacpan pick the version (omit --version) so you get a complete, indexed release
- Keep a -s dir fallback recipe in CI for distributions without supported build scripts
When it happens
Trigger: Running fpm -s cpan -t deb Some::Module (or the API equivalent FPM::Package::CPAN#input) where the resolved release tarball contains neither Build.PL nor Makefile.PL at its root, e.g. the build files live in a subdirectory or the release ships without them. Also triggered when --version pins a release whose tarball layout is unusual or the mirror served a truncated archive.
Common situations: Packaging a distribution built with an exotic toolchain or a hand-assembled release missing build scripts; a CPAN mirror serving partial tarballs; a name/version combination resolving to a broken release on metacpan; the tarball extracting into a nested directory so the files are not found in cwd.
Related errors
- Could not find package metadata. Checked for META.json, META
- Unexpected CPAN 'author' field type: #{metadata["author"].cl
- metacpan release query failed
- metacpan query failed
- #{self.class.name} does not yet support reading #{self.type}
AI-assisted analysis of jordansissel/fpm@b6d77ba72a (2026-08-21).
Data as JSON: /api/errors/4bc1eeebaf01d8ab.
Report an issue: GitHub.