Monday, September 29, 2008

Vim C# Compiling

This is the first post in my series on using Vim to do C# development. You can read the introduction into why someone might want to do that here.

The most important thing to be able to do comes in two parts:
  1. Compile
  2. Step through errors
In college we did development in Java without any kind of IDE. So you typed in your text editor. Then switched to the DOS prompt and "javac"ed. When there were errors, which there always were, you opened the file with the error and navigated to the line where it occurred. This was slow and tedious, but not the end of the world. Until you get used to Visual Studio and being able to F5, and then simply double click on an error.

How do we do the same thing in Vim? First, we have to compile. To start with, I'm going to compile using the following command:
devenv slnname.sln /Build Debug

This will perform the build exactly like Visual Studio would, just without opening Visual Studio. I put this command in a .bat file in the same directory as the .sln called build.bat.

To get Vim to use this batch file to compile:
set makeprg=build.bat

Now from within Vim just type :make when your current directory (:cd) is the one containing the build.bat file, and your solution will build.

What about parsing out the errors? Easy:
set errorformat=\ %#%f(%l\\\,%c):\ %m

This tells Vim how to parse the error output.

Now if there are errors, hitting Enter will take you directly to the file and line where the first error occurred. :cn will take you to the next and :cp will take you to the previous. :cl will list all errors. Read :help quickfix.txt for more.

You could also use msbuild to compile your solution. The command for this is simply msbuild /nologo /v:q. It will find the .sln in the current directory and build it for you. However, with this command you have to modify your .csproj so that the error output includes full paths (otherwise the errorformat wont be able to parse it). To do that, just add the following line to the common PropertyGroup element of your .csproj:
<GenerateFullPaths>True</GenerateFullPaths>

The error format is the same as for devenv. But you don't need the build.bat (if you will always have only one solution in the directory at a time), instead you can use this:
set makeprg=msbuild\ /nologo\ /v:q

Now you can happily compile C# solutions and step through errors from right inside Vim.

If you don't like having to add the GenerateFullPaths node to your project file, you can add it to the msbuild command line instead as follows:
:set makeprg=msbuild\ /nologo\ /v:q\ /property:GenerateFullPaths=true

There is one more enhancement we can make. Vim has the ability to easily switch between compilers and set all the settings that the compiler needs as part of the switch. You can enable this by creating a "devenv.vim" file in vimfiles\compiler (on windows) containing the following code:
" Vim compiler file
" Compiler: DevEnv

if exists("current_compiler")
finish
endif
let current_compiler = "devenv"

if exists(":CompilerSet") != 2 " older Vim always used :setlocal
command -nargs=* CompilerSet setlocal <args>
endif

" default errorformat
CompilerSet errorformat=\ %#%f(%l\\\,%c):\ %m

" default make
CompilerSet makeprg=build.bat

To use this, just type :compiler devenv. Or, if you want Vim to always use this anytime you're editing a C# file (a file with a .cs extension) add the following to your _vimrc:
" setup C# building
if !exists("autocommands_loaded")
let autocommands_loaded = 1
autocmd BufNewFile,BufRead *.cs compiler devenv
endif

If you have any improvements to add, please let me know in the comments!

7 comments:

  1. Just curious is it possible to do quickwatch with this method? I see you can step through errors which logicaly means you can step through lines of code but without being able to check the value of variables i'm not sure that would help me.

    ReplyDelete
  2. You're asking if there's a way to integrate a debugger, at this time I don't know of a way to do it.

    After I detail the things that I can do in Vim, I'm going to list the things I can't. Debugging being prime among them.

    ReplyDelete
  3. Thanks for posting these articles, I'm just starting C# dev and was looking for a way do it within gvim. The errorformat you've got didn't work for me however (fyi, I'm using VS 2008). Instead I borrowed one that Mark Feeney published in one of his vim scripts. It's:
    set errorformat=%f(%l\\,%c):\ error\ CS%n:\ %m

    ReplyDelete
  4. Thanks, Jim. I'm using VS 2008 too, so I'm not sure why the error format wouldn't have worked for you.

    ReplyDelete
  5. Kevin,

    Thanks so much. I have been having a blast using vim lately. Your blog posts have been enormously helpful.

    There appears to be a typo in your post. The first error format has two "$" symbols. In the next error format those "$" are changed to "%".

    Hoping this saves someone else some head scratching.

    ReplyDelete
  6. Barnabas, thanks, you're right, it was a typo. I updated it so both cases are correctly using "%".

    ReplyDelete
  7. Actually, devenv loads VS, it just loads it in the background. In some cases that's the only way to compile, but these days using MSBuild usually works and avoids loading the environment which can be very slow.

    ReplyDelete

Note: Only a member of this blog may post a comment.