Winforms: Use -refout to auto generate ref assemblies

Created on 6 Dec 2018  路  17Comments  路  Source: dotnet/winforms

Instead of having separate 'ref' projects in the solution, use -refout to generate ref assemblies automatically from src assemblies.

Details: https://github.com/dotnet/roslyn/blob/233957b90f555c731f8e22b5319bb7e869567580/docs/features/refout.md

enhancement

Most helpful comment

Indeed the CoreFX tooling for reference assemblies was designed without consulting the compiler team. As a result it turned out they made a variety of decisions that caused their reference assemblies to be observably different from there implementation assemblies. This caused a deal of customer confusion as subtle changes to their build caused them to silently switch between reference + implementation assemblies and as a result get different compilation results.

Concrete example:

Guid g; 
Console.WriteLine(g.ToString());

Does this compile or not? The answer is, frustratingly, it depends because of choices the CoreFX team made in reference assembly generation.

The refout and refonly compiler features are designed to produce reference assemblies that have complete fidelity for compiling with the implementation assembly. I strongly suggest you use that if possible for generating reference assemblies.

Note: we have worked with the CoreFX team and addressed many of the tooling issues. Hence it should be less of an issue going forward. But you can still run into version compat issues as the language evolves. That can't happen with refonly and refout.

All 17 comments

Starting a discussion here after talking about this issue with @ericstj

If we make this change to -refout, we will only have the ref dll's; not the ref source.

Reasons we might want ref sources:

  1. You have a nice concise record of the public API that can be reviewed by API design
  2. It forces you to make concious changes to public API and consider if they are breaking.
  3. It allows you to make some changes only in the reference or implementation (like adding an obsolete attribute, or having publics that aren't exposed to the public).
  4. ability to run the build implementation in parallel (this may not be a huge gain for us as we have relatively few assemblies)

in particular, we should note benefit 3.

if we used the /t:GenerateReferenceSource option, we could rebuild reference from source when necessary (giving us the same benefits of the -refout flag) but still allowing us to have these benefits because we have the reference source

I really like 2 and 3. Especially 2. If forces us to manually recognize public api changes instead of being able to forget and the build just goes on as normal.

We also IMHO 'ought to start including apicompat as part of our public builds here. if the reference is incompatible with the implementation, our build should fail. @AdamYoblick do you agree? I can create an issue and try to add it as a step to our process 馃槃

Yeah apicompat is fine but that eliminates the option for benefit 3 (unless the apicompat handles the case where the source has MORE publics than the ref, then we're ok).

But yes, apicompat should be automatic as part of the CI build.

we can check the apicompat in one direction but not the other?

for example, I apicompat is capable of ensuring the implementations satisfy the reference without ensuring that references parity the implementation.

We 'ought to be able to do the same with core and framework to ensure that core is a superset of framework if we want

I know nothing about apicompat 馃槅

One of the big problems with not using the built-in compiler refout feature, however, is that it is very easy to end up in a world where the information you are including or excluding does not match what the C# compiler thinks is should be included/excluded.

There have been issues in the past where the /t:GenerateReferenceSource option in CoreFX has not matched (and still may not match) the C# view that has caused issues. One such example is the inclusion of private fields for structs, which impacts unsafe code and whether or not you can take the address of a given object. -- CC. @jaredpar

Indeed the CoreFX tooling for reference assemblies was designed without consulting the compiler team. As a result it turned out they made a variety of decisions that caused their reference assemblies to be observably different from there implementation assemblies. This caused a deal of customer confusion as subtle changes to their build caused them to silently switch between reference + implementation assemblies and as a result get different compilation results.

Concrete example:

Guid g; 
Console.WriteLine(g.ToString());

Does this compile or not? The answer is, frustratingly, it depends because of choices the CoreFX team made in reference assembly generation.

The refout and refonly compiler features are designed to produce reference assemblies that have complete fidelity for compiling with the implementation assembly. I strongly suggest you use that if possible for generating reference assemblies.

Note: we have worked with the CoreFX team and addressed many of the tooling issues. Hence it should be less of an issue going forward. But you can still run into version compat issues as the language evolves. That can't happen with refonly and refout.

@jaredpar is there an issue in either roslyn or corefx to bring these two closer together that we can link here? I'd love to read more on what the difference are, as I think there's some benefits here to having the source

@zsd4yr the corefx story is complicated. They have essentially the most complicated reference assembly generation story possible. Their tooling is designed to support their specific scenario. And that meants they have an on-going tax: when we change the language, they likley have to respond to how they generate reference assemblies. We have a tighter loop now to keep the fidelity up but it's still a different tool.

That makes sense. We probably don't want this change to make us less agile in rev'ing the language we support

cc @ericstj as we were discussing this

Hey All, discussing internally before moving forward. Someone from the team will come back here and update the thread once a decision is made. Thanks for your patience

We are going to move ahead with autogeneration via the compiler. @Shyam-Gupta will provide further updates when appropriate

Was this page helpful?
0 / 5 - 0 ratings