5

I am starting to develop a ROS (Robot Operating System) application for the first time using Emacs. Here is my ~/.emacs.d/init.el configuration for Flycheck and company packages:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Flycheck
;;;;;;;; Description: code linting (particularly C/C++ for me)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'cc-mode)
(add-hook 'c++-mode-hook 'flycheck-mode)
(add-hook 'c-mode-hook 'flycheck-mode)
;; Check buffer on save, new line and immediately after anbling flycheck-mode
(setq flycheck-check-syntax-automatically '(mode-enabled save)) ;; new-line also possible
;; Add include paths
(add-hook 'c++-mode-hook
          (lambda () (setq flycheck-clang-include-path
                           (list (expand-file-name "/opt/ros/kinetic/include/")))))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; company-mode
;;;;;;;; Description: text completion framework
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'company)
;; Use company-mode in all buffers
(add-hook 'after-init-hook 'global-company-mode)
;; Use company-mode with Clang
(setq company-backends (delete 'company-semantic company-backends))
(set 'company-clang-arguments (list "-std=c++11")) ;; enable C++11 code completion


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Irony
;;;;;;;; Description: asynchronous completion capability for company-mode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(add-hook 'c++-mode-hook 'irony-mode)
(add-hook 'c-mode-hook 'irony-mode)
(add-hook 'objc-mode-hook 'irony-mode)

(defun my-irony-mode-hook ()
  (define-key irony-mode-map [remap completion-at-point]
    'irony-completion-at-point-async)
  (define-key irony-mode-map [remap complete-symbol]
    'irony-completion-at-point-async))

(add-hook 'irony-mode-hook 'my-irony-mode-hook)
(add-hook 'irony-mode-hook 'irony-cdb-autosetup-compile-options)
;; Use comapny-mode with Irony
(add-hook 'irony-mode-hook 'company-irony-setup-begin-commands)
(setq company-backends (delete 'company-semantic company-backends))
;; Enable tab-completion with no delay
(setq company-idle-delay 0)
(define-key c-mode-base-map (kbd "<S-SPC>") 'company-complete)
;; Add support for completing C/C++ headers
(require 'company-irony-c-headers)
(eval-after-load 'company
  '(add-to-list
    'company-backends '(company-irony-c-headers company-irony)))
;;(add-to-list 'company-c-headers-path-system "/usr/include/c++/5.4.0/")
;; Integrate Irony with Flycheck
(eval-after-load 'flycheck
  '(add-hook 'flycheck-mode-hook #'flycheck-irony-setup))
;; Set cppcheck standard to C++11
(setq irony-additional-clang-options '("-std=c++11"))

My problem is that it seems like Flycheck is not recognizing where the ROS header files are located. On my system, they are all in /opt/ros/kinetic/include/ and I tried to include this path in the above code with the command:

;; Add include paths
(add-hook 'c++-mode-hook
          (lambda () (setq flycheck-clang-include-path
                           (list (expand-file-name "/opt/ros/kinetic/include/")))))

However, this seems to not fix things. I still get the error:

enter image description here

Please help me with an answer on the best practice of adding custom include paths for projects for both Flycheck and company-mode to use, with the include path in this particular case being /opt/ros/kinetic/include. Thank you!

space_voyager
  • 709
  • 5
  • 19

1 Answers1

5

Irony-mode maintainer's here.

Also using ROS at work.

If you use catkin, then you can get along with irony-mode easily.

I do not have ROS at my disposal right now but you should be able to do something along these lines.

With catkin_make:

# create build/compile_commands.json
catkin_make -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

emacs src/my_packages/src/foo.cpp

If I explain a bit more:

First step, tells CMake (which catkin uses under the hoot) to generate a compilation database. You can read more about the compilation database here:

If I got the command right, you will have a new file in you build directory: build/compile_commands.json.

Second step, when you open Emacs on the file. irony-autosetup-compile-options will look if there is a compilation database in a parent directory of your file, or in a subdirectory build/ in a parent path of your file, which should be the case with the command we typed earlier. Type C-h v irony-cdb-search-directory-list RET for more information.

With catkin_tools:

# create ~/catkin_ws/build/xxx/compile_commands.json
# for all the packages located in ~/catkin_ws/src/xxx
catkin config --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

# in emacs, type:
#     M-x irony-cdb-json-add-compile-commands-path RET
# you will be prompted with the compile_commands.json to add, in this case,
# set the "Project root" to ~/catkin_ws/src/xxx/
# and set the "Compile commands" to ~/catkin_ws/build/xxx/compile_commands.json
emacs src/my_packages/src/foo.cpp
Guillaume Papin
  • 886
  • 6
  • 7
  • I use [catkin_tools](http://catkin-tools.readthedocs.io/en/latest/index.html), running `catkin -DCMAKE_EXPORT_COMPILE_COMMANDS=ON` produces `Error: No verb provided`. Any idea what to do? – space_voyager Nov 07 '16 at 20:00
  • I managed to get the first command to work by first running `catkin config --append-args -DCMAKE_EXPORT_COMPILE_COMMANDS=ON`, then I can run `catkin build` and the `.json` databases are created under `catkin_ws/build/my_package/compile_commands.json`. What do I do from there? – space_voyager Nov 07 '16 at 20:08
  • Oups, there is a typo in my answer, does it work if you use `catkin_make`: `catkin_make -DCMAKE_EXPORT_COMPILE_COMMANDS=ON`. But since you are not using catkin_make, it looks like you can do: `catkin build --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=ON`. If the compile_commands.json is in such paths, you have to tell irony-mode about the location: `M-x irony-cdb-json-add-compile-commands-path RET`. – Guillaume Papin Nov 07 '16 at 20:15
  • As I said in my second comment, the `compile_commands.json` files are in `~/catkin_ws/build/my_package/compile_commands.json` for package `my_package` which, itself, is located in `~/catkin_ws/src/my_package/`. Are these the correct paths for Irony? Because as I understood from the docs, Irony will look in `~/catkin_ws/build` but not in `~/catkin_ws/build/my_package` for the json database... – space_voyager Nov 07 '16 at 20:17
  • 1
    That's right, irony-mode will not look but you can use `M-x irony-cdb-json-add-compile-commands-path RET` to add non-standard paths like this. – Guillaume Papin Nov 07 '16 at 20:19
  • That's beautiful. But where does `irony-cdb-json-add-compile-commands-path ` store its stuff to memorize the non-standard path to `.json` across sessions? Also, this means I have to run the command for every new project - is there any way to tell `catkin` to put the `json` database in `~/catkin_ws/src/my_package/build` by default so that Irony can automatically find it? – space_voyager Nov 07 '16 at 20:27
  • Irony store this information in `~/.emacs.d/irony/cdb-json-projects`. Right now there is no way to specify irony to look for a pattern more complex than "look in the subdirectory". One would have to add this functionality to the code. – Guillaume Papin Nov 07 '16 at 20:34
  • I guess you could use [compdb](https://github.com/Sarcasm/compdb) to merge all the compilation database into one, but it's getting difficult to discuss in this small comment boxes. :) – Guillaume Papin Nov 07 '16 at 20:36
  • Ok, I don't mind doing the `M-x irony-cdb-json-add-compile-commands-path RET` way. Thanks for helping :) – space_voyager Nov 07 '16 at 20:43
  • I've just opened a [GitHub issue](https://github.com/Sarcasm/irony-mode/issues/344) about this explaining a situation of a ROS GitHub repo for which the method you outlined here seems to fail. – space_voyager Nov 07 '16 at 22:53