2009-09-12 3 views
5

У меня есть сценарий Perl (foo.pl), который загружает Foo.pm из того же каталога, используя требуется механизм:Как я могу распространять приложение Perl в виде одного файла?

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) не работает.

ответ

3

Вашего код не работает (хотя это было бы полезно указать сообщение об ошибке (ы), которые вы), потому что вы пытались использовать 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 
} 

Дополнения:

2

Общая схема должна заключаться в замене вашего «требовать ...» на содержимое того, что вам нужно. Для этого есть нечто большее (BEGIN {} может понадобиться), и я не совсем уверен, что с этим связано. Конечно, вы бы хотели его автоматизировать.

Вот альтернатива: сформировать единый исполняемый файл, в котором модули вы зависите от упакованы внутри него с помощью PAR/pp

+0

Привет Вранг-Вранг! Спасибо за советы. К сожалению, создание исполняемого файла не является вариантом, так как тот же скрипт будет использоваться на нескольких платформах. – knorv

+1

knorv: Если вы не включаете какие-либо модули с компонентом XS/C/compiled, PAR может создавать файлы .par, которые являются кросс-платформенными. Это НЕ бинарный исполняемый файл, как «pp -o foo.exe foo.pl». – tsee

4

Файл может содержать несколько пакетов. Сначала поместите свой класс, а затем главный сценарий:

package Foo::Bar; 

sub new { 
    my $class = shift; 
    return bless {}, $class; 
} 

#... 

package main; 

my $foo = Foo::Bar->new(); 
print ref $foo; # Foo::Bar 
+3

Оператор 'package' не создает новую область, поэтому вы можете использовать' {package Foo :: Bar; REST_OF_THE_CODE} ', чтобы не допустить утечки данных между двумя пакетами. –

2

У вас уже есть несколько хороших ответов. Кроме того, можно создать модуль, который можно запустить непосредственно в виде скрипта.

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. 
} 

Для получения дополнительной информации см Брайен d Фой-х How a Script Becomes a Module.

5

Если вы заинтересованы в паковать свой скрипт на Perl в двоичном со всеми модулями она зависит от включенных, вы можете использовать PAR Packager:

pp -o binary_name foo.pl