Emacs Rust Debugging

Rust-GDB

Use rust-gdb to launch gdb with the Rust-specific pretty-printers enabled, PR#19954 – add rust-gdb for Rust pretty printers.

GDB Rust Breakpoints

In gdb use break FILENAME:LINE_NUM instead of rbreak FUNCTION_NAME.
Rust has lifetime parameters, which can cause the gdb error umatched quote.

Example
Code: struct Foo<‘a> {num: i32} impl<‘a> Foo<‘a> { fn add_one(self) {} }
GDB:
    (gdb) rbreak add_one
     unmatched quote
    (gdb)

Emacs GUD

  1. To Launch: M-x gdb
  2. Instead of gdb enter rust-gdb, add -args to pass arguments to the proccess being debugged.
  3. Example: rust-gdb --i=mi --args PATH_TO_EXECUTABLE EXECUTABLE_ARGS

Emacs GUD – Keybindings

I never remember the Emacs GUD keybindings, instead my .emacs includes:

(global-set-key [f5] 'gud-cont)
(global-set-key [f7] 'gud-tbreak)
(global-set-key [S-f11] 'gud-finish)
(global-set-key [f9] 'gud-break)
(global-set-key [f10] 'gud-next)
(global-set-key [f11] 'gud-step)

Emacs Rust Development Setup

========BASIC SETUP===========

=======PROJECT SETUP==========
Read the Cargo guide.

=======GGTAGS SETUP==========

For cross referencing via ggtags:

  1. Download and install Gnu Global (the Gnu Global package available in Ubuntu 14.04 doesn’t allow adding new lang defs).
  2. Ensure that $HOME/.ctags includes the Rust lang definitions from ctags.rust.
  3. Set the env variable GTAGSCONF to $HOME/.globalrc
  4. Set the env variable GTAGSLABEL to ctags, e.g. export GTAGSLABLE=”ctags”
  5. Sometimes eshell in emacs doesn’t inherit the env variables, in which case run gtags . in a normal shell.
  6. To .emacs add
    (add-hook 'prog-mode-hook
          '(lambda ()
             (when (derived-mode-p 'rust-mode) 
    	 (ggtags-mode 1))))
    	 
    
  7. Copy to .globalrc
    # Configuration file for GNU GLOBAL source code tag system.
    #
    # Basically, GLOBAL doesn't need this file ('gtags.conf'), because it has
    # default values in its self. If you have the file as '/etc/gtags.conf' or
    # "$HOME/.globalrc" in your system then GLOBAL overwrite the default values
    # with the values in the file.
    #
    # The format is similar to termcap(5). You can specify a target with
    # GTAGSLABEL environment variable. Default target is 'default'.
    #
    default:\
    	:tc=native:
    native:\
    	:tc=gtags:
    ctags:\
    	:tc=exuberant-ctags:
    #---------------------------------------------------------------------
    # Configuration for gtags(1)
    # See gtags(1).
    #---------------------------------------------------------------------
    common:\
    	:skip=HTML/,HTML.pub/,tags,TAGS,ID,y.tab.c,y.tab.h,gtags.files,cscope.files,cscope.out,cscope.po.out,cscope.in.out,SCCS/,RCS/,CVS/,CVSROOT/,{arch}/,autom4te.cache/,*.orig,*.rej,*.bak,*~,#*#,*.swp,*.tmp,*_flymake.*,*_flymake:
    #
    # Built-in parsers.
    #
    gtags:\
    	:tc=common:\
    	:tc=builtin-parser:
    builtin-parser:\
    	:langmap=c\:.c.h,yacc\:.y,asm\:.s.S,java\:.java,cpp\:.c++.cc.hh.cpp.cxx.hxx.hpp.C.H,php\:.php.php3.phtml:
    #
    # Plug-in parser to use Exuberant Ctags.
    #
    exuberant-ctags|plugin-example|setting to use Exuberant Ctags plug-in parser:\
    	:tc=common:\
    	:langmap=Asm\:.asm.ASM.s.S:\
    	:langmap=Awk\:.awk.gawk.mawk:\
    	:langmap=C\:.c:\
    	:langmap=C++\:.c++.cc.cp.cpp.cxx.h.h++.hh.hp.hpp.hxx.C.H:\
    	:langmap=Flex\:.as.mxml:\
    	:langmap=HTML\:.htm.html:\
    	:langmap=Java\:.java:\
    	:langmap=JavaScript\:.js:\
    	:langmap=Lisp\:.cl.clisp.el.l.lisp.lsp:\
    	:langmap=Perl\:.pl.pm.plx.perl:\
    	:langmap=Python\:.py.pyx.pxd.pxi.scons:\
    	:langmap=Ruby\:.rb.ruby:\
            :langmap=Rust\:.rs:\
    	:langmap=Scheme\:.SCM.SM.sch.scheme.scm.sm:\
    	:langmap=Sh\:.sh.SH.bsh.bash.ksh.zsh:\
    	:langmap=YACC\:.y:\
    	:gtags_parser=Asm\:/usr/local/lib/gtags/exuberant-ctags.la:\
    	:gtags_parser=Awk\:/usr/local/lib/gtags/exuberant-ctags.la:\
    	:gtags_parser=C\:/usr/local/lib/gtags/exuberant-ctags.la:\
    	:gtags_parser=C++\:/usr/local/lib/gtags/exuberant-ctags.la:\
    	:gtags_parser=Flex\:/usr/local/lib/gtags/exuberant-ctags.la:\
    	:gtags_parser=HTML\:/usr/local/lib/gtags/exuberant-ctags.la:\
    	:gtags_parser=Java\:/usr/local/lib/gtags/exuberant-ctags.la:\
    	:gtags_parser=JavaScript\:/usr/local/lib/gtags/exuberant-ctags.la:\
    	:gtags_parser=Lisp\:/usr/local/lib/gtags/exuberant-ctags.la:\
    	:gtags_parser=Perl\:/usr/local/lib/gtags/exuberant-ctags.la:\
    	:gtags_parser=Python\:/usr/local/lib/gtags/exuberant-ctags.la:\
    	:gtags_parser=Ruby\:/usr/local/lib/gtags/exuberant-ctags.la:\
            :gtags_parser=Rust\:/usr/local/lib/gtags/exuberant-ctags.la:\
    	:gtags_parser=Scheme\:/usr/local/lib/gtags/exuberant-ctags.la:\
    	:gtags_parser=Sh\:/usr/local/lib/gtags/exuberant-ctags.la:\
    	:gtags_parser=YACC\:/usr/local/lib/gtags/exuberant-ctags.la:
    

======================TIPS======================
Usable keyboard shortcuts for navigation, with Rust code:

  • M-.       – ggtags-find-tag-dwim – Go to definition
  • C-c M-g – ggtags-grep              – Grep for references

Bind ggtags-grep to “M-]”, for finding references:

(add-hook 'prog-mode-hook
      '(lambda ()
         (when (derived-mode-p 'rust-mode)
           (define-key ggtags-mode-map (kbd "M-]") 'ggtags-grep)
           )))