How does Foswiki find Perl libraries? And how do I change that?
How Foswiki Finds Perl Libraries
Foswiki is implemented in Perl, and uses a number of external Perl libraries. Some of these are normally installed by default in any Perl installation, and some have to be installed explicitly. There are a number of different ways in which libraries can be installed, and Foswiki uses a configurable library system to help cope with this.
How Perl works
Perl relies on being able to find the libraries that make it work at "run time" i.e. every time a Foswiki script is executed.
Where Perl libraries live
Perl uses something called the
@INC
path (pronounced at-ink path) to find libraries. The
@INC
path is a list of directories. Perl searches these directories for each new library it needs to load, starting at the first, and proceeding in order to the last. Perl will always use the
first version of a library it finds in the
@INC
path, so the order of the path is important.
On any system Perl is set up with a default
@INC
path that defines where all the pre-installed system libraries are to be found. If you have access to the command-line, you can review this 'base path' using the following (UNIX) shell command:
perl -V
This will display the default content of the
@INC
variable at the end of the output.
Unless you run this command as the webserver user, you can't be 100% sure the webserver will have the same @INC path.
CPAN
Perl comes with a standard mechanism for installing and managing Perl libraries, called CPAN. If you use CPAN, and install as the root user, then the libraries are installed in the base path. However on some systems, notably hosted platforms, you don't have access to the root user and have to install using a local CPAN library. In addition, Foswiki comes with some pre-installed local CPAN libraries, in the
lib/CPAN
directory.
HowToInstallCpanModules has extensive instructions on installing CPAN modules, including setting up your own local CPAN library.
Other install methods
On some systems, Perl libraries can be installed in the base path
without using CPAN - for example on Debian, where you can
apt-get
some perl libraries.
How Foswiki works
When a Foswiki script starts up, it starts with the default @INC path, the same as any other Perl script. Of course Foswiki itself is implemented as a set of Perl libraries, and the @INC path has to be modified to find these libraries, so one of the first things every Foswiki script does is to
require
a small module called
bin/setlib.cfg
to do this.
setlib.cfg
is itself very flexible, in order to be able to cope with all the different types of system Foswiki might be installed on. It's driven by an even smaller Perl module that is usually written by the person installing Foswiki, called
bin/LocalLib.cfg
. Normally this is very easy to set up - Foswiki can pick intelligent defaults - but sometimes you have to be able manipulate the paths using it.
You can review the
@INC
path that is set by
setlib.cfg
by viewing the 'Web Server Environment' section in
configure
.
LocalLib.cfg
gives the installer three ways to manipulate the @INC path, through the settings of three Perl variables:
-
$foswikiLibPath
-
@localPerlLibPath
-
$CPANBASE
$foswikiLibPath
This is the most commonly modified setting. It is set to the path where the Foswiki libraries reside i.e. the directory where
Foswiki.pm
is to be found, and is always put
first on the
@INC
path. If you
don't set it, then Foswiki will build it from the path of the
setlib.cfg
. On some systems, this might fail, most notably on persistent environments like mod_perl or FastCGI, and it could be a bit slower than hard coding the path, so it's a good practice to set it.
99% of Foswiki installs will never need to go beyond this point.
@localPerlLibPath and $CPANBASE
These two are inextricably linked, so have to be dealt with together.
$CPANBASE
is a simple path, and is intended to let you point to a local CPAN installation (see
HowToInstallCpanModules).
@localPerlLibPath
is a
list of paths that can be added to
@INC
. Neither
$CPANBASE
nor
@localPerlLibPath
are defined by default, but either or both can be defined in
LocalLib.cfg
. There's no simple way to describe their interactions, so here goes:
- If
$CPANBASE
is defined, then
-
$foswikiLibPath/CPAN/lib
is not added to @INC
- you have to do it yourself if you need it.
- The directory pointed at by
$CPANBASE
must exist, otherwise the setting is ignored.
- If
@localPerlLibPath
is defined and $CPANBASE
is defined, then
- the paths in
@localPerlLibPath
, followed by $CPANBASE
, are added to the beginning of @INC
.
- If
@localPerlLibPath
is defined and $CPANBASE
is not defined, then
- the paths in
@localPerlLibPath
, followed by $foswikiLibPath/CPAN/lib
are added to the end of @INC
.
Scenarios
Let's say for example that you are on a hosted platform where Foswiki is installed in
/var/www/foswiki
, and you need a more recent version of a Perl library that the hosting provider has already installed in the default perl libraries. How can you override their version of the library? Let's further assume you have created a personal CPAN install in
/users/me/CPAN
and installed the library there. Your
LocalLib.cfg
might look as follows:
# By Rule 1, have to manually add the shipped CPAN modules to @INC. Do this by defining @localPerlLibPath.
@localPerlLibPath = ( '/var/www/foswiki/lib/CPAN' );
# By Rule 2, defining $CPANBASE will get our local CPAN library added *before* the default system libraries
$CPANBASE = '/users/me/CPAN';
Use
configure
to review your modified
@INC
path.
Troubleshooting your library installation
If Foswiki appears to be having trouble finding libraries, there are some basic steps you should follow.
First, open the
configure
"Web Server Environment" section, and check the
@INC
path displayed there. Your perl modules must exist somewhere on those paths for Foswiki to find them. The order of these paths is important; a library might be installed in several different places on your system, but Perl will only ever use the
first version it finds in the @INC path - even if that's the
wrong version.
Next, check the permissions on the directories (and the files under them) in the @INC path. The web server user has to be able to
read.
--
CrawfordCurrie,
OlivierRaginel - 06 Nov 2009