Search code examples
perlexporter

Modules use each other in cycle. Compilation error in Perl


There are 3 modules, so that they use each other by pattern a -> b -> c -> a. I cannot compile such case.

For instance,

I get a compilation error

"Throw" is not exported by the LIB::Common::Utils module
Can't continue after import errors at /root/bin/ppm/LIB/Common/EnvConfigMgr.pm line 13
BEGIN failed--compilation aborted at /root/bin/ppm/LIB/Common/EnvConfigMgr.pm line 13.

Utils.pm

use Exporter qw(import);
our @EXPORT_OK = qw(
        GetDirCheckSum
        AreDirsEqual
        onError
        Throw);
use LIB::Common::Logger::Log;

Log.pm

use Log::Log4perl;

use LIB::Common::EnvConfigMgr qw/Expand/;

EnvConfigMgr.pm

use Exporter qw(import);

our @EXPORT = qw(TransformShellVars ExpandString InitSearchLocations);
our @EXPORT_OK = qw(Expand);

use LIB::Common::Utils qw/Throw/;

Why doesn't it get compiled and how to make it work?


Solution

  • You need to use require instead of use somewhere in the loop of dependencies so as to delay the binding. It is most convenient with a module that exports nothing, as otherwise you need to write an explicit import call

    In your case LIB::Common::Logger::Log doesn't use Export, so putting

    require LIB::Common::Logger::Log
    

    into LIB/Common/Utils.pm fixes the problem

    You have access to the code that isn't working, and you could have saved us a lot of time by simply showing the malfunctioning code. You ignored two comments asking for more information so I have set up these files

    Note that this code does nothing: it simply compiles

    LIB/Common/Utils.pm

    package LIB::Common::Utils;
    
    use Exporter 'import';
    
    our @EXPORT_OK = qw/
        GetDirCheckSum
        AreDirsEqual
        onError
        Throw
    /;
    
    require LIB::Common::Logger::Log;
    
    sub GetDirCheckSum { }
    
    sub AreDirsEqual { }
    
    sub onError { }
    
    sub Throw { }
    
    1;
    

    LIB/Common/Logger/EnvConfigMgr.pm

    package LIB::Common::EnvConfigMgr;
    
    use Exporter 'import';
    
    our @EXPORT = qw/ TransformShellVars ExpandString InitSearchLocations /;
    our @EXPORT_OK = 'Expand';
    
    use LIB::Common::Utils 'Throw';
    
    sub TransformShellVars { }
    
    sub ExpandString { }
    
    sub InitSearchLocations { }
    
    sub Expand { }
    
    1;
    

    LIB/Common/Logger/Log.pm

    package LIB::Common::Logger::Log;
    
    use Log::Log4perl;
    
    use LIB::Common::EnvConfigMgr 'Expand';
    
    1;
    

    main.pl

    use strict;
    use warnings 'all';
    
    use FindBin;
    use lib $FindBin::Bin;
    
    use LIB::Common::Utils;