Need some help with getting Vim to run a build.bat

I need someone experienced in Vim to help me out if its not too much trouble. I just started using Vim a few days ago so I am not too experienced. I want to get Vim to do with what Casey does with Emacs. Scan for a build.bat file and run it.

EDIT:

Right now it just runs the batch file that the directory I used cd to go to. The batch file sets up the VC vars every build. I set F5 and F6 to traverse through the errors. Right now cw just opens the file the first error is in which is annoying, maybe someone knows if I can still open the output without it jumping to the first error.

Figured it out a little bit. So far this is what I got.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
function! DoBuildBatchFile()
    set makeprg=build.bat
    set errorformat=%f(%l):\ %m
    silent make
    cw
    echo 'Build Complete'
endfunction

nnoremap <F7> <C-O>:call DoBuildBatchFile()<CR>

"Go to next error
nnoremap <F6> <C-O>:cn<CR>
"Go to previous error
nnoremap <F5> <C-O>:cp<CR>

Edited by mojobojo on
I've had pretty much the same solution as you for a while now, just look in the current directory for build.bat and run it. Been meaning to improve my own handling for a while now and this seemed like as good a time as any to work on it.

I've only been using vim for about a year, so I'm definitely no vimscript expert, but this snippet should get you what Casey described as his Emacs behaviour. It starts in the directory of the currently focused file and looks up directories until it hits the top level or finds a build.bat.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function BuildProject()
    "save the current working directory so we can come back
    let l:starting_directory = getcwd()

    "get the directory of the currently focused file
    let l:curr_directory = expand('%:p:h')
    "move to the current file
    execute "cd " . l:curr_directory

    while 1
        "check if build.bat exists in the current directory
        if filereadable("build.bat")
            "run make and exit
            make
            break
        elseif l:curr_directory ==# "/" || l:curr_directory =~# '^[^/]..$'
            "if we've hit the top level directory, break out
            break
        else
            "move up a directory
            cd ..
            let l:curr_directory = getcwd()
        endif
    endwhile

    "reset directory
    execute "cd " . l:starting_directory
endfunction
I use a setup similar to Casey's for my own projects, but with small differences, than make it easier to work with Vim. I always use console Vim (via Cygwin in Windows), so I don't know whether this will work for gVim.

I always edit all my source files from the project's root directory (i.e. I start vim like this: "vim code/*").

The build scripts are in the 'misc' directory and the build output goes to the 'build' directory.

The build script's (e.g. build.bat) file names are in reference to the root dir:
1
2
3
[...]
if not exist "build" mkdir build
cl %compiler_flags% -Fabuild\ -FAs -Fdbuild/ -Febuild/ -Fobuild/ -Fmbuild/main.map code/main.c


Note that there are no "pushd/popd build" calls and that the output is specified to be the 'build' directory explicitly.

To execute the build script I use the Dispatch Vim plugin. In Vim: ":set makeprg=misc/build.bat". Then I call the script via ":Make" or with a custom shortcut (e.g. <leader>m) and it executes in the background. Once finished it brings the errors in the quickfix window. Without the plugin, calling ":make" will do the same, but synchronously.

To get Vim to understand the output errors from cl, I added these lines to my vimrc (MSBuild + cl.exe + fxc.exe --for HLSL):
1
2
3
4
5
6
7
" error message formats
" Microsoft MSBuild
set errorformat+=\\\ %#%f(%l\\\,%c):\ %m
" Microsoft compiler: cl.exe
set errorformat+=\\\ %#%f(%l)\ :\ %#%t%[A-z]%#\ %m
" Microsoft HLSL compiler: fxc.exe
set errorformat+=\\\ %#%f(%l\\\,%c-%*[0-9]):\ %#%t%[A-z]%#\ %m


I think that's all. I know this is not exactly how Casey + Emacs do it, but it's what I've found to work best for me :)
Here's what I'm using for my HH-inspired game project:

https://github.com/nxsy/hajonta/blob/master/scripts/windows/vimrc

FWIW, I did not need to update errorformat when using MSVC's compiler (cl), possibly because I used /FC. Here's my build.bat:

https://github.com/nxsy/hajonta/blob/master/scripts/windows/build.bat

This was a great discovery for me:

set switchbuf=useopen,split

This would ensure existing open buffers would be used in preference (so you don't end up with multiple views into the same file), and would do a split if the file isn't already visible.
Right now it builds and it catches the errors. Almost there except I have this really annoying issue where when I hit F7 and it builds, it opens another buffer in place of my code file. If I hit build again it opens another buffer. It just keeps opening files I recently edited which is really odd. Here is my vimrc

https://gist.githubusercontent.co...c55191bbcd6/My%20Windows%20_vimrc
Its working now. Figured out that I was binding the keys wrong. Vim executes commands based off of spawning a new cmd so if I launch Vim in a visual studio environment it still wont see cl. Right now I am getting past this by adding this in the bat file.

1
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat"


Here is the stuff to put in the vimrc file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
" Ensure the buffer for building code opens in a new view
set switchbuf=useopen,split
 
" Thanks to https://forums.handmadehero.org/index.php/forum?view=topic&catid=4&id=704#3982
" error message formats
" Microsoft MSBuild
set errorformat+=\\\ %#%f(%l\\\,%c):\ %m
" Microsoft compiler: cl.exe
set errorformat+=\\\ %#%f(%l)\ :\ %#%t%[A-z]%#\ %m
" Microsoft HLSL compiler: fxc.exe
set errorformat+=\\\ %#%f(%l\\\,%c-%*[0-9]):\ %#%t%[A-z]%#\ %m
 
 
function! DoBuildBatchFile()
    " build.bat
    set makeprg=build
    " Make sure the output doesnt interfere with anything
    silent make
    " Open the output buffer
    copen
    echo 'Build Complete'
endfunction
 
" Set F7 to build. I like this since I use visual studio with the c++ build env
nnoremap <F7> :call DoBuildBatchFile()<CR>
 
"Go to next error
nnoremap <F6> :cn<CR>
"Go to previous error
nnoremap <F5> :cp<CR>

Edited by mojobojo on
These are nice solutions, but I found a much simpler one -- set makeprg=build.bat.

Simply cd to your project directory (where the build.bat is) and edit files relative to there. This has additional benefits, like the default location of saving a random file (e.g. opening an empty buffer, writing a todo list or something, and saving it just as :w todo-list.txt) is in your project, and you can run git commands and such with the correct current directory.

Just a thought.
get AsyncRun and do:

:AsyncRun build.bat
copen

works like a charm for me.