Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I write a makefile for a custom bash command with a Perl library

I wrote a bash command that uses an extensive perl module library. I know that I can install a custom bash command in usr/bin simply enough, but I have never had dependencies for a command before.

My makefile, for better or worse, looks like this

install:
    cp program.pl /usr/bin/program -f -v
    chmod +x /usr/bin/program -v

it's short, but I don't really need to compile anything. program.pl is a short perl script that uses Getopt::Long to interact with the module. I have been installing the module separately using MakeMaker as documented here.

my file structure feels a bit overkill for how simple the command should be, but due to how MakeMaker works, it ended up like this

program/
    program.pl
    makefile
    perl/
        Makefile.PL
        MANIFEST
        lib/
            Program/
                Package01.pm
                Package02.pm
                Package03.pm

and, instead of running a recursive make in the root directory, I have been running make in both places, which I know isn't right (while also being annoying).

I see that all these modules just wind up in /usr/local/share/perl/5.34.0/Program but I'd rather it be a little more portable than putting it there myself in my root makefile. What is the correct way to do this? I would like to make this command public eventually and I don't want to mess up an install

like image 496
anony mous Avatar asked Dec 17 '25 12:12

anony mous


2 Answers

It sounds like program.pl and Program::PackageXX.pm are a bundle.

If so, you should Perl's installer to install not just the modules but the script.

Makefile.PL
MANIFEST
bin/
   program.pl
lib/
   App/
      Program.pm
      Program/01.pm
      Program/02.pm
      Program/03.pm

Makefile.PL:

#!perl

use strict;
use warnings

use ExtUtils::MakeMaker;
 
WriteMakefile(
   NAME          => 'App::Program',
   VERSION_FROM  => 'lib/App/Program.pm',
   ABSTRACT_FROM => 'lib/App/Program.pm',
   AUTHOR        => 'Name E<lt>name[at]cpan.orgE<gt>',
   PREREQ_PM     => { ... },
   EXE_FILES     => [ 'bin/program.pl' ],
   ...,
);

(App::... is the preferred namespace for such things.)

Then, simply install the distro as normal.

perl Makefile.PL
make test
make install

This will install the script in the dir given by

perl -V:installsitescript

It should already be in your PATH. If not, add it.

like image 198
ikegami Avatar answered Dec 19 '25 06:12

ikegami


It's likely you can just run the command while adding the path to the libraries it needs. Inside the top level Makefile, you would run:

perl -Iperl/lib program.pl

There are various other ways to set the library search path for Perl.

The trick might be that your local Perl module needs other modules, and that those are specified in the Makefile.PL. You can install those locally with the help of local::lib:

% perl -Mlocal::lib
PATH="/Users/brian/perl5/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="/Users/brian/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
PERL_LOCAL_LIB_ROOT="/Users/brian/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
PERL_MB_OPT="--install_base \"/Users/brian/perl5\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=/Users/brian/perl5"; export PERL_MM_OPT;

Those are the default values, but you can specify your own base:

% perl -Mlocal::lib=/Users/brian/Dev/perl-lib
Attempting to create directory /Users/brian/Dev/perl-lib
PATH="/Users/brian/Dev/perl-lib/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="/Users/brian/Dev/perl-lib/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
PERL_LOCAL_LIB_ROOT="/Users/brian/Dev/perl-lib${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
PERL_MB_OPT="--install_base \"/Users/brian/Dev/perl-lib\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=/Users/brian/Dev/perl-lib"; export PERL_MM_OPT;

Adjust those values for what you need, put them in your environment, and cpan should respect them:

 % cd perl && cpan .

If you don't mind installing the dependencies in your home directory rather the project directory, don't set any env vars. cpan's -I switch will use local::lib for you and create and install into ~/perl5/lib:

 % cd perl && cpan -I .

Inside your program, pull in local::lib and it should figure it out:

use local::lib;

Or use a relative path:

use local::lib 'perl-lib';
like image 21
brian d foy Avatar answered Dec 19 '25 07:12

brian d foy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!