Can't locate Config.pm in #INC - perl

I have a Perl app on my development server that I would like to replicate on my local machine (mac osx). I'm not a perl programmer by trade (I'm a PHP/Rails developer), and the developer of this app is no longer around so I can't contact him for help. I've gotten pretty close to getting it to work. I was able to install all the packages using CPAN (at least I think I got them all) but I keep running into the following error:
Can't locate WebCNP/Config.pm in #INC (
#INC contains: /Library/Perl/5.16/darwin-thread-multi-2level
/Library/Perl/5.16
/Network/Library/Perl/5.16/darwin-thread-multi-2level
/Network/Library/Perl/5.16
/Library/Perl/Updates/5.16.2/darwin-thread-multi-2level
/Library/Perl/Updates/5.16.2
/System/Library/Perl/5.16/darwin-thread-multi-2level
/System/Library/Perl/5.16
/System/Library/Perl/Extras/5.16/darwin-thread-multi-2level
/System/Library/Perl/Extras/5.16 .
)
at webcnp_lib.pl line 30.
On the server, the app's file structure looks like this:
/var/www/cgi-bin (empty dir)
/var/www/conf
/var/www/error
/var/www/html (empty dir)
/var/www/icons
/var/www/perl (the config file is located in this directory)
- /WebCNP/Config.pm
/var/www/ssi (all the .pl files for the app are located here, including all the JS and CSS files)
Line 30 of /var/www/ssi/webcnp_lib.pl has the following:
use WebCNP::Config;
Any ideas what I could be doing wrong?
Just so you know I've copied the file structure of the app from my development server to my local machine and created a virtual host so that it points to the app's root directory (/var/www).
Thanks in advanced for any insight!

was able to fix this with a symbolic link
ln -s /path/to/my/app/WebCNP /Library/Perl/5.16/WebCNP
I take this isn't a module from CPAN.
I would be a bit hesitant to use a symbolic link. This will work, but you're basically linking in a file you have under your own control to the master /Library directory on MacOS X. You delete your file, and that link won't be pointing to anything.
You can use use lib to add directories that contain your modules to the #INC directory:
use lib qw(/path/to/my/app);
This will now include this path for module searches.
If you rather install the module itself, why not simply copy it into /Lbrary/Perl/5.16 itself? It's what cpan would have done. At least this way, you're Perl module directory isn't dependent upon a link that can be removed.

/var/www/perl isn't present in #INC, so Perl won't look there. The most common approach to solve this for CGI scripts would be to add the following to your scripts (but not modules):
use FindBin qw( $RealBin );
use lib "$RealBin/../perl";

I was able to fix this with a symbolic link
ln -s /path/to/my/app/WebCNP /Library/Perl/5.16/WebCNP
Not sure if this is the most elegant approach, but seems to work well for this app. Thanks everyone for your replies! This has been very insightful.

Old post, I know, but there is a much more portable way. When you install the modules, you need to do two things.
Add the installation path to PERL5LIB (i.e. PERL5LIB=$PERL5LIB:/My/Module/Path/lib) in your environment configuration (.profile or other files which get read on system initialization)
Add a PREFIX to your perl Makefile.PL call (perl Makefile.PL PREFIX=/My/Module/Path)
It goes without saying that you need to make certain your Makefile.PL is written correctly.

Related

Perl: "Install" a custom module from a local .pm file into the Perl execution environment?

Perl newbie here with very little time and support to learn Perl but all the expectations from management to use it like a Perl Pro :)
I am using Perl (v5.30.2 by Larry Wall) under Cygwin (windows 10)
My developer issued a new script, that now uses a Perl module I didn't have.
They then sent me the .pm file (which they authored themselves and it is not on any online Perl repo).
I was unable to use CPAN to install that file into my Perl execution environment.
Where should the .pm file be saved at? (please specify the exact folder)
How to tell CPAN to install this file for usage? Ideally, a one-time affair, as I don't want to forget installing this file, if I have to do that every time I need to run the Perl script...
Just in case there may be any security concern from the dear answer-ers: There isn't any security concern here, this is all under an environment that has no connection to the internet.
A Perl module is just a file (or collection of files). You don't have to put them anywhere special, but you need to tell Perl where to find them.
When you call use or require with a bareword, Perl translates that module name, like Some::Module, into Some/Module.pm (or whatever is appropriate for your system. Anyone still using VMS?).
Once it has the filename form of the module, it looks for that subpath in the directories in #INC. It tries the first directory. If it doesn't find it it moves on to the next, and so on down the line. These directories are decided when someone configures and installs Perl. And, before v5.26, it included the current working directory (see v5.26 removes dot from #INC and Doesn't Perl include current directory in #INC by default?
)
But, you can tell Perl where else to look. perlfaq8 has How do I add a directory to my include path (#INC) at runtime?. ikegami also showed FindBin in the comments (How do I add the directory my program lives in to the module/library search path?).
Beyond that, you can tell require to load a path, although you then need to ensure that the program can find that path even if someone runs it from another directory
require './this_file/over/here';
require '/usr/local/lib/this_file/over/here';

Can't update #INC with export PERL5LIB

I'm trying to add the HTML::Entities module path to #INC. I did export PERL5LIB=/mypath/HTML/ followed by source ~/.bashrc. That path is reflected in PERL5LIB, but not in #INC. Is there an additional step that I'm missing?
I'm using perl 5.26.2 on CentOS6.5
Edit:
I (wrongly) assumed that my path wasn't being added to #INC because when I run my perl script I get
Can't locate HTML/Entities.pm in #INC (you may need to install the HTML::Entities module)
(#INC contains:
/home/hek/anaconda3/bin/aux/lib/perl5
/home/hek/anaconda3/lib/site_perl/5.26.2/x86_64-linux-thread-multi
/home/hek/anaconda3/lib/site_perl/5.26.2
/home/hek/anaconda3/lib/5.26.2/x86_64-linux-thread-multi
/home/hek/anaconda3/lib/5.26.2
)
(Line breaks added for readability)
But it does appear below
echo $PERL5LIB
/opt/rh/devtoolset-2/root//usr/lib64/perl5/vendor_perl:/opt/rh/devtoolset-2/root/usr/lib/perl5:/opt/rh/devtoolset-2/root//usr/share/perl5/vendor_perl:/opt/perl/lib/site_perl/5.14.2/x86_64-linux-thread-multi/HTML/
perl -e 'use Data::Dumper; print Dumper(\#INC), "\n"'
$VAR1 = [
'/opt/rh/devtoolset-2/root//usr/lib64/perl5/vendor_perl',
'/opt/rh/devtoolset-2/root/usr/lib/perl5',
'/opt/rh/devtoolset-2/root//usr/share/perl5/vendor_perl',
'/opt/perl/lib/site_perl/5.14.2/x86_64-linux-thread-multi/HTML/',
'/home/hek/anaconda3/lib/site_perl/5.26.2/x86_64-linux-thread-multi',
'/home/hek/anaconda3/lib/site_perl/5.26.2',
'/home/hek/anaconda3/lib/5.26.2/x86_64-linux-thread-multi',
'/home/hek/anaconda3/lib/5.26.2',
'.'
];
Why would there be this discrepency?
I do have multiple versions of perl installed, but which perl returns the version that I need to use, ~/anaconda3/bin/perl.
I tried changing the shebang in my script from #!/usr/bin/env perl to #!/~/anaconda3/bin/perl, but that didn't help.
Two possibilities:
Either the PERL5LIB env var wasn't set in the parent of the perl process giving the error (e.g. you launched it from a web server), or
The -T command line switch was provided to perl process giving the error (since this causes PERL5LIB to be ignored).
In either case, you can use use lib in the source instead of PERL5LIB.
use HTML::Entities looks for a file HTML/Entities.pm in the directories in #INC. No such path is found because it's looking for ones like /opt/perl/lib/site_perl/5.14.2/x86_64-linux-thread-multi/HTML/HTML/Entities.pm.
Leave off the HTML/ part in the directory you're trying to add to the search path and you might have better luck.
Edit: There's still the version mismatch, but as long as the module is pure Perl without any XS components I don't think that will be a big problem. Still better to get it in the right path for the version of perl you're actually using. Do that and you shouldn't have to manipulate the search path at all.
This is to summarize the problems and state what seems to be the simplest solution.
From the output of your test one-liner it is clear that a module installed under v5.14.2 is used in a program meant to run under v5.26.2. That is not good, even if it happens to work.
So install HTML::Entities under the perl build that needs it, v5.26.2.
That also solves the problem you are asking about, since then you won't have to muck about with PERL5LIB or anything else.
Further, the #INC in your one-liner test clearly isn't loaded in your real run, just as you suspected. Possible reasons are given in ikegami's answer, as well as the solution, to use lib "...";. But then you need to use the module version installed for v5.26.2, and once you installed it with that perl there'll actually be no need to specify extra library paths.
Finally, if you end up needing to add that path for some reason, leave off the HTML (last) directory, as Shawn's answer indicates. With use HTML::Entities the directory HTML will be searched (for Entities.pm file) and you only need to provide the directory that contains it.

Perl - Use lib with perl module which have dependencies

I have a Perl script which uses the module Net::SSH::Any. Since it does not belong to the “default” Perl installation, I have to use the use lib functionality to include it in my script.
Now, I have the directory c:\lib\net\ssh\any\ on my drive and I specify this: use lib c:/lib; at the beginning of my script.
It “works”: it didn’t say that the module is missing but it says that it couldn’t locate auto/Net/SSH2/autosplit.ix and at the end no backend available at...
When I add the auto directory (containing the correct structure) in the c:\lib\ directory and launch the script, I get this error:
No backend available at...
Which is an internal error of Net::SSH::Any mentioning it could not access the backend directory (which is already included :/)
Does anyone know how to solve something like that? I hope I was clear enough.
You need to use Local::Lib.
This will let you install and load a whole bunch of libraries and their dependencies in an alternate location. I use cpanm to manage my modules and a command something like this (which I put in a wrapper script).
cpanm -L $cpandir $M --no-skip-installed
Where $cpandir is your locallibdir and $M is the module you are trying to install.
Then in your code you would specify
use local::lib '~/foo';
However, I recommend setting a PERL5LIB environment variable, which will append your custom location to #INC and make the extra use local::lib line unnecessary. You would typically edit .bashrc or .profile in your home directory with a line like:
export PERL5LIB=/home/myusername/mymods/
The issue was caused by the fact that the module was downloaded and installed on a 32bits windows but I tried to run it on a perl 64bits installation! So the Net::SSH2 required module couldn't be executed properly.
To resume:
-How to detect the issue: by executing this command: (thanks to Salva)
"perl -Ic:\lib -MNet::SSH2 -e1"
-Modules definitions in my script:
use lib 'c:\lib';

Where to find the perl shared objects directory?

I just purchased a commercial perl shared object that is really light on its documentation. Specifically it's an ".so" file and I know that it needs to go into whatever directory perl is using to find shared objects.
Normally I encounter ".pm" files and know how to install those with no problem, but this is the first time I have ever used something in perl where I had to install a ".so" file, or copy it to a directory.
Anyone know how I would find this directory? It's at a level of Perl's sausage making which I'm not familiar with (plus I'm a bacon gal anyway. LOL!).
Janie
Update: (for more clarity). The company that sold this has the file named as "hcmodule.so". Their example perl script has a use pragma in it of "use hcmodule" and a call later as..
$retval = hcmodule( ........ <SNIP>..);
If this helps unmurky things a bit.
Perl loads shared objects from directories under its lib directory. In some installations of Perl, that will be the lib directory parallel to the bin directory where the main Perl binary is found. In some systems, it will be located elsewhere. For example, my own build of Perl (5.14.1 on MacOS X) says (part of output from perl -V):
#INC
/Users/jleffler/Perl/v5.14.1-64/lib/perl5/site_perl/5.14.1/darwin-2level
/Users/jleffler/Perl/v5.14.1-64/lib/perl5/site_perl/5.14.1
/Users/jleffler/Perl/v5.14.1-64/lib/perl5/5.14.1/darwin-2level
/Users/jleffler/Perl/v5.14.1-64/lib/perl5/5.14.1
On the other hand, the system Perl (5.12.3) says:
#INC:
/Library/Perl/5.12/darwin-thread-multi-2level
/Library/Perl/5.12
/Network/Library/Perl/5.12/darwin-thread-multi-2level
/Network/Library/Perl/5.12
/Library/Perl/Updates/5.12.3
/System/Library/Perl/5.12/darwin-thread-multi-2level
/System/Library/Perl/5.12
/System/Library/Perl/Extras/5.12/darwin-thread-multi-2level
/System/Library/Perl/Extras/5.12
The shared objects on MacOS X have a .bundle extension (instead of .so), and some of the bundles I have are:
.../lib/perl5/site_perl/5.14.1/darwin-2level/auto/DBD/Informix/Informix.bundle
.../lib/perl5/site_perl/5.14.1/darwin-2level/auto/DBD/SQLite/SQLite.bundle
.../lib/perl5/site_perl/5.14.1/darwin-2level/auto/DBI/DBI.bundle
The corresponding PM files are:
.../lib/perl5/site_perl/5.14.1/darwin-2level/DBD/Informix.pm
.../lib/perl5/site_perl/5.14.1/darwin-2level/DBD/SQLite.pm
.../lib/perl5/site_perl/5.14.1/darwin-2level/DBI.pm
In any case, Perl will expect to look for the .so file in a directory related to the name of the module. There should be install instructions, especially since you paid for it. There will be (at least) a shared object and a .pm file to be installed, in two related related directories.
Have you tried perl -V to see if it has the information you want? Do you have the environment variable LD_LIBRARY_PATH set?
I'm on Linux, and doing perl -V (uppercase V) showed that Perl libraries are in /usr/lib/perl/5.10 and a few other libraries.
Exactly what Perl *.so file did you purchase? I've never heard of someone selling Perl shared libraries.

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?