Skip to content

ResolveAssemblyReference

Kirill Osenkov edited this page Dec 16, 2016 · 21 revisions

One of the most important tasks in the MSBuild toolset is ResolveAssemblyReference (RAR). Its purpose is to take all the references specified in .csproj files (or elsewhere) via the item and map them to paths to assembly files on disk. The compiler only can accept a .dll path on disk as a reference, so ResolveAssemblyReference converts strings like mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 to paths like C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\mscorlib.dll which are then passed to the compiler via the /r switch.

Additionally RAR determines a closure of all .dll/exe references recursively, and for each of them determines whether it should be copied to the build output directory or not. It doesn't do the actual copying (that is handled later, after the actual compile step), but it prepares an item list of files to copy.

RAR is invoked from the ResolveAssemblyReferences target: image

If you notice the ordering, ResolveAssemblyReferences is happening before Compile, and CopyFilesToOutputDirectory happens after Compile (obviously).

Inputs

RAR is very detailed about logging its inputs: image The Parameters node is standard for all tasks, but additionally RAR logs its own set of information under Inputs (which is basically the same as under Parameters but structured differently). RAR logs this information in a method called LogInputs(): https://github.com/Microsoft/msbuild/blob/xplat/src/XMakeTasks/AssemblyDependency/ResolveAssemblyReference.cs#L1249

The most important inputs are Assemblies and AssemblyFiles:

    

http://source.roslyn.io/#MSBuildFiles/C/ProgramFiles(x86)/MSBuild/14.0/bin_/amd64/Microsoft.Common.CurrentVersion.targets,1820

Assemblies is just using the contents of the Reference MSBuild item at the moment when RAR is invoked for the project. All the metadata/assembly references, including your NuGet references, go here. Each reference has a rich set of metadata attached to it: image

AssemblyFiles comes from ResolveProjectReference output item called _ResolvedProjectReferencePaths'. ResolveProjectReferenceruns before RAR and it converts items to paths of built assemblies on disk. So theAssemblyFiles` will contain the assemblies built by all referenced projects of the current project: image

Another useful input is the boolean FindDependencies parameter which takes its value from the _FindDependencies property:

FindDependencies="$(_FindDependencies)"

You can set this property to false in your build to turn off analyzing indirect dependency assemblies.

Execution

The source code of the main Execute() method can be found in MSBuild source code on GitHub: https://github.com/Microsoft/msbuild/blob/xplat/src/XMakeTasks/AssemblyDependency/ResolveAssemblyReference.cs#L1877

The algorithm simplified is:

...
Line 1923: LogInputs();
...
// useful environment variable to set to crank up detailed search result logging
Line 1930: _logVerboseSearchResults = Environment.GetEnvironmentVariable("MSBUILDLOGVERBOSERARSEARCHRESULTS") != null;
...
Line 2087: ReferenceTable dependencyTable = new ReferenceTable(...) // main data structure
...
Line 2052: ReadStateFile(); // read the cache file from the `obj` directory if present
...
Line 2182: dependencyTable.ComputeClosure(allRemappedAssemblies, _assemblyFiles, _assemblyNames, generalResolutionExceptions);
...
Line 2213: // Build the output tables.
           dependencyTable.GetReferenceItems
           (
               out _resolvedFiles,
               out _resolvedDependencyFiles,
               out _relatedFiles,
               out _satelliteFiles,
               out _serializationAssemblyFiles,
               out _scatterFiles,
               out _copyLocalFiles
           );
...
Line 2274: WriteStateFile(); // write the cache file to the `obj` directory
...
Line 2284: LogResults();
...

Clone this wiki locally