In Perl, can't locate packgeName.pm in #INC error - perl

This is a module math.pm with 2 basic functions add and multiply:
package Math;
use strict;
use warnings;
use Exporter qw(import);
our #EXPORT_OK = qw(add multiply);
sub add {
my ($x, $y) = #_;
return $x + $y;
}
sub multiply {
my ($x, $y) = #_;
return $x * $y;
}
1;
This is script script.pl that call the add function:
#!/usr/bin/perl
use strict;
use warnings;
use Math qw(add);
print add(19, 23);
It gives an error:
can't locate math.pm in #INC <#INC contain: C:/perl/site/lib C:/perl/lib .> at C:\programs\script.pl line 5.
BEGIN failed--compilation aborted at C:\programs\script.pl line 5.
How to solve this problem?

use lib
Adding a use lib statement to the script will add the directory to #INC for that specific script. Regardless who and in what environment runs it.
You just have to make sure to have the use lib statement before trying to load the module:
use lib '/path/to/module';
use Math qw(add);
For more details to set #INC look at this:
How do I include a Perl module that's in a different directory

Add the following to script.pl before use Math ...;:
use FindBin qw( $RealBin );
use lib $RealBin;
If script.pl and math.pm aren't in the same directory, adjust accordingly.
Also, you might have problems if the file is named math.pm and you use use Math; and package Math;. It would be best to rename the file so the spelling is consistent.
ren math.pm Math.pm

Related

How can I use an external lib in a BEGIN block

I want to use an external library in the BEGIN block of a Perl script.
The first test which I did was to check whether my #INC is getting popullated if I push some values:
use strict;
use warnings;
BEGIN {
push #INC, "d:/external_pm/";
use Data::Dumper;
print Dumper #INC;
}
Which works as expected and shows:
$VAR1 = 'D:/perl/5163/site/lib';
$VAR2 = 'D:/perl/5163/lib';
$VAR3 = '.'; # I am not sure about this one?!
$VAR4 = 'd:/external_pm/';
Now I want to import a module right after the push:
use strict;
use warnings;
BEGIN {
push #INC, "d:/external_pm/";
use Data::Dumper;
print Dumper #INC;
use ExtScript;
}
The error which follows is showing me that #INC was not updated:
Can't locate ExtScript.pm in #INC (#INC contains: D:/perl/5163/site/lib
D:/perl/5163/lib .) at file.pl line 9.
BEGIN failed--compilation aborted at file.pl line 9.
Why the #INC it's not updating?
I can't import a module in the BEGIN block? Or is a missusage of Perl?
use statements are executed at compile time (specifically, during the BEGIN phase), whereas normal code is run later. Let's look at this simplified snippet:
BEGIN {
push #INC, "some/dir";
use Example;
}
If we spell out all phases explicitly, that would be equivalent to:
BEGIN {
push #INC, "some/dir";
BEGIN { require Example; Example->import() }
}
So the Example module will be imported before the push runs.
There are a number of ways to address this.
The simplest way is to put only the #INC manipulation into a BEGIN block, and import the module outside:
BEGIN { push #INC, "some/dir" }
use Example;
A better solution is to use the lib pragma to handle #INC:
use lib "some/dir";
use Example;
However, there is a major difference: use lib puts additional directories at the beginning of the module search path, so you may accidentally override other modules. push #INC only adds directories to the end, as a fallback if a module wasn't found in other locations.
use ExtScript; is executed before push #INC. Either
move use ExtScript; out of the BEGIN block
or change it to require/import
or use the -I command-line option or PERL5LIB env variable.

Undefined subroutine &main::key_enc

I have a Perl module named McuEnc.pm which is located at /home/eric/temp directory:
package McuEnc;
use 5.010;
use strict;
use warnings;
use Exporter qw(import);
our #EXPORT_OK = qw(key_enc data_enc data_dec);
sub key_enc { some code }
sub data_enc { some code }
sub data_dec { some code }
1;
I have a Perl script named test.pl which is also located at /home/eric/temp directory:
use 5.010;
use strict;
use warnings;
use McuEnc qw(key_enc data_enc data_dec);
key_enc("1111");
...
I have changed working directory to /home/eric/temp. Now if I run test.pl script, it runs correctly. But if I create a new directory /home/eric/temp/My and move the McuEnc.pm file into it and then modify the test.pl script as follwoing:
use 5.010;
use strict;
use warnings;
use My::McuEnc qw(key_enc data_enc data_dec);
key_enc("1111");
...
then I'm getting the following error when I run test.pl again:
Undefined subroutine &main::key_enc called at ./test line 6.
However, I can still call the subroutine correctly with:
McuEnc::key_enc("1111");
So why I'm getting the error message? what is wrong?
This was answered by Sobrique in the comments, but it was never posted as an official answer:
"The use statement doesn't match the package statement. Try package My::McuEnc instead"

How to create own modules in Perl

Module
package ExampleModule;
use strict;
use base "Exporter";
our #export = qw/hello_world/;
sub hello_world
{
print "Hello,world";
}
1
Test:
perl -c examplemodule.pm
examplemodule.pm syntax OK
Script:
use ExampleModule;
hello_world();
exit;
but I'm getting error
Error:
Can't locate ExampleModule.pm in #INC (#INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at until.pl line 229.
BEGIN failed--compilation aborted at until.pl line 229.
What is the wrong in my Module please let me know
EDIT
package ExampleModule;
use strict;
use base "Exporter";
our #EXPORT = qw(hello_world);
sub hello_world {
print "Hello,world";
}
1;
saved with ExampleModule.pm
#!/usr/bin/perl -w
use strict;
use lib "/home/Admin/Desktop/Perl_Work_Space/ExampleModule.pm/";
use ExampleModule ;
hell_world();
exit;
saved with first.pl
getting error
[Admin#localhost Perl_Work_Space]$ perl first.pl
Undefined subroutine &main::hell_world called at first.pl line 5.
You're missing path to your module in #INC. To fix it you can tell perl where to look for modules,
use lib "lib/"; # relative or absolute path to ExampleModule.pm
use ExampleModule;
hello_world();
Also ExampleModule.pm should have package line at the top, and use but don't inherit Exporter module,
package ExampleModule;
use strict;
use Exporter "import";
our #EXPORT = qw/hello_world/;
sub hello_world {
print "Hello,world";
}
1;
In addition to the use lib ...; statement, the packagename and the filename have to have the same spelling including the capitalization. So rename the file to ExampleModule.pm.
Although I'm wondering why perl -c examplemodule.pm does not emit a warning.
And you have to use our #EXPORT = qw/hello_world/;

Perl subroutine naming conflicts

How does Perl resolve subroutine naming conflicts when parsing modules in the #INC path?
I'm writing a Perl module and I don't want my subroutine names to conflict with anything that already exists.
This should shed some light here.
Test script
#!/usr/bin/perl
use warnings;
use strict;
# import 'print_stuff' from TestPackage
# so you can call this sub without package name
use TestPackage qw(print_stuff);
my $string = "whatever";
TestPackage::print_stuff($string);
print_stuff($string);
sub print_stuff {
my $str = shift;
print "test.pl: $str\n";
}
Test package
package TestPackage;
# Export subs, which will enable you to call these
# subs without package name(TestPackage)
require Exporter;
#ISA = qw(Exporter);
#EXPORT_OK = qw(print_stuff);
sub print_stuff {
my $str = shift;
print "TestPackage: $str\n";
}
1;
Output:
$ test.pl
TestPackage: whatever
test.pl: whatever
Use package to build separate namespaces in modules, so you can avoid this kind of problems. The package statement declares the compilation unit as being in the given namespace. This link may helps you.

Why doesn't my Perl script use my module?

module.pm
package module;
use 5.012;
use warnings;
sub Parse
{
return 1;
}
1;
script.pl
#!/usr/bin/perl -w
use 5.012;
use warnings;
use lib 'C:/';
use module;
print Parse("value");
Stdout
Undefined subroutine &main::Parse
You need either to write:
print module::Parse("value");
or to change the module package to export the name Parse.
See http://perldoc.perl.org/perlmod.html#Perl-Modules for guidance in exporting symbols from your module.
(By the way, you should really name your module Module rather than module. Lowercase module-names are used for Perl built-in features like use warnings and use strict.)
Several things:
First, use Local as your module prefix. That way, if you just happen to have a module with the same name in your Perl installation, it will use yours. Call it "Local::Module". Then, create a Local directory, and name your module Module.pm.
The other thing you have to understand is that you define your module in another namespace. By default, everything is in the main namespace until you use the package statement. That creates another namespace that your package uses. This way, if your package has a function foo, and you've defined a function foo in your main program, they won't collide.
Thus, you have two choices: One (the preferred now) is to simply call your subroutine with the full package name prepended to it. The second is to export your subroutine names to your main program. This can cause problems with duplicate names, but you don't have to keep typing in the package name every time you call your subroutine.
Without Exporting the name
Local/Module.pm
# /usr/bin/env perl
# Local/Module.pm
package Local::Module;
use strict;
use warnings;
sub Parse {
my $value = shift; #Might as well get it.
print "I got a value of $value\n";
return $value;
}
1; #Need this or the module won't load
program.pl
# /usr/bin/env perl
# program.pl
use strict;
use warnings;
use Local::Module;
Local::Module::Parse("Foo");
With export:
Local/Module.pm
# /usr/bin/env perl
# Local/Module.pm
package Local::Module;
use strict;
use warnings;
use Exporter qw(import);
our #EXPORT_OK(Parse); #Allows you to export this name into your main program
sub Parse {
my $value = shift; #Might as well get it.
print "I got a value of $value\n";
return $value;
}
1; #Need this or the module won't load
program.pl
# /usr/bin/env perl
# program.pl
use strict;
use warnings;
use Local::Module qw(Parse);
Parse("Foo");