Problems with MSBuild OutputPath and OutDir in TFS2010 - msbuild

We have a very large solution (some 300+) projects and we are trying to build it via MSBuild on TFS2010.
We can build it via MSBuild on all out development machines, and are in the process of adopting TFS.
The structure of our code is like so:
bin\Client
bin\Server
Framework\ClientFramework.csproj
Modules\Module1\Project1
Modules\Module2\Project2
etc.
Each project has a relative OutputPath which builds the code to the bin Client or Server directory. So for example, Project1.csproj has an OutputPath of "..\..\bin\Client".
We seem to be having a problem that in TFS MSBuild the OutDir is set to a Fixed Path:
C:\Builds\MyProject\Binaries\
So things are getting confusing when resolving the relative OutputPath on top of the OutDir
ClientFramework goes to C:\Builds\MyProject\Binaries\..\bin\Client
Project1 goes to C:\Builds\MyProject\Binaries\..\..\bin\Client
etc.
We also have some Post build events that copy some 3rd Party dll's to the bin folders, these paths cannot be resolved properly either.
I think the solution we are after is to build everything to our existing bin\Client, bin\Server structure and then move the Folders from bin to Binaries.
Any ideas on how to accomplish this or how we should be working, are appreciated, but updating our existing projects might prove problematic, as it all works with VS, developer command line builds and with CC.net.

Since this is first link that pops up with a Google search of "TFS OutDir", I must provide a newer solution. I spent an entire day playing around with OutDir, OutputPath, and overriding them with TeamBuildOutDir. A better solution is to set the MSBuild property GenerateProjectSpecificOutputFolder. It comes with .NET 4.5. More info here: http://blog.codeassassin.com/2012/05/10/override-the-tfs-team-build-outdir-property-net-4-5/

I found the answer on MSDN : http://msdn.microsoft.com/en-us/library/ff977206.aspx

Related

MSBuild - Can I build for a Build Configuration without a solution?

I want to build a project with a particular named Build Configuration, let's call it Conf-A.
This is running as an MSBuild step on TeamCity. When the build runs, it spits out:
The OutputPath property is not set for project ... You may be seeing this message because you are trying to build a project without a solution file, and have specified a non-default Configuration or Platform that doesn't exist for this project.
This project is part of a hulking great solution we load on our dev machines.
The error makes sense for my situation, since I'm building just the proj file, but I don't want to use the solution file since I'm trying break-up this monolithic app.
I want the build-server to treat this project as it's own component, even if for the moment it is part of a solution and has references to other projects (assemblies) in the solution.
Must I build this via a solution file?
I could potentially copy the solution file and prune off all the other projects that are not required, but that's more complexity.
(Maybe the error is a red-herring).
you dont need to build a sln. Its like the error says. You just havent specified a value for the variable OutputPath in your msbuild. You can add it to your files or you can pass it in at the cmd line - msbuild someproj.proj /p:OutputPath=C:\notallovermydrive

MSBuild task does not build solution file

I have a project file that should build another solution. I tried using the MSBuild task for this, like this:
<MSBuild Projects="MySolution.sln" Properties="Configuration=$(Configuration)"/>
I tried a lot of variants, like supplying hardcoded configuration, target Rebuild and so on. Building reports an error when I pass a wrong solution name, non-existing configuration or target and so on, so it definitely loads the solution and the project files. It exits relatively fast though and produces no output. According to documentation and examples, this should work though. I also tried passing an ItemGroup for the project, including project-specific properties as suggested by examples or in MSBuild - How to build a .NET solution file (in an XML task script) from pre-written command line commands , but that does not work either. It runs without error but no output.
When passing a list of project files instead (or a single project file), it builds correctly, but the problem is that dependencies between the projects are not properly resolved. At the end, I have to supply all project files in the solution and add them to the list, which is what I want to avoid.
So, why does solution building not work, even though it should? What is wrong here?
Is this a .net project? If so you probably need to pass in a platform as well as a configuration.
<MSBuild
Projects="MySolution.sln"
Targets="build"
Properties="Configuration=$(Configuration);Platform=$(Platform)" />
If the project just contains web sites and libraries then the platform should be Any CPU if your solution just contains executables then x86 or x64 or if it's a mixture of different types of platform then you can use mixed platforms
To check what are available open the solution in Visual Studio, right click on the solution in solution explorer and select "Configuration Manager" you'll then have a drop down for "Active Solution Platforms"

What parameters does TeamCity pass to MSBuild under the covers?

I just downloaded TeamCity 7 today and decided to get it up and running for my Azure solution. I am not trying to do anything fancy (yet) and started with a very basic command line build:
msbuild /t:Publish /p:Configuration=Release;TargetProfile=Production;PublishDir=S:\HoursTracker\Deployments
This builds successfully and produces a package that looks like this*:
I then attempted to configure TeamCity in an identical fashion:
This builds successfully and produces a package that looks like this*:
What I don't understand is why there is such a huge discrepancy in the size of the MVC project. Publishing directly from Visual Studio produces the exact same result as my MSBuild command so I'm convinced that TeamCity is the odd man out. Since I assume TeamCity is not broken, can someone please educate me on how to properly configure it so that I get the expected output?
*I have renamed the package files with .zip so that the details were viewable for this post.
Ming's answer helped me solve the mystery. After inspecting the contents of the zip files, I discovered the difference was that my MSBuild package contained bin and obj folders and the TeamCity package did not.
After making this discovery, I realized that I could specify multiple targets to MSBuild and prepended "Clean" to my targets switch like so:
msbuild /t:Clean;Publish /p:Configuration=Release;TargetProfile=Production;PublishDir=S:\HoursTracker\Deployments
As expected, this removed those folders. So apparently, TeamCity specifies "Clean" implicitly for you. Mystery solved.
Windows Azure packages may be larger than we expect. You can rename the cssx file to zip and you will find out what’s inside the package. In addition to the web application’s usual files, there’re a bunch of Windows Azure files. For example, if you enable diagnostics, you will see a diagnostics folder, where you’ll find files used by Windows Azure diagnostics runtime.
Best Regards,
Ming Xu.
Why you specified x64 for msbuild runner? Try selecting tools version as well. You have not specified /p:Platform parameter. Does publish task involve rebuild?
TeamCity starts msbuild with number of /p: parameters taken from " properties and environment variables " section, plus some well-known parameters like configuration name or project name.

MSBuild target _CopyWebApplication does not copy all necessary files to the bin folder

Elsewhere on the Web, you can find recommendations on using something like this to simulate the Publish feature in the VS 2005-2008 IDE from a command-line (I hope I did not goof up the syntax!):
msbuild /t:ResolveReferences;_CopyWebApplication /p:BuildingProject=true;OutDir=C:\inetpub\wwwroot\ blah.csproj
Now, it looks like the .dll's copy fine. However, there are certain configuration files and template files that are copied to the bin folder which are needed for the app to work. For example, an NHibernate configuration file shows up in blah.csproj as:
<None Include="blah.cfg.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
While using Publish from within the IDE copies this file as it should, the aforementioned _CopyWebApplication target does not. I need this file to be copied in the build script. Is this desired behavior for _CopyWebApplication? Any recommendations on how to fix this?
EDIT 4/21/2010:
Let me clarify that we are limited (for now) to VS 2005 and VS 2008 projects, and that our build scripts are written for MSBuild 3.x. We are not yet ready to move to VS 2010.
Let me also specify that we are looking for a solution available from within a command line so that we can automate a Publish-like command along with custom build options, and possibly automate deployments down the road.
This is just a workaround.
In the build script for publishing Web sites, after running MSBuild on the Web project itself to publish it (Targets="ResolveReferences;_CopyWebApplication"), I added a copy operation:
<Copy SourceFiles="#(ProjectBinFiles)" DestinationFolder="$(StageBin)\%(ProjectBinFiles.RecursiveDir)" />
where ProjectBinFiles is an Item representing the files in the bin directory in the source directory, and StageBin is a Property representing the bin folder in the published site's directory. So far, it seems to work.
I was having a similar issue as well. I think the answer is using MSDeploy. Investigating it now, but may provide functionality required...
I had this same issue in VS 2012 and eventually fixed it by doing the following to any files which needed to be copied:
Set the Copy to Output file property to Copy if newer
Set the Build Action file property to Content (or Compile if the file needs to be compiled)

MSBuild overwriting dependencies

Ok, so I've got a somewhat complicated problem with my build environment that I'm trying to deal with.
I have a solution file that contains multiple C# projects which is built by a NAnt script calling MSBuild - passing MSBuild the name of the solution file and a path to copy the binaries to. This is because I want my automated build environment (CruiseControl.Net) to create a folder named after the revision of each build - this way I can easily go back to previous binaries for any reason.
So idealy I have a folder layout like this
c:\build\nightly\rev1
c:\build\nightly\rev2
c:\build\nightly\rev3
...
c:\build\nightly\rev10
etc.
The problem that's arisen is I recently added the latest version of the Unity IoC container to my project, checking it directly out of MS's online SVN repository. What's happening is I have a Silverlight 3 project that references the Silverlight version of Unity but I also have other projects (namely my Unit testing project) that reference the standard (non-Silverlight) version of Unity.
So what happens is since MSBuild is dumping everything into one single folder the Silverlight version of the Unity assembly is overwriting the non-Silverlight version because they have the exact same assembly file name.
Then when CruistControl runs my unit tests they fail because they don't have the proper dependencies available anymore (they try to load the Silverlight specific Unity assembly which obviously doesn't work).
So what I want to do is:
keep my desired output directory
structure (folder\revision)
I don't want to have to manually edit
every single proj file I have as this
is error prone when adding new
projects to the solution
Idealy I would like MSBuild to put everything into a folder structure similar to this:
nightly\revision1\project1
nightly\revision1\project2
nightly\revision1\project3
...
nightly\revision2\project1
nightly\revision2\project2
nightly\revision2\project3
etc
I can't modify the Unity project to give it a different file name because it comes from another SVN repository I cannot commit changes to. I found a similar question posted here and the suggested solution was to use a "master" MSBuild file that used a custom task to extract all the project file names out of the solution then loop over each one building them. I tried that but it doesn't build them in the order of their dependencies, so it fails for my project.
Help?
Firstly I would always have the build server delete the old working copy and check out a fresh copy to avoid any problems with stale artifacts from the previous build.
Next I would have nant or msbuild build the solutions as before with the artifacts from each build going to their local working output folders.
After that I'd move the artifacts from their working paths to their output paths, this shouldn't require digging through the project files since you can just tell msbuild/nant to copy working\project1\bin\release\**\*.* to artifacts\project1\.
The script that does this should ideally be stored along with the source with the main file, e.g. build.nant or build.proj in top level of the trunk.
For third party libraries I would simple include the DLLs directory in your repository. Nothing worse than writing some code and having a third party dependency break your build because of changes on their end.
Simply document the versions of the libraries you are using, and if you must update them, you'll have a better sense of what breaks the build before you even check it in.
Also, doesn't CC.Net automatically handle the providing of releases based on revision? I'm using TeamCity and it keeps a copy of the artifacts of every build.
I highly recommend reading JP Boodhoo's Automating Builds with NAnt blog series. That's been my starting point and have made lots of changes for my own taste. I also highly recommend checking out the builds of many open sources projects for examples. I've learned a lot from the builds of the Castle/Nhibernate/Rhino-Tools stack.