Thomas Becker's Free Software Utilities
Copyright (C) 2007 Thomas Becker
Contents
- Overview
- Download and Installation
- Feedback and Bug Reports
- Using Devenv Emulation
GNU Emacs supports integrated compiling and debugging. This brings
with it such conveniences as jumping from a compiler error message
directly to the offending location in the source code, and
source-level debugging in Emacs buffers. Some people argue that
turning an editor into a development environment like that is an
ill-fated endeavour from the start; they hold that a development
environment should be a stand-alone program of which the editor is an
integrated component. Be that as it may, many of us, including myself,
use GNU Emacs' compiling and debugging features.
Unfortunately, if you use GNU Emacs out of the box, compiling and debugging come
with some annoyances. My personal pet peeves are:
-
In an integrated development environment such as Microsoft Visual Studio, the first
thing you do is open a project (or "solution" in Microsoft speak). After that, tasks
such as compiling an individual source file, building the whole thing, starting a
debug session, etc. can be kicked off with function keys. One never has to to type
a compile, make, or debug command anymore. For me, that does make a big difference
in productivity.
-
Many compilers, including gcc, output error messages where the file location of the
error is given as a relative path. That causes trouble in large projects, where source
files are scattered over several directories. In that case, jumping from the error
messages in the compilation output buffer to the respective locations in the source
files via
next-error (pressing Ctrl-x `) has a
problem: depending on your setup, it can either work when compiling individual
source files, or it can work when compiling the entire project, but not for both.
The Devenv Emulation package removes these annoyances and adds some
minor conveniences. Among other things, it provides function key
bindings that are modeled after Microsoft Visual Studio.
Besides download and installation, all
that is required to get the benefit of Devenv Emulation is to give
Emacs some information about your current project build environment.
Typically, this is done in the Emacs initialization file. See the
documentation below for details.
Devenv Emulation can be downloaded from
here.
To install Devenv Emulation, place the file
devenv-emulation.elc in some directory DIR. Add the line
(load-file "DIR/devenv-emulation.elc")
to your Emacs initialization file, where you have replaced the string
"DIR" in the load-file call with the actual directory
where devenv-emulation.elc resides. "DIR" may of course be omitted
if devenv-emulation.elc is in a directory where Emacs looks for lisp
files. Be sure to load devenv-emulation.elc and not
devenv-emulation.el. It is customary but not necessary to put the
.el file in the same directory as the .elc file.
Click
to send feedback and bug reports concerning Devenv Emulation.
To use Devenv Emulation, you must give Emacs some information about
your current project build environment. That is the equivalent of
opening a project in an integrated development environment. Typically,
this is done in the Emacs initialization file. However, all the
settings described below can be made or modified at any time during an
Emacs session.
In most cases, only two variable settings are required, like this:
(setq devenv-emulation-active-project-name "hello_world")
(setq devenv-emulation-active-compilation-directory "~/HelloWorld/")
Furthermore, you will have to set some key bindings for the most
common compile and debug commands. All this is explained further in
the sections below.
Remember, one of the main reasons for using Devenv Emulation is to deal
with compilers (such as gcc) that give the error loactions in their
messages relative to the compilation directory. There is one prerequisite
on your build environment for Devenv Emulation to do its job in that
situation: the compilation directory, that is, the working directory under
which the compiler gets called, must be the same across all targets. It
would be very hard to make Emacs' integrated compiling work properly and
consistently if the error locations weren't always relative to the same
directory. What this means is that you must not use the cd
command in your makefile(s), or if you do, then change to the same directory
everytime.
You must tell Devenv Emulation about your active compilation directory
with a line like
(setq devenv-emulation-active-compilation-directory "~/HelloWorld/")
The directory can be specified in unexpanded form, as in the example above, and
it may be given with or without the trailing slash.
This variable setting, like all the other ones described below, can
also be made interactively with M-x set-variable.
One of the benefits of Devenv Emulation is that you can compile
individual source files or make the entire project by hitting a
function key, and you can make other targets by calling a Lisp
function via a key combination.
For this to work, you must tell Devenv Emulation what your make command is.
The simplest way to achieve this is to specify an
active project name with a variable setting like this:
(setq devenv-emulation-active-project-name "hello_world")
Devenv Emulation will then perform the following
lookup when it is told to make a target:
-
If the active compilation directory
contains a script whose name is the active
project name with "
make_" prepended to it, then
that script will be called with the target name as the only
argument. (See Section "Target Names"
below for an explanation of where Devenv Emulation gets the target
name from.) In our example so far, Devenv Emulation would call
make_hello_world <target_name>
with ~/HelloWorld as the current directory.
-
If the script as described in 1. above does not exist, Devenv
Emulation assumes that your active
compilation directory contains a makefile whose extension is
.mak and whose basename is the same as the
active project name, and that you want to
call the standard make program on this makefile.
In our example, Devenv Emulation would call
make -f hello_world.mak <target_name>
with ~/HelloWorld as the current directory.
If none of these two alternatives is good for you, you can specify a different
compile command altogether like this:
(setq devenv-emulation-active-compile-command "gmake -f my_make_file.mak")
If this variable is non-nil, it supersedes the lookup described in
1. and 2. above. Again, the target name will be passed as the only
argument, and the working directory for the call will be the
active compilation directory.
Devenv Emulation provides a function that prompts the user for a
target to be made. Furthermore, it has predefined functions to make
the entire project, to clean the entire project for a full rebuild,
and to compile the source file that is being visited in the current
buffer. (See Section "Functions and Key
Bindings" below for more details.)
The default target names that Devenv Emulation uses for making and cleaning the entire
project are "all" and "clean". You can change these by setting
variables as follows:
(setq devenv-emulation-make-all-target "tutto")
(setq devenv-emulation-clean-all-target "klean")
The default target name for compiling the source file that is visited in the current
buffer is obtained by appending .o to the basename of the
source file. For example, the target name for compiling hello_world.cpp
is hello_world.o. You can specify a different extension for the target
name as follows:
(setq devenv-emulation-object-file-extension ".obj")
Note that the period is part of the extension that you set. Hence, you can use this
to remove the extension of the source file altogether, or to append something to
the basename of the file. Similarly, you can append a prefix to the target name:
(setq devenv-emulation-object-file-prefix "release/")
Together, the two settings above will cause the target name for the source file
hello_world.cpp to become release/hello_world.obj.
If you need more elaborate rules to turn source file names into the corresponding
target names, you can do so by defining the lisp function
devenv-emulation-file-name-2-target. If this function is defined,
the full, expanded path of the source file will be passed to it, and the return
value will be used as the corresponding target name. In the following example,
the target name used for each source file will be the full path name of the source file,
with the file extension set to "obj":
(defun devenv-emulation-file-name-2-target (file-path)
(concat (file-name-sans-extension file-path) ".obj"))
Note that you can use this function to make the target names for your source
files dependent on some global variable setting. This can be useful, for example,
to switch between debug mode and release mode.
When it comes to starting a debug session, Devenv Emulation assumes by
default that your executable for debugging is in the
active compilation directory, and that its name is
identical to the active project name. In our
example, the debugger would try to debug
~/HelloWorld/hello_world
If this is not good for you, you can specify the full pathname of your
executable by assigning it to the variable
devenv-emulation-active-executable. Here's an example
that modifies the default behavior so that the executable is found in
the subdirectory "bin" of the
active compilation directory
and has the extension "exe":
(setq devenv-emulation-active-executable
(concat
devenv-emulation-active-compilation-directory
"bin/"
devenv-emulation-active-project-name
".exe"
))
If you find yourself having to switch frequently between different projects or
different modes such as relase mode and debug mode, you will want to have an
easy way to switch between different settings for the Devenv Emulation package.
Even if you don't know much about Emacs Lisp programming, you can easily achieve
this by wrapping each set of settings in a function call. The following is an
excerpt from a .emacs file that allows to switch interactively between
release mode and debug mode for a project that was created under Windows with
the Qt qmake program:
(setq devenv-emulation-active-project-name "QtProject")
(setq devenv-emulation-active-compilation-directory "C:/Development/QtProject")
(setq devenv-emulation-object-file-extension ".obj")
;
(defun devenv-emulation-release-mode ()
"Switches to release mode"
(interactive)
(setq devenv-emulation-active-executable
(concat
devenv-emulation-active-compilation-directory
"/release/"
devenv-emulation-active-project-name
".exe"
))
(setq devenv-emulation-active-compile-command "nmake_release.cmd")
(setq devenv-emulation-object-file-prefix "release\\")
)
;
(defun devenv-emulation-debug-mode ()
"Switches to debug mode"
(interactive)
(setq devenv-emulation-active-executable
(concat
devenv-emulation-active-compilation-directory
"/debug/"
devenv-emulation-active-project-name
".exe"
))
(setq devenv-emulation-active-compile-command "nmake_debug.cmd")
(setq devenv-emulation-object-file-prefix "debug\\")
)
One can now interactively switch between debug mode and release mode, like this:
M-x devenv-emulation-release-mode
M-x devenv-emulation-debug-mode
Devenv Emulation is not worth a whole lot unless you make some key bindings.
The suggested default bindings are collected in the function
devenv-emulation-set-key-bindings. It is recommended that
you make these key bindings globally, by calling
(devenv-emulation-set-key-bindings global-map)
The key bindings are described in more detail in the next section.
Given the abundance of GNU Emacs packages and modes, it may happen
that some package's or mode's key bindings conflict with Devenv
Emulation's bindings. In that case, you have two options. For one thing,
you can easily modify the key bindings to your preference by copying,
modifying, and renaming the Emacs Lisp function
devenv-emulation-set-key-bindings out of the source file
devenv-emulation.el.
Alternately, you can override the offending package's or mode's key
bindings. To override other packages' key bindings, make the call to
devenv-emulation-set-key-bindings last in you Emacs
initialization file. To trump a mode's key bindings, you need to call
devenv-emulation-set-key-bindings on the current local
map as the last function in that mode's hook, like this:
(add-hook 'joes-mode-hook
'(lambda ()
(devenv-emulation-set-key-bindings (current-local-map))))
If Joe's mode does not have a hook, then it's a bad mode and you
should not be using it.
For details on how the make command, the target names, and the path name
of the debug executable are obtained, see Sections
"The Build Command",
"Target Names", and
"The Debug Executable" above.
F7
|
|
Build the active project.
|
Shift-F7
|
|
Clean the active project for a full rebuild.
|
Ctrl-F7
|
|
Compile the file that the active buffer is visiting.
|
Ctrl-C m
|
|
Make a specific target. Prompts for a target name. The default is the previously
chosen target. Minibuffer history is kept specifically for target names.
If you want minibuffer completion to be available, you must tell Devenv
Emulation what your targets are. This is done with a function call like this:
(devenv-emulation-add-target-names-for-completion "netlib" "guilib" "dblib" "mathlib")
|
F4
|
|
Go to the next compilation error message and the corresponding source code (Emacs function next-error).
|
Shift-F4
|
|
Go to the previous compilation error message and the corresponding source code (Emacs function previous-error).
|
F5
|
|
Start debugging. If there is no active debug session, then gdb is called on
the active executable, and the GUD buffer is displayed. The active executable
is not started, so you get a chance to set breakpoints. Pressing F5
again will then start the active executable under the debugger, that is, it will
pass the command "run" to gdb.
|
Shift-F5
|
|
Kill the active executable if it is being debugged, that is, pass the command
"kill" to gdb.
|
F9
|
|
Set a breakpoint at the source line that the point is on (Emacs function gud-break).
|
Shift-F9
|
|
Delete the breakpoint(s) on the current source line (Emacs function gud-remove).
|
Ctrl-F9
|
|
Set a temporary breakpoint on the current source line (Emacs function gud-tbreak).
|
F10
|
|
Execute current source line (Emacs function gud-next).
|
Shift-F10
|
|
Continue execution (Emacs function gud-cont).
|
F11
|
|
Execute until another source line is reached (Emacs function gud-step).
|
Shift-F11
|
|
Run until the selected stack frame returns (Emacs function gud-finish).
|
F12
|
|
Move down the stack frames (Emacs function gud-down).
|
Shift-F12
|
|
Move up the stack frames (Emacs function gud-up).
|
Ctrl-C c
|
|
Switch to buffer *compilation* if it exists. If a GUD buffer is visible,
then that window is used. If not, the compilation buffer is shown in a
new window that is displayed in the same manner as when a compilation is
first started.
|
Ctrl-C d
|
|
Switch to the GUD buffer if it exists. If a compilation buffer is visible,
then that window is used. If not, the GUD buffer is shown in a
new window that is displayed in the same manner as when a debug session is
first started.
|
Back to top
|