所以,我的代码(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 {}块的事情,但我真的不知道我在那里做什么,并且很可能最终会重构。但是,如果某人对这类问题有一些聪明的洞察力,那么这将是获得一些积分的好机会!
答案 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。
工具链:
#!/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
。