1
votes

We have a solution that we would like built against two architectures (x86 and x64) and put in the same folder on build. The solution has four projects, three of which we are outputting as AnyCPU, since they are called by the fourth project and thus will take on whatever bitness it is running under.

I have already gone into the csproj file and changed it like so:

  <Choose>
    <When Condition=" '$(Platform)'=='x64' ">
        <PropertyGroup>
            <AssemblyName>TaskLoaderHost64</AssemblyName>
        </PropertyGroup>
    </When>
    <When Condition=" '$(Platform)'=='x86' ">
        <PropertyGroup>
            <AssemblyName>TaskLoaderHost32</AssemblyName>
        </PropertyGroup>
    </When>
  </Choose>

Additionally I set the OutputPath for all cominations of Platform and Configuration to \bin\Debug or \bin\Release (removing the architecture portion). When building in Visual Studio, I set Architecture to x86, build taskloaderhost project, set to x64, build, and in the bin\debug folder I have one copy each of the three AnyCPU project outputs and one each of x86 and x64 TaskLoaderHost outputs. This is exactly what I want. Everything in the same folder.

Moving this to TFS, I created a Build Definition that builds the TaskLoaderHost project in both x86 and x64 flavors. And instead of the above, I get the following at the drop location root.

\ \logs \x64 \x64\Debug \x86 \x86\Debug

Where did the extra directories come from? Specifying OutDir in MSBuildArguments does nothing, and TFS seems to ignore the OutputPath property (but it does read the Assembly Name property) from the csproj file.

Anyone know a way to force it to put output from two different architectures in the same directory?

Interesting Fact

If you do not specify OutputPath in the project file, TFS complains about the fact that it is undefined, and refuses to output it. If you do specify it, TFS does not use that value in the Drop location filesystem structure.

1

1 Answers

1
votes

I found the following article on MSDN that describes how this can be done, and I have it working on my TFS Build Server. It is written against TFS 2010, but works well enough for 2012 as well.

Control Where the Build System Places Your Binaries

Essentially what you do is edit the BuildTemplate and Project definitions (csproj/vbproj/etc) that are being built.

In the Build Template, edit the Run MSBuild found at this location: Process > Sequence > Run On Agent > Try Compile Test and Associate Changesets and Work Items> Sequence > Compile, Test, and Associate Changesets and Work Items > Try Compile and Test > Compile and Test > For Each Configuration in BuildSettings.PlatformConfigurations > Compile and Test for configuration > If BuildSettings.HasProjectsToBuild > For Each Project in BuildSettings.ProjectsToBuild > Try to Compile the Project > Compile the Project > Run MSBuild for Project.

Remove the value in the OutDir property, and put the following into the CommandLineArguments property: String.Format("/p:SkipInvalidConfigurations=true;TeamBuildOutDir=""{0}"" {1}", BinariesDirectory, MSBuildArguments)

Finally place the following after the other conditional property groups in your Project file:

<PropertyGroup Condition="$(TeamBuildOutDir) != '' ">
<OutputPath>$(TeamBuildOutDir)\$(SolutionName)\$(MSBuildProjectName)\$(Configuration)</OutputPath>
</PropertyGroup>

I changed the OutputPath on mine a little. Since I am building a single project which has the other projects as dependencies, I only had to put the above PropertyGroup in a single project file.