jmo has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I've got 3 modules using eachother and that makes perl -c go crazy. This is what they look like:
a.pm:
package a; BEGIN { use Data::Dumper; print STDERR 'a:',Dumper \%INC; } use b; my $a = { foo => &b::bar () }; 1;
b.pm:
package b; BEGIN { use Data::Dumper; print STDERR 'b:',Dumper \%INC; } use c; sub bar { 1; } 1;
c.pm:
package c; BEGIN { use Data::Dumper; print STDERR 'c:',Dumper \%INC; } use a; 1;
running perl -c a.pm, except printing the %INC var in different states gives me:
Undefined subroutine &b::bar called at a.pm line 7. Compilation failed in require at c.pm line 6. BEGIN failed--compilation aborted at c.pm line 6. Compilation failed in require at b.pm line 6. BEGIN failed--compilation aborted at b.pm line 6. Compilation failed in require at a.pm line 6. BEGIN failed--compilation aborted at a.pm line 6.
Does anyone know why this happends? %INC holds all three modules. b.pm and c.pm both compile when doing perl -c on them. Also, removing "use c;" in b.pm makes a.pm compile.

Replies are listed 'Best First'.
Re: Circular module dependencies
by herveus (Prior) on Oct 04, 2004 at 11:25 UTC
    Howdy!

    I'm going to number the lines so it's easier to follow the flow...

    1 package a; 2 BEGIN { 3 use Data::Dumper; 4 print STDERR 'a:',Dumper \%INC; 5 } 6 use b; 7 my $a = { foo => &b::bar () }; 8 1; 9 10 b.pm: 11 12 package b; 13 14 BEGIN { 15 use Data::Dumper; 16 print STDERR 'b:',Dumper \%INC; 17 } 18 use c; 19 sub bar { 1; } 20 1; 21 22 c.pm: 23 24 package c; 25 BEGIN { 26 use Data::Dumper; 27 print STDERR 'c:',Dumper \%INC; 28 } 29 use a; 30 1;
    Now, you say perl -c a.pm...that begins at line 1.

    Lines 2 through 5 get compiled and immediately executed. Line 6 gets compiled, and leads to b.pm being processed. Move to line 12.

    Lines 14-17 get compiled and executed. Line 18 gets compiled and leads to c.pm being processed. Move to line 24.

    Lines 24-28 get compiled and executed. Line 29 now causes a.pm to get processed (again). Since a.pm has not yet been required or used, it gets run through the mill a second time. Move to line 1.

    Lines 1-8 get compiled, then executed. Since b has already been used, it should get skipped (but import gets run, in the general case). Next, it turns to line 7 and executes it. That attempts to execute b::bar, but we have not yet gotten to line 19 in b.pm to define that subroutine.

    Here the execution blows up.

    Now, the problem is that you are use-ing modules that do more than define subroutines. When naked code calls routines in other modules, those routines had best be defined before you execute them. Better is to simply avoid getting into those situations.

    Consider switching lines 18 and 19 and see what happens...

    yours,
    Michael
Re: Circular module dependencies
by Joost (Canon) on Oct 04, 2004 at 09:17 UTC
    You are probably using some case-insensitive file-system. (update: Using "b" is dangerous for case-insensitive filesytems) Don't use the B package names for yourself, B a core module.

    edited: something else is going on, not yet sure what, though.

    edited: apparantly, this is some kind of nasty interaction with compiletime/runtime: this error only occurs if you load a.pm as a normal code (instead of useing a.pm):

    test.pl:

    #!perl use lib '.'; use a;
    end then:
    > perl -c test.pl [ ... lots of output omitted ] test.pl syntax OK

    I don't have the time to investigate this further, though.

Re: Circular module dependencies
by simonm (Vicar) on Oct 05, 2004 at 16:55 UTC
    If you want to test compilation of a module, then test its use as a module, not as a script: perl -c -e 'use a'