赋予'use lib'的perl动态路径

时间:2010-12-30 23:06:25

标签: perl shared-libraries relative-path

所以,我的代码(Perl脚本和Perl模块)就像这样一个树:

 trunk/  
   util/  
   process/  
   scripts/  

'util'目录有实用程序,'process /'目录中的东西需要。他们可以这样访问:

use FindBin;
use lib "$FindBin::Bin/../util";
use UtilityModule qw(all);

只要您在树中与“util /”处于同一级别,该构造就不关心您从哪里开始。
但我认为'scripts /'过于拥挤,所以我创建了

   scripts/scripts1  
   scripts/scripts2  

现在我看到这不起作用。如果我运行脚本'trunk / scripts / scripts1 / call_script.pl',并且它调用'/trunk/process/process_script.pl',那么'process_script.pl'将无法尝试从UtilityModule()获取例程,因为FindBin返回的路径是顶级调用脚本的路径。

我想到解决这个问题的前十种方法都涉及到:

use lib $path_that_came_from_elsewhere;

但这似乎是Perl不喜欢做的事情,除了通过FindBin技巧。

我尝试了一些涉及BEGIN {}块的事情,但我真的不知道我在那里做什么,并且很可能最终会重构。但是,如果某人对这类问题有一些聪明的洞察力,那么这将是获得一些积分的好机会!

6 个答案:

答案 0 :(得分:6)

您是否考虑过使用lib::abs$FindBin的一个特性(在某些情况下可能与你的一样有限)是它相对于执行的二进制而不是相对于调用者而言。另一方面,lib :: abs相对于它所放置的模块是有效的。此外,你还可以使用globs:

use lib::abs qw{../modules/*/somelib};

答案 1 :(得分:3)

use是伪装的BEGIN块,所以它引用的任何东西也必须在BEGIN时间定义。模块FindBin中的变量就是这种情况,但不一定适用于其他变量。

# this will fail: $path is not yet defined at BEGIN time
my $path = '../util';
use lib $path;

# this ought to work
my $path;
BEGIN { $path = '../util' }
use lib $path;

至于让FindBin为/ scripts和/ scripts / scripts [12]中的两个脚本返回正确的目录,这对我来说似乎很棘手。你的问题在这个问题上仍然有点模糊。在我看来,你应该在scripts / scriptN目录中拥有所有脚本;这样../../util总是解析到正确的地方。但我不确定这适用于你的情况。

答案 2 :(得分:2)

如果没有根据您的确切需求进行定制,我会经常使用此代码段(source< - 最后评论)来使用本地库而无需硬编码。你可能无需太多工作就可以完成剪裁。

use Cwd 'abs_path';
use File::Basename;
use lib dirname( abs_path $0 );

注意:来自perldoc perlvar $0包含正在执行的程序的名称。

答案 3 :(得分:1)

如果您的可能中继位置在其路径中的任何位置都不包含“脚本”(例如,不存在“/ usr / scripts / stuff / trunk / scripts /”情况,则可以使用此处概述的方法:

How do I use beta Perl modules from beta Perl scripts?

它基本上涉及一个分析脚本路径的特殊库,并将@INC修改为对该路径绝对的位置(例如,在您的情况下,它找到“/ prefix / scripts /”目录并添加“/前缀/脚本/../ utils /“到@INC 即使脚本不在”/ prefix / scripts /“但在”/ prefix / scripts / scripts1“中

如果您不想使用通用库,那么这些内容会快速而且肮脏:

# Must be at the very beginning of your scripts
use Cwd 'abs_path';
BEGIN {
    my $full_path_script_name = abs_path($0);
    if ($full_path_script_name =~ !^(.+)/scripts/!) {
        my $prefix = $1;
        unshift(@INC, "$prefix/../util");
    }
}

答案 4 :(得分:0)

我通常使用shell脚本前缀命令(通常称为工具链)来操作运行环境PERL5LIB。

  • 项目/
    • LIB /
    • UTIL /工具链
    • 仓/应用

工具链:

 #!/bin/sh
 export PERL5LIB=$PWD/lib:$PERL5LIB
 export PATH=$PWD/util:$PWD/bin:$PATH
 exec $*

此脚本的限制是您必须始终从项目目录中调用它。

呼叫:

 % ./util/toolchain application

这样做可以从库和可执行脚本中消除不必要的use lib path。它将它留给了运行环境(它应该在哪里)。它还使脚本和库可以轻松地重新定位以用于生产安装目的。

答案 5 :(得分:0)

如果您愿意将util重命名为lib,则可以使用perl包FindBin::libs。参见

http://metacpan.org/pod/FindBin::libs

然后你可以简单地说

use FindBin::libs;
use UtilityModule qw(all);

对于每个脚本的父目录,它将搜索lib子目录并将其用作模块的位置。

在您的情况下,trunk/scripts/scripts1中的脚本会为您的模块检查trunk/scripts/lib然后trunk/lib