PAR : Explanation needed to create a PAR archive and use it remotely - perl

I would like to deploy my Perl application to several remote servers. My perl application consists of one big program, using non-core modules : Path::Iterator::Rule, XML::Writer, and two home-made modules.
I would like to be able to deploy my application on a remote server whithout having to copy one by one all of the modules my program uses, with all their dependencies.
I had a look at PAR, which could help with what I'd like to do.
I need to create an archive ("modules.par") where I put my homemade modules, and I add Path::Iterator::Rule, XML::Writer modules ? But how can I be sure that all the dependencies of those modules are correctly added in my archive ?
I've understood that I need to do something like this in my main application :
use PAR;
use lib "modules.par";
use Path::Iterator::Rule;
use XML::Writer;
use HomemadeModule1;
use HomemadeModule2;
Sorry for the confusion, I'm really lost with all those module dependencies, ..
Edit :
So I've tried using cpanm -L extlib to create a directory with all my libraries, but I can't use cpanm on my system.
Now I'm trying to use PAR, I've created a file called "sources.par" in which all of my modules are contained, I used the following command :
pp -p myperlprogram.pl
This created the "sources.par", that I should be able to use in my program using this :
use PAR;
use lib "sources.par";
use XML::Writer;
use ..
But I still get the following message :
Can't locate XML/Writer.pm in #INC (#INC contains: sources.par CODE(0x10c0cc) /app/pro
dexpl/gld/LOA /usr/perl5/5.8.4/lib/sun4-solaris-64int /usr/perl5/5.8.4/lib /usr/
perl5/site_perl/5.8.4/sun4-solaris-64int /usr/perl5/site_perl/5.8.4 /usr/perl5/s
ite_perl /usr/perl5/vendor_perl/5.8.4/sun4-solaris-64int /usr/perl5/vendor_perl/
5.8.4 /usr/perl5/vendor_perl . CODE(0x10c1e0)) at /app/prodexpl/gld/LOA/AnalyseF
ichier.pm line 7.
BEGIN failed--compilation aborted at /app/prodexpl/gld/LOA/AnalyseFichier.pm lin
e 7.
Compilation failed in require at /app/prodexpl/gld/LOA/loganalysis.pl line 9.
BEGIN failed--compilation aborted at /app/prodexpl/gld/LOA/loganalysis.pl line 9
.
Any ideas what I could do ? You can see that #INC contains my sources.par file..

Create a package using either Module::Build or Module::Build::Tiny, and then just install the package on these remote machines. That way you can just specify what the dependencies are, and cpanm can install them as well.

Related

App::FatPacker on Windows

I have a script on Windows which uses multiple pure Perl modules from CPAN.
I am trying to ship this script without the need to reinstall those modules from CPAN using App::FatPacker.
I installed App::FatPacker ( up to date (0.010007) version ) on Portable Strawberry Perl 5.24 .
When I run the following command
fatpack pack myscript.pl > myscript.packed.pl
I get
syntax OK
but the fatlib is empty and when I run my script it fails.
I tried to use this script which does nothing but load Geo::IP::PurePerl
use strict;
use warnings;
use Geo::IP::PurePerl;
and run again this command :
fatpack pack myscript.pl > myscript.packed.pl
Then I ran myscript.packed.pl on another instance of Strawberry Perl 5.24, I get the following error:
Can't locate Geo/IP/PurePerl.pm in #INC (you may need to install the Geo::IP::PurePerl module
I tried to debug it by building step by step
The fatpack trace creates a trace list as expected, including Geo::IP::PurePerl
The fatpack packlists-for finished successfully but the fatlib is empty.
Any idea?
I would say that packlists-for isn't finding any .packlist files
The documentation for fatpack says this
packlists-for
$ fatpack packlists-for Module1 Module2 Module3
Searches your perl's #INC for .packlist files containing the .pm files for the modules requested and emits a list of unique packlist files to STDOUT.
These packlists will, in a pure cpan-installation environment, be all non-core distributions required for those modules.
Unfortunately most vendors strip the .packlist files so if you installed modules via e.g. apt-get you may be missing those modules; installing your dependencies into a local::lib first is the preferred workaround.
I think that's useful advice that may well fix your problem

Perl - How to reference a module installed locally?

I have a module Term:TermKey, which is in a file TermKey.pm. I don't want to install it into my perl; I want it to be referenced locally so that the script can be moved to other machines without messing about with each perl installation. How do I do this? None of the recommendations I have seen online works. I always get some form of:
Can't locate loadable object for module Term::TermKey in #INC (#INC contains: /home/fritz/multi.kodis/Term /etc/perl /usr/local/lib/perl/5.18.2 /usr/local/share/perl/5.18.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.18 /usr/share/perl/5.18 /usr/local/lib/site_perl .) at test.pl line 6.
Compilation failed in require at test.pl line 6.
BEGIN failed--compilation aborted at test.pl line 6.
To test this. I placed copies of TermKey.pm in all of:
./TermKey.pm
./Term/TermKey.pm
./Term/Term/TermKey.pm
(just as a test)
Yet it doesn't work for any of:
use lib '';
use Term::TermKey;
use lib '.';
use Term::TermKey;
use lib './';
use Term::TermKey;
use lib './Term';
use Term::TermKey;
use lib './Term/';
use Term::TermKey;
use lib '/home/[user]/[project]'
use Term::TermKey;
use lib '/home/[user]/[project]/Term'
use Term::TermKey;
use FindBin;
use lib "$FindBin::RealBin";
use Term::TermKey;
What the heck? This should be easy, what am I missing?
"Can't locate loadable object for module" does not mean that Perl can't find Term/TermKey.pm. It means that it can't find Term/TermKey.so (or whatever shared libraries are called on your platform).
Term::TermKey is not a pure-Perl module. Instead, it includes XS code, which needs to be compiled into C and then into a shared library. Also, that library links to libtermkey, which must also be installed on your system.
This makes it much harder to move the module from system to system. An XS module compiled for Perl 5.18.2 won't work with 5.20.0; it has to be recompiled. You can upgrade minor releases (like from 5.18.0 to 5.18.2) without having to recompile, although going the other direction (from 5.18.2 to 5.18.0) isn't guaranteed to work.
So, you might be able to get this to work if all the machines are running the same version of Perl on the same OS with the same libraries installed. The easiest way (if it works at all) would be to install cpanm and local::lib and do something like:
cpanm --local-lib some-dir Term::TermKey
Then you could copy some-dir to another machine (with the caveats listed above). It isn't necessary to install local::lib on the other machines; you can just
use lib 'some-dir/lib/perl5';

How can I install missing perl modules on an embedded system?

I'm running Linux on an embedded system, specifically Yocto Linux on a Cyclone V FPGA. I'm able to use Perl in its most basic form, but I'm unable to load any Perl modules. For example, when trying to use the GetOpt::Long module, I get the following error
root#socfpga_cyclone5:/mnt/sdcard# ./test.pl
Can't locate Getopt/Long.pm in #INC (#INC contains:
/etc/perl
/usr/lib/perl/site_perl/5.14.2/
/usr/lib/perl/site_perl/5.14.2
/usr/lib/perl/vendor_perl/5.14.2/
/usr/lib/perl/vendor_perl/5.14.2
/usr/lib/perl/5.14.2/
/usr/lib/perl/5.14.2
/usr/local/lib/site_perl
/usr/lib/perl/5.14.2
.) at ./test.pl line 3.
BEGIN failed--compilation aborted at ./test.pl line 3.
Does anybody know how I can go about installing these modules? Do the modules depend on hardware architecture at all? Is it reasonable to just copy and paste the .pm files somewhere from some source (and where would I be able to find and download these .pm files)?
I know your question is more than two years old, but it's a good question and I'm sad that nobody has answered it.
The perl ecosystem is very large, and the disk footprint of a full-featured perl installation is a problem on embedded systems. For that reason only a minimal system is installed when you add perl to your image. Other perl modules are available as bitbake packages.
Most of the time you can figure out what packages a recipe offers from the recipe, but the perl recipe is very complicated. The easiest way to find out what packages are built by the perl recipe is to build it (bitbake perl) and then look in the packages-split directory, which you will find in your bitbake work directory. For my system (cortex A8) that looks something like this:
$ ls -1 /poky/build/tmp/work/cortexa8hf-vfp-neon-poky-linux-gnueabi/perl/5.20.0-r1/packages-split
perl
perl-dbg
perl-dev
perl-doc
perl-lib
perl-lib.shlibdeps
perl-misc
perl-misc.shlibdeps
perl-module-anydbm-file
perl-module-app-cpan
perl-module-app-prove
perl-module-app-prove-state
(...)
If the module you want is listed, just add it to IMAGE_INSTALL like this:
IMAGE_INSTALL += "\
perl \
perl-module-base \
perl-module-bytes \
perl-module-data-dumper \
perl-module-digest-md5 \
perl-module-file-spec \
perl-module-file-spec-functions \
perl-module-findbin \
perl-module-getopt-long \
(...)"
If you want a module that isn't already being build, you will need to make your own recipe for it using the cpan class. See the examples in poky/meta/recipes-extended/perl and /poky/meta/recipes-lsb4/perl.
Editorializing, I've not been very happy with using perl on embedded systems. The biggest issue is the deferral of dependency resolution until runtime. It's too easy to mess this up and end up with Can't locate foobar.pm in #INC errors.
Have a look at this thread: https://lists.yoctoproject.org/pipermail/yocto/2013-July/015198.html
It sounds like perl modules have been packaged by whatever other thing needed first, but someone is working on making them available separately.
Some modules could be installed by just copying; others require a compiler or other build steps first. You are best off using whatever tools the yocto project provides.

Cant Locate Image/Info.pm Module Error

I'm trying to get the resolution,width,height of the images in the specific file.
I have the following code.
#use strict;
use Image::Info qw(image_info dim);
use File::List;
#perl2exe_include Image::Info::JPEG;
#perl2exe_include PerlIO;
my $file = <ImageFilePath>;
my $info = image_info($file);
my $res = $info->{resolution};
print "$$res[0]\n";
I have the Perl Version 5.16.3
I get the following error:
Can't locate Image/Info.pm in #INC (#INC contains: c:\program files\Perl\lib c:/program files/Perl/site/lib c:/program files/Perl/lib .) at Img_Res.pl line 3.
BEGIN failed--compilation aborted at Img_Res.pl line 3.
Can anyone give me the solution to this?
From the code part of question I am concluding that you are trying to create an executable using Perl2EXE, because you are using the line
#perl2exe_include Image::Info::JPEG;
and also assuming that you are running command
perl2exe c:\somepath\somescript.pl -o somescript.exe
The answer from #James Green is correct to an extent, however its incomplete (as in fails to explain his second bullet point).
You need to install "Image::Info" and any other modules that you are using (Use the answer from #James Green).
After installation, Open to windows explorer and locate the module that you just installed,
It will normally be in the following folders
"PERL_PATH\perl\lib"
"PERL_PATH\perl\site\lib"
"PERL_PATH\perl\vendor\lib"
Once you locate the module is installed in the one of the 3 locations above. Navigate to the location where Perl2EXE is installed.
PERL2EXE_PATH\perl2exe-XX.xx-Win\
Locate the folder with the current version of perl you are using. In your case the folder name should be
Win32-5.16.3 or Win64-5.16.3
Open the folder and locate the .conf file.
Edit the line with header libdir.
libdir=perl-Win32/site/lib;perl-Win32/lib;perl-Win32/vendor/lib;.
Ensure all the perl/lib directories are included in the search path.
Save it and rerun your command. This should work.
Sometimes even after all this the perl2exe command fails, this is due to the limitation of the program being able to decipher the qw command.
So to avoid this directly call the module (ex: use Module::Name;) in your code instead of using the qw.
You need to ensure you've done two things:
install the Image::Info module
make sure #INC includes the path to wherever you installed the module
I see you're on Windows, which means you're likely using either Strawberry Perl, or ActiveState's Perl. If you're using Strawberry Perl you should have some success following the directions on http://www.cpan.org/modules/INSTALL.html -- I believe ActiveState has its own built-in package manager, ppm, and to get started with that you'll want to look here: http://www.activestate.com/activeperl/ppm-perl-modules

Running Perl Scripts on servers that don't have the modules

I need to run a perl script to gather system information that will be deployed and executed on different unix servers.
Right now I am writing it and testing it, and I'm receiving this error.
Can't locate XML/DOM.pm in #INC (#INC contains: /usr/local/lib64/perl5
/usr/local/share/perl5 /usr/lib64/perl5/vendor_perl
/usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at
test.pl line 7. BEGIN failed--compilation aborted at test.pl line 7.
So I am simply using XML::DOM which should be part of Perl but it isn't for this version on this particular server which is 5.10.1.
Anyways, is there a way I can create and design my script and package modules into it while keeping the .pl extension, which is the requirement for this script?
If the modules don't require compiled libraries, you can include them by copying the text out of the module into your .pl file. That's a horrible hack but it should work.
Perl modules should contain a package statement that gives them their name. When you get to your main program section you'll need a package main; statement of your own.
You can put the modules in any directory, and then include this directory to be included in the search for modules via the lib pragma. Be aware that a module Foo::Bar has to be in the file MY-ROOT/Foo/Bar.pm and may not be in MY-ROOT/Bar.pm, where MY-ROOT is your module directory.
use lib 'MY-ROOT';
use Foo::Bar;
However, this only works for pure-Perl modules, and doesn't support XS.
In lieu of using the lib pragma as amon suggests, consider installing perlbrew and cpanminus which is designed to work hand-in-hand to add and/or update modules.
perlbrew is designed to be leveraged by specifying #!/usr/bin/env perl as the interpreter line in your Perl scripts while adding a line like source ~/perl5/perlbrew/etc/bashrc to your ${HOME}/.bash_profile to locate the local version of Perl you want.