I am trying to get VIM to run the right makefile for a specific source file. For example, if the current file is ui8_c_buff_test.cpp and if I use the makeprg configuration below and run make,

let &makeprg = 'make -f '.fnameescape(substitute(expand('%'), '\m_test\.cpp$', '.makefile', '')) 

the system should run against the ui8_c_buff_test.cpp and execute make -f dispatcher/unittest/ui8_c_buff.makefile, but it is running against the .vimrc file where the makeprg is set, and I get the following result:

/home/sporty/.vimrc:1: *** missing separator (did you mean TAB instead of 8 spaces?).  Stop.

But if I run the following command,

:echo 'make -f '.fnameescape(substitute(expand('%'), '\m_test\.cpp$', '.makefile', ''))

I get a correct result, which is:

make -f dispatcher/unittest/ui8_c_buff.makefile

So how can I get the makeprg to run against the current file instead of .vimrc?

I asked a question here: Determining makefile based on source file name, and got an answer, but most of the time it does not work.

1 Answer 1


The right-hand side of let &makeprg = ... is evaluated only once. If you put that command in your .vimrc as it is, %expands to /home/sporty/.vimrc and you get the interesting effect you describe. You need to put it in an autocmd, so that it gets re-evaluated every time you open a file of the relevant type. Also, you probably want to use the local version of makeprg rather than the global one:

autocmd  BufRead,BufNewFile  *.cpp
    \ let &l:makeprg = 'make -f '.fnameescape(substitute(expand('%:t'), '\m_test\.cpp$', '.makefile', ''))

You'll probably still have to solve the problem of running make in the correct directory. One way to get around that is to always open your files starting from the base directory of your project.

Edit: As @Ben points out in comments, you can deal with changing directories automatically with another autocmd:

autocmd QuickfixCmdPre *.makefile
    \ let s:makefile = substitute(expand('%:t'), '\m_test\.cpp$', '.makefile', '') |
    \ let s:base = findfile(s:makefile, escape(expand('%:p:h'), ' ') . ';') |
    \ if s:base !=# '' |
    \     execute 'lcd ' . fnameescape(expand(s:base, '%:p:h')) |
    \ endif
  • Another way to fix "make" directory: use the QuickfixCmdPre autocmd, and search up until you find a directory containing a makefile. Change directories to that location.
    – Ben
    Commented Sep 24, 2015 at 18:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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