Как я могу распространять свое Perl-приложение в виде одного файла?
-
06-07-2019 - |
Вопрос
У меня есть сценарий Perl (foo.pl), который загружает Foo.pm из того же каталога, используя механизм require:
require "./Foo.pm";
...
my $foo = new Foo::Bar;
Foo.pm придерживается стандартного формата модуля:
package Foo::Bar;
...
1;
Вместо того, чтобы распространять свое приложение в виде двух файлов (foo.pl и Foo.pm), я хотел бы распространять только один файл.Более конкретно, я хотел бы сделать Foo.pm частью сценария foo.pl.
Как мне этого добиться?
Тривиальный подход — простое объединение двух файлов (cat foo.pl Foo.pm > foo2.pl) не работает.
Решение
Ваш код не работал (хотя было бы полезно указать полученные вами сообщения об ошибках), поскольку вы попытались использовать Foo::Bar до того, как он был определен.Попробуй это:
use strict;
use warnings;
my $foo = Foo::Bar->new();
# more code...
# end code
# begin definitions
BEGIN {
package Foo::Bar;
use strict;
use warnings;
# definitions...
1;
package Foo::Baz;
# more stuff, if you need to define another class
}
Дополнения:
- строгий контроль везде.
- конструктор вызывается явно, а не через метод indrect-object: В чем разница между new Some::Class и Some::Class->new() в Perl?
Другие советы
Если вы заинтересованы в упаковке скрипта Perl в двоичный файл со всеми модулями, от которых он зависит, вы можете использовать PAR Packager :
pp -o binary_name foo.pl
Файл может содержать несколько пакетов. Сначала поместите ваш класс, а затем основной скрипт:
package Foo::Bar;
sub new {
my $class = shift;
return bless {}, $class;
}
#...
package main;
my $foo = Foo::Bar->new();
print ref $foo; # Foo::Bar
Общая схема заключается в замене вашего " требовать ... " с содержанием того, что вам требуется. Это больше, чем это (BEGIN {} может понадобиться), и я не совсем уверен, в чем дело. Конечно, вы хотели бы автоматизировать это.
Вот альтернатива: создайте один исполняемый файл, в котором модули, от которых вы зависите, упакованы в него, используя PAR / pp
У вас уже есть несколько хороших ответов. Кроме того, можно создать модуль, который можно запустить непосредственно в виде скрипта.
package Foo;
__PACKAGE__->run(@ARGV) unless caller();
sub run {
# Do stuff here if you are running the Foo.pm as
# a script rather than using it as a module.
}
Дополнительные сведения см. в Брайана Д. Фоя о том, как скрипт становится модулем . р>