For this post I want to share how I set up my Emacs installation for C Linux Kernel development. But if for some reason you don’t like emacs, you should give a try to KDevelop, that is for sure one of the best if not the best C/C++ IDE out there for Unix.
The first question you may ask is: why Emacs? Because it is better than vim, and because you can use Emacs in the command line when you use a remote server.
The original idea of this post was to present Emacs as an IDE for C development, but after I kept digging more about different tools and workflows I decided that the best approach is to create multiple post where in which one I describe a different aspect of kernel development workflow.
When considering an Emacs setup for editing the Linux kernel we need to keep attention to at least two aspects:
“a infinite number of monkeys typing into GNU emacs would never make a good program” - Linus T
You can READ coding style explanation by Linus here. But the code is the following:
(setq-local indent-tabs-mode t) (setq-local tab-width 8) (setq-local c-indent-level 8) (setq-local c-brace-imaginary-offset 0) (setq-local c-brace-offset -8) (setq-local c-argdecl-indent 8) (setq-local c-label-offset -8) (setq-local c-continued-statement-offset 8) (setq-local backward-delete-char-untabify-method 'hungry) (setq-local c-basic-offset 8) (setq-local c-default-style "linux")
Basically, Emacs can’t indent your C code very well by default. We can make our lives easier with:
(define-key c-mode-map (kbd "RET") 'newline-and-indent) (smartparens-global-strict-mode 1) (ws-butler-mode 1)
By “Codding Intelligence” I’m referring to all the typical functionalities you expect in a IDE, like code completion, debugging, semantic completions, etc. If you want a full fledged tutorial step by step with the full code, you should visit this link.
In my personal case I decided to use gtags for code navigation.
;; bindings (define-key helm-gtags-mode-map (kbd "C-c g a") 'helm-gtags-tags-in-this-function) (define-key helm-gtags-mode-map (kbd "C-c g r") 'helm-gtags-resume) (define-key helm-gtags-mode-map (kbd "C-c g s") 'helm-gtags-show-stack) (define-key helm-gtags-mode-map (kbd "C-j") '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) ;; vars and modes (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) (setq-local eldoc-documentation-function #'ggtags-eldoc-function) (eldoc-mode 1) (helm-gtags-mode 1)
(define-key c-mode-map (kbd "C-c TAB") 'company-complete) (define-key c-mode-map (kbd "C-c SPC") 'helm-company) (setq-local company-idle-delay nil) ; no invoke automatically (auto-complete-mode 0) (company-mode 1)
(define-key c-mode-map (kbd "C-c i") 'helm-semantic-or-imenu) (semantic-mode 1) (global-semantic-stickyfunc-mode 1) (global-semantic-idle-summary-mode 1) (setq-local eldoc-documentation-function #'ggtags-eldoc-function) (eldoc-mode 1)
BTW, you can read my emacs.d folder from github.