What I am trying to do seems a very basic stuff, but I can\'t find anything about it. I am working on a project built as usual:
project
|-- bin
|-- inc
`-- s
By far the easiest solution is to have a Makefile in your src directory, which is the way that many, many projects are set up regardless of editor/IDE. You can still have a top-level Makefile that calls make -C src
, with the rules for building in src located in src where they belong.
set makecmd="make -C .." in your .vimrc
Slight modification of what Adam said:
:set makeprg=[[\ -f\ Makefile\ ]]\ &&\ make\ \\\|\\\|\ make\ -C\ ..
Unescaped, this is
[[ -f Makefile ]] && make || make -C ..
which means, pseudo code style
if file-exists(Makefile)
then make
else make -C ..
This only goes one directory up. If you'd like a more general solution that will go as many directories up as necessary, you'll need to be able to search ancestor directories until a Makefile is found, and I'm not sure how to do that simply from the command line. But writing a script (in whatever language you prefer) and then calling it from your makeprg shouldn't be hard.
To answer your second question, you can navigate through the errors using the quickfix functionality in VIM. Quickfix stores the errors in a buffer and allows you to navigate forward/backwards through them.
You may have to define the error regexp to allow VIM to identify these from Make's output, but I seem to remember that it works out-of-the-box rather well (I've had to modify how it works for Java Ant builds - obviously doesn't apply here)
Another approach can be used if you have a single makefile on project root directory:
project
|-- bin
|-- inc
|-- src
| Makefile
With your project path in variable like b:projectDir
it is possible to use an "autocommand" to change to that directory before start executing :make
or :lmake
:
augroup changeMakeDir
au!
autocmd QuickfixCmdPre *make
\ if exists("b:projectDir") &&
\ b:projectDir != expand("%:p:h") |
\ exe 'cd ' . b:projectDir |
\ endif
augroup END
Projectroot plugin can be used to set b:projectDir
; it also provides the commands to change the current directory to the project root directory:
augroup changeMakeDir
au!
autocmd QuickfixCmdPre make ProjectRootCD
augroup END
The solution of rampion is a first step, but computed on vim load. When I load a multi tab session, the path can be inconsistent from one tab to another.
Here my solution (+ extra with tabnew).
fun! SetMkfile()
let filemk = "Makefile"
let pathmk = "./"
let depth = 1
while depth < 4
if filereadable(pathmk . filemk)
return pathmk
endif
let depth += 1
let pathmk = "../" . pathmk
endwhile
return "."
endf
command! -nargs=* Make tabnew | let $mkpath = SetMkfile() | make <args> -C $mkpath | cwindow 10