Search code examples
perl

Module::Install and bash completion scripts


I have a Perl script with the following Makefile.PL:

# Load the Module::Install bundled in ./inc/
use lib '.'; # added since from Perl 5.26 '.' is no more in @INC
use inc::Module::Install;

##############################################################################
# Define metadata (we read it from the binary)

name              'check_updates';
version_from      'check_updates';
perl_version_from 'check_updates';
all_from          'check_updates.pod';

##############################################################################
# Specific dependencies

include 'version';

my %prereqs = (
    'Carp'     => 0,
    'English'  => 0,
    'POSIX'    => 0,
    'Readonly' => 0,
    'Monitoring::Plugin' => 0,
    'Monitoring::Plugin::Threshold' => 0,
    'Monitoring::Plugin::Getopt' => 0,
);

install_script  'check_updates';

auto_install;

tests 't/*.t';
test_requires 'Test::More'       => 0;
test_requires 'File::Spec'       => 0;

# https://metacpan.org/pod/release/DAGOLDEN/CPAN-Meta-2.142690/lib/CPAN/Meta/Spec.pm#license
license 'gpl_3';

WriteMakefile(
    PREREQ_PM            => \%prereqs,
    INSTALLSCRIPT        => '/usr/lib/nagios/plugins/contrib',
    INSTALLSITESCRIPT    => '/usr/lib/nagios/plugins/contrib',
    MAN1PODS             => { 'check_updates.pod' => 'blib/man1/check_updates.1', },
    MAN3PODS             => { },
);

I would also like to copy a bash-completion script (i.e. check_updates.completion) to the correct directory (given by pkg-config --variable=completionsdir bash-completion, e.g. /opt/local/share/bash-completion/completions)

Is there a way to generate a Makefile rule to just copy the file to the directory?

The execution of pkg-config --variable=completionsdir bash-completion can also be performed in Makefile.PL generating a Makefile with a hardcoded rule.


Solution

  • According to the documentation in Module::AutoInstall :

    Starting from version 0.43, Module::AutoInstall supports modules that require a MY::postamble subroutine in their Makefile.PL. The user-defined MY::postamble, if present, is responsible for calling Module::AutoInstall::postamble and include the output in its return value.

    I tested this with this simple Makefile.PL:

    use strict;
    use warnings;
    use inc::Module::Install;
    
    name           'My-Module';
    all_from       'lib/My/Module.pm';
    include        'Module::AutoInstall';
    
    my %prereqs = (
        'Carp'     => 0,
        'English'  => 0,
        'POSIX'    => 0,
        'Readonly' => 0,
    );
    install_script 'myscript';
    auto_install;
    
    WriteMakefile(
      PREREQ_PM            => \%prereqs,
    );
    
    sub MY::postamble {
        my $dest_path = "/opt/local/share/bash-completion/completions";
        my $script_name = "check_updates.completion";
        my $str = "install::\n\t\$(CP) ${script_name} ${dest_path}\n";
        return &Module::AutoInstall::postamble . $str;
    }
    

    and it seems to work fine here (it copies the given file to the specified path when you run sudo make install)