{"record":{"id":"4bc1eeebaf01d8ab","repo":"jordansissel/fpm","slug":"i-don-t-know-how-to-build-name-no-makefile-pl","errorCode":null,"errorMessage":"I don't know how to build #{name}. No Makefile.PL nor Build.PL found","messagePattern":"I don't know how to build #(.+?)\\. No Makefile\\.PL nor Build\\.PL found","errorType":"validation","errorClass":"FPM::InvalidPackageConfiguration","httpStatus":null,"severity":"error","filePath":"lib/fpm/package/cpan.rb","lineNumber":262,"sourceCode":"                     \"-Mlocal::lib=#{build_path(\"cpan\")}\",\n                     \"Makefile.PL\", \"PREFIX=#{prefix}\", \"LIB=#{perl_lib_path}\",\n                     # Empty install_base to avoid local::lib being used.\n                     \"INSTALL_BASE=\")\n        else\n          safesystem(attributes[:cpan_perl_bin],\n                     \"-Mlocal::lib=#{build_path(\"cpan\")}\",\n                     \"Makefile.PL\", \"PREFIX=#{prefix}\",\n                     # Empty install_base to avoid local::lib being used.\n                     \"INSTALL_BASE=\")\n        end\n        make = [ \"env\", \"PERL5LIB=#{build_path(\"cpan/lib/perl5\")}\", \"make\" ]\n        safesystem(*make)\n        safesystem(*(make + [\"test\"])) if attributes[:cpan_test?]\n        safesystem(*(make + [\"DESTDIR=#{staging_path}\", \"install\"]))\n\n\n      else\n        raise FPM::InvalidPackageConfiguration,\n          \"I don't know how to build #{name}. No Makefile.PL nor \" \\\n          \"Build.PL found\"\n      end\n\n      # Fix any files likely to cause conflicts that are duplicated\n      # across packages.\n      # https://github.com/jordansissel/fpm/issues/443\n      # https://github.com/jordansissel/fpm/issues/510\n      glob_prefix = attributes[:cpan_perl_lib_path] || prefix\n      ::Dir.glob(File.join(staging_path, glob_prefix, \"**/perllocal.pod\")).each do |path|\n        logger.debug(\"Removing useless file.\",\n                      :path => path.gsub(staging_path, \"\"))\n        File.unlink(path)\n      end\n\n      # Remove useless .packlist files and their empty parent folders\n      # https://github.com/jordansissel/fpm/issues/1179\n      ::Dir.glob(File.join(staging_path, glob_prefix, \"**/.packlist\")).each do |path|","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/jordansissel/fpm/blob/b6d77ba72a560b687723376a0e5115c3a92634ad/lib/fpm/package/cpan.rb#L244-L280","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\nfpm -s cpan -t deb Some::Module --version 0.01   # 0.01 tarball lacks build scripts\n\n# after\nfpm -s cpan -t deb Some::Module                  # let metacpan pick a complete release\n# or package a manual install:\n#   perl Makefile.PL && make && make install DESTDIR=/tmp/root\nfpm -s dir -t deb -n some-module -v 1.00 /tmp/root","handlingStrategy":"validation","validationCode":"# Pre-check the release tarball fpm will fetch, before invoking the CPAN source\nrequire 'net/http'\nrequire 'json'\n\nurl = URI('https://fastapi.metacpan.org/v1/release/_search?_source=download_url')\nbody = { query: { term: { name: \"#{dist}-#{version}\" } } }.to_json\nresp = Net::HTTP.post(url, body, 'Content-Type' => 'application/json')\nraise 'metacpan unreachable' unless resp.code == '200'\n\ndl = JSON.parse(resp.body)['hits']['hits'][0]['_source']['download_url']\n# fpm extracts the tarball and needs Build.PL or Makefile.PL at the root;\n# inspecting the tarball member list locally requires downloading it first:\nsystem(\"curl -sL http://www.cpan.org/#{dl} -o /tmp/pkg.tar.gz\")\nfiles = `tar tzf /tmp/pkg.tar.gz`.split(\"\\n\")\nhas_build = files.any? { |f| f =~ /(Build\\.PL|Makefile\\.PL)$/ }\nabort 'no Build.PL/Makefile.PL: package manually with -s dir' unless has_build","typeGuard":null,"tryCatchPattern":"begin\n  FPM::Package::CPAN.new.input(module_name)\nrescue FPM::InvalidPackageConfiguration => e\n  # message matches /No Makefile.PL nor Build.PL/\n  warn \"#{module_name} has no supported build script; falling back to -s dir\"\n  build_and_package_manually(module_name)\nend","preventionTips":["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"],"tags":["fpm","cpan","perl","build-system","packaging"],"backgroundTag":"unsupported-build-system","analyzedSha":"b6d77ba72a560b687723376a0e5115c3a92634ad","analyzedAt":"2026-08-21T16:39:02.570Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}