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

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.

Related

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

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.

Force Exclude /usr/lib64/perl5 Library Directory from Custom Perl Install

I need to create a custom system-wide perl install on a CentOS machine. I don't want to use perlbrew as I want to alter the config variables myself, plus I get the same linkage problems.
Essentially, I cannot figure out how to compile perl so that /usr/lib64/perl5 is not included by the linker or in #INC. That is the old centos version, and it sucks. No matter how I compile though, perl -V yeilds this:
#INC:
/usr/local/lib64/perl5
/usr/lib64/perl5/vendor_perl
/usr/local/perl5/lib/site_perl/5.16.3/x86_64-linux-thread-multi-ld
/usr/local/perl5/lib/site_perl/5.16.3
/usr/local/perl5/lib/5.16.3/x86_64-linux-thread-multi-ld
/usr/local/perl5/lib/5.16.3
And then when I run, I get insane library errors like this: undefined symbol: Perl_Gthr_key_ptr from libraries inside /usr/lib64/perl5.
Note that PERL5LIB has no effect on this, it is compiled in.
Thanks.
In order to remove a directory from #INC, you can use no lib. For example,
no lib "/usr/lib64/perl5/";
would remove the /usr/lib64/perl5/ directory from #INC.
For more, try perldoc lib.

#INC Perl- Can't locate Class/CSV.pm in #INC

I am currently trying to create/generate a CSV file using one of three classes:
use Class::CSV;
use Text::CSV;
use Text::CSV_XS;
Though when I try and run it, to check my code I come up with the same error message:
Can't locate Class/CSV.pm in #INC (#INC contains: C:/Per/site/lib C:/Perl/lib .) at C:\Users\<DIRECTORY> - <DIRECTORY>.file.pl line1
I have tried searching for the files though I haven't had any luck. Has anyone else come up against this problem? I have looking in the Directory and the CSV.pm file does exists.
Assuming that Class::CSV is installed on your system, your library search path is incomplete. (Your error message lists C:/Per/site/lib as a search lib, which looks like a typo for C:/Perl/site/lib, which you might want to look into.)
You need to locate the correct CSV.pm file where the library is located. For example, if it's found in:
C:/Perl/lib/foo/Class/CSV.pm
Then you have one of the following options.
Modify the environment for Perl or the invocation so that this is set (assuming my Windows skill haven't expired completely, someone feel free to edit and correct if I get the syntax wrong):
PERL5LIB=%PERL5LIB%;C:/Perl/lib/foo
You can use the -I option to perl to add the path:
perl -IC:/Perl/lib/foo my-app.pl
You can use the use lib command in the program itself to add the search path:
use lib 'C:/Perl/lib/foo';
use Class::CSV;
# etc.
You probably don't have these modules installed.
run this in your shell
perl -MCPAN -e shell
then run
install Class::CSV
I'm assuming that you found these classes on CPAN
You can simply run the following command
perl -MCPAN -e 'install Class::CSV'
to run
install Class::CSV in CPAN shell.

Building perl module gives metafile error

I'm working on installing a perl module (not using CPAN) on a Linux machine. When I run the command:
perl Build.PL
I get the following error:
ERROR: Missing required field 'dist_abstract' for metafile
Could not get valid metadata. Error is: Invalid metadata structure.
Errors: Missing mandatory field, 'abstract' (abstract) [Validation: 1.4],
value is an undefined string (abstract) [Validation: 1.4]
at /usr/local/share/perl5/Module/Build/Base.pm line 4559
Could not create MYMETA files
I've tried Googling bits and pieces of this error but haven't found any solutions. Just looking for a clue as to what might be causing this error.
Here's a link to a zip file containing the files required to install it:
https://oncourse.iu.edu/access/content/user/brilewis/Filemanager_Public_Files/DataDownloader.zip
First at all please make sure you have package Module::Build installed.
You need ungzip few gzipped files in this package. I don't realize why author gzipped them:
gzip -d *.gz
I really don't know why author archived each install file. It looks like some mistake to me.
Than you can install all dependencies (this module requires some):
./Build installdeps
And then finally install module itself:
./Build
./Build test
./Build install
However I must warn you that this module packaged in a bit strange way and there's no guarantee it works.
The NAME section of the module does not have a - in it, e.g.,
=head1 NAME
Foo::Bar implements a Foo framework.
will fail, but if you make it
=head1 NAME
Foo::Bar - implements a Foo framework.
then it will work.
Do you have root access on your machine? Can you use the cpan utility to build and install your module. Using cpan is fairly straight forward:
$ cpan
After that, it will do a lot of configuration, simply take the default values. When it finishes, it'll come to a cpan> prompt. All you have to do there is type this:
cpan> install Module::Name
Where Module::Name is the module you're trying to install. Check the CPAN archive to get the name of your module.
If there are any dependencies, CPAN will ask if you want to download and install those. Say Yes, and CPAN will install the dependencies, then your module.
Using cpan is the best way to install third party modules you find in the CPAN archive. It takes care of all the dependencies, testing, and building for you.
Try installing through CPAN, and then see if you still have your issues.

How do I use a dependency on a Perl module installed in a non-standard location?

I need to install two Perl modules on a web host. Let's call them A::B and X::Y. X::Y depends on A::B (needs A::B to run). Both of them use Module::Install. I have successfully installed A::B into a non-system location using
perl Makefile.PL PREFIX=/non/system/location
make; make test; make install
Now I want to install X::Y, so I try the same thing
perl Makefile.PL PREFIX=/non/system/location
The output is
$ perl Makefile.PL PREFIX=/non/system/location/
Cannot determine perl version info from lib/X/Y.pm
*** Module::AutoInstall version 1.03
*** Checking for Perl dependencies...
[Core Features]
- Test::More ...loaded. (0.94)
- ExtUtils::MakeMaker ...loaded. (6.54 >= 6.11)
- File::ShareDir ...loaded. (1.00)
- A::B ...missing.
==> Auto-install the 1 mandatory module(s) from CPAN? [y]
It can't seem to find A::B in the system, although it is installed, and when it tries to auto-install the module from CPAN, it tries to write it into the system directory (ignoring PREFIX). I have tried using variables like PERL_LIB and LIB on the command line, after PREFIX=..., but nothing I have done seems to work.
I can do make and make install successfully, but I can't do make test because of this problem. Any suggestions?
I found some advice at http://servers.digitaldaze.com/extensions/perl/modules.html to use an environment variable PERL5LIB, but this also doesn't seem to work:
export PERL5LIB=/non/system/location/lib/perl5/
didn't solve the problem.
The answer is local::lib, but you probably already know that :)
OK, the following prescription did it:
perl Makefile.PL --skipdeps --no-manpages PREFIX=/non/system/location INSTALLSITELIB=/non/system/location/lib INSTALLSITEBIN=/non/system/location/bin INSTALLMAN1DIR=/non/system/location/man/man1 INSTALLMAN3DIR=/non/system/location/man/man3
This is just "monkey see monkey do" but now make test works.
The --skipdeps option here suppresses a convenient feature/exasperating problem with Module::Install where it tries to use CPAN.pm to download missing modules.
The --no-manpages is supposed to stop it installing man pages but it doesn't work.
Because this is the top link i thought i'd update with my experience (which has taken a while to get working, hence updating the 7 year old post).
first run perl -le 'print join $/, #INC'
add (note, no / at the end!!)
export PERL5LIB=/nonstddir/scripts/modules/lib/site_perl:/nonstddir/scripts/modules/lib
run perl -le 'print join $/, #INC' make sure the new dirs are added. this makes it work. if you add a / at the end of the path, the INC entry will look weird and wrong. Mine had a // in the middle.
When done and working, mine looks like
/nonstddir/scripts/modules/lib/site_perl/5.8.4/sun4-solaris-64int
/nonstddir/scripts/modules/lib/site_perl/5.8.4
/nonstddir/scripts/modules/lib/site_perl
/nonstddir/scripts/modules/lib/sun4-solaris-64int
/nonstddir/scripts/modules/lib
/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/site_perl
/usr/perl5/vendor_perl/5.8.4/sun4-solaris-64int
/usr/perl5/vendor_perl/5.8.4
/usr/perl5/vendor_perl