Kelly O'Hair's Weblog (blogs.sun.com)

pageicon Monday Feb 16, 2009

The pain of vcvars32.bat, and an ant solution

On Windows, and using Ant to do native compilations with Visual Studio requires certain environment variables to be set. So to be able to say "just run ant", you need to require the user to have set these properties before they start ant. The standard way to set them is with the script vcvars32.bat or vsvars32.bat. So how do you just make this work inside ant? You can't just call vcvars32.bat from your ant script, or can you?

Turns out that you can dip into a cmd.exe environment just long enough to run vcvars32.bat, print out the settings as a properties file and pop back out. As an example, see the file genVSproperties.bat. Of course, the \ characters need to be changed to /. This results in something like:


############################################################
# DO NOT EDIT: This is a generated file.
windows.vs.vsvars32.bat=C:/PROGRA~1/MICROS~2.NET//Common7/Tools/vsvars32.bat
windows.vs.VS71COMNTOOLS=C:/PROGRA~1/MICROS~2.NET//Common7/Tools/
windows.vs.DEVENVDIR=C:/Program Files/Microsoft Visual Studio .NET 2003/Common7/IDE
windows.vs.VCINSTALLDIR=C:/Program Files/Microsoft Visual Studio .NET 2003
windows.vs.VSINSTALLDIR=C:/Program Files/Microsoft Visual Studio .NET 2003/Common7/IDE
windows.vs.MSVCDIR=C:/Program Files/Microsoft Visual Studio .NET 2003/VC7
windows.vs.INCLUDE=C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/ATLMFC/INCLUDE;C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/INCLUDE;C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/PlatformSDK/include/prerelease;C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/PlatformSDK/include;C:/Program Files/Microsoft Visual Studio .NET 2003/SDK/v1.1/include;
windows.vs.LIB=C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/ATLMFC/LIB;C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/LIB;C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/PlatformSDK/lib/prerelease;C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/PlatformSDK/lib;C:/Program Files/Microsoft Visual Studio .NET 2003/SDK/v1.1/lib;
windows.vs.LIBPATH=
windows.vs.PATH=C:/Program Files/Microsoft Visual Studio .NET 2003/Common7/IDE;C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN;C:/Program Files/Microsoft Visual Studio .NET 2003/Common7/Tools;C:/Program Files/Microsoft Visual Studio .NET 2003/Common7/Tools/bin/prerelease;C:/Program Files/Microsoft Visual Studio .NET 2003/Common7/Tools/bin;C:/Program Files/Microsoft Visual Studio .NET 2003/SDK/v1.1/bin;C:/WINDOWS/Microsoft.NET/Framework/v1.1.4322;"C:/cygwin/bin;C:/cygwin/;c:/PROGRA~1/MICROS~2.NET/Common7/IDE;c:/PROGRA~1/MICROS~2.NET/Vc7/bin;c:/PROGRA~1/MICROS~2.NET/Common7/Tools;c:/PROGRA~1/MICROS~2.NET/Common7/Tools/Bin/prerelease;c:/PROGRA~1/MICROS~2.NET/Common7/Tools/Bin;c:/PROGRA~1/MICROS~2.NET/SDK/v1.1/bin;c:/PROGRA~1/Java/JDK16~1.0_1/bin;C:/cygwin/home/ohair/import/APACHE~1.1/bin;C:/cygwin/usr/local/bin;C:/cygwin/bin;C:/cygwin/bin;C:/cygwin/usr/X11R6/bin;C:/cygwin/usr/sbin;C:/cygwin/sbin;C:/cygwin/home/ohair/hgws/home_bin/bin;C:/cygwin/home/ohair/hgws/home_bin/bin/win32;C:/cygwin/home/ohair/bin;c:/WINDOWS/System32;c:/WINDOWS;c:/WINDOWS/System32/Wbem;C:/cygwin/lib/lapack";
############################################################

So in your ant build script you can effectively do this (on Windows only of course :^):


<target name="generate-vs-properties">
    <exec dir="." executable="cmd" output="vs.properties">
        <arg value="/q"/>
        <arg value="/c"/>
        <arg value="genVSproperties.bat"/>
    </exec>
    <replace file="vs.properties" token="\" value="/"/>
    <property file="vs.properties"/>
</target>

So now what? The last piece of the puzzle is that to need to set the environment variables when you run Visual Studio, e.g.


<property file="vs.properties"/>
<exec dir="." executable="${windows.vs.VS71COMNTOOLS}/../../Vc7/bin/cl.exe" failonerror="true">
  <env key="VS71COMNTOOLS" value="${windows.vs.VS71COMNTOOLS}"/>
  <env key="INCLUDE" value="${windows.vs.INCLUDE}"/>
  <env key="LIB" value="${windows.vs.LIB}"/>
  <env key="LIBPATH" value="${windows.vs.LIBPATH}"/>
  <env key="PATH" value="${windows.vs.PATH}"/>
  <arg line="${compile_options}"/>
</exec>

Hope this is helpful to someone.

-kto

Comments:

To pick a nit that is both trivial and important, in the last bit you are running the Microsoft C++ compiler (cl.exe), and not Visual Studio.

This is important, in that you *can* invoke Visual Studio to do builds from Ant - and I do. An old project uses Ant to VC6 (later versions of Visual Studio may differ).

<exec executable="msdev" failonerror="true">
<arg line='${msdev.workspace} /MAKE "RWPublisherComponents - Win32 Release"'/>
</exec>

(Don't know if the above will survive the comment processor.)

Posted by Preston L. Bannister on February 16, 2009 at 03:28 PM PST #

Valid point, msdev.exe and devenv.exe apparently don't need you to setup environment variables. But require you to create and save in your source repository the Visual Studio project file.

If using Visual Studio projects are acceptable, then life gets easier, but instead of being dependent on ant tasks and a C++ compiler, or a Makefile and a C++ compiler, you become dependent on Visual Studio.

Just depends on what is acceptable for your project.

-kto

Posted by Kelly Ohair on February 16, 2009 at 05:11 PM PST #

There is some advantage to using the IDE (or should be). For years I was using Makefiles (one for Windows, one for Unix) invoked from a build script (in Perl) in parallel to the IDE files. The build script used a trick similar to yours to extract variables produced by a run of vcvars32.bat.

I'd chosen to *avoid* using the IDE for the controlled builds, long ago, when IDE files were binary (so you could not use "diff" to audit changes). But MSVC switched to audit-able text project files, long ago, and I eventually ditched the Makefiles (on Windows) as a duplication of effort.

If the IDE is worth using (and it usually is), then constructing IDE project files is worthwhile, and separate Makefiles (or Ant scripts building C/C++ code) is a duplication of effort (and worse - a slightly larger risk that one or both are wrong). Minimising the difference between your development and controlled builds is a good thing.

Which is the consideration that got me to switch, finally. :)

Posted by Preston L. Bannister on February 16, 2009 at 06:15 PM PST #

Very valid points. One way to build is extremely important, and if the IDE is used and used regularly by the development team, then using project file builds would indeed be the best way.

But just because the project files are text files doesn't make you independent from the how the IDE behaves and where it leaves the build artifacts.

Now if we had some kind of standard xml IDE project file format... ;^)

-kto

Posted by Kelly Ohair on February 16, 2009 at 06:26 PM PST #

Post a Comment:
Comments are closed for this entry.