Where to put non-essential .pl files in a distribution? - perl

I would like to include a few additional .pl files in my CPAN module. These files are not essential to use the module, but are provide useful functionality/glue when the module is used in some common frameworks and applications.
Currently, I just include the .pl files in a "extras" directory of the distribution. This has the drawback that the files are not installed on make install. Is there a way to include them in the installation and where should they go? (They aren't executables and don't belong in "bin".) Would "share" make sense? Or are these kinds of files usually just not installed and it is left to the user to get them out of the .tgz archive and use as needed?
I use Dist::Zilla to manage my distribution.

I would suggest the following:
If they're actual complete programs or are almost complete, polish then up and make them standalone items that could go into /bin with POD of their own.
If they're utility glue, make a ::Utils module for them to live in and document their usage.
If these are useful code snippets but not something you can install somewhere or are sample usages or handy idioms, create a ::Cookbook all-POD module and include them there with the appropriate illuminating explanation for each one.

I don't know exactly how Dist::Zilla works, but the resulting archive has to be compatible with what ExtUtils::MakeMaker creates.
When you create a module with module-starter, it creates a module template using ExtUtils::MakeMaker. It creates several files and directories like the lib directory where your module lives and the t directories where your tests live.
One thing it doesn't create is a bin directory. However, if you create a bin directory, and you put files under this directory (such as Perl scripts), these files will be installed under the bin directory in your Perl's distribution and linked to /usr/local/bin or /usr/bin. Would this be a good place for your scripts?

I liked #Joe's answer, except that in my case the files were WebWork macros -- individual .pl files that make my module callable from WebWork end-user's code. So they don't fit under any of the categories discussed here, and as .pl files can't be made a module.
This is what I ended up doing:
put all .pl macro files into 'extras/WebWork' in the distribution.
add to "dist.ini" file a [ShareDir] stanza with dir = extras property.
now the WebWork admin can install my distribution from CPAN and then use perl -MFile::ShareDir -e 'print File::ShareDir::dist_dir("Statistics-R-IO")' to find the macros and make them available in WebWork.

Related

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.

dpan does not find Perl module in package root

We use MyCPAN::App::DPAN (Version 1.28) just like in Question: How can I manage Perl module dependencies?
This works quite well in general. But we ran into troubles with some specific packages:
As expample DBD::Oracle does not have their main *.pm file in DBD-Oracle-1.27/lib/DBD/Oracle/Oracle.pm but in DBD-Oracle-1.27/Oracle.pm.
It seems that dpan does not find this *.pm file, since it is not listed in modules/02packages.details.txt.gz. Whereas DBD::Oracle::Object (other Perl-Module of this distribution, but located DBD-Oracle-1.27/lib/DBD/Oracle/) is listed there.
In dpan.conf we only have set the recommended values:
dpan_dir /some/dir
indexer_id Me
pause_full_name The Admin Team
pause_id TAT
system_id my system id
Other Packages with the same problem:
Apache::DB
Packages that work:
Crypt::Blowfish (no extra modules)
Math::Round (no extra modules)
XML::Twig (no "lib" dir, but extra modules)
Does someone have any tips/hints?
DPAN works by indexing the distributions and storing the results in a file in the indexer_reports directory. As a workaround until I can investigate your problem, you can just edit the report it created for the problem distributions. As long as you haven't set fresh_start in your configuration, it will use the cached report which you have edited to add the missing module.

Can I move a Perl installation from one computer to another computer?

I am trying to set up an application dependant on few Perl modules, but the server I am installing to, does not have Internet connection. I read about offline module installs via ppd files, however I would have to resolve all the dependencies one by one.. All the more tedious considering I don't have direct internet connection.
I am hoping to find a solution, where I install ActivePerl on my PC and install all the libraries that I want and then copy paste the directories to my server. If it is just a matter of fixing some environment variables, that would be fine. Just want to know the definitive list of variables to modify. Not sure whether it is mandatory to install the perl libraries on the computer in which it is intended to run? (One is 32 bit platform and other one is 64 bit, but the server is already running various 32 bit applications so I hope it is not a major problem) For best compatibility, I plan to install ActivePerl on both the systems and merge the library directories to be identical.
The answer was on Perl FAQ, my bad didn't go through it properly.
I copied the perl binary from one machine to another, but scripts don't work.
That's probably because you forgot libraries, or library paths differ.
You really should build the whole distribution on the machine it will
eventually live on, and then type "make install". Most other approaches
are doomed to failure.
One simple way to check that things are in the right place is to print
out the hard-coded #INC that perl looks through for libraries:
% perl -le 'print for #INC'
If this command lists any paths that don't exist on your system, then
you may need to move the appropriate libraries to these locations, or
create symbolic links, aliases, or shortcuts appropriately. #INC is also
printed as part of the output of
% perl -V
You might also want to check out "How do I keep my own module/library
directory?" in perlfaq8.
From this link
Occasionally, you will not be able to
use any of the methods to install
modules. This may be the case if you
are a particularly under-privileged
user - perhaps you are renting web
space on a server, where you are not
given rights to do anything.
It is possible, for some modules, to
install the module without compiling
anything, and so you can just drop the
file in place and have it work.
Without going into a lot of the
detail, some Perl modules contain a
portion written in some other language
(such as C or C++) and some are
written in just in Perl. It is the
latter type that this method will work
for. How will you know? Well, if there
are no files called something.c and
something.h in the package, chances
are that it is a module that contains
only Perl code.
In these cases, you can just unpack
the file, and then copy just the *.pm
files to a directory from which you
will run the modules. Two examples of
this should suffice to illustrate how
this is done.
IniConf.pm is a wonderful little
module that allows you to read
configuration information out of a
.ini-style config file. IniConf.pm is
written only in Perl, and has no C
portion. When you unpack the .tar.gz
file that you got from CPAN, you will
find several files in there, and one
of them is called IniConf.pm. This is
the only file that you are actually
interested in. Copy that file to the
directory where you have the Perl
programs that will be using this
module. You can then use the module as
you would if it was installed
``correctly,'' with just the line:
use IniConf;
Time::CTime is another very handy
module that lets you print times in
any format that strikes your fancy. It
is written just in Perl, without a C
component. You will install it just
the same way as you did with IniConf,
except that the file, called CTime.pm,
must be placed in a subdirectory
called Time. The colons, as well as
indicating an organization of modules,
also indicates a directory structure
on your file system.

How do I start a new Perl module distribution?

I'm trying to set up a large-ish project, written in Perl. The IBM MakeMaker tutorial has been very helpful so far, but I don't understand how to link all the modules into the main program. In my project root, I have MANIFEST, Makefile.PL, README, a bin directory, and a lib directory. In my bin directory, I have my main script (Main.pl). In the lib directory, I have each of my modules, divided up into their own respective directories (i.e. Utils::Util1 and Utils::Utils2 in the utils directory, etc). In each module directory, there is also a t directory, containing tests
My MANIFEST file has the following:
bin/Main.pl
lib/Utils/Util1.pm
lib/Utils/Util2.pm
lib/Utils/t/Utils1.t
lib/Utils/t/Utils2.t
Makefile.PL
MANIFEST
README
Makefile.PL is the following:
use ExtUtils::MakeMaker;
WriteMakefile(
'NAME'=>'Foo',
'VERSION_FROM'=>'bin/Main.pl',
'PREREQ_PM'=>{
"XML::Simple"=> 2.18}, #The libraries that we need and their
#minimum version numbers
'EXE_FILES' =>[("bin/Main.pl")]
);
After I make and run, the program crashes, complaining that it cannot find Utils::Util1, and when I run 'make test, it says no tests defined. Can anyone make any suggestions? I have never done a large scale project like this in perl, and I will need to add many more modules
If you are just starting to create Perl modules (which is also Perl's equivalent of a project), don't use Makemaker. Module::Build is the way to go, and it's now part of the standard library. Makemaker is for us old salts who haven't converted to Module::Build yet. :) I'll strike that now that Module::Build is unmaintained and out of favor; I still use MakeMaker.
You should never start off a Perl project by trying to create the structure yourself. It's too much work and you'll always forget something.
There's h2xs, a program that comes with perl and was supposed to be a tool to convert .h files into Perl's glue language XS. It works fine, but its advantage is that it comes with perl:
% h2xs -AXn Module::Name
Something like Module::Starter is a bit more sophisticated, although you have to get it from CPAN. It's the tool we use in Intermediate Perl because it's simple. It fills in some templates with your information:
% module-starter --author=... --email=... --module=...
If you are doing to do this quite a bit, you might then convert that to Distribution::Cooker so you can customize your files and contents. It's a dinky utility I wrote for myself so I could use my own templates.
% dist_cooker Module::Name
If you're really hard core, you might want Dist::Zilla, but that's more for people who already know what they are doing.
Might I also suggest module-starter? It'll automatically create a skeleton project which "Just Works". I learned what little I know about Perl modules organization by reading the generated skeleton files. It's all well-documented, and quite easy to use as a base for growing a larger project in. You can check out the getting-started docs to see what it gives you.
Running module-starter will give you a Perl distribution, consisting of a number of modules (use the command line option --module, such as:
module-starter --distro=Project --module=Project::Module::A,Project::Module::B [...]
to create multiple modules in a single distribution). It's then up to you whether you'd prefer to organize your project as a single distribution consisting of a number of modules working together, or as a number of distributions which can be released separately but which depend on each other (as configured in your Build or Makefile.PL file) to provide a complete system.
Try this structure:
bin/Main.pl
lib/Utils/Util1.pm
lib/Utils/Util2.pm
Makefile.PL
MANIFEST
README
t/Utils1.t
t/Utils2.t
As ysth said, make does not install your modules, it just builds them in a blib directory. (In your case it just copies them there, but if you had XS code, it would be compiled with a C compiler.) Use make install to install your modules for regular scripts to use.
If you want to run your script between make and make install, you can do:
perl -Mblib bin/Main.pl
The -Mblib instructs perl to temporarily add the appropriate directories to the search path, so you can try out an uninstalled module. (make test does that automatically.)
By default, tests are looked for in a top-level t directory (or a test.pl file, but that has some limitations, so should be avoided).
You say "After I make and run"...make puts things into a blib directory structure ready to be installed, but doesn't do anything special to make running a script access them. (make test is special; it does add appropriate paths from blib to perl's #INC to be able to run the tests.) You will need to do a "make install" to install the modules where your script will find them (or use a tool like PAR to package them together with your script).

How can I force Perl to run the module from the test directory only?

I have perl module file and test script pl which I use to run some function, and after browsing through the use lib and this previous question here...
I still don't know how to do this.
Basically I have a production directory which contains the module file, and I have a test directory file which contains the same module and the test script file. each time I try to run the script file, it will automatically calls the module in the directory. by printing out the #INC, it seems that the production directory is hosted in there. thus I try to remove it by using
no lib qw(prod_dir);
and while printing out the #INC shows that the directory is no longer there, somehow the script is still calling that other module...
I know this probably sounds really dumb, but hope someone can help me see the light here :)
thanks.
After you have required or used the module, check %INC to see where it came from.
For example:
use Data::Dumper;
print $INC{'Data/Dumper.pm'}."\n";
Note that "::" becomes "/" and you append ".pm". That might give you a clue.
Remember that the current directory (".") is usually an entry in #INC. But the first step is finding out what directory the module was loaded from.
Another thing to remember is that the directories in #INC are searched in order. use lib prepends to that list (making it the first-searched directory), so you may just need to add the appropriate directory.
Can you say more about what you are trying to do and how you are trying to do it? Is this stuff in a standard Perl distribution structure? If you aren't using the standard distribution structure, can you show us a directory listing so we know where things are? Can you also include the code you use to try to load the module? Just update your original question when you pull together the details.
Typically, I run tests through the build runner, which automatically sets up the right #INC.
If I want to run one test in my distribution, I use the blib module to find the build library which has the development versions of my modules:
% perl -Mblib t/test.t
Some people do the same thing with prove.
If you aren't using the basic distribution set-up, consider using it. The tools and best techniques rely on it.
If you just have your module and test file in the same directory, have you tried adding the current directory to #INC with PERL5LIB?