From EPrints Documentation
Jump to: navigation, search

Setting up an EPrints development environment using Eclipse, Epic and the Perl Debugger

This describes a way to implement Perl development within Eclipse, which will help enable code inspection, auto-completion (in some circumstances), and most importantly interactive debugging with running processes.

Set up the development environment

You will need to install Eclipse, which can be obtained from:

You should ensure that when Eclipse runs it runs using the Sun Java implementation, NOT the gcj, as there are bugs in the gcj which prevent Perl debugging from working correctly.

Once you have obtained Eclipse, you need to install the EPIC Perl development extension to the platform. Details for EPIC can be obtained at:

Go to:

  Help -> Software Updates -> Find and Install ...

Select the button: "Search for new features to install", and hit "Next"

Add a new remote site, using the url for epic, which was (at one pont at least):

Download and install the latest version of EPIC, and follow the on-screen instructions for running it.

You now have all the tools you need to develop with Perl in Eclipse.

Set up your code in the IDE

Making changes to EPrints

If you are making changes directly to EPrints, you can start a new "Perl Project" in eclipse, and import the EPrints source code into it from the standard installation directory (something like /usr/share/eprints3/perl_lib). You need to ensure that there is only one copy of the EPrints source files available to Apache, otherwise there is much scope for confusion. Therefore, either copy the files in from the EPrints perl library to your IDE, and delete (or move) the original files out of the way, or set up your development environment's working directory as /usr/share/eprints3/perl_lib. I would strongly recommend the former, as this will keep your EPrints directory free of development clutter. Later we will configure Apache to point to your development environment for the EPrints source files, so nothing will break.

Adding your own modules external to EPrints

If you are coding a separate module which will use the EPrints modules as a set of dependencies, you should create a new "Perl Project" for your module, and place all your code in here. I have found it useful to import the entire EPrints perl module as another Perl Project in Eclipse, and to set that on the "Perl Include Path" (see the next section). In this way, when you ctrl-click on a package/module name, Eclipse will open the code in a new source tab, but the code which runs will still be the EPrints code in /usr/share/eprints3/perl_lib (unlike in the above section). Later we will configure Apache to point to your development environment for the source of your new module, so it will be able to run alongside EPrints with no problems.

Configuring dependencies

To set up any external libraries upon which your project is dependent, right click on the project name and select "Properties". Go to "Perl Include Path" and insert the path to the root of the perl modules which your code will depend on. This will allow Eclipse/EPIC to check for modules, functions, and so forth to aid code completion.

Install Perl Modules for interactive debugging

You will need to ensure that 2 particular perl modules are installed to enable interactive debugging. Download and install the following modules from CPAN:

Apache::DB; this provies a wrapper for perldb to run in a web context:

PadWalker; this provides real time variable inspection and modification:

Set up Apache for interactive debugging

In your apache configuration, you need to include

  • The include paths of your perl module
  • The include path of the Eclipse debug code (which we will create in a section below, for the time being just trust me on the file paths)
  • The auto-reload of changed files for our module (which saves us from having to restart apache all the time) (Reload configuration courtesy of Tim Brody)
  • The perl options for debugging

You will need to include something like the following in your apache configuration (I have this in my /etc/apache2/httpd.conf file):

PerlSwitches -I/path/to/your/perl/module -I/path/to/your/perl/module/debug -I/path/to/development/eprints

PerlModule Apache2::Reload
PerlInitHandler Apache2::Reload
PerlSetVar ReloadAll Off
PerlSetVar ReloadModules "EPrints::* MyModule::*"

<IfDefine PERLDB>

    PerlSetEnv PERLDB_OPTS "RemotePort= DumpReused ReadLine=0 PrintRet=0"
    PerlSetEnv PERL5DB "BEGIN { $DB::CreateTTY=0; require '/path/to/your/perl/module/debug/'; }"
      use Apache::DB ();
    <Location />
      PerlFixupHandler Apache::DB

The PerlSwitches line includes three module locations into the @INC configuration for the mod_perl environment. The first of these is the root of the directory where the perl modules that you are developing are located.

The second of these is the location of the debug tools that EPIC will use to interrogate the Apache interactive debugger. I have placed these in the development environment here, so that we can manage them alongside our other code. We will come on to how to generate the content of this directory in the next point; for the time being just ensure that there is a place for it to go, and that the include points to it

The third is the location of the EPrints source code in your development environment, which ensures that EPrints can run even if the source has been removed from /usr/share/eprints3/perl_lib.

Of these three options, you can omit the first or third depending on your development setup, and the path to the debug module is entirely up to you.

In the conditional <IfDefine> we set the configuration to ensure that the interactive debugger can send information out to the EPIC debug environment, and that at can find the script. Note that the script is part of the EPIC debugger configuration, and will be created in the next step.

The rest of the configuration ensures that mod_perl is using Apache::DB. This will only happen when we pass -D PERLDB as an argument when we start apache.

Generating the EPIC debug configuration

In Eclipse, go to:

 Run -> Debug ...

Start a new "Perl Remote" configuration, specifying the project you wish to work with, and setting the "Target Host" path to the location of the perl module in your IDE. On the first execution of this configuration you must also specify that you want to create the debug package, and give it a path to save the file to. The other settings on this page should be fine as the default (assuming that you are running Eclipse and Apache on the same machine).

Run the configuration, which will attemt to connect to the debugger. At this stage it will fail, so stop the process and go and look for the debug package which was created where you requested. Unzip this file, and discard all content other than and files of the form *epic*.pm. Place these remaining files into the "debug" directory specified in the apache configuration in the previous section.

Start apache in debug mode

We can now start apache in debug mode, using the following command:

sudo apache2ctl -k start -X -D PERLDB

This will start the apache web server in non-forking mode (-X), and will invoke the configuration in our <IfDefine> tag, enabling debugging.

You will find that the command line is not returned to you when this operation is complete, as the debugger retains control of it.

Issue debugger requests

In the EPIC configuration, ensure that "suspend at first line" is set, execute the debugger configuration and execute a web request to your application. The code should suspend at the first executable line, and you will be moved from the "Perl" perspective of Eclipse to the "Debug" perspective. The currently executing file will be opened in front of you, and the current line of the application will be highlighted. You should now be able to set breakpoints in this file, and to step through it line by line usign the Eclipse debugger controls.

I also find it convenient to set EPIC to show you the debugger console. This gives you another way of seeing what's going on inside the perl interpreter while your code is running.

Setting break points

With the code running from inside your development environment, you can simply open the file you wish to debug and drop a breakpoint in on any active line of code by double clicking in the left margin of the code editor window.

When you make a request by, for example, loading the EPrints home page, the execution will suspend at first the very first line (assuming this is the first request) and then at your own breakpoint, and you will be brought into the "Debug" perspective in Eclipse if not already there.

It is worth reading the Eclipse documentation on how to use the debug environment, as it has a number of very useful features.

Terminating the process

You should not attempt to stop the process using the red "stop" button in the Eclipse debugger. This will cause Eclipse to hang until you then manually shut apache down from the command line. Instead, close down apache first, and then use the stop button in the eclispe debugger to terminate the debug listener. You can then re-start up both of these processes in either order.

Watching for Errors

Sometimes the process you execute will fail if there is a compile-time error. The debugger will not get a change to attach to a process, so it will not be able to show you what is wrong. It is therefore necessary to also attach to the apache log file to see what is going on. Look in /var/log/apache2/error.log for error messages. I use a command like:

 tail -f var/log/apache2/error.log

which allows me to watch the end of this file as errors scroll past.

Useful tricks

There are a number of useful things that you can do with the integrated development environment, here are a selection:

  • ctrl-click on package names and function calls to be taken to their declaration (whether that be in your own code, or in some externally referenced module on the Perl Include Path). Note that EPIC is only moderately good at this, and sometimes cannot locate things which it ought to be able to.
  • placing the editing caret on a variable will highlight all uses of that variable in the current scope
  • when a variable's type is known (e.g. it has been explicitly created using an object constructor), ctrl-space after the "->" arrow operator will provide a list of available methods. Due to the weak/dynamic typing of Perl, this will not work for variables which have been obtained by an indirect route (such as by a function call)
  • when debugging, you can step through the executing code line by line using the "step over" feature; this will then allow you to see the variables and their state in the perl interpreter at each stage of execution. Very useful for picking apart confusing bugs.
  • EPIC will constantly evaluate your code and alert you to most forms of syntax error, and warn of possible typos.
  • entering a variable prefix (i.e. $, %, &, @, etc) and pressing ctrl-space will list all variables of that type that are currently in scope
  • Running apache in debug mode retains control of the command line. To quick kill apache, use ctrl-\ in the terminal in which you started it

Trouble Shooting

Not a CODE Error

If you see "Not a CODE Error" in your apache logs, it could mean that apache has failed (for some unknown to me reason) to appropriately load some of the changes that you have made since your last code execution. I have found that very occasionally this error will go away if you wait for a short while before running your code again, but more likely you need to detach from the debug process, restart apache, and reattach before your code will run successfully again.

Further Reading

Much of this How-To has been developed by extensive reference to this blog post: