Compiling a C++ program in Vim - c++

I am using Ubuntu 16.04, with Vim
Can't find a way to compile and run my C++ program in Vim.
I have appended this to my vimrc file
nnoremap <silent> <F8> :!clear;gcc % -o %:r && ./%:r<CR>
from this question: How do I run a C program from VIM?
But it isn't working - my program doesnt seem to compile when I press F8.
Any help would be appreciated.

You should have gone for the vim way of doing things. In particular in C++.
Calling g++ from :! instead of :make is really counter-productive (:h quickfix).
Follow this path instead: https://stackoverflow.com/a/35702919/15934 (1), unless you are under windows with the poorly configured make from MingW, in which case, follow this path: https://stackoverflow.com/a/22452184/15934
(1) If you want a mapping, it would be something like:
nnoremap <silent> <F8> :update<cr>:make %<<cr>

You can simply create a makefile and then add
nmap <F8> :make!<CR>:cw<CR> to your vimrc file

Related

How can I give the filename of current buffer automatically when I execute 'compile' command in Emacs?

As you already know, we can see 'make -k' command when we execute 'M-x compile' in emacs c++ mode.
But, now I'm studying some boost libraries, so I must frequently compile just single file after writing a example code.
So, for convenience, I've been doing this like below.
(1) make an alias in shell init file for g++ compile command.
alias c="g++ -g -Wall -O0 -std=c++11"
(2) map 'M-x compile' command to Function Key F9 in .emacs
(global-set-key [f9] 'compile)
(3) write c++ code
(4) press F9 and modify filename to current open file
For example, you can see 'Compile command: c vvv.cpp' in the below screen shot.
(This screen shot is just a simple code that I made for this question.
'c' is alias for compile command and options)
But, this open filename is actually 'vector1.cpp', so 'vvv.cpp' should be automatically replaced by 'vector1.cpp'.
I think this is not bad.
But, I'd like to find a way that I don't have to modify the current filename.
"Just press F9 and RET, then the current file will be compiled." This is exactly what I want.
Is there any better idea or way I can do like this?
Or plz let me know your nice compiling way for a minimal key pressing.
Thanks.
The EmacsWiki has a nice section explaining how you can customize the compile command: Compile Command
In your case, you could add a hook to the c++ mode to define the compile-command variable as you need. Following the example on the wiki:
(add-hook 'c++-mode-hook
(lambda ()
(set (make-local-variable 'compile-command)
(format "g++ -g -Wall -O0 -std=c++11 %s" (buffer-name)))))
Adding this snippet to your .emacs should do the trick.

Vim [compile and] run shortcut

Basically what I want is a keyboard shortcut in vim that lets me [compile and] run the currently being edited C, C++ or Python program. In psuedocode:
when a shortcut key is pressed:
if current_extension == 'c' then
shell: gcc this_filename.c -o this_filename_without_extension
if retcode == 0 then shell: ./this_filename_without_extension
else if current_extension == 'cpp' then
shell: g++ this_filename.cpp -o this_filename_without_extension
if retcode == 0 then shell: ./this_filename_without_extension
else if current_extension == 'py' then
shell: python this_filename.py
end if
end key
I realise I might be asking a bit much but would love it if this was possible!
Something like this would work. Just create filetype autocmd that map <F4> or whatever you want to save and compile and run the program. It uses exec to build the string and uses shellescape to escape the file name.
autocmd filetype python nnoremap <F4> :w <bar> exec '!python '.shellescape('%')<CR>
autocmd filetype c nnoremap <F4> :w <bar> exec '!gcc '.shellescape('%').' -o '.shellescape('%:r').' && ./'.shellescape('%:r')<CR>
autocmd filetype cpp nnoremap <F4> :w <bar> exec '!g++ '.shellescape('%').' -o '.shellescape('%:r').' && ./'.shellescape('%:r')<CR>
% is the current buffer filename. %:r is the buffer filename without extension
http://singlecompile.topbug.net seems to do more than what you want. For a simpler solution you could also just add the following to your vimrc
au BufEnter *.cpp set makeprg=g++\ -g\ %\ -o\ %<
au BufEnter *.c set makeprg=gcc\ -g\ %\ -o\ %<
au BufEnter *.py set makeprg=python\ %
au BufEnter *.[rR] set makeprg=Rscript\ %
map <F5> :call CompileGcc()<CR>
func! CompileGcc()
exec "w"
silent make
endfunc
HTH
It's 2018 now, vim 8 has released for 2 years and shipped with all the mean stream Linux distributions and Mac OS X. But a lot of vim tutorials are still teaching people something ten years ago.
You can compile your C++/Java programs in vim as convenience as Sublime Text or NotePad++ with some dedicated plugins for Vim 8 or NeoVim.
For example, the AsyncRun plugin will allow you run shell commands in background and read output from quickfix window in realtime.
See the screen capture.
Just like compiling programs in IDEs, the compilation errors will be matched by errorformat and be highlighted and become selectable. You can navigate errors in the quickfix window or continue editing while compiling.
Quick setup
Copy & paste the lines below to your vimrc:
Plug 'skywind3000/asyncrun.vim'
" open quickfix window automatically when AsyncRun is executed
" set the quickfix window 6 lines height.
let g:asyncrun_open = 6
" ring the bell to notify you job finished
let g:asyncrun_bell = 1
" F10 to toggle quickfix window
nnoremap <F10> :call asyncrun#quickfix_toggle(6)<cr>
When you input “:AsyncRun echo hello ” in the command line:
see the capture here
You will see the realtime command output in the open quickfix window.
Compile and run a single file
Compiling a single file with AsyncRun is much simpler than Sublime Text’s build system. We can setup F9 for this:
noremap <silent> <F9> :AsyncRun gcc -Wall -O2 "$(VIM_FILEPATH)" -o "$(VIM_FILEDIR)/$(VIM_FILENOEXT)" <cr>
The macros in $(..) form will be expanded as the real file name or directory, and then we will have F5 to run the executable:
noremap <silent> <F5> :AsyncRun -raw -cwd=$(VIM_FILEDIR) "$(VIM_FILEDIR)/$(VIM_FILENOEXT)" <cr>
The double quotation mark is used to handle path names containing spaces. The option -cwd=$(VIM_FILEDIR) means running the file in the file's directory. The absolute path name $(VIM_FILEDIR)/$(VIM_FILENOEXT) is used because linux needs a ./ prefix to running executables in current directory, but windows doesn't . Using the absolute path name of the binary file can handle this crossing platform issue.
Another option -raw means the output will not be matched by vim's errorformat, and will be displayed in quickfix as what it is. Now you can compile your file with F9, check the compilation errors in quickfix window and press F5 to run the binary.
Build C/C++ Projects
No matter what build tool you are using, make or cmake, project building means acting to a group of files. It requires locating the project root directory. AsyncRun uses a simple method called root markers to identify the project root. The Project Root is identified as the nearest ancestor directory of the current file which contains one of these directories or files:
let g:asyncrun_rootmarks = ['.svn', '.git', '.root', '_darcs']
If none of the parent directories contains these root markers, the directory of the current file is used as the project root. This enables us to use either <root> or $(VIM_ROOT) to represent the project root. and F7 can be setup to build the current project:
noremap <silent> <F7> :AsyncRun -cwd=<root> make <cr>
What if your current project is not in any git or subversion repository ? How to find out where is my project root ? The solution is very simple, just put an empty .root file in your project root, it will be located easily.
Let’s move on, setup F8 to run the current project:
noremap <silent> <F8> :AsyncRun -cwd=<root> -raw make run <cr>
The project will run in its root directory. Of course, you need define the run rule in your own makefile. then remap F6 to test:
noremap <silent> <F6> :AsyncRun -cwd=<root> -raw make test <cr>
If you are using cmake, F4 can be map to update your Makefile:
nnoremap <silent> <F4> :AsyncRun -cwd=<root> cmake . <cr>
Due to the implementation of c runtime, if the process is running is a non-tty environment, all the data in stdout will be buffered until process exits. So, there must be a fflush(stdout) after your printf statement if you want to see the real-time output. or you can close the stdout buffer at the beginning by
setbuf(stdout, NULL);
At the mean time, if you are writing C++ code, a std::endl can be appended to the end of std::cout. It can force flush the stdout buffer. If you are developing on windows, AsyncRun can open a new cmd window for the child process:
nnoremap <silent> <F5> :AsyncRun -cwd=$(VIM_FILEDIR) -mode=4 "$(VIM_FILEDIR)/$(VIM_FILENOEXT)" <cr>
nnoremap <silent> <F8> :AsyncRun -cwd=<root> -mode=4 make run <cr>
Using the option -mode=4 on windows will open a new prompt window to run the command, just like running command line programs in Visual Studio. Finally, we have these key mappings below:
F4: update Makefile with cmake.
F5: run the single file
F6: run project test
F7: build project
F8: run project
F9: compile the single file
F10: toggle quickfix window
It is more like build system in NotePad++ and GEdit. If you are using cmake heavily, you can write a simple shell script located in ~/.vim/script/build.sh to combine F4 and F7 together: it will update Makefile if CMakeList.txt has been changed, then exectute make.
Advanced usage
You can also define shell scripts in your dotfiles repository and execute the script with F3:
nnoremap <F3> :AsyncRun -cwd=<root> sh /path/to/your/dotfiles/script/build_advanced.sh <cr>
The following shell environment variables are defined by AsyncRun:
$VIM_FILEPATH - File name of current buffer with full path
$VIM_FILENAME - File name of current buffer without path
$VIM_FILEDIR - Full path of current buffer without the file name
$VIM_FILEEXT - File extension of current buffer
$VIM_FILENOEXT - File name of current buffer without path and extension
$VIM_CWD - Current directory
$VIM_RELDIR - File path relativize to current directory
$VIM_RELNAME - File name relativize to current directory
$VIM_ROOT - Project root directory
$VIM_CWORD - Current word under cursor
$VIM_CFILE - Current filename under cursor
$VIM_GUI - Is running under gui ?
$VIM_VERSION - Value of v:version
$VIM_COLUMNS - How many columns in vim's screen
$VIM_LINES - How many lines in vim's screen
$VIM_SVRNAME - Value of v:servername for +clientserver usage
All the above environment variables can be used in your build_advanced.sh. Using the external shell script file can do more complex work then a single command.
Grep symbols
Sometimes, If you don't have a well setup environment in you remote linux box, grep is the most cheap way to search symbol definition and references among sources. Now we will have F2 to search keyword under cursor:
if has('win32') || has('win64')
noremap <F2> :AsyncRun! -cwd=<root> grep -n -s -R <C-R><C-W> --include='*.h' --include='*.c*' '<root>' <cr>
else
noremap <F2> :AsyncRun! -cwd=<root> findstr /n /s /C:"<C-R><C-W>" "\%CD\%\*.h" "\%CD\%\*.c*" <cr>
endif
The above script will run grep or findstr in your project root directory, and find symbols in only .c, .cpp and .h files. Now we move around the cursor and press F2, the symbol references in current project will be displayed in the quickfix window immediately.
This simple keymap is enough for most time. And you can improve this script to support more file types or other grep tools in your vimrc .
That’s the practical way to build/run C/C++ projects in Vim 8 or NeoVim. Just like Sublime Text’s build system and NotePad++’s NppExec.
No more outdated vim tutorials again, try something new.
this is my map it really work you can update it to any language:
" <!----------------------------" gcc compile C files----------------------------------------!>
autocmd filetype c nnoremap <Leader>c :w <CR>:!gcc % -o %:r && ./%:r<CR>
" <!----------------------------" java compile files----------------------------------------!>
autocmd filetype java nnoremap <Leader>c :w <CR>:!javac % :r&& java %:r<CR>
" <!----------------------------" php compile files----------------------------------------!>
autocmd filetype php nnoremap <Leader>c :w <CR>:!clear && php %<CR>
now if you are ine one of those file in vim just do in normal mode:
<leader>c
I know I came here 7 years later. I tried the code of other answers and the result didn't satisfied me, so I tried this:
autocmd filetype cpp nnoremap <F9> :w<bar>term ++shell g++ %:p -o %:p:r && %:p:r<CR>
When F9 is pressed, it (like all the answers above) compiles and executes the current file. The output is displayed in a :terminal section splitted screen.
You can change the g++ command to run another language code.
It is saved in a gist, with another mapping to display the output, also in a splitted section, but in a new file, so you can save the output.
Hopefully it could help someone.
I wanted to find a shortcut too. But I didn't want to use autocmd for some reason. I used bash script. I was already using a bash script to compile and run my C/C++ codes. So, I thought, why don't I use a bash script and use it in fltplugin file for C and C++. I made two separate bash scripts. One for C and one for C++. Here is the script for C (For C++, it is also similar just change the compiler to clang++/g++,
std=c2x to std=c++20 and $filename.c to $filename.cpp),
filename=$1
compiler=clang-10
if [ $2 ]; then
if [ $2 == "-v" ]; then
FLAGS="-g -Wall -Wextra -pedantic -std=c2x"
fi
else
FLAGS="-Wall -Wextra -pedantic -std=c2x"
fi
$compiler $FLAGS $filename.c -o $filename -lm
return_value=$?
if [ $return_value -eq 0]; then
if [ $2 ]; then
if [ $2 == "-v" ]; then
valgrind ./$filename
rm $filename
fi
else
./$filename
echo
echo "[process exited $return_value]"
rm $filename
fi
fi
Saved it as run. I made it executable for all users,
$ chmod 777 run
I moved it to my user bin directory.
$ mv run ~/bin
If you dont have a user bin directory, make on. Go to your home directory, and make a directory named bin.
$ cd ~
$ mkdir bin
Then move the run (or whatever name you gave to your script) file to the bin directory.
$ mv run ~/bin
Let's move on.
Then I made a c.vim file in ~/.vim/after/ftplugin directory. And add two new key remaps to the c.vim file.
nnoremap <F9> :vertical bo term run %:r<CR>
# This will run my code with valgrind
nnoremap <F2> :vertical bo term run %:r -v<CR>
Here are some screen shots,
Clicking F9 shows me the output screen in a vim buffer,
Clicking F2 shows me the output using valgrind in a vim buffer
You can do same for C++, just make a cpp.vim file in ~/.vim/after/ftplugin directory. And make another run file (like run_cpp), save it in your user bin(~/bin) file. Make some custom key bindings, and you are good to go.

Setting up vim as C++ IDE

I wish to setup vim as C++ IDE so I can do all work from it.
I'm using these plugins for vim:
Clang complete - accurate completion
nerdtree - browse files
snipmate - insert snippets
AutoComplPop - omni-completion
buffergator - buffer management
vim-powerline - nice statusbar
vundle - to manage plugins
But I lack things like Jump to definition and compiling multiple files in one executable, project view...
I'm using
nmap <F8> :w % <bar> :!g++ -W -Wall -Wextra -pedantic -std=c++11 % -o %:t:r<CR> <bar> :!./%:t:r<CR>
to compile current file, but it won't work if there are multiple file that create one executable.
I know I could just use eclipse, netbeans, code::blocks and such, but I really like vim... If such thing as vim ide isn't possible do I have to learn GNU build system or some other method?
Any advice is welcome.
You need to create a makefile which handles the build process.
Then from vim just run :make, it will run the build and pop all errors in quickfix window where you can navigate and jump to error locations.
First, to jump to definitions, you might try this:
http://www.santiagolizardo.com/article/vim-jump-to-classes-and-functions-defined-in-different-files/64003
I haven't tested it, so I can't tell you if it works.
Now, to build multiple file projects, it might be better for you to learn how to use makefiles and automake. These links might help you:
http://homepages.gac.edu/~mc38/2001J/documentation/g++.html
http://www.openismus.com/documents/linux/automake/automake
Good luck.
Edit: A similar question was answered on this link: https://stackoverflow.com/a/563992/1820837
"Jump to definition" is already there, it's <C-]> with the cursor on a keyword or :tag foo on the command line.
For these to work, you need a tags file generated by exuberant-ctags and to tell Vim where to find it. See :help tags and :help ctags.
Without a tags file, gd goes to the definition of the keyword under your cursor if it's in the same file. But it's not as generally useful as <C-]>.
For "Jump to definition" I can recommend the YouCompleteMe, plugin which is really easy to setup with vundle.
Otherwise there is also ctags, but I find it less useful.
To use vim as a IDE, I find this post useful.

reference a filename in vi

Sometimes I run make directly from the vim command line. However, sometimes I would just like to build one file currently being edited: !g++ filename.cpp . Is there a shortcut to reference the file without having to type it..?
Guys, I DO NOT want to use make at all. all I want to do is to build it from vi's command line, using g++/gcc
You can use % to reference the current file
so:
:!g++ %
in VIM "%:p" stands for the current file.
try "!g++ %:p"
If your make program is actually GNU make, just execute:
:make %<
If you want to add flags like -Wall or -pedantic then just set $CFLAG (for compiling C files, or $CPPFLAGS for C++ files), or if you want to specify libraries then set $LDFLAGS from vim.
:h :make
:h %<
EDIT:
Unlike plain calls to :!gcc, this solution is compatible with the quickfix mode (:h quickfix), and it does not require to change &makeprg to 'g++ $CPPFLAGS -o $* $*.cpp $LDFLAGS'.
NB:
No need to write any makefile to take advantage of GNU-make.
And even if you have one Makefile, and as long as you don't mess with the default implicit rules, this solution will also work!
You can use this to refer to the filename you are working on with the extension substituted with .o:
%r.o
Your filename.cpp becomes filename.o which is useful if you put something like this in your .vimrc.:
set makeprg=gmake\ %:r.o
That way you can just do this in vim and it will then launch the command declared using makeprg on the current file:
:make
As mentioned the shortcut is %.
You can bind the whole thing to one key by putting the following in your .vimrc file:
map <F9> :!gcc %<CR>

compile directly from vim

I'd like to compile cpp file w/o turning off vi.
I know the :!g++ file.cpp but I prefer :make so I added this line in .vimrc file
au FileType C set makeprg=gcc\ %
au FileType Cpp set makeprg=g++\ %
but I keep getting
"make: ***** No targets specified and no makefile found. Stop.** "message.
can anyone tell me what is wrong with my setting?
I use to compile successfully with the option above.
You need the substitution there, try something like:
set makeprg=gmake\ %:r.o
Oh, this assumes that you've got:
a (M|m)akefile in the directory, or
default SUFFIX rules are available for your environment (which it looks like there aren't)
Check for the default by entering:
make -n <my_file>.o
and see if that gives you something sensible.
If there is a makefile in another location you can add the -f option to point at the makefile, for example:
set makeprg=gmake\ -f\ ../some_other_dir/makefile\ %:r.o
BTW For learning about make, and especially gmake, I'd suggest having a look at the excellent book "Managing Projects with GNU Make" (sanitised Amazon link).
HTH.
cheers
I should change C,Cpp into c,cpp, then it works fine.
thank you all, especially Rob Wells, your answer helped me a lot. thank you.
I think it's much easier if you write a Makefile and put it where vi can find it. I'm not sure if you actually use vi (I've only used Vim), but when there is a Makefile compiling should be as easy as writing :make (no set makeprg needed).
It can be easily achieved by the use of key maps.
First open up your vimrc file and these lines to the file,
autocmd filetype cpp nnoremap <F4> :!g++ % -ggdb -o %:r <CR>
autocmd filetype cpp nnoremap<F5> :!g++ % -ggdb -o %:r && ./%:r <CR>
The first line maps the key F4 to compiling the file. The second line maps the key F5 to compile and run.
If you use gdb frequently then this may also come handy.
autocmd filetype cpp nnoremap<F10> :!g++ % -ggdb -o %:r && gdb -tui %:r <CR>
This line maps the key F10 to compile and start gdb
Hope this helps.
I recommend a vim plugin called SingleCompile instead of what you have done:
http://www.vim.org/scripts/script.php?script_id=3115
First of all, just make the bloody make file. Every tool out there is expecting to work with make and if your compilations are that simple it takes about 30 seconds to write a make file that compiles all c and cpp files into an executable.
Second, if you refuse to use a make file then try
:help system
That should give you enough info to come up with your own command similar to this
:com Mymake call system("g++ ".expand("%"))