The easy way to build stand-alone Perl apps
The Perl toolchain has such a large install base it’s tempting to just upload your app to PAUSE and let users install it via CPAN. Many authors have taken this approach and it makes sense in most cases to reuse the power of the CPAN in providing a common install, dependency management and update mechanism. Sometimes however you want to distribute a dependency-free Perl app in a single executable file, and for these cases you’ll want to look at App::FatPacker.
You’ll need a Unix-based system (Linux, OSX, BSD) and to install App::FatPacker. It runs on every version of Perl from 5.8.8 upwards, so just fire up the terminal and enter the following:
Coding your app
You can convert any typical Perl script into a standalone app, as long as it doesn’t have XS dependencies (see “Alternatives to App::Fatpacker” below for more info on how to create apps with XS dependencies). One suggestion would be to use the following shebang line:
This shebang line will call the “env” program passing “perl” as a parameter. This deals with the issue of the Perl binary beng installed in different locations on platforms as it will use the Perl binary in the user’s $PATH. This is documented in perlrun. It is also compatible with Perlbrew.
Producing the single file app
This couldn’t be simpler: once you have your Perl script ready to go, open the terminal and enter the following, replacing the paths with your own:
fatpack pack /path/to/script > /path/to/app
This will pack all of the dependencies used by your script into a single executable app.
Running the app
Now that your app is in a single file, distributing and running it is a piece of cake. Simply copy the file to any directory in your $PATH. In order to be able to run your new app, you’ll need to set it’s permission to be executable. You can do this with chmod:
chmod 755 /path/to/app
Now the app should run simply by entering the app filename in the terminal.
A simple example
Let say we have the following script, BillCalc.pl which calculates how much each person should pay at dinner using the fictitious “Math::Bill” library.
#!/usr/bin/env perl use strict; use warnings; use Math::Bill; use feature 'say'; use Carp 'croak'; croak "Error: missing arguments. Requires a bill total and number of people at dinner. e.g:\n BillCalc 100.40 3" unless @ARGV == 2; my $bill = Math::Bill->new($ARGV, $ARGV); say 'Each person should pay: ' . $bill->apportion . ' each';
We can pack BillCalc.pl into a single file app using App::Fatpacker:
fatpack pack BillCalc.pl > BillCalc BillCalc.pl syntax OK
App::Fatpacker prints out a confirmation message (“BillCalc.pl syntax OK”) and we should now have a new file, called “BillCalc” in our current directory. This file will contain all of the contents of “Math::Bill” and any other dependencies in BillCalc.pl.
Let’s move this to a directory in my $PATH, /home/sillymoose/local/bin
mv BillCalc /home/sillymoose/local/bin
And change the file permissions to be executable:
chmod 755 /home/sillymoose/local/bin/BillCalc
Now we can run the BillCalc app at the command line:
BillCalc 120 3 Each person should pay: 40 each
For an example of a real-world Perl app created with App::FatPacker, check out our article on every, the cron scheduling app.
Alternatives to App::FatPacker
PP is another Perl tool that can create stand-alone Perl apps. It also supports XS module dependencies (unlike App::FatPacker).
Of course you can also distribute an application via CPAN, where you have the flexibility of including the dependent modules in your application’s inc directory, or include the modules as dependencies in the makefile, and let CPAN install them for you - this is also more disk space efficient. Perl applications on CPAN place the app in the application’s bin directory and use “EXE_FILES” directive in the makefile to install the app to the Perl bin directory. If you’re interested in this approach, check out the Module::Starter source as a good example to copy from.
This article was originally posted on PerlTricks.com.
Something wrong with this article? Help us out by opening an issue or pull request on GitHub