2013-03-08 2 views
1

use lib에 대한 상대 경로를 찾는 데 문제가 있습니다. 다음은 내가하려는 일의 예입니다.모듈을 기준으로 경로에 lib를 사용하십시오.

myscript.pl이라는 스크립트가 포함 된 foo이라는 디렉터리 호출이 있습니다.

use lib 'bar'; 
    use Mod1; 

내가 Mod1.pm 다른 모듈을 사용할 때까지이 잘 작동 foo/bar/asdf/Mod2.pm : 나는 라인을 넣어 myscript.pl의 상단에 있도록 myscript.pl는 이름의 모듈 Mod1.pmbar라는 하위 디렉토리에 사용합니다. 의 맨 위에 use lib 'asdf'을 입력하면 실행중인 디렉토리에 상대적인 검색을 수행하므로 작동하지 않습니다 myscript.pl. 그래서 약간의 검색을했고, FindBin을 발견하고, Mod1.pm에이 라인을 추가하는 시도 : FindBin 내가 실행하고 스크립트 (myscript.pl가)에있는 디렉토리를 발견하기 때문에

use FindBin; 
    use lib "$FindBin::Bin/asdf"; 

이이 중 하나가 작동하지 않았다 FindBin (이 경우 Mod1.pm)을 사용하는 파일이 아닙니다. 그래서 내 질문은 Mod1.pm이있는 스크립트가 어디에 있든 상관없이 Mod1.pm이있는 곳을 찾아서 Mod2.pm을 찾을 수있는 방법이 있습니까?

편집 : 내 상황의 자세한 설명은 귀하의 의견의 일부를 해결하기 위해 : 나는 저장소에 코드 일하고 있어요, 모든 CPAN 라이브러리 저장소의 디렉토리에 설치해야

. 즉, use lib에는 절대 경로가있을 수 없습니다. 내 프로젝트에는 중앙 모듈 "Mod1.pm"이 있습니다. use 저장소의 여러 디렉토리에있는 상당량의 CPAN 모듈이 있습니다. use lib 문은 모두 use lib '../../foo/bar/asdf' 형식이므로 스크립트를 실행하는 곳과 관계없이 찾을 수 있습니다. 그러나이 문제는 Mod1.pm을 사용하는 스크립트를 실행할 수있는 곳을 제한합니다. 또 다른 짜증나는 부작용은 내가 정확히 perl -c Mod1.pm Mod1pm에 대한 편집 내용을 확실하게 할 수 없다는 것입니다. Mod1.pm이있는 곳이 아닌 적절한 장소에서 실행하고 있지 않는 한 제정신입니다. 오, 이미 지저분한 코드가있는 프로젝트에 참여하는 즐거움 ... 또 다른 불쾌한 부작용은 내가 문제를 해결하기 위해 제안하는 CPAN 모듈을 사용할 수 없다는 것입니다. 그걸 찾아야 해.

+0

Mod1.pm – chrsblck

+0

에서 'lib/bar'를 사용하십시오. @chrsblck 이는 foo에서 스크립트를 실행하는 경우에만 작동합니다. 내가 어디에서 실행하는지 또는 스크립트가있는 곳과 관계없이 작동하도록합니다. – Lorkenpeist

+0

그러면 절대 경로를 사용해 보거나이 디렉토리를'$ PERL5LIB'에 추가 할 수 있습니다. – chrsblck

답변

4

보통 당신은 당신의 주요 프로그램은 알렉 첸으로 수행해야하는 경우에 그 자체로 모든 라이브러리를 찾으려면 대답했다.

플러그인을 찾는 것과 같은 경우에는 라이브러리가 위치와 관련하여 다른 라이브러리를 찾길 원할 수 있습니다.

__FILE__에는 소스 코드의 현재 파일 위치가 포함되어 있습니다.

package Mod1; 

use strict; 
use warnings; 

use File::Basename; 

# Must put this in a BEGIN block so it happens at "compile time" while the 
# "use"s are being executed. But the "my" declaration must happen outside 
# the BEGIN block else it can't be seen. 
my $module_dir; 
BEGIN { $module_dir = dirname(__FILE__); } 

use lib $module_dir; 

use Mod2; 

위의 재미있는 방법은 각 Perl 파일에 2 개 이상의 실행 단계가 있기 때문입니다. "컴파일 시간"과 "실행 시간". use 문은 컴파일 할 때 발생합니다. use lib $module_dir으로 컴파일하려면 BEGIN 블록으로 $module_dir을 컴파일 타임에 설정해야합니다. 혼란스러워? 더 쉬운 방법이 있습니다 ...

모듈이 @INC을 전 세계적으로 변경하는 것은 나쁜 형태입니다. 모듈을 로딩하면 프로그램의 전역 상태가 변경되어서는 안됩니다 (기능의 일부가 아닌 경우). 대신에 지역화 할 수 있습니다.

package Mod1; 

use strict; 
use warnings; 

use File::Basename; 
my $module_dir = dirname(__FILE__); 

{ 
    local @INC; 
    push @INC, $module_dir; 
    require Mod2; 
} 

하지만 파일로 직접 요구하는 것이 더 간단 할 것입니다.

package Mod1; 

use strict; 
use warnings; 

use File::Basename; 
use File::Spec; 
my $module_dir = dirname(__FILE__); 
require File::Spec->catfile($module_dir, "Mod2.pm"); 

그리고이되는 펄, 매우 인기있는 가진 플러그인, Module::Pluggable을 처리하는 모듈이 있습니다.

+0

옵션 1을 시도했지만 ('use lib ($ module_dir. '/ asdf')')), 스크립트가 실패합니다 @INC에는''bar''와''/ asdf ''가 포함되어 있다는 오류 메시지가 표시됩니다. @INC에''bar/asdf ''가 들어 있기를 기대 했으므로 여기서 무슨 일이 일어나고 있는지 모르겠습니다 ... 아마도'lib 사용'이 어떻게 작동하는지 오해하고 있습니까? (옵션 3은 저에게 효과적 이었지만 관련없는 이유로 실제 작업에는 사용할 수 없습니다. 주석 제한은 포함하기에 너무 작습니다.) – Lorkenpeist

+0

@Lorkenpeist 제 실수. 엄격한 경고와 경고 (당신이 항상해야하고 나는 예제에서 무시 당했을 때)를 켜면'$ module_dir'이 정의되지 않았 음을 알 수 있습니다. 코드를 수정하고 설명을 추가했습니다. 아마도 귀하의 게시물에 옵션 3이 불가능한 이유를 추가 할 수 있습니까? 그것은 이상한 제한 사항으로 File :: Spec 또는 require를 사용할 수 없습니다. 아니면 Module :: Pluggable을 사용하고 싶습니까? – Schwern

+0

내 게시물에 더 많은 정보를 추가했습니다. 근본적으로 모든 CPAN 모듈이 어디에 있는지 찾아내는 것은 고통 스러울 것입니다 (모든'use lib' 문구가 먼저오고'use' 문구가옵니다.) 그래서'use'가 각각'use lib'와 함께 사용되는지는 명확하지 않습니다.). 나는 옵션 3의 외모를 좋아하기 때문에 나는 파고 갈 수 있다고 생각한다. 나는 그것을 작동 시키려고 노력할 것이다. 또 다른 우려는'use' 문장의 일부가'Mod Mod blah'의 형식이라는 것입니다.'require'를 위해 어떻게 해야할지 모르겠습니다. require에 대한 perldoc 페이지에는 2 개의 인수 버전이 없습니다. – Lorkenpeist

5

use libmyscript.pl이어야합니다. 이는 규칙입니다.

use File::Spec; 
use FindBin qw($Bin); 
use lib File::Spec->catdir($Bin, 'bar'); 
use Mod1; 

그럼 그냥 다른 CPAN 모듈을 사용하여 같은 Mod1.pmMod2.pm를 사용

. 
├── bar 
│   ├── Mod1.pm 
│   └── asdf 
│    └── Mod2.pm 
└── myscript.pl 

다음 use libmyscript.pl의 : 예를 들어

, 당신의 파일이 구성되어 있습니다. Mod2.pm을 사용할 때 모듈 이름 앞에 dir 이름을 추가하는 것을 잊지 마십시오.

Mod1.pm에 :

package Mod1; 

use asdf::Mod2; 

1; 

Mod2.pm에서 :

package asdf::Mod2; 

1; 
+0

제안 해 주셔서 감사합니다. 그러나 실제 작업에서 "Mod1"에는 꽤 많은 다른 모듈이 포함되어 있기 때문에 옵션이 저에게 효과적이지 않을 것입니다. 모든 단일 스크립트에서 '사용'하는 것이 고통 스러울 것입니다. Mod1을 사용합니다. 불행히도, 꽤 많이 있습니다. 포함 된 많은 모듈이 다른 라이브러리에 의존하는 CPAN 라이브러리이고'package' 라인을 변경해도 좋지 않을 것입니다 ... – Lorkenpeist

+0

[local :: lib] (http : //search.cpan.org/dist/local-lib/lib/local/lib.pm) – Alec

관련 문제