Compiling a portable Perl and including a CPAN module - perl

I am trying to compile a portable version of perl containing a CPAN module, specifically the YAML module. I intend to be able copy this portable version into my home directory on numerous Redhat Linux machines, add it to my $PATH and use this version instead of the default perl version to run some tests.
I have already managed to compile a portable version of perl and got it working on different machines. However, when I compile the YAML module and install it, it works locally but then fails when I copy it to other machines.
Here's my compilation steps locally for the YAML module
perl Makefile.pl
make test
make install
Which installs the YAML module locally and also works locally when I use the YAML module in a script.
This is the error once I copy perl to another machine and try to use the YAML module...
Can't locate loadable object for module YAML::XS::LibYAML in #INC
even though lib/site_perl/5.10.1/x86_64-linux/YAML/LibYAML.pm exists in my local copy.
Is what I'm attempting to do possible?
If so, where am I going wrong?

Possibly you should explore PAR with which you can create an archive of your module dependencies and ship it alongside your application.

Related

Installing an perl based web-app in extremely restricted environment

Because i have a long series of comments with #ikegami, I cleaning up the question, in a hope it will be more understandable. Unfortunately, english isn't my "main" language. :(
Let say, having an environment where:
no development tools are installed (no make, nor gcc or like)
perl is installed with its core packages, nothing more
no outgoing network access is allowed - e.g. the user couldn't use curl nor cpan to download/install perl dependencies
the user even doesn't have admin (root) rights
but want install and evaluate some perl based web-app, let call it as MyApp
The MyApp
doesn't uses any XS-based module. (at least, I hope - in the development me using plenv and cpanm, so never checked the installed dependencies in depth)
it is an pure PSGI app, the simple plackup app.psgi works OK
the app uses some data-files which should be included in the "deployment".
The main question is: how to prepare the MyApp, and the all used CPAN-modules, to be easily installed in such restricted environment?
The goal is:
i don't need save my efforts and my time
but i want save the user's time and want minimize the needed actions on his side, so the installation (deployment) should be simple-as-possible.
E.g. how to get an running web-app to the user's machine with minimum possible (his) steps.
- the simplest thing is could be something as:
- copy one file (zip, or tarbal)
- unpack it
- from the terminal execute some run.pl in the unpacked directory.
To get the above simple installation, my idea was the following:
1.) Create an tarball, and after the unpacking will contain 3 folders and 1 perl-script, let say:
myapp_repo/
myapp_repo/distlib #will contain all MyApp's perl modules also ALL used CPAN modules and their dependecies
myapp_repo/datafiles #will contain app-specific data files and such
myapp_repo/install.pl
myall_repo/lib #will contain modules directly used by the `install.pl`
2.) I will develop an install.pl script, and it will be used as the installer-tool, like
perl install.pl new /path/to/app_root
and it will (should):
create the all needed directories under the /path/to/app_root (especially the lib where the will install the perl modules)
will call "local" cpanm internally (from the myapp_repo/lib) to install the app's perl modules and their CPAN dependencies using only distribution files from the distlib.
will generate and install the needed runtime script and the app.psgi into the /path/to/app_root/bin
will install the needed data-files for the app.
3.) So, after this the user should be able to simply run:
/path/to/app_root/bin/plackup /path/to/app_root/bin/app.psgi
In short, the user should use:
the system-wide perl and the system-wide perl-core modules
and any other
runtime perl-scripts (like plackup)
and the required CPAN-modules
should be installed to an self-contained directory tree using only files (no net-access).
E.g. the install.pl should somewhat call internally the cpanm to achieve (as equivalent) for the following cpanm command
cpanm --mirror file://path/to/myapp_repo/distlib --mirror-only My::App
which, should install My::App and all dependencies without network access using only the files from the myapp_repo/distlib
Some questions:
Is possible to use cpanm (called as an locally installed module) without the make?
For creating the myapp_repo/distlib, me thinking about using Pinto. Is it the right tool for achieve the above?
forgot me something? or with other words:
Is the above an viable (read: working) way?
are are any other tools, which i could/should to use for simplifying the creation of such distribution tarball?
#ikegami suggesting some method:
- "install everything" in one fresh-directory on my machine
- transfer this self-contained directory to the target machine
It sound very good, because this directory could contain all the needed app-specific data-files too, unfortunately, I don't understand the details how his solution should be done.
The FatPacked solution looks interesting too - need learn about it.
Don't write your own make or installer. Just copy it make from a different machine (which is basically what apt/yum/etc do anyway, and which you'd have to do even if you wrote your own). You'd be able to use cpan in 5 minutes!
Also, that should allow you to install gcc if you need it (e.g. to install an XS module), although it doesn't sound like you do. If you do install gcc, I'd install my own perl to avoid having to deal with PERL5LIB.
Tools such as minicpan will allow you to install any module from CPAN without internet access. Of course, you can keep using the command you are already using it if mirrors the packages you need.
The above explains how to simply and quickly setup a machine so it can use cpan and thus install any module easily.
If you just want to install a specific module and its dependencies, you can completely avoid using cpan on the target machine. First, you need a fresh install of Perl (preferable of the same version as the one on the target system). Then, simply install the module to a fresh dir on your machine, and transfer that dir to the target machine. That's it; nothing else needs to be done. This even works for XS modules if the two machine are similar enough.
This is what ppm (ActiveState's Perl package manager) does.
Unfortunately, while this solution is almost as simple as the one above, it's not nearly as flexible, it doesn't run the test suite of the modules being installed, etc. It does have the advantage of not requiring the transfer of any binary (if you're not installing any XS modules).

SOAP::Lite module installation on cPanel

I am creating a custom module to be placed in the directory /usr/local/cpanel/Cpanel. My perl module requires SOAP::Lite. Since the scripts placed in the directory /usr/local/cpanel/Cpanel are run under cpanel's internal perl version 5.6.2, does on install the SOAP::Lite module?
Trying to build the module with cpanel's build tool fails as another perl module is require to build the source module for soap::lite from cpan.
Perl modules are usually installed using the cpan program that comes with Perl. This checks all the dependencies for you and installs everything you need. This is what you should do.
If you don't have the ability to access and run this program, then you may not have permission to install modules at all. Possibly you could get whoever is running your system to do it for you (also ask them to upgrade your nearly 9 year old version of Perl while they are at it!).
Beyond that, there are not many options. You could try building the required modules on another, similar system and copying over--if you enjoy pain.

Deploying C-dependent Perl libraries

I have an application that I deploy on both Linux (Red Hat) and Unix (Solaris). My application installs itself using the built in Perl, and from then creates its own local Perl (new user).
I would like to know what is the best way to deploy Curses::UI? Currently I install other modules by just copying them to my local perl lib folder, but these are pure Perl modules that don't depend on C libraries (.so shared objects, XS, etc.).
Also will I have to compile libncurses for each platform beforehand?
NOTE: The computer doesnt have network connectivity, hence I cant use the CPAN module.
You should use a CPAN client (CPAN.pm, CPANPLUS) to deploy modules such as Curses::UI from CPAN. Usually you need development libs to compile XS modules. For Curses::UI the Ubuntu package is called libncurses-dev. Other Linux distributions probably have an ncurses devel package under the same or similar name.
You said you have a local Perl lib. A very good way to have a local lib is the module of the same name - local::lib. Its documentation will tell you how to easily install modules into your local::lib using a CPAN client.
For the CPAN modules that need to be built, try looking at carton. It has a bundle command that will bundle all your cpan modules together so they can be installed/built on the target machines without any network involved.
As for libcurses, I'd probably lean toward having a custom installer to build it on the target machine if it's not already installed. That or make your software refuse to be installed unless that library is found. Unfortunately I don't know of a good way to build dependent C libraries locally other than doing a custom build script.

Installing Perl module without CPAN

I'm writing a Perl script that does date operations that need to take holidays into account, so I think I need either Date::Manip or Date::Calc. The server I'm going to put this script on is behind a firewall and therefore CPAN can't connect to the internet. Generally I can install Perl modules by just putting the .pm files in the Perl lib folder, but these two modules both have a C++ component or depend on a non-core module (YALM::Syck for Date::Manip) with a C++ component.
The server I'm deploying to also doesn't have GCC, so copying the installation package and building it there didn't work since it couldn't compile the C++. I tried building the packages on my home Linux PC and then copying them to the server, but got an error saying the module file was incorrect. The server is an IBM AIX box, so the module I compiled for my home pc is probably incompatible.
Is there any way I can get Date::Manip or Date::Calc working on this server? Are there any pure Perl (including dependencies) modules I could use instead?
All the favourites are not pure-perl.
http://deps.cpantesters.org/?pureperl=on;module=DateTime
http://deps.cpantesters.org/?pureperl=on;module=Date%3A%3AManip
http://deps.cpantesters.org/?pureperl=on;module=Date%3A%3ACalc
Set up a development box and mirror the production server. Install the compiler in the development environment. Build the modules and package them for deployment on production (AIX has packages, right‽).
You seriously need a proper toolchain for your server, including a compiler. It's fine to build the CPAN module on another machine and copy the installed files across, but obviously the build environment has to have the same architecture, same OS, and same perl version as the operational server.

How can I create a portable perl when I can't install modules on the target host?

I need to run Perl applications I develop on cygwin Windows on HP unix / Solaris hosts. I am not a superuser on the unix machines and I can't touch the default Perl module location nor can I install modules to the default Perl module location. Also the unix installation lacks most basic modules and I can't change that.
For example, I have a Perl application that needs Expect which has native C compiled parts to it. How would I roll out this application to unix with its required dependencies without having to install anything else on that box?
Is there way to build the entire Perl application under Cygwin Windows and then just roll out one executable to unix and run it from my home directory there?
EDIT addition based on answers so far:
Thanks in particular to brian, the local LIB dir solution seems to work in case of native Perl, but in case of Perl module needing C components, cross platform compiling, ie compiling on cygwin to run on Solaris, is not really possible as I feared.
However would having an other linux installation help, i.e. would this be possible easier between different flavors of Unix like package Perl on linux and then deploy to Solaris/HP? And what about something like lcc ?
Also I'd still like to hear little more if somebody has rolled out a native Perl package on Windows that includes all dependencies for a complicated Perl app that can then be moved to unix as just one file? (I do now understand that it won't work in case native C code is included like in in Expect.pm, but what about in case of app only using pure perl modules?)
Basically for many reasons I am trying to minimize time I need to spend being logged into these "production" unix hosts and do as much as possible locally beforehand.
Added a new cross-compile question, since I felt I was maybe veering too far from the original perl question.
EDIT -- Par looks promising for pure Perl, although same deal, it doesn't look to solve the cross platform compile problem for native extensions
In this case, I'd consider delivering a complete application complete with its own Perl. You get to choose any version you like and any modules you like. Compile everything, organize everything into a directory, then tar the result. To deploy, copy the file and untar. Use the advice that others have already noted about library search paths, etc. In essence, your application gets its own stack.
Now, the trick there is the cross compilation. Why are you developing on Cygwin? Is that a target too? Is there a reason you don't have an HP/UX or Solaris development machine? What architecture are you targeting (RISC, SPARC, Intel, etc). If you can't get hardware to run those, get some virtual machines for your targets and develop there.
Aside from that, you can install modules anywhere you have permissions. See perlfaq8:
How do I keep my own module/library directory?
How do I add the directory my program lives in to the module/library search path?
How do I add a directory to my include path (#INC) at runtime?
I haven't tried this particular feature, but perl2exe says it supports cross platform builds.
Compiling a Perl script with all its dependencies on Windows with Cygwin and running it Solaris is just not going to work.
Now the question is: do you have access to a compiler on that Solaris computer? It's not because you do not have root access that you cannot compile and install Perl modules in your home directory by using:
perl Makefile.PL PREFIX=$HOME
If you have CPAN available on your Solaris system you can set the prefix in the CPAN shell this way:
start the shell perl -MCPAN -e shell;
change the prefix with conf makepl_arg PREFIX=/path/to/your/home/directory
For your script to run, you can either start perl with the -I $HOME command-line switch, e.g.:
perl -I $HOME script.pl
Your other option would be to place this at the begining of your script
use lib $ENV{'HOME'};
Set your environment variable PERLLIB to your personnal Perl lib directory or use the -I command line switch to Perl to indicate it.
If you have access to the HP-UX machine you can compile Expect there and install it in your directory. But cross compilation from Windows to HP-UX is probably much more difficult. You would have to build a GCC cross compiler.
If you have a compiler on each of your systems (and some other tools needed by configure like grep), you should not only be able to compile modules, but you should also be able to build your own perl executables.
You'll want local::lib. Once you've done that, the pure Perl modules should work cross platform, but you'll have to identify and reinstall the compiled modules on the foreign platform. Do the initial install on a real unix, cpan on cygwin is slow.
I've run across this several times on my work systems. We have a base install of Perl 5.8 and I don't have the ability to add modules. Here's the solution I use:
Create a folder called 'lib' in your
project root (ex:
~/projects/MyProject/lib)
Any
modules you download from CPAN
should have a Makefile as well as a
directory called "lib". Copy the contents of the lib folder into your newly created lib folder. Some modules may only contain a single .pm file, and no lib structure. Just copy the .pm file.
Your code should do the following: first, use any modules that have been installed normally, then unshift your #INC environment variable to use your local libraries:
# Declare Includes --------------------------------------------------------------------------------
use Getopt::Long;
use vars qw($VERSION);
use DirHandle;
use FileHandle;
# Force perl to use our local 'lib' directory for imported modules, this allows us to
# use modules without having to install them in th emain perl assembly. However, this
#also prevents these modules from being used in other projects.
BEGIN { unshift #INC, "lib"; }
use Error qw(:try);
use SOAP::Transport::HTTP;
#use LWP::Protocol::https;
use XML::Simple;
use XML::Writer;
use XML::Writer::String;
The caveat to this method is that some Perl modules don't use the 'lib' method or have additional dependencies. If you run into problems, examine the Makefile.PL for the module and see what it's doing.