-
Notifications
You must be signed in to change notification settings - Fork 8
Linux is an IDE (all of it)
My initial intention after installing a fresh Ubuntu distribution was to set up any well known IDE and click around until I could compile, debug and run the project. Boy, was I not naive! Several days later, I have had discarded Clion because it is a paying application, I had unsuccessfully tried Code::Blocks, Eclipse, and lost my patience before trying Qt Builder -- yet, I have not been able to find an acceptable IDE to just do the basic stuff with reasonable simplicity. And then I found this Stack Oveflow question «C++ IDE for Linux?» where accepted and most voted answer states that «UNIX is an IDE. All of it».
After further investigations I found out that Sublime Text is a popular editor, although real hardcore geeks will only deign speak to you if you can configure Vim to be an IDE. As for a debugger, you have gdb at your disposal, the straight from the seventies, pre user interface, bare bones, 8x8 pixel black and white font, command line debugger. Yes, it seems bleak. But, you know, I am the proud owner of a Mac, and if you hate yourself enough to keep using Linux then it is not my problem. And I hope you enjoy the pain.
Inevitably came the day when I had to fix a bug that manifested itself only in Linux and Raspberry Pi, and I had to go through it. At first I couldn't understand how is it possible that Linux, the one environment preferred by developers, has no decent IDE. Then I configured properly my Vim. Then I found my way with gdb. And I started liking it.
It took me 7 days to evolve from feral hate to feeling comfortable. After fixing bug I went back to Xcode with no intention of return... and I liked it less. Some days later, I configured Vim in my Mac just as described below.
Let's accept, no, let's embrace that Linux is and IDE, and let's make the most out of it.
I use the following plugins:
- Vundle - The mother of all Vim plugins, the one that lets you install the others.
- YouCompleteMe - Provides excellent auto-completion with a reasonable set up and also instant compilation. This is the plugin that makes Vim as good as any IDE.
- NERDTree - To have a folder tree on your left side. It helps you to navigate, create new folders and files, and have a general view of your project.
- CPP enhanced highlight - A somewhat better c++ syntax highlight.
- ConqueGdb - To embed a gdb window in Vim. It shows the position of your breakpoints and current execution cursor on your source code.
The Vim configuration is in a .vimrc
file in your home folder. Open it with vim ~/.vimrc
. Add the following content:
set nocompatible " be iMproved, required by Vundle.
filetype off " Vim makes cache for filetype plugins from runtime path.
" If vundle changes runtime path it must reset before calling
" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
Plugin 'VundleVim/Vundle.vim'
Plugin 'Valloric/YouCompleteMe'
Plugin 'scrooloose/nerdtree'
Plugin 'octol/vim-cpp-enhanced-highlight'
Plugin 'Conque-GDB'
call vundle#end() " Place rest of configuration below this line.
filetype plugin indent on " Restore filetype autodetection deactivated above.
syntax on " Syntax highlighting.
set exrc " Load the .vimrc from current folder.
set secure " Prevent security issues from exrc.
The exrc
option makes Vim to load local .vimrc
files, so you can further configure for a particular folder. It is handy to add the file at the project root , so it behaves like a workspace configuration.
The first time you add Vundle in ~/.vimrc
you need to manually download from the official repository:
cd ~
mkdir .vim
git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim
After that, and for any other plugin that you may add to the .vimrc
file, you have to execute :PluginInstall
:
- Open Vim, anywhere.
- Type the command:
:PluginInstall
.
This plugin needs additional actions to be properly installed:
sudo apt install build-essential cmake python3-dev
cd ~/.vim/bundle/YouCompleteMe
python3 install.py --clang-completer
For example:
- Use
set exrc
to make Vim to load the.vimrc
configuration file from the current folder. - Use
set secure
(see https://vi.stackexchange.com/questions/5055/why-is-set-exrc-dangerous)
In the src
folder, create a .vimrc
file. This will be like a workspace configuration. In it, place:
set path+=src/**10
autocmd vimenter * NERDTreeVCS
To open include file:
- gf : Open it.
- C-W f : Open it in a separate tab.
- C-W v : Open current file in a vertical split. Then you can gf to jump to the include file.
To go back after opening an include file:
- gf : Open an include file.
- Ctrl + O : Brings you back to the previous file.
- Ctrl + I : If you're back from a file, then jumps into the next file.
- The mnemonic would be O = OUT, I = IN => Ctrl - O brings you out, Ctrl brings you in. If every jump is like going through a door, that is. (comment by kronn in https://stackoverflow.com/questions/133626/how-do-you-return-from-gf-in-vim)
Create a symlink from the src
folder to the compile_commands.json
:
ln -s build/compile_commands.json compile_commands.json
To set up formatting:
- Read this: https://www.cs.ubc.ca/~goyal/tips/vim-advanced/chapter04.txt
- In
.vimrc
, add following elements:
set path+=src/**10 " For 'gf', looks in current folder, and up to 10 level of sub-sub-folders
set hidden " For 'gf', let's you go to next file without requiring to save current.
set cindent shiftwidth=4 " In C/C++, size of the tabulation increase each time you have a {
set tabstop=4 " In all files, size of the Tab
set expandtab " Use spaces instead of Tab
autocmd vimenter * NERDTreeVCS " Automatically opens NERDTree
To compile and run using vim and conque:
- Edit files as you wish.
- When you want to compile, or perform any other task:
- Ctrl Z - Pauses Vim, and you're back to the command line.
- Do whatever, but
make
-
fg
command reopens Vim at the exact point where you left it. - See more ways here: https://stackoverflow.com/questions/1236563/how-do-i-run-a-terminal-inside-of-vim
- From Vim, type:
-
:ConqueGDB build/rascapp
- The path may vary
-
- From Gdb:
- Here you have some commands: https://www.cs.rochester.edu/~nelson/courses/csc_173/review/gdb.html
- Like any other Vim window,
[I]
let's you type, and[esc]
gets you back in Vim command mode.
In the first step, a little bit below, I will give short specific instructions for compiling with debug symbols, and debug the programs with gdb.
To debug with gdb, assuming that you're still in build
folder:
gdb ./rascapp
[Now you're in gdb]
b main-window.cpp:10 # Place a break-point on line 10 of this file.
run # Run the program. It will stop at the break point.
where # It will show the stack trace
list # It will show some context.
print width # Displays the value of this variable
n # Step over
s # Step into
c # To continue the program
q # Quit gdb
When opening gdb with a core dump you need to be very sure that is has be produced with the exact same application you're loading. When you're developing, you change your application several times per minute and you don't always remember. So, if possible, recompile, relaunch, reproduce the crash, and then open it with gdb.
-
where
shows the stack trace. It informs you in what method the fault happened, plus which method called it, and which method called the method which called, etc. As crashes may occur in a library, you have to look for the first entry where it is your code. -
frame n
navigates to the nth entry of the stack trace.where
displays a number besides each entry of the stack trace.
See more about gdb commands here:
/settings More information about this topic:
- http://www.brendangregg.com/blog/2016-08-09/gdb-example-ncurses.html
- https://wiki.ubuntu.com/Apport
- https://superuser.com/questions/849099/where-does-ubuntu-14-04-drop-core-files
- https://stackoverflow.com/questions/13122480/core-dump-apport-no-crash-report
- https://unix.stackexchange.com/questions/343275/why-is-editing-core-pattern-restricted
Here are some pages I liked when I did my research:
- C Programming in Linux Tutorial #056 - GDB debugger (1/2)
- Quick Intro to gdb
- CppCon 2015: Greg Law " Give me 15 minutes & I'll change your view of GDB"
- Hitchhikers guide to the gdb
Usually Linux distributions save a core dump file whenever an application crashes. However, there are multiple elements that may difficult you finding the core files.
The first step is setting the maximum size of the core file with ulimit -c
. If it is 0, then core dumping is disabled:
ulimit -c
> 0
ulimit -c unlimited
ulimit -c
> unlimited
Then you need to check core_pattern
configuration file to verify where, and under what name, the core files are dumped:
cat /proc/sys/kernel/core_pattern
Here you may find different situations:
- You find a apport configuration like this:
|/usr/share/apport/apport %p %s %c %d %P
- The pipe
|
means that the content of the core file is sent to an application. -
Apport is used, among others, by Ubuntu to send crash reports to the authors of the applications installed via
apt-get
. As a consequence of its main goal, Apport just ignores crash reports of user applications like the one you're trying to develop and debug.
- Or you find a relative path and file name.
- Or you find an absolute path and file name.
Depending on your preference, you can either configure Apport not to ignore your core dumps, or save directly the core dumps without using another application.
To configure Apport not to ignore crash reports of user applications, create configuration file called settings
in folder ~/.config/apport
. Most probably, the folder .config
already exists, but you will need to create the apport
folder:
cd ~/.config
mkdir apport
cd apport
vim settings
The content of the Apport settings file is the following:
[main]
unpackaged:true
Next time you have a core dump, you can use apport-cli
, and then option [K]
to locate it:
> (rascapp:12147): GLib-CRITICAL **: 18:02:14.510: Source ID 17 was not found when attempting to remove it
> Segmentation fault (core dumped)
apport-cli
>
>*** Send problem report to the developers?
>
>After the problem report has been sent, please fill out the form in the
automatically opened web browser.
>
> What would you like to do? Your options are:
> S: Send report (9.1 MB)
> V: View report
> K: Keep report file for sending later or copying to somewhere else
> I: Cancel and ignore future crashes of this program version
> C: Cancel
> Please choose (S/V/K/I/C): K
> Problem report file: /var/crash/_home_xxx_Documents_gtk-opencv-patterns_build_app_rascapp.1001.crash
Crash reports generated by Apport are need to be unpacked it before you can access the contained core dump. I personally like to use a sub-folder in the temporary build
directory of my work space because, as they get outdated as soon as you modify your source code, I don't want to keep them for long:
cd ~/where/my/project/is/gtk-opencv-simple/build
rm -rf crash
mkdir crash
cd crash
apport-unpack /var/crash/_home_xxx_Documents_gtk-opencv-patterns_build_app_rascapp.1001.crash .
This will create plenty of files in the selected folder, and one of them is called CoreDump
. This is the one you can open with gdb
:
gdb ../app/rascapp CoreDump
Personally, I prefer the core dumps to be saved locally, besides the application that crashed. For this you can configure the core_pattern
using a sysctl
command (and you probably need to reset the ulimit -c
):
sudo sysctl -w kernel.core_pattern=core.%e.%p
ulimit -c unlimited
With the above configuration, when your application has a core dump a file named core.rascapp.19936
appears within your current folder. If, like me, you run your application from the build
temporary folder, then you can open the core dump with the following command:
gdb app/rascapp core.rascapp.19936
Depending on your Linux distribution, you may find the following error when you modify the maximum core file size:
-bash: ulimit: core file size: cannot modify limit: Operation not permitted
The following article helps you to properly configure this limit:
If you get an error like the following:
[ 95%] Building CXX object modules/stitching/CMakeFiles/opencv_perf_stitching.dir/perf/opencl/perf_stitch.cpp.o
c++: internal compiler error: Segmentation fault (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-7/README.Bugs> for instructions.
modules/stitching/CMakeFiles/opencv_perf_stitching.dir/build.make:62: recipe for target 'modules/stitching/CMakeFiles/opencv_perf_stitching.dir/perf/opencl/perf_stitch.cpp.o' failed
make[2]: *** [modules/stitching/CMakeFiles/opencv_perf_stitching.dir/perf/opencl/perf_stitch.cpp.o] Error 4
CMakeFiles/Makefile2:4438: recipe for target 'modules/stitching/CMakeFiles/opencv_perf_stitching.dir/all' failed
make[1]: *** [modules/stitching/CMakeFiles/opencv_perf_stitching.dir/all] Error 2
Makefile:162: recipe for target 'all' failed
make: *** [all] Error 2
This is usually a problem with not having enough memory. If, like me, you're using a virtual Linux machine, then the solution is simply increasing the available memory. If not, then try not having multi-threaded compilation (don't use make -j
option).
Se more about this issue: https://github.com/opencv/opencv/issues/8552
The complete line, visible at the bottom of the Vim window says:
- NoExtraConfDetected: No .ycm_extra_conf.py file detected, so no compile flags are available. Thus no semantic support for C/C++/ObjC/ObjC++
To fix this you need to have the compile_commands.json
file in your build
folder, plus a link to it from the source folder. Add the following lines in your main CMakeLists.txt
file:
...
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
...
After that, you may need to delete and recreate your build
folder (see above for more indications). Then, create a symlink from the src
folder into the build/compile_commands.json
file:
ln -s build/compile_commands.json compile_commands.json
You should be good with all that.