Would it be possible to add a build property holding the name of the MsBuild arguments file that one could pass on to recursive calls to MsBuild?
We have a pretty complex environment that needs to be configured before our build can be run. The setup is handled by a script which developers use to get a command-line for each project's workspace. The solution we're using with TeamCity, since we cannot set all of the properties inside the MsBuild script itself, is to launch MsBuild via a launcher script which runs the setup first. Since TeamCity doesn't allow one to override the executable of MsBuild, we came up with an alternative solution:
1. Build using Build.bootstrap.proj instead of Build.proj.
2. Build.bootstrap.proj will call Build.proj using an exec task which runs the setup script first.
3. Pass the target(s) we want to build as a property instead of using the target box in TeamCity.
This works rather well. However, TeamCity has a whole lot of very interesting properties that get passed to the initial MsBuild process that we want to utilize in the child process. We found out that TeamCity generates a temporary file holding all of those properties as MsBuild command line switches, so we manually pass that on to any child build. However, since the name of the file (Build.bootstrap.proj.teamcity.msbuild.tcargs) is not exposed in a property we have to hard code it and I would really prefer to have an "official" name for the file instead, to avoid problems should the name change or the location move with future versions of TeamCity.
The alternative would be to pass properties manually for each step, but that would be error prone and require modifications to the build script whenever we add properties to the build, or want to utilize some new TeamCity feature.
Here's the bootstrapper file we use:
<?xml version="1.0" encoding="UTF-8"?>
<Project DefaultTargets="BootStrap" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<BuildMode Condition="'$(BuildMode)' == ''">ReBuild</BuildMode>
<BuildFile Condition="'$(BuildFile)' == ''">$(_DEVROOT)\Code\Build.proj </BuildFile>
<TeamCityArgs>@$(MSBuildProjectDirectory)\TeamCity.BootStrap.proj.teamcity.msbuild.tcargs</TeamCityArgs><!-- It would be nice not having to hard-code this-->
<Exec Command="msbuild35.cmd $(MSBuildProjectFullPath) /t:Build $(MSBuildArgs) $(TeamCityArgs)"/>
<Exec Command="$(_COMMONROOT)\msbuild35f.cmd $(BuildFile) /t:$(BuildMode) /p:CCNetLabel=$(build_number) $(MSBuildArgs) $(TeamCityArgs)"/>
The script normally has more tasks, which require the dual recursive call, but I removed them to isolate the proceedure we use. The msbuildxxx.cmd file are part of the checked out files for each project.