msbuild, multiple projects and dependency resolution - msbuild

I have solution that consists of 10 projects. Each project has a test assembly (making 20 projects).
Currently, my build script builds all the test assemblies, then runs all the tests, great.
Except that each test assembly references 2 or more of the core assemblies (directly and indirectly), which means there is lots of redundant building going on.
How can I simplify things (without reducing number of assemblies) to speed up the build?
I guess I could build each project directly without resolving the inter-project references and bung it all in a single output dir, but how do i still resolve the other references projects have to 3rd aprty ddls etc.
Other suggestions?
thanks

I am working on a tool to automate the build process it is still on development and it's open source here is the link:
https://github.com/jupaol/NCastor
To speed up your build you could try to build in parallel your projects:
http://geekswithblogs.net/deadlydog/archive/2012/03/30/parallel-msbuild-ftwndashbuild-faster-in-parallel.aspx
http://www.hanselman.com/blog/FasterBuildsWithMSBuildUsingParallelBuildsAndMulticoreCPUs.aspx
To force MSBuild to use a single output directory:
<BuildProperties>
Configuration=$(Configuration);
Platform=$(Platform);
OutputPath=$(BuildingPath);
$(BuildProperties);
</BuildProperties>
<MSBuild Projects="$(FullSolutionFilePath)" Properties="$(BuildProperties);" Targets="ReBuild"/>

Can you build the referenced assemblies first, copy them to a "Common" folder, and have the "Common" folder assemblies referenced in the using projects as "Referenced Libraries"?
We do this with our CompanyName.Enterprise libraries and it works fine. They get built once or twice a year and the projects using them build daily.

Related

How can I set the build destination in Team Services for WIX

I am using Windows installer xml and now my project moves to Team Services.
However, my Paths wont work anymore and I need to update my setup.
On the local build machine I used this hardlink: C:\Projects\Solution\Project\bin\Release\Assembly.dll
My Question: What is the best way to build 4 projects and then run a 5th project, which uses the assemblies in the bin/release directory?
Add a reference to the project and then use $(var.Project.TargetPath) instead of the hardlink (or $(var.Project.TargetDir)Assembly.dll). The references will add dependencies on those projects to the wixproj which means they all must be build before the wixproj so all the binaries will exist. All the projects should be included in the same solution as the wixproj.
Here's a resource for all the automatically defined compile time variables you can use http://wixtoolset.org/documentation/manual/v3/votive/votive_project_references.html
Alternatively if you can't do it this way you can define the variables in the <DefineConstants> of the wixproj. It would be something like "ProjectDir=$(MSBuildThisFileDirectory)..\Project\bin\Release\" and then in your wix component where you are using the SourceDir hardlink you would use SourceDir=$(var.ProjectDir)Assembly.dll
All of this stuff is taking advantage of MSBuild. It takes a long time to wrap your head around how MSBuild works but it is definitely worth it if you will be using Visual Studio to build all your projects.

Indirect references in VB.NET solution breaking build

Project A references Projects B. Project B references Project C. Project A does not reference Project C.
This builds fine locally. However, on the build server it errors out because Project A does not reference Project C.
Error:
error BC30009: Reference required to assembly 'ProjectC, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' containing the implemented interface 'ProjectC.IFoo'. Add one to your project.
How can I catch this before committing?
Edit:
Here's more info on my issue: http://sstjean.blogspot.com/2006/11/msbuild-cant-find-secondary-references.html
Here are two things you can do as a best practice to ensure your projects are referenced correctly and MSBuild will be able to find your referenced projects correctly.
Use project references instead of referencing dll's. Create a folder called dependencies or libs and place any referenced dll's within this folder.
Check the build order and project dependencies tab for each project by right clicking project and selecting project build order. Ensure that every reference in your project is being built by that project.
MSBuild does not know what a .sln file is. MSBuild reads and parses the .sln file to determine the build order of projects. By having project references MSBuild will be able to traverse and build the projects in the correct order. See below link for more information.
This link also helps explain why you would see different behavior and how to catch it.
Visual Studio Integration (MSBuild)
Within Visual Studio, the solution file and project build ordering are controlled by Visual Studio itself. When building a solution with msbuild.exe on the command line, MSBuild parses the solution file and orders the project builds. In both cases the projects are built individually in dependency order, and project to project references are not traversed. In contrast, when individual projects are built with msbuild.exe, project to project references are traversed.
When building inside Visual Studio, the property $(BuildingInsideVisualStudio) is set to true. This can be used in your project or .targets files to cause the build to behave differently.
Go to your project references and right click Oracle.DataAccess then go to properties and in properties page make sure that specific version is false and copy to local is set to true.

MSBuild and .CsProjects

I am using MSbuild for CI tool and have many C# projects located in different directories. There many dependents projects as well. Some developers use Add Project option to add project and some directly connect to .dll file and i have no control over it. some cases all projects added to a solution So if i compile that solution then it takes care of all dependencies. But i do not this in my auto build. I want to compile all .csproj and output .dlls to a particular folder and then all projects including web should point to this folder for reference.
Want to know if this a ideal process?
In my Project we do the same and it works. Sometimes we have project references and sometimes we have direct dlls references in a folder called "Solution DLLs".
How we do it:
The reason is that we have many projects (120 or more) and we have split them in several solutions. One of the solutions is for framework and commmon dlls. These Dlls are copied in postbuild scripts to a "Solutions Dlls" folder and checked in in TFS. Later our build scripts copy these solutions dlls...
How it works:
It works "fine" and is acceptable. But many problems came (and sometimes still come) with postbuild scripts not working fine. We are aiming to reduce the number of csprojs to 50-60 and use again one single solution.

Team Build - Replace Project References with dll's

Following Situation:
2 Team Projects
Dvelop of Team Project A added Project References of Team Project B to their projects.
For speeding up the Build I want to replace the project references with referencing the dll's directly.
My Idea:
in the csproj of Team Project A:
<ProjectReference Condition="'$(IsDesktopBuild)' == 'true'" Include="[Project Reference] >...
in the TFSBuild.proj
<AdditionalReferencePath Include="[buildoutputOfTeamProjectB]" />
OR
Disable SolutionToBuild and use the csproj files directly.
Thanks for your suggestions.
I would suggest that each project have a dependencies folder that contains the appropriate dlls that are required for each project. When a project that is depended upon is built it would be up to you to automatically update the dll in the dependencies folder or not via your build process (cruise control/nant/msbuild?). However, I would also give some consideration around deploying versions of the depended upon dll just in case you blow up the dependent projects usage of that dll. It would suck for someone to update their project (the depended on project), kick off a build, deploy their build output to the dependent project) only to break the project that relies on their code base. That sounds like a fragile way of managing dependencies.

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.