C/C++ Development Environment for Emacs
In this guide, I will help you to setup an efficient working C/C++ environment. Despite looking long, the setup is short and easy (mostly copy/paste Emacs Lisp code into your init.el); most of the guide are explanations and demonstrations of many useful features. Following this guide, you should be able to browse the Linux kernel source tree inside Emacs effortlessly, such as jump to definition/references at cursor, go back and forth between jumping points, finding any file instantly, switching between .h and .c/.cpp. We include demos in the end.
Install GNU Global
Install GNU Global:
apt-get install global
(require 'ggtags) (add-hook 'c-mode-common-hook (lambda () (when (derived-mode-p 'c-mode 'c++-mode 'java-mode 'asm-mode) (ggtags-mode 1))))
And define some keybinding if you wish:
(define-key ggtags-mode-map (kbd "C-c g s") 'ggtags-find-other-symbol) (define-key ggtags-mode-map (kbd "C-c g h") 'ggtags-view-tag-history) (define-key ggtags-mode-map (kbd "C-c g r") 'ggtags-find-reference) (define-key ggtags-mode-map (kbd "C-c g f") 'ggtags-find-file) (define-key ggtags-mode-map (kbd "C-c g c") 'ggtags-create-tags) (define-key ggtags-mode-map (kbd "C-c g u") 'ggtags-update-tags) (define-key ggtags-mode-map (kbd "M-,") 'pop-tag-mark)
helm is a nice interactive interface to many tools, so helm-gtags is very handy. Remember to setup Helm before using helm-gtags. When includes the above file in your ~/.emacs.d, remember to add (require 'setup-helm) to your init.el.
(setq helm-gtags-ignore-case t helm-gtags-auto-update t helm-gtags-use-input-at-cursor t helm-gtags-pulse-at-cursor t helm-gtags-prefix-key "\C-cg" helm-gtags-suggested-key-mapping t ) (require 'helm-gtags) ;; Enable helm-gtags-mode (add-hook 'dired-mode-hook 'helm-gtags-mode) (add-hook 'eshell-mode-hook 'helm-gtags-mode) (add-hook 'c-mode-hook 'helm-gtags-mode) (add-hook 'c++-mode-hook 'helm-gtags-mode) (add-hook 'asm-mode-hook 'helm-gtags-mode)
And some keybindings:
(define-key helm-gtags-mode-map (kbd "C-c g a") 'helm-gtags-tags-in-this-function) (define-key helm-gtags-mode-map (kbd "M-s") 'helm-gtags-select) (define-key helm-gtags-mode-map (kbd "M-.") 'helm-gtags-dwim) (define-key helm-gtags-mode-map (kbd "M-,") 'helm-gtags-pop-stack) (define-key helm-gtags-mode-map (kbd "C-c <") 'helm-gtags-previous-history) (define-key helm-gtags-mode-map (kbd "C-c >") 'helm-gtags-next-history)
Before using the ggtags or helm-gtags, remember to create a GTAGS database by running the command ggtags-create-tags .
Or run gtags at your project root in terminal:
$ cd /path/to/project/root $ gtags
After this, 3 files are created:
- GTAGS: definition database
- GRTAGS: reference database
- GPATH: path name database
- C-M-f runs forward-sexp, move forward over a balanced expression that can be a pair or a symbol.
- C-M-b runs backward-sexp, move backward over a balanced expression that can be a pair or a symbol.
- C-M-k runs kill-sexp, kill balanced expression forward that can be a pair or a symbol.
- C-M-<SPC> or C-M-@ runs mark-sexp, put mark after following expression that can be a pair or a symbol.
- C-M-a runs beginning-of-defun, which moves point to beginning of a function.
- C-M-e is end-of-defun.
- C-M-h runs mark-defun, which put a region around whole current or following function.
Find definitions in current buffer
The Imenu facility offers a way to find the major definitions, such as function definitions, variable definitions in a file by name. ggtags can integrate Imenu:
(setq-local imenu-create-index-function #'ggtags-build-imenu-index)
If you use Helm, use helm-semantic-or-imenu. You can use it as an outline tree like in other IDEs.
Find definitions in project
Using gtags: by default, M-. runs ggtags-find-tag-dwim when ggtags-mode is enabled. The command ggtags-find-tag-dwim jump to tag base on context:
- If the tag at point is a definition, ggtags jumps to a reference. If there is more than one reference, it displays a list of references.
- If the tag at point is a reference, ggtags jumps to tag definition.
- If the tag at point is an include header, it jumps to that header.
You can jump back to original location where you invoked ggtags-find-tag-dwim by M-,, which runs pop-tag-mark (if you follow my key bindings).
You can also find arbitrary tag definition when invoking M-. on blank space. A prompt asks you for tag pattern, which is a regexp.
If ggtags gives you a list of candidates, you can use M-n to move to next candidate and M-p to move back previous candidate. Use M-g s to invoke Isearch on candidate buffer list
Using helm-gtags: If key bindings are properly setup as above, M-. runs helm-gtags-dwim, which behaves the same as ggtags-find-tag-dwim. Similarly, you jump back to original location by using M-,, which runs tags-loop-continue (Emacs default).
helm-gtags provides a really nice feature that uses Helm to display all available tags in a project and incrementally filtering, and is really fast using helm-gtags-select, which is bound to M-s in my setup above. This is useful when you want to explore tags in unfamiliar project.
Find references in project
Using helm-gtags: Either run helm-gtags-dwim or helm-gtags-find-rtags, bound to C-c g r, which only finds references.
Find functions that current functions call
If you want to list all the functions that the current function - the function that point is inside - calls, you can do that with helm-gtags-tags-in-this-function, which is bound to C-c g a in my setup.
Find files in project
projectile is a very nice and complete solution.
Browse source tree with Speedbar file browser
General completion with company-mode
Besides, company-c-headers provides auto-completion for C/C++ headers using Company. After installing from MELPA, set it up:
(add-to-list 'company-backends 'company-c-headers)
Project management with EDE
The source of this page with many demos: http://tuhdo.github.io/c-ide.html