2

私は3つのファイルを持っています:

~/multiFindBinTest.pl:

use FindBin;
use lib "$FindBin::Bin/mod2";
use pack2;

~/mod1/pack1.pm

package pack1;
1;

~/mod2/pack2.pm

use FindBin;
use lib "$FindBin::Bin/../mod1";
use pack1;
package pack2;
1;

ご覧のとおり、base.pl は pack2 を使用し、それが pack1 を使用します。ただし、これは FindBin モジュールを使用しない方法のデモンストレーションです: base.pl が実行されると、pack2 は pack1 を見つけることができません。これは、ベースから取得した "$FindBin::Bin" の値が保持されるためです.pl。

だから私の質問は簡単です.perlに別のモジュールを「使用する」モジュールを「使用する」方法はありますか?

4

4 に答える 4

2

モジュールの場所は、ステートメントがコンパイルさ@INCれた時点でにある必要があります。最も簡単な方法は、このようuseに呼び出しプログラムにすべて追加することですTest.pl

use lib "$FindBin::Bin/../mod1", "$FindBin::Bin/../mod2";

その後、すべてのモジュールのコンパイルがうまくいきます。

于 2012-12-04T21:01:55.180 に答える
2

考えられるすべてのライブラリ ルートがわかっている場合は、コマンド ラインでそれらを追加するだけです。

perl -I~/mod1 -I~/mod2 myscript.pl

それらを PERL5LIB 環境変数に追加できます。

export PERL5LIB=~/mod1:~/mod2

どちらの方法でも、ディレクトリは libaray 検索パスに置かれます。


追加情報:

個々のパッケージがその依存関係が存在する場所を「宣言」したい場合、Perl は 'lib' プラグマを提供します:

use lib '/path/to/lib/directory';
于 2012-12-04T19:12:54.397 に答える
2

モジュールファイルの場所を見つける唯一の方法は、__FILE__. FindBinとは$0常にメイン スクリプト ファイルを参照します。

モジュールの場合、これは私が思いつくことができる最もきちんとしたものです。メインコードのソリューションは問題ありませんが、この代替手段も使用できます。

use strict;
use warnings;

use File::Basename 'fileparse';
use File::Spec;

my $dir;
BEGIN {
  $dir = (fileparse(File::Spec->rel2abs(__FILE__)))[1];
}
use lib $dir.'../mod1';

use pack1;

package pack2;

1;
于 2012-12-04T22:33:44.277 に答える
0

あなたはそれを持っていませんが、あなた自身のものを作ることができます.

package libr;

use strict;
use warnings;

use File::Spec;

sub import { 
    shift; # invoker
    my ( @cands, @missed );

    ARGS:
    while ( @_ ) { 

        # Get the next argument from the queued candidates or from the 
        # arguments
        my $raw_path 
            = my $path 
            = @cands ? shift @cands : shift
            ;

        # We don't need to worry about this argument unless it has relative 
        # notation in it. 
        if ( index( $path, '::' ) > -1 ) { 

            # split it into parts
            my ( $mod, $rest ) = split qr{(?:/(?:\.(?=/))?)+}, $path, 2;
            $mod =~ s/^:://; # Allow for one-word relative nodes: 'Word::/';

            # Move it from mod notation to file...
            my ( $mod_path ) = map { s|::|/|g; $_ } $mod;

            my %set;
            while ( my $len = length $mod_path ) { 

                # Remember the more specific path first
                $set{ $_ } ||= $mod_path
                    foreach 
                        # for each key that qualifies, subtract the same
                        # number of characters from the end of the value
                        map  { substr( $INC{ $_ }, 0, $len - length ) . $rest }

                        # test each key that it starts with our string
                        grep { substr( $_, 0, $len ) eq $mod_path } 

                        keys %INC
                    ;
            }
            continue { 
                # Check if our separator is in the mod path.
                my $mark = rindex( $mod_path, '/' );
                last if $mark == -1;

                # move the unmatched part of the substring to the 
                # ending
                substr( $rest, 0, 0, substr( $mod_path, $mark ));
                # delete it from the path
                substr( $mod_path, $mark ) = '';
            }
            my @sort_order 
                  # We only want the first value...
                = map  { shift @$_ }
                  # sort by length of matching path first, then alphabetically
                  sort { $b->[2] <=> $a->[2] or $a->[1] cmp $b->[1] }
                  # store a collection of values for sorting: 
                  # lowercase string and length of matching string
                  map  { [ $_ => lc $_ => length $set{ $_ } ] } 
                  keys %set
                ;
            ### Assemble list of candidates
            @cands = ( @sort_order, map { "$_/$mod_path$rest" } @INC );
            next ARGS;
        }

        # If the path exists
        if ( -e $path ) {
            # Store the canonical path
            push @INC, File::Spec->canonpath( $path );
            # And reset tracking arrays
            @cands  = () if @cands;
            @missed = () if @missed;
        }
        elsif ( @cands ) { 
            # If we're trying out values, just remember the missed ones.
            push @missed, $path;
        }
        else { 
            # Else, we're going to tell you we couldn't match the directory
            # either to one or to all candidates we tried.
            Carp::carp( 
                  "A valid path cannot be determined from '$raw_path': "
                . ( @missed > 1  ? do { 
                      local $LIST_SEPARATOR = "\n    - ";
                      push @missed, '', $path;
                      "\n No paths:@missed\n do not exist!";
                    }
                  : "$path does not exist!"
                  ));
            @missed = () if @missed;
        } # end else
    } # end while @_
}

次に、次のように使用します。

package main;

use A::Long::Package::Name;
use Smart::Comments;

use libr 'A::Long::Package::Name/../Foo', 'Figgy::Puddin';

言葉の後に捨ててみて@INC、何が起こったのか見てみましょう。

于 2012-12-04T23:59:40.923 に答える