Perl PP doesn't include Switch module - perl

I created a perl script that includes the Switch module.
hello_world.pl
use strict;
use warnings;
use Switch;
use Data::Dumper;
my $var = "Hello World\n";
print Dumper($var);
if I launch perl hello_world.pl everything works fine. But if I pack my script with pp hello_world.pl and than launch ./a.out it gives me back this error:
Can't locate Switch.pm in #INC (you may need to install the Switch module) (#INC contains: CODE(0x7fb2631e6a88) /var/folders/rb/2b5sbs355n57svwzjjh7cb9c0000gn/T/par-6967676c6f62616c33/cache-710e967842eb844ab8d6fe5f46968c1b6f49e019/inc/lib /var/folders/rb/2b5sbs355n57svwzjjh7cb9c0000gn/T/par-6967676c6f62616c33/cache-710e967842eb844ab8d6fe5f46968c1b6f49e019/inc CODE(0x7fb262988de0) CODE(0x7fb262989930)) at script/hello_world.pl line 3.
BEGIN failed--compilation aborted at script/hello_world.pl line 3

$ corelist Switch
Data for 2016-05-09
Switch was first released with perl v5.7.3, deprecated (will be CPAN-only) in v5.11.0 and removed from v5.13.1
Switch was never a good idea. It's a source filter which means it's a clever party trick but shouldn't be used in production code. For that reason it has removed from Perl several versions ago.
I suspect that you are running your packaged program on a more recent version of Perl than the unpackaged version - one that no longer includes Switch.
You can install Switch on your target system or you can work out how to get pp to include the module in the package. But the best solution is to rewrite the code to stop using Switch.

You can try to force the modules to be included, with -M option:
pp -M Switch -M YAML ...

Related

Perlbrew cannot run simple scripts IPC::System::Simple required for Fatalised/autodying system()

I am a new perlbrew user, as I wish to upgrade to perl 5.30.0 on Ubuntu.
I have done
perlbrew init
perlbrew install perl-5.30.0
perlbrew switch perl-5.30.0
so I try to run this test script:
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use feature 'say';
use autodie ':all';
but this gives the long error
IPC::System::Simple required for Fatalised/autodying system() at /home/con/Scripts/say.pl line 6.
main::BEGIN() called at /home/con/Scripts/say.pl line 6
eval {...} called at /home/con/Scripts/say.pl line 6
BEGIN failed--compilation aborted at /home/con/Scripts/say.pl line 6.
Command exited with non-zero status 2
I thought that libraries (especially standard ones) were supposed to be loaded automatically via perlbrew? How can I get this simple script to run?
From autodie we see that it's documented behavior
If system is specified as an argument to autodie, then it uses
IPC::System::Simple to do the heavy lifting. See the description of that
module for more information.
So one does need IPC::System::Simple installed for :all tag (which implies system).
It strikes me as curious that a core functionality requires a non-core module, and quietly too (doesn't complain at installation).
I'm getting exactly the same error on a non-perlbrew Perl. It seems autodie requires IPC::System::Simple when running under fatal warnings or with :all, but it doesn't require it during installation.
See also https://bugzilla.redhat.com/show_bug.cgi?id=1183231.
The solution, according to #ikegami, and that worked for me: /home/con/perl5/perlbrew/perls/perl-5.30.0/bin/perl -e'use IPC::System::Simple'; /home/con/perl5/perlbrew/perls/perl-5.30.0/bin/cpan IPC::System::Simple; /home/con/perl5/perlbrew/perls/perl-5.30.0/bin/perl -e'use IPC::System::Simple'
of course, for anyone in the future, this will be slightly different for you, as your directories may be set differently, and username isn't con

Specify shebang on project using Perl Module::Build

I'm packaging clusterssh to openSUSE and need to change default shebang from #!/usr/bin/env perl to #!/usr/bin/perl. clusterssh uses Module::Build.
I'll probably use the patch (as Debian package do), but I wonder easy usage for fix_shebang_line(#files) in RPM packaging.
It's already called during the building process.
Basically, uninstalled scripts should use #!/usr/bin/perl or #!perl, and the installation process should rewrite that to the point to the perl used to run the installer. That way, a script installed by /usr/bin/perl will use /usr/bin/perl, and a script installed using /home/ikegami/usr/perlbrew/perls/5.26.2t/bin/perl will use /home/ikegami/usr/perlbrew/perls/5.26.2t/bin/perl.
(This applies to both the Module::Build installer and the ExtUtils::MakeMaker installer.)
Note that the documentation for fix_shebang_line says it doesn't touch a shebang line of #!/usr/bin/env perl (because it's not recognized as invocation of perl), so simply patching the scripts to use #!/usr/bin/perl instead of #!/usr/bin/env perl does the trick.
With that change, the install-ready staging directory (blib) produced by ./Build will contain the edited files.
$ perl -e'CORE::say $^X'
/home/ikegami/usr/perlbrew/perls/5.26.2t/bin/perl
$ for fn in ccon crsh csftp cssh ctel; do printf '%-6s ' "$fn:"; head -n 1 "bin_PL/$fn"; done
ccon: #!/usr/bin/perl
crsh: #!/usr/bin/perl
csftp: #!/usr/bin/perl
cssh: #!/usr/bin/perl
ctel: #!/usr/bin/perl
$ perl Build.PL
Could not get valid metadata. Error is: ERROR: Missing required field 'dist_abstract' for metafile
Could not create MYMETA files
Creating new 'Build' script for 'App-ClusterSSH' version 'v4.13.203'
$ ./Build
Building App-ClusterSSH
Using perl binary: /home/ikegami/usr/perlbrew/perls/5.26.2t/bin/perl
Using perl version v5.26.2
Generating: /home/ikegami/tmp/clusterssh/bin_PL/cssh
Generating: /home/ikegami/tmp/clusterssh/bin_PL/csftp
Generating: /home/ikegami/tmp/clusterssh/bin_PL/ccon
Generating: /home/ikegami/tmp/clusterssh/bin_PL/crsh
Generating: /home/ikegami/tmp/clusterssh/bin_PL/ctel
Generating: /home/ikegami/tmp/clusterssh/bin_PL/clusterssh_bash_completion.dist
$ for fn in ccon crsh csftp cssh ctel; do printf '%-6s ' "$fn:"; head -n 1 "blib/script/$fn"; done
ccon: #!/home/ikegami/usr/perlbrew/perls/5.26.2t/bin/perl
crsh: #!/home/ikegami/usr/perlbrew/perls/5.26.2t/bin/perl
csftp: #!/home/ikegami/usr/perlbrew/perls/5.26.2t/bin/perl
cssh: #!/home/ikegami/usr/perlbrew/perls/5.26.2t/bin/perl
ctel: #!/home/ikegami/usr/perlbrew/perls/5.26.2t/bin/perl
I didn't bother running ./Build install, whose main task is to copy the files from the staging directory into their final locations. Besides, that part will need to be replaced by your package manager anyway (assuming you're simply placing the contents of the blib directory into your package).
If you somehow need to do it yourself, you could use the following:
find bin -type f \
-exec perl -i -pe'
s/^#!\S*perl\S*/#!$^X/ if $. == 1;
close ARGV if eof;
' {} +
Notes:
Use the perl you wish the scripts to use.
GNU tools assumed; adjust as necessary.
close ARGV if eof; resets the line number ($.) for each file.
eof is different than eof(), and only the former will work here.
The line breaks are optional and may be removed.

Perl: par packer executable with Unicode::GCString, Can't locate object method "new"

I'm using the PAR::Packer module to create a Windows executable of a Perl script that uses the Unicode::GCString module.
A stripped down version of the script is as follows:
mwe.pl
#!/usr/bin/env perl
use strict;
use warnings;
use Unicode::GCString;
my $gcs = Unicode::GCString->new("hello world");
print $gcs->columns();
exit(0);
When I run
perl mwe.pl
the output gives the 'width' of the string:
11
which is as expected.
I create mwe.exe using the command
pp -o mwe.exe mwe.pl
and when I run
mwe.exe
I receive the error
Can't locate object method "new" via package "Unicode::GCString" at
script/mwe.pl line 6
Having reviewed AppData\Local\Temp\par-xxxxxx\cache-xxxxx\inc\lib, I believe that Unicode::GCString is present, as is Unicode::LineBreak.
Does anyone have any ideas on how to fix this?
A solution can be to use this version of "pp" I call it "ppp.pl"
$ENV{PAR_VERBATIM}=1;
system 'pp', #ARGV;
Details at https://metacpan.org/pod/distribution/PAR/lib/PAR/Environment.pod#PAR_VERBATIM
The cause is related to this bug Bug #38271 for PAR-Packer: PodStrip does not strip "=encoding utf8" which cause the executable generated by pp failed to exec
Also the boilerplate inside Unicode::GCString

Can't locate SOAP/Lite.pm in #INC

I am trying to build LDV project by following this instructions, and i know nothing about perl.
i am getting the following error while running the test
ldv-task: NORMAL: Calling LDV-core.
Can't locate SOAP/Lite.pm in #INC (#INC contains: /home/acsia/perl5/perlbrew/perls/perl-5.10.0/lib/5.10.0/x86_64-linux /home/acsia/perl5/perlbrew/perls/perl-5.10.0/lib/5.10.0 /home/acsia/perl5/perlbrew/perls/perl-5.10.0/lib/site_perl/5.10.0/x86_64-linux /home/acsia/perl5/perlbrew/perls/perl-5.10.0/lib/site_perl/5.10.0 .) at /home/acsia/Desktop/LDV/consol-tools/ldv-core/ldv-core line 7.
BEGIN failed--compilation aborted at /home/acsia/Desktop/LDV/consol-tools/ldv-core/ldv-core line 7.
output of
perlbrew use
is :EDITED:
Currently using perl-5.22.0
output of
locate SOAP/Lite.pm
is
/usr/local/lib/perl5/site_perl/5.22.0/SOAP/Lite.pm
output of
which perl
is
/usr/local/bin/perl
and the LDV-core file is starting like this by default
#!/usr/bin/perl -w
#
my $instrumnet = 'ldv-core';
use FindBin;
# To prevent meaningless module warnings use this instead of use.
BEGIN { $SIG{'__WARN__'} = sub{}; require SOAP::Lite; SOAP::Lite->import(); $SIG{__WARN__}='DEFAULT'; }
use POSIX ":sys_wait_h";
use XML::Twig;
use IO::Socket::INET;
#use File::MimeInfo;
use File::Basename;
use Cwd qw(abs_path);
etc,... etc....
Thanks for your time...
If LDV-Core isn't yours, you should install SOAP::Lite using your system's package manager. If it's yours, read on.
perlbrew plays with your PATH so that executing perl will execute the desired perl.
But your script explicitly uses /usr/bin/perl, so which perl is currently selected using perlbrew switch or perlbrew use is irrelevant.
Stop overriding the default install location, and stop looking where you shouldn't.
unset PERL_MM_OPT
unset PERL_MB_OPT
unset PERL5LIB
unset PERLLIB
echo -ne 'o conf makepl_arg ""\no conf commit\n' | cpan
echo -ne 'o conf mbuildpl_arg ""\no conf commit\n' | cpan
The first four lines only have a temporary effect. You should stop setting those variables in your login script to make the change permanent.
Install SOAP::Lite in the desired Perl.
perlbrew use perl-5.22.0 # Or perl-5.10.0 or whatever
cpan SOAP::Lite
Fix your script's shebang.
perl -i~ -pe'
next if $. != 1;
s/^#!.*//s;
$_ = "#!$^X\n$_";
' LDV-core
PS — You don't need use FindBin;.
perlbrew perl is a way to install many perl versions in same machine. It is like virtenv in python. Perlbrew allow you to switch between various versions of perl and run perl programs against those versions.
system perl means the default version of perl which mostly come with linux distros. perlbrew changes that version against which program needs to run and your program will start running against different version.
If you are making something which does not require a lot of perl versions it is always better to use one version of perl and run programs against them.
Also if you are using linux distros and do not want to get into cpan and how to install perl modules, best is to search for corresponding libraries against that module and install them. For example in your case i search this way
aptitude search soap | grep perl
This give me two libraries on my ubuntu machine of which one is against this module. Installing them is easy and you can focus on your work rather than on how to install cpan modules.

PerlApp-generated-exe can't Load packages

PerlApp generate perl script to executable. I get a problem using the PerlApp
Here are the steps:
Generate a perl script (e.pl) with the following 2 lines
require Date::Manip;
require Date::Manip::DM6;
perlapp e.pl --add Date::Manip --add Date::Manip::DM6
e.exe generate the following errors:
c:_test>e.exe
ERROR LOADING MODULE: Date::Manip::DM6 at /Date/Manip.pm line 35.
You need to add more than just Date::Manip::DM6:
perlapp --add Date::Manip::** e.pl
The wildcards indicate that all submodules in the Date::Manip namespace should be added, including some that are more than 1 level down. The error is because DM6 depends on these other submodules, some of which seem to be implicit.
Also you don't need to require Date::Manip::DM6 as that is not how you're meant to use the module. Version 6 is used automatically depending on your version of perl, which gets included in your compiled exe.
Just in case you're suffering from an XY Problem:
Considering using pp instead of PerlApp. The following works just fine:
use strict;
use warnings;
use Date::Manip;
print "Hello World\n";
And then packaging:
pp hello_date.pl