해킹 때문에 필요하다 require
(및 use
) 모두 컴파일 실행 모듈을 반환하기 전에.
동일합니다 eval
. eval
코드를 실행하지 않고 컴파일하는 데 사용할 수 없습니다.
내가 찾은 가장 방해가 적은 솔루션은 재정의하는 것 DB::postponed
입니다. 컴파일 된 필수 파일을 평가하기 전에 호출됩니다. 불행히도 디버깅 할 때만 호출됩니다 ( perl -d
).
다른 해결책은 다음과 같이 파일을 읽고 수정하고 수정 된 파일을 평가하는 것입니다.
use File::Slurper qw( read_binary );
eval(read_binary("Foo.pm") . <<'__EOS__') or die $@;
package Foo {
no warnings qw( redefine );
sub bar { 7 }
}
__EOS__
위의 내용은 올바르게 설정되지 않았 %INC
으며 경고에 사용되는 파일 이름을 엉망으로 만들고 호출하지 않습니다 DB::postponed
. 다음은 더 강력한 솔루션입니다.
use IO::Unread qw( unread );
use Path::Class qw( dir );
BEGIN {
my $preamble = '
UNITCHECK {
no warnings qw( redefine );
*Foo::bar = sub { 7 };
}
';
my @libs = @INC;
unshift @INC, sub {
my (undef, $fn) = @_;
return undef if $_[1] ne 'Foo.pm';
for my $qfn (map dir($_)->file($fn), @libs) {
open(my $fh, '<', $qfn)
or do {
next if $!{ENOENT};
die $!;
};
unread $fh, "$preamble\n#line 1 $qfn\n";
return $fh;
}
return undef;
};
}
use Foo;
내가 사용하는 UNITCHECK
내가 (사용하여 재정의를 앞에 추가하기 때문에 (실행 컴파일 후하지만 전에 호출되는) unread
대신에 전체 파일을 읽고 새로운 정의를 추가하는 것보다). 해당 접근 방식을 사용하려면 파일 핸들을 사용하여 반환 할 수 있습니다
open(my $fh_for_perl, '<', \$modified_code);
return $fh_for_perl;
@INC
후크 를 언급하기 위해 @Grinnz에게 찬사를 보냅니다 .
Foo::bar
있지만use Foo
컴파일 단계 (이전에 정의 된 경우 재정의 막대)와 Foo의 런타임 단계를 모두 실행합니다. 내가 생각할 수있는 유일한 것은@INC
Foo 가로 드되는 방식을 수정하기 위한 매우 해킹 된 후크 일 것입니다 .