Automatically generate build number based on timestamp with WiX 3.6 - visual-studio-2010

I found a number of ways to automatically increment build numbers with Team build setup environments, but none of them are satisfying for me, because I have a C++ MFC application where most of the approaches won't work.
So I thought about another solution, that might work for our team (since it is not that big):
I want to have a build number like this:
$(major).$(minor).$(buildnumber) <!-- where buildnumber is like YYMMDDHHMM -->
I think $(major) and $(minor) can be set using preprocessor variables from the command line (or pre-build tasks like grepping them from a file and putting them into variables), but the build number is the one that should be unique based on the build.
This approach would work for each developer on his local machine as well as in the CI environment (TFS in our case).
Is there a way to achieve this? Or is there another idea to automatically generate increased build numbers (not necesarrily based on a timestamp) I did not see yet?

The implementation of this requirement involves two parts:
1) The build automation generating a ProductVerion property
2) The build automation passing this property into the WiX build.
For #1, I like to use TFS Versioning but there are many solutions out there that will do what you want.
For #2, I put code like this in the .wixproj:
<PropertyGroup>
<MSIProductVersion Condition=" '$(MSIProductVersion)' == '' ">0.1.0</MSIProductVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DefineConstants>Debug;WiXProductVersion=$(MSIProductVersion)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DefineConstants>WiXProductVersion=$(MSIProductVersion)</DefineConstants>
</PropertyGroup>
In the actual wxs I do this:
<Product Id="*" Name="IsWiX" Language="1033" Version="$(var.WiXProductVersion)"
Manufacturer="ISWIX LLC" UpgradeCode="some upgrade code">
<Package InstallerVersion="200" Compressed="yes" />
The concept is TFS passes in MSIProductVersion and this gets passed into the compiler and mapped to the Version attribute. For local developer builds the MSI just get's 0.1.0 as the version ( a good indicator that it's not an official build ).

I solved it using the "verbuild.exe" utility found here
Follow steps from that page:
Create initial version header file: verbuild <version header file> -c
Create a resource (.rc) file that:
Includes the header file from step 1
Includes the changes to replace proper versions in the .rc file using those from the header file (e.g., VERSION_FILE)
Change build to call verbuild to update the build number before building the projet:
I run a batch file to increment the build number: verbuild <version header file> %1 -xFP

Related

How to build wix toolset project?

I've installed Wix Toolset 3.11.0.1528 and extension for VS 2015 0.9.17.13693
After pressing build I get:
The WiX Toolset v4 build tools must be installed to build this project. To download WiX Toolset v4 visit ...
I don't get it. I have version 3.11 installed and it wants v4. I don't want to build anything from source.
What should I do to make it use available WiX version?
Bit of a necro post but if anyone finds it helpful, well then, good.
Edit the XML as pointed out above by replacing the namespace from v4 to the v3 one.
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"/>
Then edit the proj file of your setup and remove the reference to the WIX target path.
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\WiX Toolset\v4\wix.targets</WixTargetsPath>
Finally, replace the import and target tags with the 3.11 version of the code.
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
<Error Text="The WiX Toolset v3.11 (or newer) build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
</Target>
Ah. Ok. At VS project manager (or whatever they call it), when you add New project, you have two almost identical choices:
Setup project - A project for creating an MSI file
Setup project - A project fro creating a WiX based XML MSI file
So the first one uses <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" ...
And the second one: <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" ...
The second one fails. And just changing this url doesn't help.
Choose the first variant and just use it.

Sequentially build configurations in Visual Studio without MSBuild or plugins?

MSDN describes how to create a batch build, but does not provide a way to automate different batches (and one click solution for the GUI)
This question describes conditionally invoking a second build but doesn't appear to suffice for more than two sequential configurations
This question addresses the same situation, but again only for two configurations
In my test case, each configuration:
defines its own MACROS (which impact source code)
is applicable to multiple projects (class libraries). The projects are interdependent and require a specific build order in the context of the current configuration
I would like visual studio to build multiple configurations sequentially with a single build command.
Can child configurations be nested under a parent configuration, and be executed sequentially by visual studio when the parent configuration is built?
UPDATE : ATTEMPTED SOLUTION 1 [2016-03-11]
In response to Stijn's suggested answer I've tried the following:
Setup DotNetFramework 4.5 WinForms solution with 3 test projects and with 6 Configurations:
CORE_DEBUG
CORE_RELEASE
EXTENDED_DEBUG
EXTENDED_RELEASE
Debug
Release
The Debug Configuration must:
NOT trigger it's own configuration build (i.e. 'Debug')
must trigger the CORE_DEBUG and EXTENDED_DEBUG Configurations in sequence
I've added the following modified target to the first project's project file:
<Target Name="AfterBuild" Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
Building with the 'Debug' Configuration now, causes an EXTENDED_RELEASE build to trigger. Having a look at the solution file, I see that Visual Studio decided to automatically link 'Debug' to 'EXTENDED_RELEASE':
{4F9706AA-26A9-483C-81C4-22E301C54C89}.Debug|Any CPU.ActiveCfg = EXTENDED_RELEASE|Any CPU
{4F9706AA-26A9-483C-81C4-22E301C54C89}.Debug|Any CPU.Build.0 = EXTENDED_RELEASE|Any CPU
Removing the above two lines from the solution file doesn't help, since Visual Studio just regenerates them. In summary this now has two undesirable outcomes:
Visual Studio executes a 'Debug' build for Project1
Visual Studio then executes an 'EXTENDED_RELEASE' for Project2 and Project3
Conclusion: While this approach can work, it also (first) performs debug and release configuration builds respectively. Visual Studio
also lists all 6 Configurations in the build menu (we only want Debug
and Release to be visible, and behind the scenes Debug must trigger
CORE_DEBUG and EXTENDED_DEBUG, and Release must trigger CORE_RELEASE
and EXTENDED_RELEASE)
UPDATE : ATTEMPTED SOLUTION 2 [2016-03-16]
Moving on to a makefile project solution: I've created a makefile project as specified by stijn's answer below, and it worked perfectly!
Conclusion : This is the preferred solution in my opinion because it gives the user the most power and ability to control exactly how the build(s) must be executed and how the configurations must be handled.
The principle of the second SO question can be adjusted to build more than one configuration/platform sequentially by just invoking MsBuild multiple times. For instance:
<Target Name="AfterBuild" Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<MSBuild Projects="$(MySolution)" Properties="Configuration=Release;Platform=x86"/>
<MSBuild Projects="$(MySolution)" Properties="Configuration=Debug;Platform=x64"/>
<MSBuild Projects="$(MySolution)" Properties="Configuration=Release;Platform=x64"/>
</Target>
This can be cleaned up by using item batching, removing the condition and instead automatically determining which config is invoked and then only building the others etc but that's a bit out of scope here.
I'm not really convinced doing this in an AfterBuild target is the best way though, because then you'd need to adjust one of your 'normal' projects to also trigger a build of everything else. An alternative is to add a MakeFile Project to your solution, set up it's dependencies so that it comes last in the build order (at least if that is what you need), and set it's command line to invoke msbuild in a way similar as described above. You can even keep all logic in the same project file: set the 'Build Command Line' to
msbuild $(MsBuildThisFile) /t:CustomBuild /p:Configuration=$(Configuration);Platform=$(Platform)
so building the project will 'recurse' and make it call itself again with the same properties as called with by VS, but executing the CustomBuild target where you can then build your other projects/solutions to taste.
EDIT re: update
You're almost there, but you have to go to Configuration Manager and make sure the configurations are setup properly to begin with. From the start:
create new solution, add 3 projects
right-click solution, select Configuration Manager
in the Active solution configuration combobox select new
enter CORE_DEBUG for name, select DEBUG under Copy settings from and make sure the Create new project configurations is checked like
repeat for other configurations
for EXTENDED_RELEASE for instance, it should now look like
you probably did most of this already, but somehow Debug got assigned to EXTENDED_RELEASE somehow so that is one thing you should fix; you could do that by editing the solution manually but instead of removing lines you'd have to edit them to be correct else VS just adds them again, as you noticed
Now open first project in a text editor and near the end of the file where AfterBuild is already inserted but commented out, add
<ItemGroup>
<Configurations Condition="'$(Configuration)'=='Debug'" Include="CORE_DEBUG;EXTENDED_DEBUG" />
<Configurations Condition="'$(Configuration)'=='Release'" Include="CORE_RELEASE;EXTENDED_RELEASE" />
<Projects Include="$(SolutionDir)WindowsFormsApplication1.csproj;$(SolutionDir)WindowsFormsApplication2.csproj;$(SolutionDir)WindowsFormsApplication3.csproj" />
</ItemGroup>
<Target Name="AfterBuild" Condition="'#(Configurations)' != ''">
<Message Text="Projects=#(Projects) Configuration=%(Configurations.Identity)" />
<MSBuild Projects="#(Projects)" Targets="Build" Properties="Configuration=%(Configurations.Identity)" />
</Target>
you might need to adjust the paths to the projects. This will build CORE_DEBUG and EXTENDED_DEBUG for Debug builds, and likewise for Release builds. AfterBuild is skipped when the Configurations ItemGroup is empty, i.e. when not building Debug or Release which is exactly the point.
EDIT re: makefile
You can specify multiple commands for the makefile commandline. Click the arrow next to the 'Build Command Line' box and select '' To be sure you have everything right, Configuration Manager has to be set up to only build the makefile project for Debug/Release like:
and the makefile project's commandline looks like
Alternatively, and I'd prefer this myself, you create an msbuild file with the same content as above:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Configurations Condition="'$(Configuration)'=='Debug'" Include="CORE_DEBUG;EXTENDED_DEBUG" />
<Configurations Condition="'$(Configuration)'=='Release'" Include="CORE_RELEASE;EXTENDED_RELEASE" />
<Projects Include="$(SolutionDir)WindowsFormsApplication1.csproj;$(SolutionDir)WindowsFormsApplication2.csproj;$(SolutionDir)WindowsFormsApplication3.csproj" />
</ItemGroup>
<Target Name="Build" Condition="'#(Configurations)' != ''">
<Message Text="Projects=#(Projects) Configuration=%(Configurations.Identity)" />
<MSBuild Projects="#(Projects)" Targets="Build" Properties="Configuration=%(Configurations.Identity)" />
</Target>
</Project>
and your makefile command then invokes that file like
msbuild /path/to/msbuildfile /t:Build /p:Configuration=Debug;SolutionDir=$(SolutionDir)

Determine whether it's a build or rebuild in .cmd script called in prelink step inside Visual Studio

How can a .cmd script run from within a Visual Studio (2005, 2008, 2010, 2012 and 2013 respectively) project's pre-link stage determine whether this is a full rebuild (Build.RebuildSolution/Build.RebuildOnlyProject) or "ordinary" build (Build.BuildSolution/Build.BuildOnlyProject)?
This is an external script (LuaJIT, if you must know) and I don't want to rebuild the library every single build of the project. Instead I'd like to limit the complete rebuild to situations where I choose exactly that option.
How can a .cmd script run from within a Visual Studio (2005, 2008, 2010, 2012 and 2013 respectively) project's pre-link stage determine whether this is a full rebuild ... or "ordinary" build ... ?
I do not know if the exact thing that you are asking can be done - perhaps someone else knows how to do it. I will, however, suggest an alternate approach.
My approach is to remove the build of the Lua library from the pre-link step to a separate Visual Studio NMake project. If you create an NMake project, you will be able to know which type of build (build or rebuild) is occurring.
Note that later versions of Visual Studio simply refer to the project type as "Make". For discussion purposes here, I will refer to the project type as "NMake". I believe this is just a naming difference, and that the underlying build project remains the same between the two versions.
As a simple test, I created two Visual Studio applications: 1) an NMake project that calls a batch file to create a static library, and 2) a console application that consumes the library from step 1.
The NMake Project
In Visual Studio, if you create a new NMake project, you will see a dialog that allows you to provide MS-DOS commands:
As you can see, there are commands for: Build, Clean, Rebuild, and others. I don't have a screen shot of the above dialog with my commands, but here is my NMake project's properties:
My Build command just checks for the existence of the output file (lua.lib). If it does not exist, then it calls the rebuild.bat batch file. My Rebuild command always calls the batch file. My Clean command just deletes the output. I am not really sure what the Output command is used for, but I just filled in the path to the build output (lua.lib).
Now if you do a build, the lua.lib file will only be created if it is not there. If it is already there, nothing is done. If you do a rebuild, then a new lua.lib file is created.
The Console Application
In my console application, I added a reference to the NMake project - this way the NMake project is built prior to the console application. Here is the console application's reference page:
I also added the lua.lib file as an input during the application's link stage:
When the console application is built (during a build), it will build the NMake project if needed, and use the output (lua.lib) during the linker stage. When the console application is rebuilt (during a rebuild), it will also rebuild the NMake project.
Other Thoughts
My screen shots above only show the debug version of the properties. Your projects will have to account for the release version. There probably is a VS macro to handle this, but I am not sure since it has been ages since I've done anything with C/ C++.
In my testing above I use a single build batch file for both the build and rebuild. Obviously, you could do the same or you could use different batch files.
It may be a bit of a hack, but in .csproj file there are sections
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
You can set an variable from BeforeBuild and retrieve it from cmd script. Later on reset this variable in AfterBuild and you should be good to go.
Ok, this is going to be a long one.
First of all - do not take my code 'as is' - it is terrible one with lots of hacks, I had no idea msbuild is so broken by default (it seems at work I have access to waaaay more commands that make life easier). And another thing - it seems vcxproj is broken at some poin - I was not able to integrate the way I wanted with only BeforeRebuild and AfterRebuild targets - I had to redefine hole Rebuild target (it is located in C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets)
So, the idea is the following: when a Rebuild is happening we create an anchor. Then, during PreLink stage we execute cmd which is able to use created anchor. If the anchor is in place - we deal with Rebuild, if there is no anchor - it is a simple Build. After Rebuild is done - we delete the anchor.
modifications in vcxproj file:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
....
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
....
<PreLinkEventUseInBuild>true</PreLinkEventUseInBuild>
....
</PropertyGroup>
....
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
.....
<PreLinkEvent>
<Command>D:\PreLink\b.cmd</Command>
</PreLinkEvent>
.....
</ItemDefinitionGroup>
.....
<Target Name="BeforeRebuild">
<Exec Command="echo 2 > D:\PreLink\2.txt" />
</Target>
<Target Name="AfterRebuild">
<Exec Command="del D:\PreLink\2.txt" />
</Target>
<!-- This was copied from MS file -->
<PropertyGroup>
<_ProjectDefaultTargets Condition="'$(MSBuildProjectDefaultTargets)' != ''">$(MSBuildProjectDefaultTargets)</_ProjectDefaultTargets>
<_ProjectDefaultTargets Condition="'$(MSBuildProjectDefaultTargets)' == ''">Build</_ProjectDefaultTargets>
<RebuildDependsOn>
BeforeRebuild;
Clean;
$(_ProjectDefaultTargets);
AfterRebuild;
</RebuildDependsOn>
<RebuildDependsOn Condition=" '$(MSBuildProjectDefaultTargets)' == 'Rebuild' " >
BeforeRebuild;
Clean;
Build;
AfterRebuild;
</RebuildDependsOn>
</PropertyGroup>
<Target
Name="Rebuild"
Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
DependsOnTargets="$(RebuildDependsOn)"
Returns="$(TargetPath)"/>
<!-- End of copy -->
</Project>
And the cmd looks like this:
if exist 2.txt (
echo Rebuild818181
) else (
echo Build12312312
)
The output from Output window:
1>Task "Exec" (TaskId:41)
1> Task Parameter:Command=D:\PreLink\b.cmd
1> :VCEnd (TaskId:41)
1> Build12312312 (TaskId:41)
Things to improve:
Use normal variables instead of external file (it seems MsBuild extension pack should do it)
Probably find a way to override only BeforeRebuild and AfterRebuild instead of the hole Rebuild part
It is much easier. Just add the following target to your build file or visual Studio Project
<Target Name="AfterRebuild">
<Message Text="AFTER REBUILD" Importance="High" />
<!--
Do whatever Needs to be done on Rebuild - as the message shows in VS Output
window it is only executed when an explicit rebuild is triggered
-->
</Target>
If you want a two step solution use this as a template:
<PropertyGroup>
<IsRebuild>false</IsRebuild>
</PropertyGroup>
<Target Name="BeforeRebuild">
<Message Text="BEFORE REBUILD" Importance="High" />
<PropertyGroup>
<IsRebuild>true</IsRebuild>
</PropertyGroup>
</Target>
<Target Name="BeforeBuild">
<Message Text="BEFORE BUILD: IsRebuild: $(IsRebuild)" Importance="High" />
</Target>

Automate VS 2010 "Publish" Config File Substitutions

I'm using the config file replacement feature of Visual Studio 2010's "Publish" functionality, as described in this article. I want to automate this using MSBuild/Hudson. Does anybody know how to do this?
I like how it works but if I cannot automate it I'll have to switch to XmlMassUpdate or similar.
Explanation
To transform your config file you'll have to execute the TransformWebConfig target.
This target takes two files Web.config and Web.$(Configuration).config and generates a Web.config. The generated file is the transformed version of the original one for the current configuration.
This file is generated in folder : obj\$(Configuration)\TransformWebConfig
Usage
You don't really explain what you want to achieve, so here a basic usage, a job that generates a transformed config file in a given folder.
Add the following piece in the end of your project file *.csproj after the import of Microsoft.WebApplication.targets
<PropertyGroup>
<!-- Directory where your web.config will be copied -->
<TransformedWebConfigDestination>$(MSBuildProjectDirectory)</TransformedWebConfigDestination>
</PropertyGroup>
<!--
This target transforms the web.config based on current configuration and
put the transformed files in $(TransformedWebConfigDestination) folder
-->
<Target Name="ConfigSubstitution">
<CallTarget Targets="TransformWebConfig"/>
<ItemGroup>
<TransformedWebConfig Include="obj\$(Configuration)\TransformWebConfig\Web.config"/>
</ItemGroup>
<!-- Copy the transformed web.config to the configured destination -->
<Copy SourceFiles="#(TransformedWebConfig)"
DestinationFolder="$(TransformedWebConfigDestination)"/>
</Target>
In Hudson you could add a Build step in your build, or create a dedicated job configured as follow:
MsBuild Build File : Your csproj file.
Command Line Arguments : /t:ConfigSubstitution /p:Platform=AnyCpu;Configuration=Test;TransformedWebConfigDestination=DestinationFolder
Edit your web project.csproj
under
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
Add -
<UseMsDeployExe>True</UseMsDeployExe>
Look at the Build output (make sure VS Tools - Options - Project & Solutions -Build & Run - MSBuild Output Verbosity - Detailed)
You should be able to see the msdeploy commands VS uses to produce the package. It's my understanding that VS actually uses Web Platform Pipeline API's and .target files to actually produce the deploy packages when building using MSBuild, and this command changes to use MsDeploy instead.
This stuff is so in need of documentation, its very frustrating.
I am using this in Hudson to target Release:
/Property:Configuration=Release
The exact settings are:
Build
MSBuild Version: msbuild-4 (configured to point to v4 msbuild)
MsBuild Build File: project_name.sln
Command Line Arguments: /Property:Configuration=Release
You can test this in your project directory by running something similar (as your .NET framework version may differ) to this:
%SYSTEMROOT%\Microsoft.NET\Framework\v4.0.30319\msbuild project.sln /Property:Configuration=Release

How can I use a single Visual Studio solution to build both x86 and x64 at the same time?

I've got an x86 Visual Studio solution with many project files in it. Some of the DLL files are designed to work as plug-ins to other applications on a user's system.
We're expanding some of the DLL files to be able to support 64-bit applications. I'd like to set up the solution/projects so that just hitting "Build" will build both the x86 and x64 versions of those DLL
files. The solution contains both C++ and C# projects.
I realize that "Batch Build" is capable of building both, though it would be more convenient if developers could just click the same button as they have previously and have all of the output DLL files generated.
Here are a couple of the modifications that I've tried to a test project, but that I haven't gotten to work:
I've tried modifying the <Target Name="AfterBuild"> to try:
<Target Name="AfterBuild" Condition=" '$(Platform)' == 'x86' ">
<PropertyGroup>
<Platform>x64</Platform>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<CallTarget Targets="Build"/>
</Target>
But that results in the following error:
C:\Windows\Microsoft.NET\Framework\v3.5\Microsoft.Common.targets(565,5): error MSB4006: There is a circular dependency in the target dependency graph involving target "Build".
I think my conditions will prevent infinite recursion, but I understand how MSBuild could not see it that way.
I've also tried:
<Project DefaultTargets="MyBuild86;MyBuild64" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
...
<Target Name="MyBuild86">
<PropertyGroup>
<Platform>x86</Platform>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<CallTarget Targets="Build"/>
</Target>
<Target Name="MyBuild64">
<PropertyGroup>
<Platform>x64</Platform>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<CallTarget Targets="Build"/>
</Target>
But my DefaultTargets appears to be ignored from within the Visual Studio IDE.
Last, I've tried creating a separate project that imports the first project:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform>x64</Platform>
<PlatformTarget>x64</PlatformTarget>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<OutputPath>..\$(Configuration)\x64\</OutputPath>
<ProjectGuid>{A885CAC3-2BBE-4808-B470-5B8D482CFF0A}</ProjectGuid>
</PropertyGroup>
<Import Project="BuildTest.csproj" />
</Project>
And this so far has shown the most promise. However, Visual Studio seems to ignore my OutputPath setting from this new project and instead outputs the EXE/DLL file to the path specified in the original project. There isn't any PropertyGroup block that I can see that is being executed in the original project to override this, so I'm not sure what's happening.
We do something similar to build core assemblies for .NET Compact Framework.
Try this:
<Target Name="AfterBuild">
<MSBuild Condition=" '$(Platform)' == 'x86' " Projects="$(MSBuildProjectFile)" Properties="Platform=x64;PlatFormTarget=x64" RunEachTargetSeparately="true" />
</Target>
Importing a project in such manner works for me in Visual Studio 2010:
TestProject64.vcxproj
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="TestProject.vcxproj" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B7D61F1C-B413-4768-8BDB-31FD464AD053}</ProjectGuid>
</PropertyGroup>
</Project>
TestProject64.vcxproj.filters
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="TestProject.vcxproj.filters" />
</Project>
TestProject.vcxproj has two configurations defined inside: Release|x86 and Release|x64. As you can see, TestProject64.vcxproj has only the Release|x64 configuration. Defining of at least one configuration in TestProject64.vcxproj is necessary, otherwise Visual Studio will not be able to add TestProject64.vcxproj to a solution.
Now it's possible to include both TestProject.vcxproj and TestProject64.vcxproj to the same solution and build Release|x86 and Release|x64 at the same time.
I think the best way of doing this is to invoke MSBuild from the command line. It shouldn't need editing of MSBuild files. Just run
msbuild myproj.sln /p:Configuration="Debug|Win32"
msbuild myproj.sln /p:Configuration="Debug|x64"
I assume that if a developer is using Visual Studio then they'll only be generating the DLL files so they can debug with them, and that you have a separate build process if you're actually deploying the DLL files.
For C++, and if it's a project whose files/settings don't change often, one way to do it is create two projects within the solution, with both projects referring to the same source files. Then, in x64 builds, set one project to build 64-bit and the other 32-bit. (In x86 builds, set one as 32-bit and turn off the other.)
We've been using this for a while and it works fine.
Of course, you have to be careful that any changes you make to one are also made to its copy. i.e. if you add/remove a file or change its build setting, you have to do it in two places. Source-code changes still only need to be done once, because there's still only one copy of each source file.
And, of course, you may decide that doing this is more complex/risky than switching away from using the IDE. In our case it's worked really well, though.
You are not going to be able to do this with the UI of Visual Studio. For this you will need to hack the MSBuild files.
Try this link from MSDN for MSBuild Overview
I would suggest to create a dummy C++ Makefile project and then invoke MSBuild twice from it:
msbuild myproj.sln /p:Configuration="Debug|Win32"
msbuild myproj.sln /p:Configuration="Debug|x64"
Perhaps I've missed the point of this discussion.
Using Visual Studio, go to menu Build → Configuration Manager. In the Active Solution Platform drop down, select "New...", and a New Solution Platform dialog appears. Select x64 and accept the default Copy From. Close the dialog and the Configuration Manager.
Now open menu Build → Batch Build. Check those configurations you want to build and build them. You will find the x64 build executables separate from the Win32 executable files.
You can verify that these are what was intended by right clicking on the executable files, selecting Properties, and select the Compatibility tab. In the dropdown window you can check to see what operating systems the executable file can be run in.
Obviously, there may be some other tweaking you might have to do to get all the output files in their proper places, but this method seem somewhat simpler than fooling with build than those described above.
I ran into this problem with a project running in Visual Studio 2008 (on Windows XP) (32-bit) and also Visual Studio 2010 (on Windows 7) (64-bit).
The solution I used was to use the $(PROGRAMFILES) variable. It resolved correctly on both machines.

Resources