Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use SupportedOSPlatforms property to generate assembly attributes #41209

Closed
wants to merge 6 commits into from
Closed

Use SupportedOSPlatforms property to generate assembly attributes #41209

wants to merge 6 commits into from

Conversation

jeffhandley
Copy link
Member

@jeffhandley jeffhandley commented Aug 22, 2020

In preparation for taking in the Platform Compatibility Analyzer, we need to address build errors that will be introduced by the analyzer due to our [SupportedOSPlatform] and [UnsupportedOSPlatform] annotations.

This Draft PR uses an MSBuild-based approach similar to what was put in place for <UnsupportedOSPlatforms> such that assembly-level attributes can be generated based on the platforms listed in that property; a <SupportedOSPlatforms> property is introduced that works the same way. This approach will prevent supported and unsupported combinations in assembly attributes.

@Dotnet-GitSync-Bot
Copy link
Collaborator

I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label.

@jeffhandley jeffhandley marked this pull request as draft August 22, 2020 12:54
@jeffhandley jeffhandley added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Aug 22, 2020
… not allow supported and unsupported combinations
@jeffhandley
Copy link
Member Author

Here are the current build errors that occur when using a private build from dotnet/roslyn-analyzers#3917.

Build FAILED.

System\Net\Sockets\SocketAsyncEventArgs.Windows.cs(1222,60): error CA1416: 'ThreadPoolBoundHandle.GetNativeOverlappedState(NativeOverlapped*)' is supported on 'windows' [C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\System.Net.Sockets\src\System.Net.Sockets.csproj]
C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\Common\src\Interop\Windows\WinSock\SafeNativeOverlapped.cs(66,33): error CA1416: 'ThreadPoolBoundHandle.FreeNativeOverlapped(NativeOverlapped*)' is supported on 'windows' [C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\System.Net.Sockets\src\System.Net.Sockets.csproj]
C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\Common\src\System\Net\ContextAwareResult.Windows.cs(16,32): error CA1416: 'WindowsIdentity.GetCurrent()' is supported on 'windows' [C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\System.Net.Sockets\src\System.Net.Sockets.csproj]
C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\Common\src\System\Net\ContextAwareResult.Windows.cs(23,17): error CA1416: 'WindowsIdentity.Dispose()' is supported on 'windows' [C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\System.Net.Sockets\src\System.Net.Sockets.csproj]
System\Net\Sockets\SafeSocketHandle.Windows.cs(108,17): error CA1416: 'ThreadPoolBoundHandle.Dispose()' is supported on 'windows' [C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\System.Net.Sockets\src\System.Net.Sockets.csproj]
System\Net\Sockets\SafeSocketHandle.Windows.cs(79,74): error CA1416: 'ThreadPoolBoundHandle.Handle' is supported on 'windows' [C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\System.Net.Sockets\src\System.Net.Sockets.csproj]
System\Net\Sockets\SafeSocketHandle.Windows.cs(54,39): error CA1416: 'ThreadPoolBoundHandle.BindHandle(SafeHandle)' is supported on 'windows' [C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\System.Net.Sockets\src\System.Net.Sockets.csproj]
System\Net\Sockets\SocketAsyncEventArgs.Windows.cs(84,20): error CA1416: 'ThreadPoolBoundHandle.AllocateNativeOverlapped(PreAllocatedOverlapped)' is supported on 'windows' [C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\System.Net.Sockets\src\System.Net.Sockets.csproj]
System\Net\Sockets\SocketAsyncEventArgs.Windows.cs(96,13): error CA1416: 'ThreadPoolBoundHandle.FreeNativeOverlapped(NativeOverlapped*)' is supported on 'windows' [C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\System.Net.Sockets\src\System.Net.Sockets.csproj]
System\Net\Sockets\SocketAsyncEventArgs.Windows.cs(60,43): error CA1416: 'PreAllocatedOverlapped' is supported on 'windows' [C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\System.Net.Sockets\src\System.Net.Sockets.csproj]
System\Net\Sockets\SocketAsyncEventArgs.Windows.cs(907,17): error CA1416: 'PreAllocatedOverlapped.Dispose()' is supported on 'windows' [C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\System.Net.Sockets\src\System.Net.Sockets.csproj]
System\Net\Sockets\BaseOverlappedAsyncResult.Windows.cs(53,48): error CA1416: 'ThreadPoolBoundHandle.AllocateNativeOverlapped(IOCompletionCallback, object?, object?)' is supported on 'windows' [C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\System.Net.Sockets\src\System.Net.Sockets.csproj]
System\Net\Sockets\BaseOverlappedAsyncResult.Windows.cs(62,80): error CA1416: 'ThreadPoolBoundHandle.GetNativeOverlappedState(NativeOverlapped*)' is supported on 'windows' [C:\Users\jeffhand\git\dotnet\runtime-master-supportedosplatforms\src\libraries\System.Net.Sockets\src\System.Net.Sockets.csproj]
    0 Warning(s)
    13 Error(s)

Copy link
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good idea! LGTM 👍

@@ -243,7 +243,7 @@

<!-- Adds System.Runtime.Versioning*Platform* annotation attributes to < .NET 5 builds -->
<Choose>
<When Condition="('$(IncludePlatformAttributes)' == 'true' or '$(IsWindowsSpecific)' == 'true') and ('$(TargetFrameworkIdentifier)' != '.NETCoreApp' or $([MSBuild]::VersionLessThan($(TargetFrameworkVersion), '5.0')))">
<When Condition="('$(IncludePlatformAttributes)' == 'true' or '$(SupportedOSPlatforms)' != '' or '$(UnsupportedOSPlatforms)' != '') and ('$(TargetFrameworkIdentifier)' != '.NETCoreApp' or $([MSBuild]::VersionLessThan($(TargetFrameworkVersion), '5.0')))">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very good idea to not always require IncludePlatformAttributes when SupportedOSPlatforms or UnsupportedOSPlatforms are used 👍

You could simplify the assemblies annotated in #40612 and replace

    <IncludePlatformAttributes>true</IncludePlatformAttributes>
    <UnsupportedOSPlatforms>browser</UnsupportedOSPlatforms>

with just

    <UnsupportedOSPlatforms>browser</UnsupportedOSPlatforms>

eng/versioning.targets Show resolved Hide resolved
eng/versioning.targets Show resolved Hide resolved
Comment on lines +36 to 38
<AssemblyAttribute Include="System.Runtime.Versioning.UnsupportedOSPlatform" Condition="'@(_supportedOSPlatforms)' == '' and '@(_unsupportedOSPlatforms)' != ''">
<_Parameter1>%(_unsupportedOSPlatforms.Identity)</_Parameter1>
</AssemblyAttribute>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we produce a build warning when both $(SupportedOSPlatforms) and $(UnsupportedOSPlatforms) are set? Those are mutual exclusive choices, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea

@ghost
Copy link

ghost commented Aug 24, 2020

Tagging subscribers to this area: @safern, @ViktorHofer
See info in area-owners.md if you want to be subscribed.

@ViktorHofer
Copy link
Member

@jeffhandley curious, is this runtime specific or should customers be able to set this in their application as well? If the latter this would probably need to go into dotnet/sdk.

@jeffhandley
Copy link
Member Author

@jeffhandley curious, is this runtime specific or should customers be able to set this in their application as well? If the latter this would probably need to go into dotnet/sdk.

This is specific to the runtime repo, making it easier for us to apply assembly-wide attributes throughout our repo in various configs, but ensuring we don't produce conflicting [SupportedOSPlatform] and [UnsupportedOSPlatform] attributes. We could consider productizing this in the SDK in the future though.

@ViktorHofer
Copy link
Member

ViktorHofer commented Aug 24, 2020

Thanks Jeff. Let me rephrase. Will the platform compat analyzer, which respects these attributes, analyze non runtime libraries (customer applications) as well? If that's the case then we should probably open an issue in the sdk repo.

@jeffhandley
Copy link
Member Author

Ah, thanks for rephrasing.

The analyzer will be part of the SDK through the NetAnalyzers package. dotnet/roslyn-analyzers#3917 will add the analyzer into roslyn-analyzers, and then there will be a step to update the SDK with the latest roslyn-analyzers build.

This PR sets the runtime repo up to be able to mark entire assemblies with [SupportedOSPlatform] attributes to make the assemblies platform-specific where appropriate, so that we can be ready for the intake of that analyzer for our repo.

@eerhardt
Copy link
Member

I had a similar initial reaction as @ViktorHofer: Should this be an official product feature? If this is generally applicable to our customers, then we should probably add the capability to dotnet/sdk instead of our build infrastructure. However, I can understand if it is too late in 5.0 to get that in now - but maybe something in 6.0?

@@ -2,6 +2,6 @@
<Import Project="..\Directory.Build.props" />
<PropertyGroup>
<StrongNameKeyId>Microsoft</StrongNameKeyId>
<IsWindowsSpecific>true</IsWindowsSpecific>
<SupportedOSPlatforms>windows</SupportedOSPlatforms>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought SupportedOSPlatforms was an Item and not a property?

Copy link
Member Author

@jeffhandley jeffhandley Aug 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are 2 with similar naming:

  • <SupportedPlatform>, which is an item, and it tells the analyzer which platforms we care to see warnings about, and it's part of the SDK product
  • <SupportedOSPlatforms>, which is this property, and it results in assembly-level [SupportedOSPlatform] attributes, and it's part of the runtime repo only

These names are so similar they're surely easy to get mixed up. Perhaps a better name for the runtime repo properties that produce the assembly-level attributes would be:

  • <AssemblySupportedOSPlatformAttributes>
  • <AssemblyUnsupportedOSPlatformAttributes>

@bartonjs
Copy link
Member

I had a similar initial reaction as @ViktorHofer: Should this be an official product feature?

My understanding is that anyone building with a platform-specific TFM (e.g. net5.0-win) will have an assembly-level attribute automatically applied (whether that work is done or not, I don't know, but it was discussed). In our repository we build with the platform agnostic TFM (net5.0) for our OS-split assemblies. So I think we're just back-plumbing that SDK feature into our build variant.

Another possibility would be to try building our OS-split libraries with their OS-variant TFM, but I have no idea what impact that would have on our build composition. It's maybe the right answer for 6, but probably risky for 5 (unless it Just Works).

@@ -111,8 +111,11 @@ public static IHostBuilder CreateDefaultBuilder(string[] args)

if (isWindows)
{
#pragma warning disable CA1416 // Platform compat analyzer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary? isWindows is defined above as:

bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);

Can the analyzer not recognize this pattern?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Analyzer can track result save in local, it shouldn't warn

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was warning on this. Remind me; can the analyzer also recognize the old RuntimeInformation.IsOSPlatform() calls like this one? This branch is still intact despite the PR being close. Could you pull the branch down and check this scenario please, @buyaa-n?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can the analyzer also recognize the old RuntimeInformation.IsOSPlatform()

Yes it can

It was warning on this.

That is strange, i added exact same test and it is not warning

This branch is still intact despite the PR being close. Could you pull the branch down and check this scenario please, @buyaa-n?

Sure

Copy link
Member

@buyaa-n buyaa-n Aug 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed an issue for the bug dotnet/roslyn-analyzers#4090

@@ -274,7 +275,7 @@ private void CreateNewSocketIfNeeded()
_serverSocket.ExclusiveAddressUse = true;
}

if (_allowNatTraversal != null)
if (_allowNatTraversal != null && OperatingSystem.IsWindows())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we concerned about behavior change here at all? Previously someone would get a PNSE during socket creation, if they called TCPListener.AllowNatTraversal(bool allowed). Now it looks like it will no longer PNSE.

<AssemblyAttribute Include="System.Runtime.Versioning.UnsupportedOSPlatform" Condition="'@(_supportedOSPlatforms)' == '' and '@(_unsupportedOSPlatforms)' != ''">
<_Parameter1>%(_unsupportedOSPlatforms.Identity)</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
<Warning Condition="'@(_supportedOSPlatforms)' != '' and '@(_unsupportedOSPlatforms)' != ''"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just Error. We set warnAsError for the global build, so it is the same, we usually try to error for this kind of stuff as warnings could slip sometimes.

@jeffhandley
Copy link
Member Author

We're still iterating on this; I'm going to close the draft PR and then we will open another PR when ready for another review. The feedback here was helpful to steer the direction; thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Infrastructure-libraries NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants