At $WORK I am writing a utility to read data from a data source and write a fairly complex set of configuration files for a set of tools we use. It’s past Sysadmin 101 and into Advanced System Administration. I’ve also been given permission to write clean new Perl, and am doing several interesting things like running a code coverage analysis and keeping the code approved by perlcritic –brutal. I’m also using a GUI IDE to develop in.

It’s been a nice change, and I’m enjoying it. (Most of it. Perlcritic –brutal is picky.)

I’ve been using ActiveState‘s Komodo to write the Perl in. I’ve got a license for their big commercial version, which I’m enjoying. The RxToolkit is almost enough for the price of admission, and the syntax highlighting, ability to perltidy sections of document, run tests, debug code, and generally really manage a project without having to fiddle with a shell window and a mess of scripts and Makefiles and stuff has been nice.

I finally have all the data gathered and can begin generating the config file. I started a new module to contain the code for that process, and filled in the basics; use strict, use warnings, use 5.016000, POD, etc., etc., etc. I saved the file and went to lunch.

When I came back, the syntax checker had gone insane. Every file open had strange errors, all early in the modules.

The new module’s first real line of code was:

use Moose;

Pretty innocuous, huh? The red wavy underline said something was wrong, and the block of text it showed was:

Can't locate loadable object for module Sub::Name in @INC (@INC contains: . /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi /usr/lib/perl5/site_perl/5.16.0 /usr/lib/perl5/vendor_perl/5.16.0/x86_64-linux-thread-multi /usr/lib/perl5/vendor_perl/5.16.0 /usr/lib/perl5/5.16.0/x86_64-linux-thread-multi /usr/lib/perl5/5.16.0 /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi /usr/lib/perl5/site_perl/5.16.0 /usr/lib/perl5/site_perl .) at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Class/MOP/Mixin/HasMethods.pm line 17.

Compilation failed in require at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Class/MOP/Mixin/HasMethods.pm line 17.

BEGIN failed--compilation aborted at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Class/MOP/Mixin/HasMethods.pm line 17.

Compilation failed in require at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Class/MOP.pm line 25.

BEGIN failed--compilation aborted at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Class/MOP.pm line 25.

Compilation failed in require at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Moose/Exporter.pm line 13.

BEGIN failed--compilation aborted at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Moose/Exporter.pm line 13.

Compilation failed in require at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Moose.pm line 18.

BEGIN failed--compilation aborted at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Moose.pm line 18.

Compilation failed in require at Config.pm line 1.

BEGIN failed--compilation aborted at Config.pm line 1.

Compilation failed in require.

BEGIN failed--compilation aborted.

That sure stumped me. I went out to a shell. My tests all passed. perl -c liked the module. Everything made sense, except that the syntax checker was full of errors.

I started searching the Internet. Eventually I found a post on the old Komodo support forum that gave me a hint on how to get Komodo to show the command line it was running. I did that, and got nothing really shocking.

/usr/bin/perl -wc -I. komodolint.1211251.in

The temp file name was wackier, and I’ve forgotten it, but it was a temp file name. It takes the buffer, stores it on disc, and runs perl -wc on it, then parses the output. Pretty straightforward. The only odd thing was a -I., and what harm could that cause? (The comments in Komodo’s script had a reason for the -I., too. I wonder if they’re still needed, or if adding it to the end would be as effective.)

Plenty, as it turns out. I tried the same command in the shell, and got the same error. Still baffling, but at least I could make it happen myself!

Add the -I., and it would fail. Remove it, and all was well.

What happened?

It took me a minute, but I finally looked at the new file I added before lunch. The one that was going to write a config file. The one called Config.pm… there was the light bulb.

Perl provides a Config.pm. It’s got all sorts of good stuff from your system configuration in it. Things like the default @INC path and other wonders. If you put the current directory first, apparently it loads your Config.pm, instead of the system one. Which means it can’t find any of the shared libraries modules use. Or, sometimes even stranger things.

Try some experiments.

Create an empty directory to play in, and try simple things with an empty Config.pm:

mkdir testme cd testme touch Config.pm perl -I. -V

That’ll get you:

Config.pm did not return a true value.

BEGIN failed--compilation aborted.

That’s a pretty clear message, and would have confounded me less. But I had a valid Config.pm!

What happens if you put in a valid, but empty Config.pm?

echo "1;" > Config.pm perl -I. -V

Undefined subroutine &Config::_V called.

Also reasonably clear. My module did something, though. It used a real module that clearly does a lot of things. Let’s try a module that uses a more complex module, like where mine got stuck:

echo "use Moose; 1;" > Config.pm perl -I. -V

Can't locate loadable object for module Sub::Name in @INC (@INC contains: . /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi /usr/lib/perl5/site_perl/5.16.0 /usr/lib/perl5/vendor_perl/5.16.0/x86_64-linux-thread-multi /usr/lib/perl5/vendor_perl/5.16.0 /usr/lib/perl5/5.16.0/x86_64-linux-thread-multi /usr/lib/perl5/5.16.0 /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi /usr/lib/perl5/site_perl/5.16.0 /usr/lib/perl5/site_perl .) at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Class/MOP/Mixin/HasMethods.pm line 17.

Compilation failed in require at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Class/MOP/Mixin/HasMethods.pm line 17.

BEGIN failed--compilation aborted at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Class/MOP/Mixin/HasMethods.pm line 17.

Compilation failed in require at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Class/MOP.pm line 25.

BEGIN failed--compilation aborted at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Class/MOP.pm line 25.

Compilation failed in require at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Moose/Exporter.pm line 13.

BEGIN failed--compilation aborted at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Moose/Exporter.pm line 13.

Compilation failed in require at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Moose.pm line 18.

BEGIN failed--compilation aborted at /usr/lib/perl5/site_perl/5.16.0/x86_64-linux-thread-multi/Moose.pm line 18.

Compilation failed in require at Config.pm line 1.

BEGIN failed--compilation aborted at Config.pm line 1.

Compilation failed in require.

BEGIN failed--compilation aborted.

There we go, losing our marbles.

Remove the dot from the FRONT of the @INC path, or remove the pesky Config.pm, and all is well.

Moral of the story: Watch your @INC path, and don’t step on internal names.