How do I set up Strawberry Perl in MSYS? - perl

I have Strawberry Perl and have msys Perl 5.6 removed.
Now perl will invoke Strawberry (due to PATH env) but how do I map the perl command in .pl or other Perl script files which have #!/bin/perl or #!/usr/bin/perl shebang lines?
I was thinking of making a hardlink to perl.exe in msys/bin or merge the whole Strawberry inside the msys directory, but I'm not sure.

The solution is to create a symlink to the Strawberry Perl executable from within MSYS Tip of the hat to smaudet for his input:
First, remove or rename the Perl executables that the MSYS installation came with, if any (which the OP has already done); e.g.:
mv /usr/bin/perl /usr/bin/perl.msys
mv /usr/bin/cpan /usr/bin/cpan.msys
Then create a symlink to Strawberry Perl's executable in its place:
ln -s /c/strawberry/perl/bin/perl.exe /usr/bin/perl
# Unfortunately, doing the same for `cpan` doesn't work directly, because
# Strawberry Perl's `cpan` executable is a *batch* file, `cpan.bat`, which
# cannot be directly invoked from MSYS.
# To invoke it from MSYS (assuming it is in the %PATH%):
# cmd /c 'cpan.bat ...'
# With an explicit path:
# cmd /c 'c:\strawberry\perl\bin\cpan.bat ...'
#
# Here's how to create a stub script that still allows invocation as
# `cpan`:
echo 'cmd /c "C:\strawberry\perl\bin\cpan.bat $*"'>/usr/bin/cpan && chmod +x /usr/bin/cpan
Once the /usr/bin/perl symlink is in place, existing scripts with shebang lines #!/usr/bin/perl and #!/bin/perl will work again (the latter also works, because /bin and /usr/bin are effectively the same location in MSYS).
Note that scripts written with the more flexible shebang line #!/usr/bin/env perl do not need this, because env will directly find Strawberry Perl's perl.exe in the path.
Some background:
Unix-emulation environments such as MSYS and Cygwin do not respect Windows' %PATHEXT% variable to determine what executable to invoke a (non-binary) file with. In other words: filename extensions have no meaning with respect to execution there.
Instead, they solely go by whether the file has a shebang line:
If there is one, the executable specified in the shebang line is used.
If there is none, the default (POSIX-like) shell /bin/sh is used.
Thus, trying to invoke *.bat or *.cmd files directly fails, because they don't have a Unix shebang line and are therefore executed by /bin/sh rather than cmd.exe.
Unlike in Windows, this also works with (executable) files that have no filename extension at all.

this works beautifully on the windows side of the computer, on the MSYS side you may need to
check the PATH environment variable and fix to include the strawberry perl access path
check the scripts for complete path in the shebang line (#!/usr/bin/perl).
Those paths that are absolute in msys are in fact relative to the msys install directory in windows.
you may need to "plug" your strawberry perl install to match or change the #! line
in the latter case my recommendation would be to use something like: #!env perl that checks the environment for the perl interpreter and alleviate the burden of dealing with /cygdrive/c/my/windows/path/not/visible/from/msys/otherwise

The correct shebang would be, eg. #!"C:/strawberry/perl/bin/perl.exe". However, you might prefer to run scripts explicitly with Perl rather than rely on the shebang, eg. perl script.pl or perl "C:\strawberry\perl\bin\cpan"
Note that Strawberry Perl doesn't get the shebang right for its own scripts, such as cpan and perldoc . Bug reported at https://rt.cpan.org/Public/Bug/Display.html?id=82837

Related

Cygwin: Perl script $ENV{PATH} call returns unix path. How do I change it?

I am calling a Perl script from cygwin. The issue that I am having is that when it calls $ENV{PATH}, the path is receives is a unix path. How do I change my shell so it returns a DOS path?
Cygwin is a Unix-emulation environment for Windows. It wouldn't work unless $PATH was a Unix-style path.
If you want perl to give you a DOS path, use a DOS-compatible Perl, like Strawberry Perl. You can even run Strawberry Perl (or whatever Windows-build of perl you use) from Cygwin if you want to.
It has nothing to do with the shell, so changing shell won't help, and there's nothing you can change in the shell to help.
>echo %PATH% & perl -E"say $ENV{PATH}"
c:\progs\cygwin\bin;...;C:\Windows\system32;...
/usr/bin:...:/cygdrive/c/Windows/system32:...
The purpose of cygwin is to allow unix program to be compiled on a Windows machine with as little changes as possible, which means the system calls must behave as if the program was executing on a unix machine, which means the PATH must look like a unix path.
If you had used a Windows build of Perl (such as ActivePerl or Strawberry Perl), you wouldn't have this problem.
If you wish to continue using a Cygwin build of Perl, you could use the Cygwin tool cygpath to convert the paths for you.
$ perl -E'
my $cmd = q{IFS=: ; cygpath -w $PATH};
chomp( my #paths = `$cmd` );
say for #paths;
'
C:\progs\cygwin\home\ikegami\usr\perlbrew\bin
.
C:\progs\cygwin\home\ikegami\bin
C:\progs\cygwin\usr\local\bin
C:\progs\cygwin\bin
C:\progs\perl5163-ap1603\site\bin
C:\progs\perl5163-ap1603\bin
C:\bin
C:\Windows\system32
C:\Windows
...
You can use cygpath and call bash with: (Looks like you have to set IFS.)
` IFS=:; cygpath --windows \$PATH`
Or unsetting IFS.
`IFS=;cygpath --windows --path \$PATH`
Or you could just do it with a few simple rules.
map {
# turn cygdrives to drive letter + colon
s!^/cygdrive/(\w)/!\U$1:!;
# locate the cygwin relative paths to whatever it is on your system.
s!^/!$CYGWIN_HOME/!;
$_ = qq("$_") if m/[() ]/; # quote paths where necessary
# You don't really need to switch the slashes for perl, Java
# a lot of other multi-platform tools.
s!/!\\!g;
} split /:/, $ENV{PATH}
;
Note that you might have to expand the character set in the match expression.
I hope this helps, although maybe a bit late :)
Copy the PATH to a Cygwin-unrecognised variable and use that instead:
set MYPATH=%PATH%
perl -e 'print join("\n",split(";",$ENV{MYPATH}),"\n")'

May I use Strawberry Perl and ActiveState Perl simultaneously on one computer?

I used to delete my ActivePerl once, and all the installed modules were lost. So now I am very careful with this kind of issue. Due to some reason, I want to use Strawberry Perl now, while keeping ActiveState's ActivePerl in use.
Will this cause compatibility issues? Is it advisable?
This will not be a problem as both the Perl implementations will look at different directories for modules. That is, the #INC entries will be different.
I keep both ActivePerl and Strawberry Perl installed on my Windows 7 Pro instance. My PATH variable order decides my Perl preference. E.g, for using ActivePerl I set my PATH to something like this:
C:\Perl64\bin;C:\strawberry\perl\bin
You can always override this in your script using shebang:
#!C:\strawberry\perl\bin\perl
You could use two (many) different Perl versions at once.
Set your PATH variable to include your primary Perl path (path to perl.exe) to be sure that you are running the correct Perl when you start a program with perl script.pl.
You could use Perlbrew (or other modules) to help keeping multiple Perl installations on your computer.
It is available on Windows: http://code.activestate.com/ppm/App-perlbrew/
I found another solution for this. You could embed your Perl code into a Windows batch file. This way you could set environment variables before executing your Perl script or include your module path.
#echo off
cd %TEMP%
set perl_bindir=C:\strawberry\perl\bin
set module_dir=C:\my_perl_modules
set path=%perl_bindir%;%path%
echo Launching %0 perl script
%perl_bindir%\perl.exe -I %module_dir% -x -S %0 %*
goto endofperl
#!perl -w
use strict;
print "Hello World\n";
__END__
:endofperl

Can I do without the shebang line in my Unix Perl scripts?

Can I write a Perl program where my first line is not #!/path/?
Thank you.
The shebang (#!)is only necessary if you want to invoke the script directly at a shell prompt, e.g. ./yourscript. You can always do perl yourscript and skip the shebang.
If your concern is hard-coding a constant path (e.g. #!/usr/bin/perl as opposed to #!/usr/local/bin/perl), then use:
#!/usr/bin/env perl
This allows the Perl interpreter to be sought in your PATH, making your scripts a bit more portable (Windows aside).
Yes, from perldoc perlrun (under the -S switch):
#!/bin/sh
eval 'exec /usr/bin/perl -wS $0 ${1+"$#"}'
if $running_under_some_shell;
See that documentation for the complete story.
If you do that then you'll need to invoke Perl explicitly. If that line is there, then the system knows that it is a Perl script so when you make the script executable you can just write ./script

invoking perl scripts

I have perl scripts starting with #!/usr/bin/perl or #!/usr/bin/env perl
First, what does the second version mean?
Second, I use Ubuntu. All the scripts are set as executables. When I try to run a script by simply invoking it's name (e.g. ./script.pl) I get : No such file or directory. when I invoke by perl ./script.pl it runs fine.
Why?
The #!/usr/bin/env perl uses the standard POSIX tool env to work around the "problem" that UNIX doesn't support relative paths in shebang lines (AFAIK). The env tool can be used to start a program (in this case perl) after modifying environment variables. In this case, no variables are modified and env then searches the PATH for Perl and runs it. Thus a script with that particular shebang line will work even when Perl is not installed in /usr/bin but in some other path (which must be in the PATH variable).
Then, you problem with ./script.pl not working: you said it has the executable bit(s) set, like with chmod +x script.pl ? But does it also start with a shebang (#!) line ? That is, the very first two bytes must be #! and it must be followed by a file path (to perl). That is necessary to tell the kernel with which program to run this script. If you have done so, is the path correct ? You want to try the #!/usr/bin/env perl variant ;-)
Using #!/usr/bin/env perl gets around the problem of perl not necessarily being in /usr/bin on every system; it's just there to make the script more portable
On a related note, for your second problem, is there a /usr/bin/perl and/or /usr/bin/env? If not, that would explain why running the scripts directly doesn't work; the shebang isn't handled if you run the script as an argument to perl

How can I run a Perl script on Mac OS X?

How do I run a Perl script on OS X?
You can run your Perl script by invoking the Perl interpreter and giving your file as input:
perl myprogram.pl
The easiest way to run a perl script is with the option:
perl myprogram.pl
However, you may find it more useful to add a shebang line at the top of the perl file.
#!/usr/bin/perl
print "Hello World!\n";
In order to execute this script, you need to add execute permissions to your program. Run:
chmod +x myprogram.pl
Now, in order to run your script, you can simply type:
./myprogram.pl
A good tutorial on Perl in OSX can be found here:
http://www.mactech.com/articles/mactech/Vol.18/18.09/PerlforMacOSX/index.html
A generic documentation on executing Perl code is of course perldoc perlrun.
To answer your question directly:
You can run a perl script on any Unix system by either having the code evaluated and executed from command line:
perl -e 'print "Hello World\n"';
Or you can save your Perl script to a file (customarily having .pl extension, say script1.pl and with the first line being #!/usr/bin/perl) and then you can execute it as any Unix program (after setting proper execute permissions)
/path/to/script/script1.pl
You can also execute a script from a file by running perl interpreter as the command and giving the script as a parameter (in this case execute permissions to the script are not needed):
perl /path/to/script/script1.pl
For some reason the whole directory didn't work for me but I just did
perl ~/Desktop/file.pl
(you could also use any folder that is in your user-folder after the ~/)