osiv osiv - 1 month ago 6
Perl Question

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?

Answer

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;