Setting Up an IDE with Emacs

Directory Structure

On Windows, I adopt a directory structure similar to Unix. That is, I usually install software under c:\opt and set up my %HOME% to a given directory for instance c:\home. The home directory is where we need to put the .emacs file. If it is not specified, the .emacs (or _emacs) file is looked up in c:\.

Additionally, it is handy to have a subdirectory under the home directory (whether on Unix or Windows) where to store libraries for Emacs. This is so that we don't lose them when switching Emacs versions. I usually call it ~/site-lisp.

CygWin

Even though CygWin is not required to have an Emacs IDE, it makes things easier on Windows. Download the setup.exe from CygWin site and proceed with its installation.

NOTE: select to install GNU make; it is used to compile elisp later. While you are at it, you may want to select aspell as well.

In the remainder of this document, let's assume that the install directory is c:\opt\cygwin.

Emacs

At the time of this writing, the latest stable release of Emacs is 21.3.1. Download Emacs at the GNU site and compile/install it. Alternatively, you may get a binary version at:

Add Emacs' bin directory to your path; it is needed later to compile elisp files. Also create an .emacs file in your home directory to specify your personal preferences. For instance, the following tells Emacs to use tc-shell as its primary shell and aspell for spelling check:

;;
;; Setup Emacs to run tcsh as its primary shell.
;;
(setq shell-file-name "tcsh")
(setq shell-command-switch "-c")
(setq explicit-shell-file-name shell-file-name)
(setenv "SHELL" shell-file-name)
(setq explicit-sh-args '("-l"))
(if (boundp 'w32-quote-process-args)
  (setq w32-quote-process-args ?\")) ;; Include only for MS Windows.

;;
;; Aspell for spell checking.
;;
(setq ispell-program-name "aspell")
(setq ispell-extra-args '("--mode=sgml"))
(set-default 'ispell-skip-html t)

PMD

PMD is a Java tool that "scans Java source code for potential problems", such as unused variables, import statements etc. It is a nice feature to have in an IDE. Download and install PMD per its official instructions.

Next, we need the PMD plugin for Emacs to make Emacs aware of PMD. Drop the pmd.el file into ~/site-lisp, then add the following in your .emacs file.

;; PMD for detecting unused variable, import etc. in Java
(require 'compile)
(autoload 'pmd-current-buffer "pmd" "PMD Mode" t)
(autoload 'pmd-current-dir "pmd" "PMD Mode" t)

JDEE

The Java Development Environment for Emacs (JDEE) is an add on software that turns Emacs into an IDE such as Eclipse. It is useful to read the installation instruction on the JDEE site first. However, there are some variant to these instructions when installing the newer version of CEDET and JDEE. Below are the extra steps I use to install JDEE v2.3.4beta4 and CEDET v1.0beta2. They also apply to the JDEE v2.3.3, which is the production version at the time of this writing.

  1. Download elib 1.0 either in compressed tar or zip format from the JDEE website. After uncompressing, rename the directory to elib and put it under your ~/site-lisp. Then run make to compile all the source files.
  2. Download cedet 1.0beta2 from the Collection of Emacs Development Environment Tools homepage. Uncompress it. Compile all by running make at the base directory, or a subcomponent by running make in the corresponding subdirectory. For JDEE, we only need common, eieio, semantic and speedbar. Move them to ~/site-lisp.
  3. Download a copy of JDEE either in compressed tar or zip format. After uncompressing the distribution file, rename the base directory from jde-<version> to jde and move it to ~/site-lisp. Add (require `cedet) as the first line of code in lisp/jde.el. Then compile by running make.
  4. Add the following in .emacs
;;
;; Emacs libraries load-path
;;
(add-to-list 'load-path (expand-file-name "~/site-lisp"))
(add-to-list 'load-path (expand-file-name "~/site-lisp/common"))
(add-to-list 'load-path (expand-file-name "~/site-lisp/semantic"))
(add-to-list 'load-path (expand-file-name "~/site-lisp/speedbar"))
(add-to-list 'load-path (expand-file-name "~/site-lisp/elib"))
(add-to-list 'load-path (expand-file-name "~/site-lisp/eieio"))
(add-to-list 'load-path (expand-file-name "~/site-lisp/jde/lisp"))

;;
;; JDE 
;; Set the below variable to nil to load JDE on start;
;; or to true to defer loading until a Java file is open.
(setq defer-loading-jde t)

(if defer-loading-jde
    (progn
      (autoload 'jde-mode "jde" "JDE mode." t)
      (setq auto-mode-alist (cons '("\\.java\\'" . jde-mode) auto-mode-alist)))
  (require 'jde))

;; Java hook
(defun my-java-mode-hook()
  "Hook for running Java file..."
  (message " Loading my-jde-hook...")
  (c-set-offset 'case-label '+) ; ident switch-cases
)

(add-hook 'java-mode-hook 'my-java-mode-hook)

NOTE: Starting from version 2.3.4beta5, JDEE has been modified to support CEDET. Therefore steps 2 and 4 are slightly different.

  1. Idem.
  2. After uncompressing the distribution file, rename the base directory from cedet-<version> to cedet and move it to ~/site-lisp. Compile everything by running make at the cedet directory level. With cedet 1.0beta2b, I got a compile error in semantic/semantic-grammar-wy.el file. This can be fixed by removing extra line breaks in the file and running make again.
  3. Idem.
  4. The load-path reflects the changes in step 2.
;;
;; Emacs libraries load-path
;;
(add-to-list 'load-path (expand-file-name "~/site-lisp"))
(add-to-list 'load-path (expand-file-name "~/site-lisp/cedet/common"))
(add-to-list 'load-path (expand-file-name "~/site-lisp/cedet/semantic"))
(add-to-list 'load-path (expand-file-name "~/site-lisp/cedet/speedbar"))
(add-to-list 'load-path (expand-file-name "~/site-lisp/cedet/eieio"))
(add-to-list 'load-path (expand-file-name "~/site-lisp/elib"))
(add-to-list 'load-path (expand-file-name "~/site-lisp/jde/lisp"))

Customize JDEE

Most large Java projects nowadays use Ant to build their binary distribution. Some also use XDoclet tags to generate source files. In such project it is difficult to compile a file or an entire project within Emacs. Fortunately, JDEE allows several ways for building a project. It also allows us to specify several source directories, which makes it easier to trace source code even when the generated source files are in a different directory than the main source files.

The easiest way to customize JDEE to a given project is to create a project file, prj.el. Unlike other IDEs, JDEE does not require the include of all files in the project file and its loading before able to edit a file in the project. Instead, the project file contains a set of JDEE variables that customize the project. JDEE finds the project file by looking up the directory tree from where the edited source file is located. Therefore, it is best to put the project file at the project's root directory, or at least at the highest level of the main source files directory tree.

To illustrate, let's consider a fictive project, myProject, that has a directory structure as follows:

/projects/myProject
  - proj.el
  - build.xml
  +- src
      +- main
      +- generated
  +- lib
  +- build
      +- classes
  +- dist

build.xml is the project's Ant build file. It has many targets, among others are:

srcgen
generates source files from XDoclet tags.
build
builds the project and puts it under the myProject/build.
dist
builds the project then packages it for distribution under myProject/dist.

The source directory has two branches: src/main where are stored source files written by developers, and src/generated where generated source files are created from srcgen target. myProject/lib contains jar files used by the project and myProject/build/classes contains all the compiled class files from the source files, generated or not.

In order to set up the project, we need to customize the following JDEE variables:

Table 1 - JDEE variables of concern.
VariableDescription
jde-build-function Build method. Can either be make, Ant or a custom build function.
jde-sourcepath List of source directories.
jde-global-classpath List of classes or jars directories.
jde-ant-home Directory where Ant is installed.
jde-ant-program Name of the program or script to run Ant.
jde-ant-invocation-method How to invoke Ant. There are three ways: via the script/program that comes with Ant, via Java, or via the Ant Server.
jde-ant-buildfile Ant's build file. Default is build.xml, therefore we don't need to specify it.
jde-ant-enable-find Whether JDE is to look up in the directory tree for the build file.
jde-ant-read-buildfile Whether to prompt for the build file name. We want to turn this off as we enable the buildfile lookup.
jde-ant-args Arguments to pass to Ant.
jde-ant-read-args Whether to prompt for additional Ant arguments.
jde-ant-read-target Whether for prompt for a build target.
jde-ant-complete-target Whether to attempt target completion (from targets in the build file).

Our project file looks something like below:

(jde-project-file-version "1.0")
(jde-set-variables
 '(jde-project-name "MyProject")
 '(jde-build-function (quote (jde-ant-build)))
 '(jde-ant-invocation-method (quote ("Script")))
 '(jde-ant-home "/java/ant")
 '(jde-ant-program "/java/ant/bin/ant.sh")
 '(jde-ant-enable-find t)
 '(jde-ant-read-buildfile nil)
 '(jde-ant-args "-emacs") ; compile output in emacs format
 '(jde-ant-read-args t)
 '(jde-ant-read-target t)
 '(jde-ant-complete-target t)
 '(jde-global-classpath (quote ("./build/classes" "./build/jboss/lib" "./lib")))
 '(jde-sourcepath (quote ("./src/main/" "./src/generated")))
 '(jde-help-docsets (quote (("J2SE v1.4.2 API" "/manual/jsdk-1.4.2/api" nil))))
)

With this setup, individual files can be compiled without having to rebuild the whole project. A couple of steps are involved:

  1. First we need to generate the source from XDoclet by building with srcgen target.
  2. Then we need to compile all files by building with build target.
  3. Now that we have the necessary class files and jar files, we can compile files individually using C-c C-v C-c.

For more information on JDEE variables and project file, see the user's guide for JDEE.

Resources

GNU Emacs
An extensible, customizable, self-documenting real-time display, multi-platform editor. In other words, my editor of choice!
CygWin
A Unix-like environment for Windows. Among others, it offers several popular shells and useful commands such as find and grep.
JDEE
A Java Development Environment for Emacs.
PMD
A Java tool that scans Java source code for potential problems such as unused variables, parameters or private methods, empty if/while statements, etc.
Ant
Apache Ant is a Java-based build tool, a la Make.
XDoclet
A Java tool that generates source code or other files based on custom Javadoc @tags.
Last updated: 2005-09-15 22:40:35 -0700