-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Dllimport generator build and test fixes #59658
Dllimport generator build and test fixes #59658
Conversation
…ns (marked in source with analyzer suppressions).
src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CloseHandle.cs
Show resolved
Hide resolved
@@ -8,16 +8,13 @@ internal static partial class Interop | |||
{ | |||
internal static partial class Kernel32 | |||
{ | |||
#pragma warning disable DLLIMPORTGENANALYZER015 // Use 'GeneratedDllImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time | |||
// Disabled since GetFullPathNameW takes 'ref's into buffers (the ref parameters don't represent single characters). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is going to be the recommended way to make these work with GeneratedDllImports?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This particular P/Invoke took a dependency on the fact that chars are conditionally blittable, so no copying was done. So far, the Interop team has decided to not consider char
s as conditionally blittable.
To make this particular P/Invoke work, there are a few different options:
- Update the generator to consider
char
parameters as blittable whenCharSet=CharSet.Unicode
. - Update this P/Invoke to take
char*
parameters instead ofref char
and pass in pinned refs. - Update the first parameter to take a
string
(which will be pinned) or aReadOnlySpan<char>
(using the new Span marshalers) and the second to take achar*
, which will be passed without change. As the usage of this method calculates the refs to pass in, from aReadOnlySpan<char>
and aValueStringBuilder
, this would be possible without too much trouble.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We did (1) in #59700, so we should be able to switch this and GetLongPathNameW
back.
Fine with getting this change in to the feature branch and updating in the main merge PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the merge conflicts I had after the property order normalization, I just fixed this as part of resolving those.
…matically excludes these test projects from the .NET Framework test build.
…e/browser platforms.
9e21237
to
a24525e
Compare
…t against an issue with debug/checked CoreCLR.
…untime into dllimport-generator-build-fixes
…s.csproj to enable DNNE's architecture detection on Windows.
We do not want to have tests that only work on release flavors of the runtime. We should either fix the non-release runtime; or delete the test and leave the behavior unspecified. |
|
||
### Semantic changes compared to `DllImportAttribute` | ||
|
||
The default value of [`CharSet`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.charset) is runtime/language-defined. In the built-in system, the default value of the `CharSet` property is `CharSet.Ansi`. The P/Invoke source generator makes no assumptions about the `CharSet` if it is not explicitly set on `GeneratedDllImportAttribute`. Marshalling of `char` or `string` requires explicitly specifying marshalling information. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default value of
CharSet
is runtime/language-defined
What does it mean for the default value to be "runtime" defined when the code for it is being emitted by the generator?
I assume the generator emits a diagnostic and fails when CharSet would be used and it hasn't been explicitly specified to something other than None?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does it mean for the default value to be "runtime" defined when the code for it is being emitted by the generator?
This is for the DllImportAttribute
not for the GeneratedDllImportAttribute
. All this is saying is the new system doesn't attempt to make the choice for you and instead expects explicit statement. The CharSet.Auto
is basically not supported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CharSet.Auto
is basically not supported
CharSet.Auto
is supported (for strings). Not specifying CharSet
at all (or specifying CharSet.None
) is not supported when marshalling char
or string
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bah. Right. I am confusing the "default" with the concept of specifically setting CharSet.Auto
. Apologies.
|
||
When converting from native to managed, the built-in system would throw a [`MarshalDirectiveException`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshaldirectiveexception) if the string's length is over 0x7ffffff0. The generated marshalling code will no longer perform this check. | ||
|
||
In the built-in system, marshalling a `string` contains an optimization for parameters passed by value to allocate on the stack (instead of through [`AllocCoTaskMem`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshal.alloccotaskmem)) if the string is below a certain length (MAX_PATH). For UTF-16, this optimization was also applied for parameters passed by read-only reference. The generated marshalling code will include this optimization for read-only reference parameters for non-UTF-16 as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The generated marshalling code will include this optimization for read-only reference parameters for non-UTF-16 as well.
Why only "readonly reference parameters"? What's an example of something where we could do so but we're choosing not to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inadvertent stack corruption. We were leery of supporting the stackalloced solution for all cases so deferred support. This is one of those point in time decisions that can be updated in V2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inadvertent stack corruption.
By whom? The generator is generating all of the code in the implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the callee. Readonly parameters assume and are contracted to be read only on the native side so we assume that here. If the callee does incorrectly write to the buffer it could negatively impact the runtime state and so was deferred until we see a strong use case.
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.Roslyn3.11.csproj", "{E00A72D2-A6C2-4334-92AC-7CF7ECC87F4D}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.Roslyn4.0.csproj", "{EBEF8790-8095-4FD9-8436-1354B30E1529}" | ||
EndProject |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are all these .slns being updated with additional projects?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I built the slngen.proj
project in 27034bc to regenerate all of the solutions since I added new project references for the DllImportGenerator. Looks like someone didn't run it beforehand and this update also updated the solutions with the logging source generator as well.
@@ -4,6 +4,7 @@ | |||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | |||
<IncludeRemoteExecutor>true</IncludeRemoteExecutor> | |||
<IgnoreForCI Condition="'$(TargetOS)' == 'Browser'">true</IgnoreForCI> | |||
<EnableDllImportGenerator>true</EnableDllImportGenerator> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this needed? We can't just enable it everywhere?
DLLIMPORTGENANALYZER014 | Usage | Error | RefValuePropertyUnsupported | ||
DLLIMPORTGENANALYZER015 | Interoperability | Disabled | ConvertToGeneratedDllImportAnalyzer | ||
DLLIMPORTGENANALYZER016 | Usage | Error | GenericTypeMustBeClosed | ||
DLLIMPORTGENANALYZER017 | Usage | Warning | GeneratedDllImportContainingTypeMissingModifiers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will we shift to using the SYSLIB prefix we use in our other generators?
https://github.com/dotnet/runtime/blob/main/docs/project/list-of-diagnostics.md
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, IIRC the docs earlier stated that everything is an error, but that doesn't map to the severity column here.
namespace Microsoft.Interop.Diagnostics | ||
{ | ||
[EventSource(Name = "Microsoft-Interop-SourceGeneration-Events")] | ||
internal sealed class Events : EventSource |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these still needed? Weren't similar events added to the Roslyn infrastructure for all generators?
private const string GeneratedDllImport = nameof(GeneratedDllImport); | ||
private const string GeneratedDllImportAttribute = nameof(GeneratedDllImportAttribute); | ||
|
||
private static readonly Version MinimumSupportedFrameworkVersion = new Version(5, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
5 or 6 (or 7)?
@stephentoub can you please move your feedback to #59579? Once I get a green build, this PR will retarget to the feature/use-dllimport-generator branch (as mentioned in the PR description) and all of the files you have commented on will no longer be in the diff for the PR. Whereas #59579 is the PR that will merge the generator into main, so your feedback will be more useful there. |
I had ~40 comments. I'm not going to recreate them all on the other PR. There was no indication in the PR description that feedback shouldn't be provided here, this wasn't marked as no review, etc. If you'd like to address or respond to my feedback elsewhere, that's fine. |
I explicitly marked it as a draft PR and as No-Merge, which means I didn't want review on it. I honestly thought that we had gotten rid of the NO REVIEW tag with the move to use draft PRs. Also, I explicitly stated in the PR description that I'm going to re-target the PR to a different branch, so most of the commits will not show up. I only suggest moving the feedback to #59579 to make sure that we don't lose the feedback when I retarget this PR. I don't know what GitHub does when you retarget a PR and the files that have comments are no longer part of the diff. I've since marked this PR as "NO REVIEW" to make sure that this doesn't happen again. Sorry for the confusion. |
…w Mono loads (or more acurately doesn't) the native library component of these tests.
@stephentoub Lots of good comments here. We will work on addressing them in the integration PR – #59579. A few of the comments are about productization points which we plan to address after the integrating into the product as making it publicly consumable is step 2. There are multiple inconsistencies that we need to address as we make the prototype follow the dotnet/runtime style guidelines. The many design queries we will attempt to answer above and continue that conversation. |
…covering the native toolchain for DNNE.
… next DNNE version.
…oolchain correctly.
…oid changing anything in eng/common.
…MacCatalyst only now for simplicity since DNNE doesn't support mobile platforms anyway)
…dotnet/runtime into dllimport-generator-build-fixes
…pported and DNNE doesn't support it.
All of the CI failures are known and tracked with runfo issues, so I'm going to re-target this and mark it ready for review. CI build of 4d55f3a against main: https://dev.azure.com/dnceng/public/_build/results?buildId=1403599&view=results |
@@ -8,16 +8,13 @@ internal static partial class Interop | |||
{ | |||
internal static partial class Kernel32 | |||
{ | |||
#pragma warning disable DLLIMPORTGENANALYZER015 // Use 'GeneratedDllImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time | |||
// Disabled since GetFullPathNameW takes 'ref's into buffers (the ref parameters don't represent single characters). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We did (1) in #59700, so we should be able to switch this and GetLongPathNameW
back.
Fine with getting this change in to the feature branch and updating in the main merge PR.
// As a result, we need to exclude the Mono run here since we build the tests once for CoreCLR and Mono for desktop test runs. | ||
// We should switch this to another mechanism in the future so we don't submit a work item of this assembly that skips every test | ||
// for Mono-on-Desktop-Platforms test runs. | ||
[assembly:ActiveIssue("https://github.com/dotnet/runtime/issues/59815", TestRuntimes.Mono)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do this via a ProjectExclusions
based on RuntimeFlavor
in tests.proj
? The assembly attribute results in us still sending the test to Helix, running through test discovery for each test to determine that it should not be run, and uploading logs - which seems rather wasteful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doh. I completely forgot about that. +1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't do that because we don't build the libraries tests for each runtime flavor, we use one build for both CoreCLR and Mono on desktop platforms (like Linux and Mac). I tried that originally and it didn't work.
...libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj
Show resolved
Hide resolved
</XmlPeek> | ||
<XmlPeek XmlContent="$(CrossTargetXml)" Query="toolchain-info/compiler-args/text()"> | ||
<Output TaskParameter="Result" PropertyName="DnneCompilerUserFlags" /> | ||
</XmlPeek> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
XmlPeek
Learned about a new task today - not sure I'm happy about it...
…dotnet/runtime into dllimport-generator-build-fixes
cab205b
to
00726aa
Compare
Build and test fixes for DllImportGenerator.
Marked as draft and targeting
main
to validate CI. Once CI is validated, will re-target againstfeature/use-dllimport-generator
.