Perl package guidelines - ArchWiki

Jump to content

# Perl package guidelines

From ArchWiki

This document covers the creation of PKGBUILDs for Perl modules distributed over CPAN, the Comprehensive Perl Authors Network. For Perl policies, see Perl Policy.

## Package naming

Perl package names should begin with `perl-`, followed by the distribution name converted to lowercase (e.g. `HTML-Parser` becomes `perl-html-parser`).

## Architecture

Most Perl distributions are architecture-independent, so packages should use `arch=('any')`. Distributions with XS modules contain .xs files and produce architecture-dependent shared libraries (.so files), so packages built from them should set `arch` to the supported architectures, e.g. `arch=('x86_64')`.

## Dependencies

In order to declare dependencies correctly in the `PKGBUILD`, consult the distribution metadata and the CPAN prerequisite specification to map them:

Phases:

- `configure` and `build` -> `makedepends`
- `test` -> `checkdepends`
- `runtime` -> `depends`
- `develop` -> ignore

Note that the above are required phases in the `requires` relationship. The other relationships are:

- `recommends` and `suggests` -> `optdepends`
- `conflicts` -> ignore

A prerequisite version, e.g. `"Path::Tiny" : "0.150"`, means "at least" that version is required, so use `perl-path-tiny>=0.150`. A `"0"` version indicates that any version of the prerequisite is acceptable, so no version constraint is needed.

Note It is not recommended to omit core module dependencies, because they can be removed from core in future Perl releases.

## Installation directories

Perl packages should install module files to vendor directories by setting `INSTALLDIRS=vendor` (`Makefile.PL`) or `--installdirs=vendor` (`Build.PL`).

This installs to:

- `/usr/lib/perl5/version/vendor_perl/` for architecture-dependent modules
- `/usr/share/perl5/vendor_perl/` for architecture-independent modules

Files should not be installed to site directories:

- `/usr/lib/perl5/version/site_perl/`
- `/usr/share/perl5/site_perl`

These are reserved for installations outside the package management system (e.g. via the cpan shell).

The `perllocal.pod` and `.packlist` files should not be present; this is handled by the #PKGBUILD examples below.

## PKGBUILD examples

The following `PKGBUILD` examples use techniques to address Perl packaging issues. Because there are two types of build scripts, two examples are provided: the first for distributions using `Makefile.PL`, and the second for distributions using `Build.PL`. Their complexity is explained in the sections below.

    PKGBUILD

    # Maintainer: Your Name <youremail@domain.example>

    _dist=Foo-Bar
    pkgname=perl-foo-bar
    pkgver=1.0
    pkgrel=1
    pkgdesc='This packages the Foo-Bar distribution, containing the Foo::Bar module'
    arch=('any')
    url="https://metacpan.org/dist/$_dist"
    license=('Artistic-1.0-Perl OR GPL-1.0-or-later')
    depends=('perl')
    makedepends=('perl-extutils-makemaker')
    options=('!emptydirs')
    source=("https://cpan.metacpan.org/authors/id/A/AB/ABC/$_dist-$pkgver.tar.gz")
    sha256sums=('deadbeef')

    build() {
        cd "$_dist-$pkgver"

        unset PERL_MM_OPT PERL5LIB PERL_LOCAL_LIB_ROOT
        export PERL_MM_USE_DEFAULT=1 PERL_AUTOINSTALL=--skipdeps

        /usr/bin/perl Makefile.PL NO_PACKLIST=1 NO_PERLLOCAL=1
        make
    }

    check() {
        cd "$_dist-$pkgver"

        unset PERL5LIB PERL_LOCAL_LIB_ROOT

        make test
    }

    package() {
        cd "$_dist-$pkgver"

        unset PERL5LIB PERL_LOCAL_LIB_ROOT

        make install INSTALLDIRS=vendor DESTDIR="$pkgdir"
    }

    PKGBUILD

    # Maintainer: Your Name <youremail@domain.example>

    _dist=Foo-Bar
    pkgname=perl-foo-bar
    pkgver=1.0
    pkgrel=1
    pkgdesc='This packages the Foo-Bar distribution, containing the Foo::Bar module'
    arch=('any')
    url="https://metacpan.org/dist/$_dist"
    license=('Artistic-1.0-Perl OR GPL-1.0-or-later')
    depends=('perl')
    makedepends=('perl-module-build')
    options=('!emptydirs')
    source=("https://cpan.metacpan.org/authors/id/A/AB/ABC/$_dist-$pkgver.tar.gz")
    sha256sums=('deadbeef')

    build() {
        cd "$_dist-$pkgver"

        unset PERL_MB_OPT PERL5LIB PERL_LOCAL_LIB_ROOT
        export PERL_MM_USE_DEFAULT=1 MODULEBUILDRC=/dev/null

        /usr/bin/perl Build.PL --create_packlist=0
        ./Build
    }

    check() {
        cd "$_dist-$pkgver"

        unset PERL5LIB PERL_LOCAL_LIB_ROOT

        ./Build test
    }

    package() {
        cd "$_dist-$pkgver"

        unset PERL5LIB PERL_LOCAL_LIB_ROOT

        ./Build install --installdirs=vendor --destdir="$pkgdir"
    }

## CPAN mechanics

The CPAN module system involves fetching the module distribution, configuring and building it, running tests, and installing it into the system. Understanding how modules work independently of pacman and Arch Linux packages helps clarify how they should be packaged.

### Modules

Modules are declared with the `package` keyword in Perl and contained in .pm files. Multiple modules can exist in a single file. Module namespaces use `::`, e.g. `Archlinux::Module`. When loading a module, `::` is replaced with directory separators, so `Archlinux::Module` loads from `Archlinux/Module.pm`.

Core modules are included with a Perl installation. Some core modules are only available bundled with Perl, while others can be downloaded and installed separately from CPAN.

### Distributions

Distributions (also called dists or packages) are the CPAN equivalent of Arch Linux packages. They are .tar.gz archives containing .pm module files, tests, documentation, and other necessary files.

Usually a distribution contains a main module with the same name, but not always (e.g. `Template-Toolkit-2.22.tar.gz` from `Template-Toolkit` dist contains no `Template::Toolkit` module).

Because distributions are often named after their main module, the terms are sometimes used interchangeably, which can cause confusion. However, it is useful to consider them separate entities.

### CPAN

CPAN mirrors provide plain-text indices listing modules, distributions, and authors; the primary index is /modules/02packages.details.txt.gz. Here "packages" refers to Perl's `package` keyword, not pacman packages. The cpan shell is a Perl script that uses these indices to locate and install modules.

Modules are listed in `02packages.details.txt.gz`; each entry shows the module name, version, and the path to the distribution tarball that contains the module. When you ask cpan to install a module, it looks up the module, downloads and installs the relevant distribution. During the build, dependency information from metadata is used and cpan will try to ensure required dependencies are installed. If a required dependency is missing or a version requirement is not met, cpan will attempt to fetch and install a distribution that satisfies the requirement.

Only the latest version per module is listed in `02packages.details.txt.gz`. Perl package authors should not assume consumers will always receive their most recent release, since pacman dependency checking is more static and strictly enforced.

### Module versioning

Modules can define their own versions using a `$VERSION` package variable:

    package ArchLinux::Module;
    use strict;
    use warnings;
    our $VERSION = '1.00';

Module versions can differ from their distribution version, which can be problematic. Determining module versions externally requires parsing Perl code or loading the module; however, they are easily accessible from within Perl:

    use ArchLinux::Module;
    print $ArchLinux::Module::VERSION, "\n";

### Declaring dependencies

Dependencies are declared in the `Makefile.PL` or `Build.PL` script. For example, in `Makefile.PL`, `WriteMakefile()` generates the `Makefile`:

    use ExtUtils::MakeMaker;

    WriteMakefile(
        NAME      => 'ArchLinux::Module',
        VERSION   => '1.00',
        PREREQ_PM => {
            POSIX => '0.01'  # requires POSIX >= 0.01
        },
    );

Dependencies are evaluated when the build script runs, so authors can conditionally add or modify prerequisites (e.g. to depend on modules only if they're already installed or to handle OS-specific requirements). However, most dependencies are static as in the example above.

### Metadata

Meta files in modern Perl distributions contain information such as the distribution name, author, abstract, and module requirements. Older distributions used `META.yml` but newer ones use `META.json`. These files are typically generated when packaging the distribution for release, e.g. by `Makefile.PL` or `Build.PL`. See CPAN::Meta::Spec for the latest specification.

Since the build script can modify dependencies at runtime, a secondary meta file, `MYMETA.json`, is generated to reflect these runtime changes and may differ from the `META.json` packaged for CPAN.

Ancient distributions on CPAN have no meta file at all and instead only describe their prerequisites in their `Makefile.PL`, because these releases predate the idea of the `META.yml`.

## Build tools

CPAN contains a vast number of modules. Following Perl's philosophy of "There's More Than One Way to Do It" (TMTOWTDI), multiple build modules are available, each addressing specific problems.

Build modules work by placing a build script (a Perl file with a .PL suffix) in the distribution tarball. Running this script configures the distribution before building it, running tests, and installing module files to the user's preferred location.

Build tool | Build script | Details
--- | --- | ---
ExtUtils::MakeMaker | `Makefile.PL` | The oldest module for installing Perl distributions. Its downside is requiring the make program, which is not available by default on some systems (e.g. Windows).
Module::Build | `Build.PL` | Pure-Perl, eliminating the need for make. Initially, adoption was hindered because `Build.PL` required `M::B` to already be installed. This was resolved when `M::B` became a Perl core module. Note `Module::Build` was removed from core in Perl 5.22 [1].
Module::Build::Tiny | `Build.PL` | Pure-Perl, implementing a minimal subset of `Module::Build`. Arguments must be prefixed with dashes (unlike `M::B`, which accepts both), and it does not support `.modulebuildrc`.
Module::Install | `Makefile.PL` | Designed as a drop-in replacement for `ExtUtils::MakeMaker` to address some of `MakeMaker`'s shortcomings. Despite this, `M::I` depends on `MakeMaker` to operate. `Module::Install` bundles a copy of itself into the distribution, eliminating the need to have it installed on your system, unlike `MakeMaker` or `Module::Build`. Note `Module::Install` usage is discouraged by the maintainers [2] since it has become largely unmaintained and is considered obsolete in the Perl toolchain [3].

### Module::Install caveats

When `auto_install` is enabled, `Module::Install` searches for and installs missing prerequisites when `Makefile.PL` is executed. This feature is skipped when run by `CPAN` or `CPANPLUS`, but not when run inside a `PKGBUILD`, potentially allowing arbitrary module installation. See #PERL_AUTOINSTALL to disable this.

### Makefile.PL vs Build.PL

If a distribution includes both `Makefile.PL` and `Build.PL`, consult `META.json` or `META.yml` to determine which to use. If the metadata indicates `Build.PL` or if `Makefile.PL` was generated by `Module::Build`, use `Build.PL` and add `perl-module-build` to `makedepends`; otherwise use `Makefile.PL`.

Note that many distributions using `Module::Install` omit it from `META.yml`. Since `M::I` bundles itself into the distribution, packagers often overlook adding it as a declared dependency. This breaks clean chroot builds because Perl 5.26+ no longer implicitly loads modules from the current working directory [4]. To fix this, add `perl-module-install` to `makedepends`.

## Environment variables

Environment variables can affect how modules are built or installed and may break a `PKGBUILD` if not handled correctly.

### PERL_MM_USE_DEFAULT

When set to a true value, causes the build module to skip interactive prompts and use default answers. All build modules respect this variable, though module authors may not.

### PERL_AUTOINSTALL

Set this variable to pass command-line arguments to `Module::Install`'s `Makefile.PL`. Disable auto-install (recommended) with:

    export PERL_AUTOINSTALL=--skipdeps

### PERL_MM_OPT

Set this variable to pass command-line arguments to `Makefile.PL`. For example, to install modules into your home directory:

    export PERL_MM_OPT=INSTALLBASE=~/perl5

### PERL_MB_OPT

Set this variable to pass command-line arguments to `Module::Build`. For example, to install modules into your home directory:

    export PERL_MB_OPT=--install_base=~/perl5

### MODULEBUILDRC

`Module::Build` uses an rcfile to override command-line arguments, which defaults to `~/.modulebuildrc`. Set `MODULEBUILDRC` to specify an alternative rcfile path, or set it to `/dev/null` to disable this.

Note `.modulebuildrc` is considered deprecated within the Perl toolchain. [5]

### PERL5LIB

The directories searched for libraries can be set by the user (particularly if they are using `local::lib`) with this variable. That should be cleared before building.

### PERL_LOCAL_LIB_ROOT

This variable will be set if the user is using `local::lib`. That should be cleared before building.

## Perl vs Pacman version comparison

Perl versions are different from common versioning schemes, e.g. the version `1.1901` is semantically equal to `v1.190.100`, and `1.20` to `v1.200` [6].

This means that a distribution could make a release with version `1.1901`, and a year later release a new version `1.20`. For Perl, the new version is greater; however, pacman's version comparison logic considers `1.1901` greater than `1.20`.

To fix this, it's preferable to bump `epoch` in the `PKGBUILD` and keep the upstream version.

## Problems with user-installed perl

Users may install multiple perl versions for testing or custom builds. If a custom perl is in `$PATH`, it will be executed during `PKGBUILD` runs instead of the system perl.

This causes problems with compiled XS modules. XS modules use Perl's internal C API, which changes between versions. If compiled against a custom perl version, they will fail to load with link errors when run by system perl.

To avoid this, always use the absolute path `/usr/bin/perl` in `PKGBUILD`s.

## Automation

As Perl is centered around CPAN, there are tools that use it to generate `PKGBUILD`s and save you writing them by hand.

- App::cpan2arch — Generate PKGBUILD from CPAN metadata.

  https://metacpan.org/pod/cpan2arch || perl-app-cpan2archAUR

- CPANPLUS::Dist::Arch — A plugin for the second-generation CPAN shell. This plugin packages distributions on the fly as they are installed by CPANPLUS.

  https://metacpan.org/pod/CPANPLUS::Dist::Arch || perl-cpanplus-dist-archAUR

## See also

- CPAN glossary
- A spotter's guide to CPAN
- CPAN dependencies and the river model
- An introduction to CPAN distribution metadata
- CPAN packaging guidelines

Category:

- Arch package guidelines

Perl package guidelines
Add topic