I have multiple versions of Perl installed; each under a different directory. e.g. C:\Perl\5.x.y. I switch between them in a shell by setting PERL5LIB and altering my PATH so that only one version is visible at a time. Normally, this works fine, but when trying to run the version of pp (PAR::Packer) installed under 5.10.1 I have problems loading XS components. parll2nc.exe complains:
This application has failed to start because perl512.dll was not found...
I set PERL_DL_DEBUG and see the following when DynaLoader initializes:
DynaLoader.pm loaded (C:/Perl/5.10.1/site/lib C:/Perl/5.12.1/lib ., \lib)
The stuff before the comma is #INC. The first entry is correct, the second is not. I can't figure out how DynaLoader is getting a 5.12 lib path as running perl directly shows what I would expect:
C:\>perl -e "print join ' ', #INC"
C:/Perl/5.10.1/site/lib C:/Perl/5.10.1/lib .
How is DynaLoader picking up the wrong path and how do I prevent it from doing so?
Similar to the approach I suggested for this question, put a trace on #INC and see when it gets updated.
At the very top of your script, before any other use statements, put:
use Tie::Trace;
BEGIN { Tie::Trace::watch #INC };
Then you will get a warning message when another module edits your #INC array.
I figured it out. The problem is caused by an interaction of several things:
I have *.pl files associated with perl.exe (for the most recent version of Perl installed -- 5.12.1).
I have ".PL" in my PATHEXT environment variable so that I can run Perl scripts without typing the extension. e.g. C:\>foo instead of C:\>foo.pl
My installation of the pp utility does not have a batch file wrapper created with pl2bat. (I'm not sure why.)
The net result is that when I ran pp #myconfig it effectively did this:
C:\Perl\5.12.1\bin\perl.exe C:\Perl\5.10.1\site\bin\pp.pl #myconfig
i.e. it ran the version of pp.pl in my path using the version of perl associated with *.pl files, not the version of perl in my PATH. Thus the mix of libs in #INC between what came from the executable (C:\Perl\5.12.1\lib) and what came from the PERL5LIB environment variable (C:\Perl\5.10.1\site\lib).
The solution is to either run pp as perl pp.pl or (better, because you don't have to remember anything) to create a batch wrapper. Assuming that .BAT is in PATHEXT before .PL, when you type pp Windows will run pp.bat instead of pp.pl, and pp.bat invokes perl (using the version in your path).
sigh
Related
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.
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';
Is possible to use different version of Perl without using the SET or manipulating the environment variable "PATH"
I need a mechanism that allows me to work with different version of Perl for different script without affecting the system configuration.
(e.g. I am using Perl ver 5.6.1 for some scripts and perl 5.8.8 for other Perl scripts)
It's an old trick I do when I have two different, but very incompatible versions of Perl I have to use: Use different suffixes:
For example, I have ClearQuest on my system and must use cqperl (which is ClearQuest's version of Perl) to execute scripts that manipulate the issues in ClearQuest. Yet, if I have to manipulate SQL data from our database, I have to use my ActivePerl because I can't add in the DBI module into cqperl.
What I did was associate the *.pl suffix with ActivePerl and the *.cqpl suffix with cqperl. Now, when I execute a script, and it ends in *.cqpl, it uses one version of Perl while a script that ends with *.pl is executed by another version of Perl.
To associate a suffix with a program, go into a Windows Explorer window and select Folder Options from the Tools menu. Then, click on the File Types tab. Click on the New button and create a new extention to associate with the file. Then, select it in the Registered File Types window, and click on the Advanced button on the bottom.
Create an Open action, and associate it with the full path name of the Perl you want to execute that suffix. Like this:
"C:\Perl\bin\perl.exe" "%1" %*
The %* is important, so you can pass other parameters to your program.
In your case, you could use *.pl for Perl 5.8.8 and *.pl6 for Perl 5.6.
You don't even need to put Perl's bin directory in your path. Just type the name of your script and that's it.
On Unix: use shebang line.
On Windows: when perl is installed, it usually created two executables: perl.exe and perl5.N.M.exe. For ex. in my Strawberry installation I have perl.exe and perl5.10.1.exe. So if both perls are in PATH, you can call them as perl5.6.1 and 5.8.8.
I.e "perl5.6.1 program.pl".
P.S. I'd suggest to upgrade whole environment to 5.12.2 - Perl has many new useful features.
you can always just run your scripts using the perl interpreter of your choice,
let's suppose you have 2 different perls installed in с:/perl_56 and c:/perl_58.
in CMD.exe you can try this:
c:/perl_56/bin/perl.exe path_to_your_script here
and
c:/perl_58/bin/perl.exe path_to_your_script here
to run scripts through different versions of perl.
unfortunately, you can't use the "shebang" in the beginning of your scripts in windows as you could do on unix systems.
I'm new to Perl. I get the following error when I run a script:
Can't locate URI.pm in #INC (#INC contains: /usr/local/packages/perl_remote/5.6.1/lib/5.6.1/i86pc-solaris /usr/local/packages/perl_remote/5.6.1/lib/5.6.1 /usr/local/packages/perl_remote/5.6.1/lib/site_perl/5.6.1/i86pc-solaris /usr/local/packages/perl_remote/5.6.1/lib/site_perl/5.6.1 /usr/local/packages/perl_remote/5.6.1/lib/site_perl .) at (eval 2) line 3.
Compilation failed in require at /usr/local/packages/perl_remote/5.6.1/lib/site_perl/5.6.1/HTTP/Request.pm line 3.
Compilation failed in require at /usr/local/packages/perl_remote/5.6.1/lib/site_perl/5.6.1/LWP/UserAgent.pm line 10.
BEGIN failed--compilation aborted at /usr/local/packages/perl_remote/5.6.1/lib/site_perl/5.6.1/LWP/UserAgent.pm line 10.
Compilation failed in require at /usr/local/packages/perl_remote/5.6.1/lib/site_perl/5.6.1/LWP/Simple.pm line 26.
BEGIN failed--compilation aborted at /usr/local/packages/perl_remote/5.6.1/lib/site_perl/5.6.1/LWP/Simple.pm line 26.
Compilation failed in require at txotf_0_install.pl line 35.
BEGIN failed--compilation aborted at txotf_0_install.pl line 35.
What could be the possible reasons of this and how do I get the script to work. Any help will be appreciated.
Possibly you do not have URI installed. It might not be saved anywhere on your machine, or it might be "installed" in a location.
If it's just not installed, then you need to install it from CPAN.
If you have it saved to your machine, you just need to let the system know where to get it.
If you have to install it from CPAN, you likely need administrator privileges to put it in the listed directories. But CPAN will allow you to install it to a user directory, so you can still install it.
So if you can't install the module in the directories listed in #INC, then there are the various ways.
Perl 5 reads a environment variable called PERL5LIB. Any directory in that "array" will be prepended to #INC. So anything in the directory structure of $ENV{PERL5LIB} will be preferred to any system directory. (see here)
Another way you can do this is per script. The use lib pragma also inserts specified directories into #INC. (see lib)
use lib '/path/to/URI/module';
use URI;
The final way, you can do it per run. You can run perl with the -I switch on the command line perl -I/path/to/URI/module -e 1 (see perlrun)
The nonstandard paths in #INC (e.g. /usr/local/packages, perl_remote etc) indicate to me that this is a custom perl installed for a specific purpose probably with reduced functionality to prevent mischief.
Ask the sysadmin.
The array #INC contains the list of places to look for Perl scripts to be evaluated. Your script will not run because it is not in the #INC list. Either:
Put the script in one of the #INC locations; or
Add the location of the file to the $PATH environmental variable; or
Specify the full path of the script when you are calling it.
This is not to say that any of the other answers aren't all good advice (they very likely address your issue), but I ran into a similar issue which had me puzzled for a couple hours. While I'm not sure this addresses the OP's problem, perhaps someone stumbling across this in the future will save themselves some time troubleshooting...
I found on a new CentOS server that despite #INC reporting the path to my custom libraries included and despite all file and directory permissions being set correctly mod_perl was still bailing out with a message that it "Can't locate" the modules in question. This was doubly puzzling because similar scripts with the same "use lib" statement that Apache's PerlRequire was using were able to run without issue.
The culprit turned out to be SELinux, and disabling it took care of this immediately. More details on the /var/log/messages info that led me to this as well as other general gripes can be found here.
In my case I just copied the perl folder to another machine and added path to bin folder to PATH environment variable. In order to fix the issue, I had to run the proper installation of ActivePerl which at the end setup all the environment properly for perl.
I currently use Strawberry Perl as my primary Perl distribution. However, I have some applications that make Perl calls through cygwin. These generally fail because they are calling the version of Perl that was packaged with cygwin, and only looking in cygwin's lib folders. How can I modify my cygwin environment to call Strawberry Perl (and use the C:/strawberry/perl/lib dirs) instead?
If you remove Perl from cygwin using the setup program it will use Strawberry Perl by default.
If you are unable to remove Perl from cygwin, you can create a symbolic link to the Perl executable from Strawberry.
From a cygwin shell, use the following set of commands:
$ mv /usr/bin/perl /usr/bin/perl-cygwin
$ ln -s /cygdrive/c/strawberry/perl/bin/perl.exe /usr/bin/perl
This is assuming you used the default Strawberry Perl installer. Update your perl.exe location accordingly if you have it installed somewhere else.
Check to make sure the link is working properly by checking the Perl version:
$ perl -v
It should say This is perl, (version) built for MSWin32-x86-multi-thread (or similar) and not built for cygwin-thread-multi-64int.
You can change your PATH to put the Strawberry directories first. Strawberry tries to be nice by putting its directories at the end of the PATH. If you installed from the .zip file, however, it didn't change the PATH at all.
You could move /usr/bin/perl, but that's a bad idea since it breaks when cygwin tries to update what it thinks is its perl. I just had that happen to me this week and used to happen to me on my Mac until I stopped playing with the system setup and installed my own stuff completely separate.
One good thing I can add is that if you get the right perl to come first in the path, it should handle site-specific CPAN modules you may have installed with strawberry perl running in a CMD shell.
"which perl" is your friend.
If you had trouble with this, you could set the PERL5LIB environment variable, but it shouldn't be necessary.
I still pass in DOS-style file paths as parameters into the perl script, i.e. "d:\data\myfile.txt", not "/cygdrive/d/data/myfile.txt". So oddly enough, this mix of path notation works:
bash> /cygdrive/d/scripts/myscript.pl d:\data\myfile.txt
Many of these are good solutions, but I rather take an easy one that I don't have to modify more than once.
All you need to do is add/modify a line in your .bashrc file.
# Prepend strawberry perl to cygwin's path
export PATH=/cygdrive/C/Tools/Perl/perl/bin:$PATH
source .bashrc file from your shell, (or start a new shell) and run your program.
source ~/.bashrc
perl script.pl
This is probably not a preferred solution, but you should be able to modify the #! line:
#!/cygdrive/c/strawberry/perl/bin/perl5.10.0
I always refer to an explicit location and installation of perl, rather than relying on what is in /usr/bin.
I have two scripts that I use to modify the first line of Perl scripts to whichever Perl is first in my path: rightperl hardcodes to the Perl that is first in my $PATH now, envperl will change the line to #!/usr/bin/env perl so the Perl to use is only picked at the time the script is invoked. Works really well under Cygwin (and from a Unix shell in general).
If you don't want to mess around with any paths or do anything permanent there is an easy TEMPORARY hack. Type "where perl" at Cygwin sh prompt. It will list all the Perl.exe it sees in PATH in their order of execution. Change the names of the ones you don't want to be seen that get listed before the perl you want to use. But DO remember to change them back when you are done or you might have a few problems down the road.
I don't have my cygwin machine nearby so I can't test this, but perhaps you can front-end the perl command with a script: go to /bin under cygwin and move the perl.exe there to something else like perl-org.exe, then set up a shell script that execs your other perl with the same arguments.