Fat scripts
Recently we installed HipChat at the office, and I want to write a small script to send messages to it. To make it easier for others to use I wanted to distributed it as a single standalone script, no dependencies.
I wrote the script, x-hipchat, with all the bells and whistles I felt were important, and then turned to the process of pack it into a single no-dependencies script. The simplest method I could find is App::fatten.
For best results, you should create a configuration file somewhere, and use the --config-path
to point to it. In fact, if you don’t create it, you keep getting “ERROR 412: Profile ‘your-script-name’ not found in configuration file”. In the configuration file, the section name is the base name of your script. My config file looks like this:
[profile=x-hipchat]
overwrite=1
exclude_core=1
The first attempts ran fine, but the fat script failed to find JSON::backportedPP
and later HTTP::Tiny
. And if I manually included them with include=MODULE
on my config file (oh, there is a bug in 0.13, if put a single include
statement, it borks - issue open), HTTP::Tiny
will die later on, I’m guessing because some of the internal modules that HTTP::Tiny could not be found.
I tried to use trace_method=prereqscanner_lite_recurse
configuration option and fatten
found more modules, but too many to include, and some were Core, which caused problems with a different version of perl.
The final solution for this was to install with perlbrew a older version of perl (I choose 5.10.1), and create a perlbrew lib just for packing:
perlbrew install -j 4 perl-5.10.1
perlbrew lib create perl-5.10.1@fatten
perlbrew use perl-5.10.1@fatten
cpanm App::fatten Module::CoreList
(we force Module::CoreList
because App::tracepm
requires a more recent version that she declares.)
This gives me a sufficiently old perl that lacks most of the more recent core modules, and will force them into the script. This actually helped, but I still got “599 Internal Exception” from HTTP::Tiny
.
I switched to trace_method=require
that actually runs your code. This is much better because a lot of modules are only loaded later, when needed. Here App::fatten
could make my life easier. My script requires parameters but I could not find a way of pass them. A command line option to give extra parameters to the program would be nice. Fortunately I had environment variables for most options, so I used those.
Eventually I found the culprit: HipChat API is HTTPS-only, and HTTP::Tiny
and perl in general require XS modules to use HTTPS, and XS modules cannot be fat packed.
So I could not create a standalone script for this because of my HTTPS dependency. Oh well…
I think this is a good example for me to dust up my Go knowledge…