Confusion over directory search order for "use"

H

Henry Law

I want an initialisation routine that will make a set of global
variables available to my perl application, read from a configuration
file. I'm going to use a package for this and I've chosen to code the
config in XML and use XML::Simple to read it in.

My problem is that perl doesn't find my package, while it finds
others.

My package is called "Global.pm". It looks like this
-------------------------------------------
package Global;
use 5.008;
use strict;
use warnings;

require Exporter;
our @ISA = qw(Exporter);
our %EXPORT_TAGS = ( 'all' => [ qw(
$g_one $stagedir
) ] );

our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
our $VERSION = '0.01';

our $g_one = 100;
our $stagedir;
my $xml;

use XML::Simple;
$xml = XMLin("NFConfig.XML");
$stagedir = $xml -> {stagedir}; # XML has <stagedir>xxx</stagedir>

1;
-------------------------------------------
"tryit", a test program to call Global, looks like this:

#! /usr/bin/perl -w
# Try out my "Global" package

use strict;
use warnings;
use Global ':all';
use XML::Simple;

# Print two of Global's exported variables
print "Global value \$g_one: $g_one\n";
print "Stage dir: $stagedir\n";

# Let's try XML::Simple native
my $xml = XMLin("NFConfig.XML");
# XML file has <testing>test value</testing.
print "Testing: $xml->{testing}\n";
-------------------------------------------
It's also important to know that XML::Simple is not installed in @INC;
just for now Simple.pm is in a subdirectory XML from the working
directory in which Global.pm and "tryit" live. I have verified that
@INC contains ".".

Now the problem that I need help with:

As set out above, "tryit" works fine, producing this
[henry@neptune henry]$ ./tryit
Global value $g_one: 100
Stage dir: F:\$User\PC\NFBack\Work
Testing: Test value

In other words "Global.pm" is found in the working directory, and
XML::Simple has been found by getting "Simple.pm" from the "XML"
sub-directory, both from the test program "tryit" and from the Global
package.

In practice I don't want Global.pm in the working directory; I want to
put it in a sub-directory called "NFB". Since XML::Simple can be
found by looking for Simple.pm in ./XML, I reasoned that Global.pm in
../NFB would be found by writing "use NFB::Global;". But no:

[henry@neptune henry]$ grep NFB tryit
use NFB::Global ':all';
[henry@neptune henry]$ find -name Global.pm
../NFB/Global.pm
[henry@neptune henry]$ ./tryit
Global symbol "$g_one" requires explicit package name at ./tryit line
11.
Global symbol "$stagedir" requires explicit package name at ./tryit
line 12.
Execution of ./tryit aborted due to compilation errors.

Perl version is "revision 5.0 version 8 subversion 0". OS is RedHat 9
(despite the presence of backslashes in the file name above).

Can someone point out what I'm doing wrong, or tell me which bit of
perldoc would enlighten me?

Henry Law <>< Manchester, England
 
A

Anno Siegel

Henry Law said:
I want an initialisation routine that will make a set of global
variables available to my perl application, read from a configuration
file. I'm going to use a package for this and I've chosen to code the
config in XML and use XML::Simple to read it in.

My problem is that perl doesn't find my package, while it finds
others.

My package is called "Global.pm". It looks like this

You need to change the package.

[snip good-looking code]
Now the problem that I need help with:

As set out above, "tryit" works fine, producing this
[henry@neptune henry]$ ./tryit
Global value $g_one: 100
Stage dir: F:\$User\PC\NFBack\Work
Testing: Test value

In other words "Global.pm" is found in the working directory, and
XML::Simple has been found by getting "Simple.pm" from the "XML"
sub-directory, both from the test program "tryit" and from the Global
package.

In practice I don't want Global.pm in the working directory; I want to
put it in a sub-directory called "NFB".

Right you are. The current directory can't be trusted to be anything
particular.
Since XML::Simple can be
found by looking for Simple.pm in ./XML, I reasoned that Global.pm in
./NFB would be found by writing "use NFB::Global;". But no:

[henry@neptune henry]$ grep NFB tryit
use NFB::Global ':all';
[henry@neptune henry]$ find -name Global.pm
./NFB/Global.pm
[henry@neptune henry]$ ./tryit
Global symbol "$g_one" requires explicit package name at ./tryit line

[more errors]
Can someone point out what I'm doing wrong, or tell me which bit of
perldoc would enlighten me?

You need to change "package Global" to "package NFB::Global".

Docs? Uh, perlmod, I suppose. Or "perldoc use". And "perldoc Exporter".

When you say "use NFB::Global qw( fie foe)", Perl uses the module name
in two distinct ways. For one, it tries to find .../NFB/Global.pm
somewhere along its @INC. This happens in the file system, and you have
taken care of that part.

After that it looks in the class NFB::Global for a method named "import".
If it exists, it is called as "NFB::Global->import( 'fie', 'foe')".
"import" is normally, as in your case, inherited from Exporter, that's
why you put 'Exporter' on @ISA. This happens in Perl's name space.

But the whole thing breaks when Perl looks in "NFB::Global" and you have
prepared "Global". In other words, NFB::Global was loaded, but none of
its goodies were exported.

This dependency between internal name space and external facts on disk
can be considered unfortunate. It only concerns modules that make use
of the special treatment "use" gives to the "import" method. Other
modules (like most OO modules) don't have this concern.

Anno
 
H

Henry Law

You need to change "package Global" to "package NFB::Global".

.... whereupon it worked perfectly. Thank you very much, Anno, both
for the correction and the clear explanation that went with it (teach
a man to fish, etc).

Henry Law <>< Manchester, England
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top