diff --git a/eng/generators.targets b/eng/generators.targets
index c24eca9be55dd1..3290f37580be29 100644
--- a/eng/generators.targets
+++ b/eng/generators.targets
@@ -48,12 +48,6 @@
" />
-
-
-
-
-
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/LibraryImportAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/LibraryImportAttribute.cs
index b5dd3804d58f34..c4dedf19b05fbc 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/LibraryImportAttribute.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/LibraryImportAttribute.cs
@@ -14,16 +14,7 @@ namespace System.Runtime.InteropServices
/// applied to static, partial, non-generic methods.
///
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
-#if SYSTEM_PRIVATE_CORELIB
- public
-#else
-#pragma warning disable CS0436 // Type conflicts with imported type
- // Some assemblies that target downlevel have InternalsVisibleTo to their test assemblies.
- // As this is only used in this repo and isn't a problem in shipping code,
- // just disable the duplicate type warning.
- internal
-#endif
- sealed class LibraryImportAttribute : Attribute
+ public sealed class LibraryImportAttribute : Attribute
{
///
/// Initializes a new instance of the .
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/StringMarshalling.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/StringMarshalling.cs
index b31d024cea8e68..0970d95135b9b1 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/StringMarshalling.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/StringMarshalling.cs
@@ -13,12 +13,7 @@ namespace System.Runtime.InteropServices
///
/// Specifies how strings should be marshalled for generated p/invokes
///
-#if SYSTEM_PRIVATE_CORELIB || MICROSOFT_INTEROP_SOURCEGENERATION
- public
-#else
- internal
-#endif
- enum StringMarshalling
+ public enum StringMarshalling
{
///
/// Indicates the user is supplying a specific marshaller in .
diff --git a/src/libraries/System.Runtime.InteropServices/gen/DownlevelLibraryImportGenerator/DownlevelLibraryImportGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/DownlevelLibraryImportGenerator/DownlevelLibraryImportGenerator.cs
index 63ca6ca49ff81d..aa84f8615811f9 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/DownlevelLibraryImportGenerator/DownlevelLibraryImportGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/DownlevelLibraryImportGenerator/DownlevelLibraryImportGenerator.cs
@@ -35,8 +35,42 @@ public static class StepNames
public const string GenerateSingleStub = nameof(GenerateSingleStub);
}
+ // Internal definitions of LibraryImportAttribute and StringMarshalling that are injected
+ // into user projects targeting downlevel frameworks that don't have these types in the BCL.
+ // These definitions only expose the properties and enum values supported downlevel.
+ private const string GeneratedInteropTypes = """
+ //
+ #nullable enable
+ namespace System.Runtime.InteropServices
+ {
+ [global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
+ [global::Microsoft.CodeAnalysis.Embedded]
+ internal sealed partial class LibraryImportAttribute : global::System.Attribute
+ {
+ public LibraryImportAttribute(string libraryName) { }
+ public string? EntryPoint { get; set; }
+ public StringMarshalling StringMarshalling { get; set; }
+ public bool SetLastError { get; set; }
+ }
+
+ [global::Microsoft.CodeAnalysis.Embedded]
+ internal enum StringMarshalling
+ {
+ Utf16 = 2,
+ }
+ }
+ """;
+
public void Initialize(IncrementalGeneratorInitializationContext context)
{
+ // Inject internal definitions of LibraryImportAttribute and StringMarshalling into the compilation
+ // so that users targeting downlevel frameworks can apply [LibraryImport] to their methods.
+ context.RegisterPostInitializationOutput(static ctx =>
+ {
+ ctx.AddEmbeddedAttributeDefinition();
+ ctx.AddSource("LibraryImportInteropTypes.g.cs", GeneratedInteropTypes);
+ });
+
// Collect all methods adorned with LibraryImportAttribute and filter out invalid ones
// (diagnostics for invalid methods are reported by the analyzer)
var methodsToGenerate = context.SyntaxProvider
diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AdditionalAttributesOnStub.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AdditionalAttributesOnStub.cs
index ebb295f6d3fe79..8d58aa3679f45c 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AdditionalAttributesOnStub.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AdditionalAttributesOnStub.cs
@@ -128,7 +128,6 @@ public async Task SkipLocalsInitOnDownlevelTargetFrameworks(TestTargetFramework
{
string source = $$"""
using System.Runtime.InteropServices;
- {{CodeSnippets.LibraryImportAttributeDeclaration}}
partial class C
{
[LibraryImportAttribute("DoesNotExist")]
diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs
index c0896cc09e8f5d..08c9804f7f0993 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs
@@ -46,28 +46,6 @@ string ICustomMarshallingSignatureTestProvider.MarshalUsingCollectionReturnValue
string ICustomMarshallingSignatureTestProvider.CustomElementMarshalling(string type, string marshallerType, string preDeclaration)
=> CustomElementMarshalling(type, marshallerType, preDeclaration);
- ///
- /// Partially define attribute for pre-.NET 7.0
- ///
- public static readonly string LibraryImportAttributeDeclaration = """
- namespace System.Runtime.InteropServices
- {
- internal enum StringMarshalling
- {
- Custom = 0,
- Utf8,
- Utf16,
- }
-
- sealed class LibraryImportAttribute : System.Attribute
- {
- public LibraryImportAttribute(string a) { }
- public StringMarshalling StringMarshalling { get; set; }
- public Type StringMarshallingCustomType { get; set; }
- }
- }
- """;
-
///
/// Trivial declaration of LibraryImport usage
///
diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs
index 225ae48288ebc1..81b10efc82d4af 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs
@@ -500,8 +500,9 @@ protected override ParseOptions CreateParseOptions()
public static IEnumerable