perl - 如何在一个文件中定义多个相互依赖的 Perl 包
问题描述
我尝试过一些其他的例子,并有类似的东西:
{
package Foo::Bar;
}
{
package Foo::Baz;
use Foo::Bar;
}
use Foo::Baz;
# some more code
# Fails with: Can't locate Foo/Bar.pm in @INC
我的真实示例是我想捆绑/连接https://github.com/TeX-Live/texlive-source/blob/trunk/texk/texlive/linked_scripts/texlive/fmtutil.pl及其依赖项https ://github.com/TeX-Live/installer/blob/master/tlpkg/TeXLive/TLConfig.pm和https://github.com/TeX-Live/installer/blob/master/tlpkg/TeXLive/TLUtils.pm到一个文件中。
谢谢!
解决方案
问题是 Perl 不知道模块已经加载,因为您没有忠实地复制加载过程。具体来说,您没有修改%INC
.
您也可能会因为在编译时不加载模块而遇到问题。这可以使用BEGIN
块来实现。
要内联模块,请将以下内容添加到脚本的开头:
BEGIN {
# Insert module here.
$INC{ ( __PACKAGE__ =~ s{::}{/}rg ) . ".pm" } = 1;
}
所以如果你有
# script.pl
use strict;
use Foo::Baz;
# ...
# Foo/Bar.pm
package Foo::Bar;
use strict;
# ...
1;
# Foo/Baz.pm
package Foo::Baz;
use strict;
use Foo::Bar;
# ...
1;
你最终会得到
BEGIN {
# Foo/Bar.pm
package Foo::Bar;
use strict;
# ...
$INC{ ( __PACKAGE__ =~ s{::}{/}rg ) . ".pm" } = 1;
}
BEGIN {
# Foo/Baz.pm
package Foo::Baz;
use strict;
use Foo::Bar;
# ...
$INC{ ( __PACKAGE__ =~ s{::}{/}rg ) . ".pm" } = 1;
}
# script.pl
use strict;
use Foo::Baz;
# ...
请注意,上述内容并非 100% 等同于内联模块。例如,相当于
use 5.012;
use open ":std", ":encoding(UTF-8)";
use Some::Module;
实际上会是
# Non-lexical effects
BEGIN {
require 5.012;
binmode(STDIN, ":encoding(UTF-8)");
binmode(STDOUT, ":encoding(UTF-8)");
binmode(STDERR, ":encoding(UTF-8)");
}
BEGIN {
package Some::Module;
...
$INC{"Some/Module.pm"} = 1;
}
# Lexical effects
use 5.012;
use open ":encoding(UTF-8)";
要正确内联模块,最好使用@INC
钩子。使用第一种方法中的文件,最终会得到
BEGIN {
my %modules = (
"Foo/Bar.pm" => <<'__EOI__',
# Foo/Bar.pm
package Foo::Bar;
use strict;
# ...
1;
__EOI__
"Foo/Baz.pm" => <<'__EOI__',
# Foo/Baz.pm
package Foo::Baz;
use strict;
use Foo::Bar;
# ...
1;
__EOI__
);
unshift @INC, sub {
my $module = $modules{$_[1]}
or return;
return \$module;
};
}
# script.pl
use strict;
use Foo::Baz;
# ...
App::FatPacker可用于以这种方式内联模块。
警告和错误中的行号将是原始文件的行号。添加到内联模块的#line
指令将对此进行调整。
推荐阅读
- github - 运行 git push 的问题
- c# - 如何正确更新(添加/更新/删除)实体的相关数据(EF Core)
- javascript - 高效阅读 Javascript
- javascript - 在快速查询字符串解析值上获取数字和布尔类型有什么好处?
- java - 如何从 void 方法返回
- amazon-web-services - AWS SQS FIFO 队列:队列应该启用 ContentBasedDeduplication 还是显式提供 MessageDeduplicationId?
- swiftui - iOS - Swift 5 - 标签文本未在循环内更新
- swift - 敬畏中的无效转义字符串文字
- c# - 为什么 Distinct (Linq) 在 int [] 列表中不起作用?
- wpf - 有没有办法在 WPF 中使用字母间距