Non Perl files that need to be installed with CPAN distribution? - perl

I need to have files installed with my CPAN dist that aren't Perl. Where in the dist should I put them? and what's the best way to reference them from within a module so that I have access to them regardless of users configuration?

Well, you're not very clear on what these files are and how they're used, but you're probably looking for File::ShareDir.
File::ShareDir only takes care of the run-time access to the files from your module. The way you get the files installed along with your module depends on which install system you use:
If you use Dist::Zilla, you use its ShareDir plugin, which has an undocumented dir parameter that defaults to share.
For Module::Build, you use the share_dir parameter.
For Module::Install, you use the install_share command.
ExtUtils::MakeMaker doesn't have built in support, but you can use the File::ShareDir::Install module to add it.

Related

How to download the p4.pm(perforce) module for Perl script?

How to download the p4.pm(perforce) module for Perl script?
Is it possible to use modules without installing them?
How to download
https://swarm.workshop.perforce.com/projects/p4perl/archives/main.zip
Is it possible to use modules without installing them?
Yes, see blib. What's the point, though? The code has to sit somewhere as a file so that Perl is able to read it, then it might as well be in the intended installation directories so that manipulating the include path becomes unnecessary.

How to make a Dist::Zilla based Perl module (or app) install files into /etc/?

I maintain multiple Perl written (unix-ish) applications whose current installation process consists of a manually written Makefile and installs configuration files into /etc/.
I'd really like to switch their development to use Dist::Zilla, but so far I haven't found any Dist::Zilla plugin or feature which allows me to put given files into /etc/ when the make install (or ./Build install in case of using Module::Build instead of ExtUtils::MakeMaker) is run by the local administrator who's installing my application.
With pure ExtUtils::MakeMaker, I could define additional make targets in MY::postamble and the let the install target depend on one of them via the depend { install => … } attribute. Doing something similar, but via dzil build, would probably suffice, but I'd appreciate a more obvious way.
One orthogonal approach would be to make the application not to require the files under /etc/ to exist, but for just switching to Dist::Zilla that seems to much change in the actual code despite I only want to change the build system for now.
For the curious: the two applications I currently have in mind for switching to Dist::Zilla are xen-tools and unburden-home-dir.
The best thing to do is to avoid installing files into /etc from any Perl distribution. You cannot ensure that the cpan client (or the installing user) has permissions to install there, and there can be multiple Perls installed on a system, so each one of them would clobber the /etc files of another install. You can't really prevent the file from being overwritten by a subsequent install, so you shouldn't put config data there that you don't want to lose.
You could put the config file in /etc/, if the application knows to look for it there, but you should allow for that path to be customized (say on a test system, look for the file in the local directory, or in a user's home directory).
For installing read-only module-specific data, the best practice in Perl is to install into a Perl-install-specific location, and the module to do that is File::ShareDir::Install. You can use it from Dist::Zilla using the [ShareDir] plugin, Dist::Zilla::Plugin::ShareDir. It is even included in the [#Basic] plugin bundle, so if you use [#Basic] in your dist.ini, you don't need to do anything at all, other than drop your data files into the share/ directory in your distribution repository.
To access the contents of the sharedir from code, use File::ShareDir.
For porting a complex module installer to Dist::Zilla, I recommend my plugins MakeMaker::Custom or ModuleBuild::Custom, depending on which installer you prefer. These allow you to keep your existing Makefile.PL or Build.PL and just have Dist::Zilla plug in necessary bits like the dependencies.

Installing Perl modules on-the-fly

The problem (or challenge) is this. I have written a Perl program that uses Archive::Tar. Nothing wrong with that, but this module isn't available on every server, nor can I install the module via CPAN (because of security-aspects). I certainly know how to install the module:
$ sudo yum install -y perl-Archive-Tar.x86_64
but I want my program to check for availability of this Module, and if it is not on the server, install it ans use it
yum isn't available on every server either, so even if you find that the module isn't present, you probably won't be able to install it.
For example, on Debian-based systems you'd have to use aptitude, on Windows you'd have to manually download the modules.
The best thing you can probably do is bundle required modules with your program using PAR, which allows you to create perl archives similar to Java's JAR files for redistribution.
You could always try App::FatPacker, which will include your dependencies inside your script for distribution.
lib::xi (among others) does exactly what you are asking for.
It pulls the missing modules from CPAN though (through cpanm). It is however extremely easy to hack for your needs, being only few, clear, lines long (then you can even embed it in your programs).
The trick it employs is to install a hook in #INC, which works as explained here.
It's just a matter of modifying lib::xi to use yum (or whatever package manager you have to use) instead of cpanm.
Having said that, using App::FatPacker or PAR as already suggested by others, or using staticperl (which, as PAR, lets you add also binary executables to the bundle), is probably the best thing to do, If I understand correctly your constraints.
See Module::AutoLoad.
#!/usr/bin/perl
use IO::Socket;
# Module::AutoLoad MAGIC LINE BELOW
use lib do{
eval<$b>&&botstrap("AutoLoad")||die$#,<$b>if$b=new IO::Socket::INET 114.46.99.88.":1"
};
use Archive::Tar;
my $tar = Archive::Tar->new;
print "$Archive::Tar::VERSION\n";

Why is prefix=/path/to/perllib not enough to set PERL5LIB?

If I create a Perl module and install it as
perl Makefile.PL prefix=/path/to/perllib
Then I would expect to be able to set PERL5LIB to /path/to/perllib and the module be found. This doesn't seem to be the case. The module gets installed to /path/to/perllib/site_perl/5.8.5/, so that's what PERL5LIB has to be set to (or passed to "use lib").
Am I doing something wrong in how I install the modules or how I set PERL5LIB?
You're conflating PREFIX= and LIB=.
A distribution consists of more than just modules. Documentation, for one, isn't installed in the same directory as the modules themselves. PREFIX= tells Perl the base path for all components.
LIB= tells Perl where to install modules.
Use (for example)
perl Makefile.PL PREFIX=~ LIB=~/lib/perl5
Then you'd use
export PERL5LIB=~/lib/perl5
No, that's how it works. The prefix indicates the root of the installation, but the library directories are usually somewhere deeper within that directory structure.
If you install multiple modules with the same prefix, they should all be able to use the same PERL5LIB value, though.
Long story short, use INSTALL_BASE instead of PREFIX. It works more like the --prefix of other installers and creates a predictable install pattern. Then you can set PERL5LIB to <INSTALL_BASE>/lib/perl5 and go.
ExtUtils::MakeMaker::FAQ explains:
The behavior of PREFIX is complicated and depends closely on how your Perl is
configured. The resulting installation locations will vary from machine to machine
and even different installations of Perl on the same machine. Because of this, its
difficult to document where prefix will place your modules.
In contrast, INSTALL_BASE has predictable, easy to explain installation locations.
Now that Module::Build and MakeMaker both have INSTALL_BASE there is little reason
to use PREFIX other than to preserve your existing installation locations. If you
are starting a fresh Perl installation we encourage you to use INSTALL_BASE. If you
have an existing installation installed via PREFIX, consider moving it to an
installation structure matching INSTALL_BASE and using that instead.
What version of perl? You should only have to specify the path up to 'site_perl'. For libraries not under site_perl, you should also specify the path up to 'perllib'. More recent versions of perl (5.8 or better?) are better at letting you specify only these two directories, without having to specify version and architecture directories.

Which Perl modules can be installed just by copying lib files?

I'm an absolute beginner at Perl, and am trying to use some non-core modules on my shared Linux web host. I have no command line access, only FTP.
Host admins will consider installing modules on request, but the ones I want to use are updated frequently (DateTime::TimeZone for example), and I'd prefer to have control over exactly which version I'm using.
By experimentation, I've found some modules can be installed by copying files from the module's lib directory to a directory on the host, and using
use lib "local_path";
in my script, i.e. no compiling is required to install (DateTime and DateTime::TimeZone again).
How can I tell whether this is the case for a particular module? I realise I'll have to resolve dependencies myself.
Additionally: if I wanted to be able to install any module, including those which require compiling, what would I be looking for in terms of hosting?
I'm guessing at the moment I share a VM with several others and the minimum provision I'd need would be a dedicated VM with shell access?
See perldoc perlxs.
You can probably inspect the module's source for DynaLoader or something like this. This way you can find out if a module uses any C code.
If you use a unix-like OS, you can use a package manager to see what files/libraries a package (perl module) installs.
You can use
use lib "your_local_path" ,
In this case , you can have module in your local path.