Dear Monks,
I'm experiencing serious and unexplainable problems with exporting/importing symbols across modules. I'm using Perl 5.8.6 and am not far away to claim to have found a weird bug. Before I do so, I'd like to make sure I'm not missing something. Your assistance is greatly appreciated.
I've got this project with around 30 modules. These modules
make frequent mutual use of some of the subroutines and - sometimes - global variables they declare.
My problem is twofold: 1) I still do not exactly know the
best practice to distribute these symbols (subs and variables) across the modules, hence I might have some kludges in the code and 2) things that did work and things that should further keep working, suddenly stop working with no obvious reason at compile time and the error messages
are IMHO frankly wrong.
Let's start with 2). Right now my code doesn't even compile and bails out with this error message:
Undefined subroutine &PMLS::Help::globalconf called at /home/proj/pmls
+/modules/PMLS/Help.pm line 41.
Yeah. That's ok, as there is no &PMLS::Help::globalconf
defined. Looking at the source in Help.pm we see at line
41:
my $sections = &dir2array(&globalconf('pmls_help')); # rea
+d in all section help files
But OTOH we have at line 23:
use PMLS::System qw(log globalconf);
So why doesn't the compiler see this globalconf? Yes, it
works elsewhere, yes it worked
before.
"Before", I hear you mumble, "What do you mean by before?"
Well - e.g. adding
use PMLS::Help qw($help);
to PMLS::System. And it's even worse, if I simply comment out this globalconf, then the compiler stops because one of the other modules suddenly doesn't even see the
$help from
use PMLS::Help qw($help);
So it is the same problem and again it occurs in just only one module. All others work. What is so special about it? I don't know.
Now - ok: Probably best would be to build something, so the weird behaviour/error would be reproducible. This is no easy task, as this app is around 50k LOC. I will try to set up a bung of module files and try to reproduce that. But am I right in that if I export some variable/subroutine in some module and import it in another module the standard way, that it ALWAYS should be visible (provided no nameclashes etc.). Or do I have to take something else into account? Are some "use cycles" dangerous? e.g having files A B C:
A:
use B qw(bloh);
use C qw(bleh);
export = qw(blah);
<can use bloh and bleh>
B:
use C qw(bleh);
use A qw(blah);
export = qw(bloh);
<can use blah and bleh>
C:
use B qw(bloh);
use A qw(blah>;
export= qw(bleh);
<can use blah and bloh>
Should not matter - should it?
update:
I did a manual expansion of the "use module" chronology in the project. The "*" Lines show the first occurence of
an use.
From the tracestack of the error message
Uncaught exception from user code:
Undefined subroutine &PMLS::Help::globalconf called at /home/p
+roj/pmls/modules/PMLS/Help.pm line 41.
Compilation failed in require at /home/proj/pmls/modules/PMLS/System.p
+m line 42.
BEGIN failed--compilation aborted at /home/proj/pmls/modules/PMLS/Syst
+em.pm line 42.
Compilation failed in require at /home/proj/pmls/modules/GDCF.pm line
+35.
BEGIN failed--compilation aborted at /home/proj/pmls/modules/GDCF.pm l
+ine 35.
Compilation failed in require at /home/proj/pmls/modules/PMLS/FS.pm li
+ne 27.
BEGIN failed--compilation aborted at /home/proj/pmls/modules/PMLS/FS.p
+m line 27.
Compilation failed in require at /home/proj/pmls/modules/PMLS/Reposito
+ry.pm line 39.
BEGIN failed--compilation aborted at /home/proj/pmls/modules/PMLS/Repo
+sitory.pm line 39.
Compilation failed in require at /home/proj/pmls/modules/PMLS/Doc.pm l
+ine 27.
BEGIN failed--compilation aborted at /home/proj/pmls/modules/PMLS/Doc.
+pm line 27.
Compilation failed in require at /home/proj/pmls/modules/PMLS/Server.p
+m line 43.
BEGIN failed--compilation aborted at /home/proj/pmls/modules/PMLS/Serv
+er.pm line 43.
Compilation failed in require at /home/proj/pmls/bin/pmls line 16.
BEGIN failed--compilation aborted at /home/proj/pmls/bin/pmls line 16.
at /home/proj/pmls/bin/pmls line 16
I suspect, the point where it makes BOOM is here:
*use PMLS::Server
* use PMSuite::File qw(safe_save);
* use PMLS::Constants;
* use PMLS::Doc;
use PMSuite::File qw(write_file);
use PMLS::Constants;
* use PMLS::Pmts qw(getname_iso639);
use PMLS::Constants;
* use PMLS::Repository;
use PMSuite::File qw(file2array);
* use PMSuite::List qw(inref isect_union);
use PMLS::Constants;
use PMLS::Doc;
* use PMLS::FS qw(ensure_home);
* use GDCF;
use PMLS::Constants;
* use PMLS::System qw(log message);
use PMLS::Constants;
* BOOM! use PMLS::Help qw($help);
use PMSuite::File qw(dir2array dir2hash);
use PMLS::System qw(log globalconf);
use PMLS::FS qw(ensure_home);
* use PMLS::Protocol;
use PMLS::Constants;
use PMSuite::File qw(dir2array file2array);
use PMSuite::List qw(columns_list);
use PMLS::Constants;
use PMLS::Help qw($help);
use PMLS::System qw(globalconf message);
use PMLS::Help qw($help);
* use PMLS::Lexicon;
use PMSuite::File qw(safe_save);
use PMSuite::List qw(inref);
use PMLS::Constants;
* use PMLS::Meaning;
use PMLS::Constants;
use PMLS::System qw(log message);
* use PMLS::Property qw(get_proparg get_proptype prop
+dist trim);
use PMLS::Constants;
use PMLS::System qw(message);
* use PMLS::Morphology qw(procrule);
use PMLS::Constants;
use PMLS::Meaning;
use PMLS::Repository;
use PMLS::System qw(log message);
use PMLS::Pmts qw(valid_iso639);
use PMLS::Property qw(synmod);
use PMLS::Repository;
use PMLS::System qw(log globalconf message pb_fillup);
* use PMLS::Text;
use PMSuite::File qw(dir2array file2scalar);
* use PMLS::SNLP::Analyzer qw(analyse filter_analysis)
+;
* use PMLS::SNLP::CharServer;
use PMLS::System;
* use PMLS::SNLP::Comparator qw(compare);
* use PMLS::T9::Common;
use PMLS::System qw(log);
* use PMLS::T9::cz
use PMLS::System qw(globalconf);
* use PMLS::T9::de
use PMLS::System qw(globalconf);
* use PMLS::T9::es
use PMLS::System qw(globalconf);
* use PMLS::T9::fr
use PMLS::System qw(globalconf);
* use PMLS::T9::it
use PMLS::System qw(globalconf);
* use PMLS::T9::sk
use PMLS::System qw(globalconf);
use PMLS::Constants;
use PMLS::FS qw(ensure_home);
use PMLS::Help qw($help);
* use PMLS::Phrase qw(dia2asc compat);
use PMLS::Constants;
use PMLS::FS qw(ensure_home);
use PMLS::System qw(message);
use PMLS::Repository;
use PMLS::System qw(log message globalconf);
use PMLS::T9::Common;
use PMLS::Morphology qw(alias concat procrule);
use PMLS::Phrase qw(dia2asc is_regex);
use PMLS::System qw(globalconf log message miter);
use PMLS::Server;
use PMLS::System qw(globalconf message procinfo);
use PMLS::Text qw(_tident tident_out_suplang);
use PMLS::FS;
use PMLS::Help qw($help);
* use PMLS::NLP;
use PMLS::Constants;
* use PMLS::MT;
use PMSuite::List qw(get_maxval get_minval inref);
use PMLS::Constants;
use PMLS::Help qw($help);
use PMLS::Lexicon;
use PMLS::Morphology qw(build_ruleset manal);
use PMLS::Pmts qw(valid_iso639);
use PMLS::Repository;
use PMLS::System qw(kv_out log message);
use PMLS::Text;
use PMLS::T9::Common;
* use PMLS::NLA;
use PMSuite::List qw(get_maxval);
use PMLS::Constants;
use PMLS::FS qw(ensure_home);
use PMLS::Help qw($help);
use PMLS::Meaning;
use PMLS::Morphology qw(build_ruleset manal);
use PMLS::System qw(log message globalconf);
* use PMLS::NLG;
use PMLS::Constants;
use PMLS::FS qw(ensure_home);
use PMLS::Help qw($help);
use PMLS::Pmts qw(valid_iso639);
use PMLS::Repository;
use PMLS::System qw(log message globalconf);
use PMLS::Phrase;
use PMLS::Repository;
use PMLS::System qw(message);
use PMLS::Text;
use PMLS::Protocol qw(msg_compose msg_verify);
use PMLS::System qw(globalconf log message num_cpus procin
+fo cmdloop);
* use PMLS::User;
use PMLS::Constants;
use PMLS::FS qw(ensure_home);
use PMLS::Help qw($help);
use PMLS::System qw(globalconf message);