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
`-- src

I would like to make my project using the make command included in Vim. But each time I have to specify :make -C ../. I would prefer, if there is not Makefile file in the current directory, go in the parent directory. I already do that with

set tags+=./tags;/

in my .vimrc.

Furthermore, the make is by default ugly. Are there options to add color to make, and allow a direct access to the errors (as in Emacs).

Thanks

share|improve this question

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.

share|improve this answer
15  
One can use a let clause to avoid such an extensive escaping: :let &makeprg = '[[ -f Makefile ]] && make || make -C ..'. – ib. Oct 19 '11 at 3:55
1  
[[ a ]] && b || c is not exactly the same as if a then b else c. If a is true and b returns with a non-zero exit code, then c will be executed as well. – Reinier Torenbeek Mar 9 '13 at 14:12
    
reiner-torenbeek: good point. How about [[ a ]] && (b ; true) || c. – rampion Mar 9 '13 at 14:35
up vote 7 down vote accepted

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
share|improve this answer

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.

share|improve this answer
    
I don't know why projects don't opt for a top-level Makefile whenever possible. – Matthew Mitchell Apr 17 '14 at 20:50

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)

share|improve this answer

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 :makeor :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
share|improve this answer

set makecmd="make -C .." in your .vimrc

share|improve this answer
    
I would prefer, if there is not Makefile file in the current directory, go in the parent directory. If Makefile exists, use it. – Jérôme Apr 8 '09 at 9:54
    
that's not so easy. set your makecmd to be a script that tests that condition... it's not all that hard to do :) – Adam Hawes Apr 8 '09 at 11:45
    
That is exactly what I am asking. I don't know how to test if a file exists or not in the vimrc – Jérôme Apr 8 '09 at 13:08
1  
I think you meant set makeprg=... – Juan Campa Feb 12 '14 at 23:42

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.