Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using FindBin in more than one module

Tags:

perl

Here is the scenario, I have two files: 1. dir/A.pm 2. dir/new_dir/a.t

This is how A.pm looks like:

package A;
use FindBin;
use Test::More;
is (FindBin->again, 'dir', 'got dir');
1;                    

This is how a.t looks like:

use FindBin;
use Test::More qw(no_plan); 
use A;
is (FindBin->again, 'dir/new_dir', 'got dir/new_dir');

So I ran file a.t with perl new_dir/a.t and expect my tests to pass. But this is my test result:

not ok 1 - got dir
#   Failed test 'got fir'
#   at A.pm line 6.
#          got: 'dir/new_dir'
#     expected: 'dir'
ok 2 - got dir/new_dir
1..2

Am I doing anything wrong? I am very new to perl. Please help!!

like image 719
junbon Avatar asked Oct 07 '11 09:10

junbon


3 Answers

As Dave Sherohman notes, FindBin is for finding the location of the main script, not individual modules. From the documentation:

NAME
       FindBin - Locate directory of original perl script

(Admittedly, the documentation does, somewhat confusingly, refer to "modules" in the "KNOWN ISSUES" section, but it doesn't really mean what you think it means by that.)

Anyway, if you look at the source with perldoc -m FindBin, you'll see that FindBin obtains the path to the script from the $0 variable. If you're interested in finding the location of a module included via use (or require), you should look under %INC instead, something like this:

package Foo::Bar;
use File::Spec;
my ($vol, $dir, $file) = File::Spec->splitpath( $INC{'Foo/Bar.pm'} );
like image 116
Ilmari Karonen Avatar answered Nov 16 '22 13:11

Ilmari Karonen


FindBin finds the location of the file Perl launched, not of file currently executing.

I don't see why you'd need the path to a module — File::ShareDir can be used to access your module's data files — but the following will find it:

use Cwd            qw( realpath );
use File::Basename qw( dirname );

my $module_dir = dirname(realpath(__FILE__));

The same caveat as Find::Bin applies: This only works if chdir hasn't been changed.

like image 42
ikegami Avatar answered Nov 16 '22 12:11

ikegami


If I understand the question correctly, a.t is in the directory dir/new_dir/ and you're using new_dir/a.t to run it from dir/, right?

If so, then it is doing the right thing. Since a.t is in dir/new_dir, you should always get dir/new_dir from FindBin - its job is to Find the Binary (program), not to find the file it's being called from, so the result will be the same in A.pm as it is in a.t.

The ->again function is for running instances of completely different programs from within the same perl interpreter, such as what mod_perl does, not for just using different modules within a single program.

like image 3
Dave Sherohman Avatar answered Nov 16 '22 13:11

Dave Sherohman