Building from the command line: devenv /build


Greetings, dear readers!  Today I want
to talk about using devenv.exe to build a solution or project from the command line
(as opposed to interactively inside the IDE).  For
example, you can say “devenv /build debug myapp.sln” to do a debug build of myapp.sln.  Now,
I have to admit that if there was one feature I could deny any association with, it
would be this one.  There are many things
about this feature that are harder to understand and use than they should be.  (In
my defense I can say that this feature took its current form before I took over this
area!)  Rest assured, however, that we’re
working to make some improvements in this space for Whidbey.

"urn:schemas-microsoft-com:office:office" />
 

A number of users don’t even know this feature exists.  But
it’s very handy.  If you want to build
a solution or project from a build script then this lets you do it.  Just
type “devenv /?” from the command line to see what you can do.  You
can also see the documentation
page
for a full list of supported switches.  I’m
going to focus on the /build switch, but much of what I’m going to say also applies
to /clean, /rebuild, and /deploy.  And
I’m using VS 2003 but most of these comments should also apply to VS 2002.

 

A key to understanding this feature is to understand the relationship between solution
configurations & project configurations.  See
my blog
entry from 8/14/03
for more on that.

 

The most basic operation with devenv /build is to build a whole solution configuration.  This
is pretty easy.  If you have a solution
called myapp.sln, and it has a configuration called “Debug” (which it normally would
by default), then you can build it by typing “devenv /build debug myapp.sln”.  This
should give you the same result as if you opened up the IDE, picked that solution
configuration, and did Build.Build Solution.  (Note
that you can only build one solution, and one solution configuration, at a time.  If
you need to build more than one, use a batch file to wrap your calls to devenv.exe.)

 

Another thing you can do is operate on one project at a time.  If
you have myapp.sln that contains proj1.vcproj and proj2.vcproj, you might only want
to build one project at a time, without having to define a separate solution configuration.  If
you want to do this, understand that you still have to specify a solution configuration
to give the build proper context.  This
is because some things, like project-to-project references, need a solution configuration
context in which to be resolved properly.  Therefore
the syntax to build just proj1.vcproj in the solution’s debug configuration would
be:

 

devenv /build debug /project proj1 myapp.sln

 

This basically says: “Build the debug configuration of myapp.sln, and only include
the project proj1 in the build.”

 

When using the /project switch to specify a specific project to build, you can only
specify one project at a time.  If you
pass the /project switch multiple times, the last one wins & the prior /project
switches are ignored.  If you want to
build a certain set of more than one project, you should define a separate solution
configuration.

 

Another thing you can do when building just one project is specify a particular project
configuration to be built.  Let’s say
I wanted to build just proj1.vcproj again, but this time with the release configuration
– and just for fun, using the debug configuration of the solution!  I
can do it like this:

 

            devenv
/build debug /project proj1 /projectconfig “release|.net” myapp.sln

 

The switch we’ve added is /projectconfig, followed by the value of “release|.net”.   Why
the funny syntax with “|” instead of just “release”?  The
trick here is that the configuration of a project includes not only things like debug/release,
but also the platform you’re targeting.  Ordinarily,
VB & C# project target the platform “.NET” and VC++ targets the platform “Win32”
(even for managed C++, which is confusing).  But
if you buy, say, a version of VC++ that targets Win64, that’s another platform choice.  So,
just remember than when using the /projectconfig switch you need to add “|” followed
by the platform the project targets (which you can see in the Configuration
Manager dialog
under Build.Configuration Manager).

 

We hope to make many aspects of “devenv /build” a little easier to use in the next
major release, but hopefully this information will make this feature less mystifying
for the next time you want to use it.

 

That’s all for now! -Chris

Comments (23)

  1. jeff clausius says:

    chris:

    good article. its amazing the number of people who do not use automated builds in their development process, and rely on a manual build from within the ide.

    any professional developer wanting to save themselves from bugs, frustration, and a bit of time should re-read this article and then take a look at the continuous integration solutions available for .net.

    my $0.02.
    -jeff

  2. Chris Flaat says:

    Thanks for the comments, Jeff! -Chris

  3. Toby Jones says:

    Hi Chris,

    We love this feature at our company, but it does have some drawbacks for us. The problem is that the configuration manager requires unique solution configurations for every possible configuration, regardless of whether configurations are related or not.

    In my work, I’ll deal with several types of configurations: release, debug, profile build, unicode/mbcs, managed/unmanaged, xbox/pc, inline assembly/unoptimized C, etc. Some of these are truly unique configurations, requiring differing compiler options, etc. However, some are really just toggling a flag (unicode/mbcs for example). Each of these toggled flags requires twice the number of configurations. And when one of the configurations changes, all of the variants need to be changed.

    What we could really use is a way to pass preprocessor vars through devenv.

    There are a couple of solutions I’ve used for this at various times. One is to use makefiles, which bypasses the problem entirely. The other solution was to write a bunch of COM code to interface the DTE and its friends and add the preprocessor macros we want at the time.

    Neither of these is a fun solution, and it’d be cool if you could comment why this evolved the way it did.

    -Toby

  4. David Levine says:

    Hi Chris,

    It’s nice to see a blog about build related issues, devenv, and one that focuses on technical issues…thanks.

    I’ve a question or two for you about DTE and automated building. I’ve taken the BuildIt sources and modified it extensively. In our solution I need to identify those projects that are web services so that prior to starting the build I can set the IIS virtual directory to local path mapping correctly for the solution being built. The best I’ve been able to come up with is that I extract the URL property value from the project, and if I can resolve it to an URI http scheme (http://) I assume it’s a web project. Is there a better way to detect this, and is this reliable?

    Related to this is where the VSWebCache is located. I need to delete this if I change the IIS vdir mapping so that devenv does not query for the correct path for the webservice project. It stores this info in the webcache. The best I’ve come up with is when I identify a webservice project I examine the LocalPath property value – this appears to point to the webcache. Is this correct?

    What is the distinction between the ActiveFileSharePath and the FileSharePath? I’ve been using these as a sanity check to make sure the LocalPath is not the same as one of these, so I don’t accidentally delete any source files.

    I know these are a lot of questions…any help you can provide is appreciated. Thanks.

    Dave

  5. Chris Flaat says:

    For a response to Toby’s questions, see my blog entry from 9/5/03 titled "More on configurations".
    David’s questions are outside my domain of expertise, and I recommended to him that he post his questions on the microsoft.public.* newsgroups.
    -Chris

  6. Steve Hiner says:

    You mention /Clean
    Does that mean I can use "devenv /Clean MySolution.sln" and it will purge all the obj files and stuff?

    I’d LOVE to be able to do that before zipping up the project when I’m taking it home – it would shrink my zip file by about 75%.

  7. Dave Schwinn says:

    This is neat.

    You might consider adding a read-only field to the solution and project properties dialogs in the IDE that build this comand line sting for me.

  8. Les Arnott says:

    I have a mutli project solution and there are times I want to build only the debug builds or only the release builds. I need the functionality of the VS6 /MAKE switch and it would seem the VS7 /BUILD switch would do the job. But, try building with "/build debug" and it still builds all configurations. Am I missing something or is the VS6 functionality no longer supported?

  9. Dan [ms] says:

    As regards "/clean" – this only works for the C++ projects in your solution. It won’t error for VB or C# projects, but it won’t do anything either. But some amazing oversight, there is actually a Clean menu option for C# in VS 2003, but it does nothing.
    Yes, all this will be fixed in Whidbey. Everybody will have Clean. In the meantime, I just do "del /s *.obj & del /s *.exe & del /s *.dll"…

  10. Cyril says:

    Just a remark, I proposed this solution for our test server…
    But my boss returns me that we can’t install VS .NET on the test server… Another ideas to simply build the solution without using VS.NET’s scripts?
    Thanx

  11. AsbjornM says:

    You could use NAnt instead of VS.NET, I have had some struggles with it, but with an minimal buildfile it is very easy. I don’t know about limitations for this method yet but anyways, create an config file like this:

    <project name="SomeProject" default="Debug">
    <target name="Debug">
    <property name="current.runtime.config" value="net" />
    <property name="current.runtime.version" value="1.1" />
    <property name="current.runtime.description" value="Microsoft .NET Framework 1.1" />
    <property name="nant.settings.currentframework" value="${current.runtime.config}-${current.runtime.version}" />
    <solution configuration="debug" solutionfile="Solution1.sln" />
    </target>
    </project>

    Change the third last line in this buildfile to point to the correct sln file for getting this to work (works with NAnt 0.8.3)
    Nant is here: http://sourceforge.net/projects/nant

  12. Mark says:

    We’ve been using command line builds for quite a while with our automated builds. However, there is an extreme annoyance with some solutions: the solution builds just like we want; then we get the dreaded "MS Dev Environment has encountered a problem and needs to close" dialog. This wouldn’t be too bad, except it stops our automated build dead in its tracks.

    Is there a chance you know of special command-line flags or some trick that could help us around this problem? (We’ve tried /safemode; recreating the solutions; etc.)

    Thanks.

  13. sanath says:

    Quick Question. Can anyone tell me how to make set precompiler directives when using devenv from the command line? We have a base directive and a cust directive.. Is it possible to set these directives from the command line directly? thanks, – Sanath

  14. JHankins says:

    If you right-click on a project in your "Solution Explorer", and choose "Project Only", then you can build a particular project without building its dependancies.

    Is there any way to build only one project from the command line?

  15. mitesh says:

    Good Article which solved my purpose indirectly.

    I wanted to build a ATL Minsize project in release mode. And I was finding a solution for it.

    We can use the switch in following way:

    devenv build "release MinSize" "solution name".

    here "release MinSize" option can be provided or not can be checked out, by opening the solution file in notepad and at the end just checkout the valid build configuration for your project.

    Cheers

    Mitesh

  16. Dev says:

    Good article, and timely given the problem I’m working on right now. I have a bunch of VB.NET projects that were configured horribly in terms of easily getting the stuff to build in a development environment, so I’m trying to clean things up in the near future to make life easier.

    After realizing (to my horror) that unlike C#, VB.NET doesn’t offer pre/post build events, I got one working with the VS.NET automation model. This works great… the next step was getting a simple batch file to invoke VS.NET and run the full build via the command line. However I need to insure my post-build macro is loaded each time, so I wanted to use the /command MyMacro.Foo switch to pass in along with the /build switch.

    Unfortunately, I get:

    "Not enough storage is available to complete this operation."

    At which point it starts the build, but the build step macro doesn’t get invoked and I’m hosed. Is there any possible way to work around this? Any help is appreciated.

    Thanks,

    Kris

  17. Dan Libby says:

    I have been using command line builds in an automated script for about 6 months now. It has more or less worked (after considerable experimentation). The biggest problems I have had:

    – For some reason it feels the need to popup the GUI when building. This is annoying / distracting / seemingly unnecessary.

    – Sometimes VS gets into a weird state where it decides it needs to install some sort of help/documentation. It requires user input to continue/cancel (via the GUI it has unnecessarily popped up). This is not acceptable in an automated environment. It needs to either generate an error message to stderr or continue.

  18. RB says:

    Have been using this for a while. The one thing I hate (or maybe I am doing it wrong) is that you cannot get your code to a new location and build an ASP .Net project within your solution with the binaries going to the new location, rather than the web folder. I do not see why the act of compiling is linked to a web site or virtual folder.

    Using Nant of course makes life a lot easier.

  19. Peter says:

    When we use IDE to build a project, we have the file(s) checked-out, and IDE will build the changes (checked-out files), will command build do so? I.e. do I need to check in my changes in order to build them? If so, then that’s a big drawback for command build.

    Thanks,

    Peter