You know sometimes it’s just sad how fast time can go by. Looking back it’s been well over a year maybe two since I last blogged. WOW, that’s not cool. So what the hell happened, well LIFE I guess. Let’s see:
Regardless a lot has happened and it’s time to talk technology again. I love it and really miss doing it. With all of the great stuff here upon us now, it’s time to start sharing. I was reading MSDN Magazine the other day when I ran across an article about MSBuild and best practices which really got me thinking. There were two items that really stuck out for me:
While both were explained pretty well, lets put #2 into practice. *I’M LAZY* ( in a good way of course ). I would much rather write something once rather than screw with it time and time again, especially the stuff you have to do like build work.
So lets talk assembly references….
Assembly references can be easy as you want it to be but sometimes a little prep work will go a long way. The .NET compilers and runtime both have a specific order in which they look for references. If you look in your framework folder for Microsoft.Common.Targets you will find the following:
The SearchPaths property is set to find assemblies in the following order: Files from current project - indicated by {CandidateAssemblyFiles} $(ReferencePath) - the reference path property, which comes from the .USER file. The hintpath from the referenced item itself, indicated by {HintPathFromItem}. The directory of MSBuild's "target" runtime from GetFrameworkPath. The "target" runtime folder is the folder of the runtime that MSBuild is a part of. Registered assembly folders, indicated by {Registry:*,*,*} Legacy registered assembly folders, indicated by {AssemblyFolders} Look in the application's output folder (like bin\debug) Resolve to the GAC. Treat the reference's Include as if it were a real file name.
The SearchPaths property is set to find assemblies in the following order:
So what if your not one of those nine?!?!?
Since it’s all just angle brackets we can extend the “out of the box” search paths. As it was explained in the article you can override the property AssemblySearchPaths. Aaron had a great post on MSBuild Property Evaluation, it’s something you should read. Overriding a property is as simple as importing your own target file into the stack and then resetting the property ( for most cases ). You could also just add a the same property further down the stack in the same file. Both are essentially the same. With MSBuild the *stack is always important*. If you were to import your target file or override a property to early you might change the way the entire build system works. There are a number of properties that work like:
This is a very common practice throughout MSBuild implementations. As you can tell it’s just a way or protecting yourself from a change in behavior upstream. Remember MSBuild parses top down to you have no influence what might be done afterwards. In our case what we want to do is import our targets file after the Microsoft.Common.Targets file in the csproj or vbproj file(s).
*NEW*
By doing so AssemblySearchPaths will be “” and initialize itself as expected. So if we want to add to it it’s as simple as ( snip from MyTargets.Targets ):
.... $(AssemblySearchPaths); C:\binaries\; ....
....
$(AssemblySearchPaths); C:\binaries\; ....
Important point, Reference Paths are folders not files. So now if you compile from the cmd line or from VS you will have your paths in the stack. The easiest way to see what is going in is to simply run msbuild.exe /t:rebuild /v:diag on your sln file. That will dump everything that took place during the execution from MSBuild. Even the order of folders it searched for. You will actually be able to see the reference pats listed that it couldn't find.
But we are not done yet. We have a hardcoded path and remember, I’m lazy. How about we bootstrap ourselves into the build process and read the file system building the search paths based on a “root” folder you specify? Then any machine should work without any change.
$(SolutionDir)..\MyBinaries\**\*.* $(AssemblySearchPaths); @(binariesFound->'%(RootDir)%(Directory)');
Important points:
Team Build has a similar concept but much easier. At the bottom of any tfsbuild.proj fiile there is a commented collection called AdditionalReferencePath. It works the same it’s just that the Team Build process does it all for you already.
Powered by: newtelligence dasBlog 2.3.9074.18820
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
E-mail
Theme design by Jelle Druyts