perl - 如何在一个文件中定义多个相互依赖的 Perl 包

标签 perl package

我尝试了一些其他的例子,并有类似的东西:

{
    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.pmhttps://github.com/TeX-Live/installer/blob/master/tlpkg/TeXLive/TLUtils.pm到一个文件中。

谢谢!

最佳答案

问题在于 Perl 不知道模块已经加载,因为您没有忠实地复制加载过程。具体来说,您没有修改 %INC

您也可能会因为在编译时不加载模块而遇到问题。这可以使用 BEGIN block 来实现。

要内联模块,请将以下内容添加到脚本的开头:

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 Hook 。使用第一种方法中的文件,最终会得到

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 指令将对此进行调整。

关于perl - 如何在一个文件中定义多个相互依赖的 Perl 包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69434849/

相关文章:

perl - 在 Perl 中使用 `strict` 定义全局变量

perl - 如何在 perl 中的 fork 之间共享简单标量(计数器变量)?

perl - 在Perl中读取包含数据的文件的最后一行

python - 无法导入同一目录和包中的模块

php - 我的 ubuntu 机器上缺少 simplexml,但无法下载

Java 方法未定义

objective-c - 使用 perl 与正在运行的 OS X 应用程序进行通信

Perl 获取单个散列本身的散列键值计数

java - 以编程方式动态导入

r - 多个 Dockerfile 的一个 R 包文件