Coder Social home page Coder Social logo

cecil-msbuild-helper's Introduction

Cross-TFM Mono.Cecil assembly resolver and reflection/metadata importer

One common use of Mono.Cecil is in tools that run as part of the build process to apply some kind of post-processing to the output assembly. Such tools may be implemented as standalone console applications invoked from some suitable target with <Exec> or as MSBuild tasks (the latter approach is tricky because of limitations in how MSBuild handles task assembly dependencies, but this does not concern me here). Post-processing often involves examining or adding code to the output assembly, and this in turn necessitates importing type, method and field references into it. This can become complicated because the output assembly, its dependencies that may have to be examined by the post-processor, and the post-processor itself may all belong to different target frameworks (TFMs). Framework types such as System.Threading.Tasks.Task or System.IO.Stream will exist in different metadata scopes. The default implementations of IMetadataImporter and IReflectionImporter are not aware of this, and will end up creating references that make no sense in the context of the assembly being post-processed, such as mscorlib!System.IO.Stream in a netcoreapp3.1 output assembly. In addition, post-processing tools may have trouble finding the files for referenced assemblies, as the process used by MSBuild is complex and poorly documented.

This repository provides a helper class which solves most of these problems. It relies on the list of referenced assemblies created by MSBuild's compilation targets to find the assembly files and to handle both mixed-TFM dependencies (when dependencies of the assembly being post-processed belong to different TFMs) and cross-TFM operation (when the TFM the tool is running in differs from the TFM of the assembly being post-processed). The importer implementations follow type forwarders in facade assemblies which MSBuild's ResolveAssemblyReferences task adds to the list of references in mixed-TFM scenarios to produce metadata references which are valid in the post-processed assembly. The reflection importer handles cross-TFM imports by mapping framework types to netstandard prior to applying the mixed-TFM import logic. The assembly resolver looks up assembly files using the MSBuild reference list and thus has access to the same assemblies as the compiler does.

The helper can be used in both standalone tools and MSBuild tasks. For standalone tools, you will have to pass the list of assembly paths and fusion names collected by MSBuild in ReferencePath items to your tool through the command line or a temporary file. MSBuild tasks can take the items directly as a task property; in this case, define the WITH_MSBUILD_FRAMEWORK preprocessor constant in your tool project and use the constructor taking ITaskItem[].

Caution

In mixed-TFM scenarios, post-processing tools must keep TypeReference and other member references that belong to different modules strictly separate and never compare them, use them as dictionary keys, field types, base classes and so on, until imported into the assembly that is being post-processed. Type or member references from different modules to what are logically the same member will refer to different metadata scopes and will not compare equal, which is usually not the desired behavior. Cecil's assembly writer does not automatically import member references coming from different modules and will write the metadata scope as-is, potentially creating invalid references in the assembly being post-processed. Always import references into your target module before using them in or around it. Code that does not follow this rule will work while all inputs belong to the same or compatible TFMs, but will break in more or less unpredictable ways in cross- and/or mixed-TFM scenarios.

Limitations

  • Requires Mono.Cecil 0.10 or later (for jbevain/cecil#470).

  • The reflection importer currently requires that a netstandard reference be present, either added explicitly to compilation inputs as a Reference item, or via one of the (transitively closed) dependencies being netstandard.

  • The helper detects facade assemblies by content because MSBuild does not always set the Facade metadata on ReferencePath items, and there appears to be no custom attribute distinguishing facade assemblies.

References

jbevain/cecil#487, jbevain/cecil#505, jbevain/cecil#526

cecil-msbuild-helper's People

Contributors

atykhyy avatar

Watchers

 avatar

cecil-msbuild-helper's Issues

Netstandard not available in .net framework projects

Hi! Thank you for contributing this helper :)

I am trying to use your helper to solve some assembly resolving issues we have when using Mono.Cecil on Xamarin projects. Your resolver solved our problems, however we can now no longer resolve .NET framework projects due to netstandard not being in the list of referenced assemblies. I was wondering if you had some guidance as to how to overcome this problem.

For reference we are implementing your assembly resolver here: stryker-mutator/stryker-net#1770
The .NET framework test project that is failing is here: https://github.com/stryker-mutator/stryker-net/tree/master/integrationtest/TargetProjects/NetFramework

The list of referenced assemblies as we get them from Buildalyzer (msbuild wrapper basically) is:

C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\Microsoft.CSharp.dll
C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\mscorlib.dll
C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Core.dll
C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Data.DataSetExtensions.dll
C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Data.dll
C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.dll
C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Net.Http.dll
C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Xml.dll
C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Xml.Linq.dll
C:\\git\\stryker\\stryker-net\\integrationtest\\TargetProjects\\NetFramework\\packages\\Newtonsoft.Json.13.0.1\\lib\\net45\\Newtonsoft.Json.dll

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.