diff --git a/eng/pipelines/coreclr/nativeaot-post-build-steps.yml b/eng/pipelines/coreclr/nativeaot-post-build-steps.yml
index a44c7223039580..a920993b093cbc 100644
--- a/eng/pipelines/coreclr/nativeaot-post-build-steps.yml
+++ b/eng/pipelines/coreclr/nativeaot-post-build-steps.yml
@@ -29,3 +29,9 @@ steps:
- ${{ if ne(parameters.osGroup, 'windows') }}:
- script: $(Build.SourcesDirectory)/src/tests/run.sh --runnativeaottests $(buildConfigUpper) ${{ parameters.archType }}
displayName: Run tests in single file mode
+
+ # Publishing tooling doesn't support different configs between runtime and libs, so only run tests in Release config
+ # PublishAot on OSX doesn't work yet. Need an SDK with https://github.com/dotnet/installer/pull/14443.
+ - ${{ if and(eq(parameters.buildConfig, 'release'), ne(parameters.osGroup, 'OSX')) }}:
+ - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(_osParameter) -s libs.tests -c $(_BuildConfig) /p:TestAssemblies=false /p:RunNativeAotTestApps=true $(_officialBuildParameter) $(_crossBuildPropertyArg) /bl:$(Build.SourcesDirectory)/artifacts/log/$(buildConfigUpper)/NativeAotTests.binlog ${{ parameters.extraTestArgs }}
+ displayName: Run NativeAot Library Tests
diff --git a/eng/testing/linker/SupportFiles/Directory.Build.props b/eng/testing/linker/SupportFiles/Directory.Build.props
index da3533e49c939f..1e08117fd3171c 100644
--- a/eng/testing/linker/SupportFiles/Directory.Build.props
+++ b/eng/testing/linker/SupportFiles/Directory.Build.props
@@ -2,7 +2,6 @@
truetrue
- truefullfalsetrue
diff --git a/eng/testing/linker/SupportFiles/Directory.Build.targets b/eng/testing/linker/SupportFiles/Directory.Build.targets
index 491c45e4a43fa9..e735d71fa0f723 100644
--- a/eng/testing/linker/SupportFiles/Directory.Build.targets
+++ b/eng/testing/linker/SupportFiles/Directory.Build.targets
@@ -12,6 +12,10 @@
DependsOnTargets="BundleTestWasmApp"
Condition="'$(TargetArchitecture)' == 'wasm' And '$(TargetOS)' == 'browser'" />
+
+ $(CoreCLRBuildIntegrationDir)Microsoft.DotNet.ILCompiler.SingleEntry.targets
+
+
diff --git a/eng/testing/linker/project.csproj.template b/eng/testing/linker/project.csproj.template
index 80180798fd30e8..9b1c14e36b814d 100644
--- a/eng/testing/linker/project.csproj.template
+++ b/eng/testing/linker/project.csproj.template
@@ -6,6 +6,7 @@
{NetCoreAppMaximumVersion}{UseMonoRuntime}{RuntimeIdentifier}
+ {PublishAot}{MonoAOTCompilerDir}
@@ -25,6 +26,15 @@
{RepositoryEngineeringDir}
<_ExtraTrimmerArgs>{ExtraTrimmerArgs} $(_ExtraTrimmerArgs)
+ {AdditionalProperties}
+
+
+ {IlcToolsPath}
+ {IlcBuildTasksPath}
+ {IlcSdkPath}
+ {IlcFrameworkPath}
+ {IlcFrameworkNativePath}
+ {CoreCLRBuildIntegrationDir}
diff --git a/eng/testing/linker/trimmingTests.targets b/eng/testing/linker/trimmingTests.targets
index ac688f61b6b2d7..9f821e99c2a3a5 100644
--- a/eng/testing/linker/trimmingTests.targets
+++ b/eng/testing/linker/trimmingTests.targets
@@ -72,10 +72,14 @@
<_switchesAsItems Include="%(TestConsoleApps.DisabledFeatureSwitches)" Value="false" />
<_switchesAsItems Include="%(TestConsoleApps.EnabledFeatureSwitches)" Value="true" />
+
+ <_propertiesAsItems Include="%(TestConsoleApps.DisabledProperties)" Value="false" />
+ <_propertiesAsItems Include="%(TestConsoleApps.EnabledProperties)" Value="true" />
<_runtimeHostConfigurationOptionsString>@(_switchesAsItems->'<RuntimeHostConfigurationOption Include="%(Identity)" Value="%(Value)" Trim="true" />', '%0a ')
+ <_additionalPropertiesString>@(_propertiesAsItems->'<%(Identity)>%(Value)</%(Identity)>', '%0a ')
@@ -85,8 +89,16 @@
.Replace('{NetCoreAppMaximumVersion}', '$(NetCoreAppMaximumVersion)')
.Replace('{UseMonoRuntime}','$(UseMonoRuntime)')
.Replace('{RuntimeIdentifier}','%(TestConsoleApps.TestRuntimeIdentifier)')
+ .Replace('{PublishAot}','$(IsNativeAotTestProject)')
.Replace('{MicrosoftNETILLinkTasksVersion}', '$(MicrosoftNETILLinkTasksVersion)')
.Replace('{ExtraTrimmerArgs}', '%(TestConsoleApps.ExtraTrimmerArgs)')
+ .Replace('{AdditionalProperties}', '$(_additionalPropertiesString)')
+ .Replace('{IlcToolsPath}', '$(CoreCLRILCompilerDir)')
+ .Replace('{IlcBuildTasksPath}', '$(CoreCLRILCompilerDir)netstandard/ILCompiler.Build.Tasks.dll')
+ .Replace('{IlcSdkPath}', '$(CoreCLRAotSdkDir)')
+ .Replace('{IlcFrameworkPath}', '$(MicrosoftNetCoreAppRuntimePackRidLibTfmDir)')
+ .Replace('{IlcFrameworkNativePath}', '$(MicrosoftNetCoreAppRuntimePackNativeDir)')
+ .Replace('{CoreCLRBuildIntegrationDir}', '$(CoreCLRBuildIntegrationDir)')
.Replace('{RuntimeHostConfigurationOptions}', '$(_runtimeHostConfigurationOptionsString)')
.Replace('{AdditionalProjectReferences}', '$(_additionalProjectReferencesString)')
.Replace('{RepositoryEngineeringDir}', '$(RepositoryEngineeringDir)')
diff --git a/src/libraries/Directory.Build.props b/src/libraries/Directory.Build.props
index d609d71b29f30d..b7abf93f6d9efb 100644
--- a/src/libraries/Directory.Build.props
+++ b/src/libraries/Directory.Build.props
@@ -22,10 +22,12 @@
truetrue
- true
+ true
+ true
+ true
- false
+ false
@@ -36,14 +38,14 @@
'$(IsReferenceAssemblyProject)' != 'true' and
'$(IsGeneratorProject)' != 'true' and
'$(IsTestProject)' != 'true' and
- '$(IsTrimmingTestProject)' != 'true' and
+ '$(IsPublishedAppTestProject)' != 'true' and
'$(IsTestSupportProject)' != 'true' and
'$(UsingMicrosoftNoTargetsSdk)' != 'true' and
'$(UsingMicrosoftTraversalSdk)' != 'true'">true
-
+ $(NoWarn);SYSLIB0011
diff --git a/src/libraries/Directory.Build.targets b/src/libraries/Directory.Build.targets
index 8f9b52adb2805d..46cc84f810c209 100644
--- a/src/libraries/Directory.Build.targets
+++ b/src/libraries/Directory.Build.targets
@@ -127,7 +127,7 @@
-
+
diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs b/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs
index a285d3e487ef7f..9c864e489ab139 100644
--- a/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs
+++ b/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs
@@ -188,8 +188,6 @@ internal static DiagnosticListener LogHostBuilding(HostApplicationBuilder hostAp
return diagnosticListener;
}
- [UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode",
- Justification = "DiagnosticSource is used here to pass objects in-memory to code using HostFactoryResolver. This won't require creating new generic types.")]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern",
Justification = "The values being passed into Write are being consumed by the application already.")]
private static void Write(
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.cs
index 75b85af1913d47..1b08291cccd2ab 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.cs
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.cs
@@ -20,7 +20,6 @@ public virtual void Dispose() { }
public virtual System.IDisposable Subscribe(System.IObserver> observer, System.Predicate? isEnabled) { throw null; }
public override string ToString() { throw null; }
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")]
- [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")]
public override void Write(string name, object? value) { }
}
public abstract partial class DiagnosticSource
@@ -29,7 +28,6 @@ protected DiagnosticSource() { }
public abstract bool IsEnabled(string name);
public virtual bool IsEnabled(string name, object? arg1, object? arg2 = null) { throw null; }
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")]
- [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")]
public abstract void Write(string name, object? value);
}
}
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs
index 5177cb52339eca..488e6c39224fe0 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs
@@ -197,10 +197,8 @@ public abstract partial class DiagnosticSource
public virtual void OnActivityExport(System.Diagnostics.Activity activity, object? payload) { }
public virtual void OnActivityImport(System.Diagnostics.Activity activity, object? payload) { }
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")]
- [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")]
public System.Diagnostics.Activity StartActivity(System.Diagnostics.Activity activity, object? args) { throw null; }
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")]
- [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")]
public void StopActivity(System.Diagnostics.Activity activity, object? args) { }
}
public enum ActivitySamplingResult
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj
index 9c22bce30dae9b..97163bbceec0a0 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj
@@ -87,6 +87,8 @@ System.Diagnostics.DiagnosticSource
+
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs
index 75a7116c58fc16..c1677307acb5e0 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs
@@ -34,8 +34,6 @@ public partial class DiagnosticListener : DiagnosticSource, IObservable
public static IObservable AllListeners
{
- [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode",
- Justification = "ENABLE_HTTP_HANDLER is not enabled in the .NET current version")]
get
{
#if ENABLE_HTTP_HANDLER
@@ -255,7 +253,6 @@ public override bool IsEnabled(string name, object? arg1, object? arg2 = null)
/// Override abstract method
///
[RequiresUnreferencedCode(WriteRequiresUnreferencedCode)]
- [RequiresDynamicCode(WriteRequiresDynamicCode)]
public override void Write(string name, object? value)
{
for (DiagnosticSubscription? curSubscription = _subscriptions; curSubscription != null; curSubscription = curSubscription.Next)
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSource.cs
index 47fad270bab4b4..89e62d4102c988 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSource.cs
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSource.cs
@@ -17,7 +17,6 @@ namespace System.Diagnostics
public abstract partial class DiagnosticSource
{
internal const string WriteRequiresUnreferencedCode = "The type of object being written to DiagnosticSource cannot be discovered statically.";
- internal const string WriteRequiresDynamicCode = "DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.";
///
/// Write is a generic way of logging complex payloads. Each notification
@@ -36,7 +35,6 @@ public abstract partial class DiagnosticSource
/// An object that represent the value being passed as a payload for the event.
/// This is often an anonymous type which contains several sub-values.
[RequiresUnreferencedCode(WriteRequiresUnreferencedCode)]
- [RequiresDynamicCode(WriteRequiresDynamicCode)]
public abstract void Write(string name, object? value);
///
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceActivity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceActivity.cs
index 1156ed5fe3ee62..5bf9fa66916692 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceActivity.cs
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceActivity.cs
@@ -26,7 +26,6 @@ public abstract partial class DiagnosticSource
/// Started Activity for convenient chaining
///
[RequiresUnreferencedCode(WriteRequiresUnreferencedCode)]
- [RequiresDynamicCode(WriteRequiresDynamicCode)]
public Activity StartActivity(Activity activity, object? args)
{
activity.Start();
@@ -45,7 +44,6 @@ public Activity StartActivity(Activity activity, object? args)
/// An object that represent the value being passed as a payload for the event.
///
[RequiresUnreferencedCode(WriteRequiresUnreferencedCode)]
- [RequiresDynamicCode(WriteRequiresDynamicCode)]
public void StopActivity(Activity activity, object? args)
{
// Stop sets the end time if it was unset, but we want it set before we issue the write
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs
index b1b78fedc80b85..73b3ed529f070a 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs
@@ -1,5 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
@@ -234,7 +235,8 @@ public void Message(string? Message)
/// Events from DiagnosticSource can be forwarded to EventSource using this event.
///
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
- Justification = "Arguments parameter is trimmer safe")]
+ Justification = "Arguments parameter is preserved by DynamicDependency")]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))]
[Event(2, Keywords = Keywords.Events)]
private void Event(string SourceName, string EventName, IEnumerable>? Arguments)
{
@@ -255,7 +257,8 @@ private void EventJson(string SourceName, string EventName, string ArgmentsJson)
/// Used to mark the beginning of an activity
///
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
- Justification = "Arguments parameter is trimmer safe")]
+ Justification = "Arguments parameter is preserved by DynamicDependency")]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))]
[Event(4, Keywords = Keywords.Events)]
private void Activity1Start(string SourceName, string EventName, IEnumerable> Arguments)
{
@@ -266,7 +269,8 @@ private void Activity1Start(string SourceName, string EventName, IEnumerable
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
- Justification = "Arguments parameter is trimmer safe")]
+ Justification = "Arguments parameter is preserved by DynamicDependency")]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))]
[Event(5, Keywords = Keywords.Events)]
private void Activity1Stop(string SourceName, string EventName, IEnumerable> Arguments)
{
@@ -277,7 +281,8 @@ private void Activity1Stop(string SourceName, string EventName, IEnumerable
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
- Justification = "Arguments parameter is trimmer safe")]
+ Justification = "Arguments parameter is preserved by DynamicDependency")]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))]
[Event(6, Keywords = Keywords.Events)]
private void Activity2Start(string SourceName, string EventName, IEnumerable> Arguments)
{
@@ -288,7 +293,8 @@ private void Activity2Start(string SourceName, string EventName, IEnumerable
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
- Justification = "Arguments parameter is trimmer safe")]
+ Justification = "Arguments parameter is preserved by DynamicDependency")]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))]
[Event(7, Keywords = Keywords.Events)]
private void Activity2Stop(string SourceName, string EventName, IEnumerable> Arguments)
{
@@ -299,7 +305,8 @@ private void Activity2Stop(string SourceName, string EventName, IEnumerable
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
- Justification = "Arguments parameter is trimmer safe")]
+ Justification = "Arguments parameter is preserved by DynamicDependency")]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))]
[Event(8, Keywords = Keywords.Events, ActivityOptions = EventActivityOptions.Recursive)]
private void RecursiveActivity1Start(string SourceName, string EventName, IEnumerable> Arguments)
{
@@ -310,7 +317,8 @@ private void RecursiveActivity1Start(string SourceName, string EventName, IEnume
/// Used to mark the end of an activity that can be recursive.
///
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
- Justification = "Arguments parameter is trimmer safe")]
+ Justification = "Arguments parameter is preserved by DynamicDependency")]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))]
[Event(9, Keywords = Keywords.Events, ActivityOptions = EventActivityOptions.Recursive)]
private void RecursiveActivity1Stop(string SourceName, string EventName, IEnumerable> Arguments)
{
@@ -334,7 +342,8 @@ private void NewDiagnosticListener(string SourceName)
/// The Activity name
/// Name and value pairs of the Activity properties
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
- Justification = "Arguments parameter is trimmer safe")]
+ Justification = "Arguments parameter is preserved by DynamicDependency")]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))]
[Event(11, Keywords = Keywords.Events, ActivityOptions = EventActivityOptions.Recursive)]
private void ActivityStart(string SourceName, string ActivityName, IEnumerable> Arguments) =>
WriteEvent(11, SourceName, ActivityName, Arguments);
@@ -346,7 +355,8 @@ private void ActivityStart(string SourceName, string ActivityName, IEnumerableThe Activity name
/// Name and value pairs of the Activity properties
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
- Justification = "Arguments parameter is trimmer safe")]
+ Justification = "Arguments parameter is preserved by DynamicDependency")]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))]
[Event(12, Keywords = Keywords.Events, ActivityOptions = EventActivityOptions.Recursive)]
private void ActivityStop(string SourceName, string ActivityName, IEnumerable> Arguments) =>
WriteEvent(12, SourceName, ActivityName, Arguments);
@@ -641,8 +651,6 @@ public FilterAndTransform(string filterAndPayloadSpec, int startIdx, int endIdx,
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2119",
Justification = "DAM on EventSource references this compiler-generated local function which calls a " +
"method that requires unreferenced code. EventSource will not access this local function.")]
- [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode",
- Justification = "DiagnosticSource.Write is marked with RequiresDynamicCode.")]
void OnEventWritten(KeyValuePair evnt)
{
// The filter given to the DiagnosticSource may not work if users don't is 'IsEnabled' as expected.
@@ -890,8 +898,6 @@ internal static void CreateActivityListener(DiagnosticSourceEventSource eventSou
[DynamicDependency(nameof(TimeSpan.Ticks), typeof(TimeSpan))]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
Justification = "Activity's properties are being preserved with the DynamicDependencies on OnActivityStarted.")]
- [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode",
- Justification = "Activity is a reference type and is safe in aot.")]
private static void OnActivityStarted(DiagnosticSourceEventSource eventSource, Activity activity)
{
FilterAndTransform? list = eventSource._activitySourceSpecs;
@@ -911,8 +917,6 @@ private static void OnActivityStarted(DiagnosticSourceEventSource eventSource, A
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
Justification = "Activity's properties are being preserved with the DynamicDependencies on OnActivityStarted.")]
- [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode",
- Justification = "Activity is a reference type and is safe with aot.")]
private static void OnActivityStopped(DiagnosticSourceEventSource eventSource, Activity activity)
{
FilterAndTransform? list = eventSource._activitySourceSpecs;
@@ -1015,7 +1019,6 @@ private void Dispose()
Justification = "In EventSource, EnsureDescriptorsInitialized's use of GetType preserves this method which " +
"requires unreferenced code, but EnsureDescriptorsInitialized does not access this member and is safe to call.")]
[RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)]
- [RequiresDynamicCode(DiagnosticSource.WriteRequiresDynamicCode)]
public List> Morph(object? args)
{
// Transform the args into a bag of key-value strings.
@@ -1193,7 +1196,6 @@ public TransformSpec(string transformSpec, int startIdx, int endIdx, TransformSp
Justification = "In EventSource, EnsureDescriptorsInitialized's use of GetType preserves this method which " +
"requires unreferenced code, but EnsureDescriptorsInitialized does not access this member and is safe to call.")]
[RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)]
- [RequiresDynamicCode(DiagnosticSource.WriteRequiresDynamicCode)]
public KeyValuePair Morph(object? obj)
{
for (PropertySpec? cur = _fetches; cur != null; cur = cur.Next)
@@ -1248,7 +1250,6 @@ public PropertySpec(string propertyName, PropertySpec? next)
Justification = "In EventSource, EnsureDescriptorsInitialized's use of GetType preserves this method which " +
"requires unreferenced code, but EnsureDescriptorsInitialized does not access this member and is safe to call.")]
[RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)]
- [RequiresDynamicCode(DiagnosticSource.WriteRequiresDynamicCode)]
public object? Fetch(object? obj)
{
PropertyFetch? fetch = _fetchForExpectedType;
@@ -1295,7 +1296,6 @@ public PropertyFetch(Type? type)
Justification = "In EventSource, EnsureDescriptorsInitialized's use of GetType preserves this method which " +
"requires unreferenced code, but EnsureDescriptorsInitialized does not access this member and is safe to call.")]
[RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)]
- [RequiresDynamicCode(DiagnosticSource.WriteRequiresDynamicCode)]
public static PropertyFetch FetcherForProperty(Type? type, string propertyName)
{
if (propertyName == null)
@@ -1319,10 +1319,7 @@ public static PropertyFetch FetcherForProperty(Type? type, string propertyName)
continue;
}
- Type elemType = iFaceTypeInfo.GetGenericArguments()[0];
- Type instantiatedTypedPropertyFetcher = typeof(EnumeratePropertyFetch<>)
- .GetTypeInfo().MakeGenericType(elemType);
- return (PropertyFetch)Activator.CreateInstance(instantiatedTypedPropertyFetcher, type)!;
+ return CreateEnumeratePropertyFetch(type, iFaceTypeInfo);
}
// no implementation of IEnumerable found, return a null fetcher
@@ -1355,20 +1352,50 @@ public static PropertyFetch FetcherForProperty(Type? type, string propertyName)
Log.Message($"Property {propertyName} is static.");
return new PropertyFetch(type);
}
- Type typedPropertyFetcher = typeInfo.IsValueType ?
- typeof(ValueTypedFetchProperty<,>) : typeof(RefTypedFetchProperty<,>);
- Type instantiatedTypedPropertyFetcher = typedPropertyFetcher.GetTypeInfo().MakeGenericType(
- propertyInfo.DeclaringType!, propertyInfo.PropertyType);
- return (PropertyFetch)Activator.CreateInstance(instantiatedTypedPropertyFetcher, type, propertyInfo)!;
+
+ return CreatePropertyFetch(typeInfo, propertyInfo);
}
}
+ [UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode",
+ Justification = "MakeGenericType is only called when IsDynamicCodeSupported is true or only with ref types.")]
+ private static PropertyFetch CreateEnumeratePropertyFetch(Type type, Type enumerableOfTType)
+ {
+ Type elemType = enumerableOfTType.GetGenericArguments()[0];
+#if NETCOREAPP
+ if (!RuntimeFeature.IsDynamicCodeSupported && elemType.IsValueType)
+ {
+ return new EnumeratePropertyFetch(type);
+ }
+#endif
+ Type instantiatedTypedPropertyFetcher = typeof(EnumeratePropertyFetch<>)
+ .GetTypeInfo().MakeGenericType(elemType);
+ return (PropertyFetch)Activator.CreateInstance(instantiatedTypedPropertyFetcher, type)!;
+ }
+
+ [UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode",
+ Justification = "MakeGenericType is only called when IsDynamicCodeSupported is true or only with ref types.")]
+ private static PropertyFetch CreatePropertyFetch(Type type, PropertyInfo propertyInfo)
+ {
+#if NETCOREAPP
+ if (!RuntimeFeature.IsDynamicCodeSupported && (propertyInfo.DeclaringType!.IsValueType || propertyInfo.PropertyType.IsValueType))
+ {
+ return new ReflectionPropertyFetch(type, propertyInfo);
+ }
+#endif
+ Type typedPropertyFetcher = type.IsValueType ?
+ typeof(ValueTypedFetchProperty<,>) : typeof(RefTypedFetchProperty<,>);
+ Type instantiatedTypedPropertyFetcher = typedPropertyFetcher.GetTypeInfo().MakeGenericType(
+ propertyInfo.DeclaringType!, propertyInfo.PropertyType);
+ return (PropertyFetch)Activator.CreateInstance(instantiatedTypedPropertyFetcher, type, propertyInfo)!;
+ }
+
///
/// Given an object, fetch the property that this propertyFech represents.
///
public virtual object? Fetch(object? obj) { return null; }
- #region private
+#region private
private sealed class RefTypedFetchProperty : PropertyFetch
{
@@ -1407,6 +1434,74 @@ public ValueTypedFetchProperty(Type type, PropertyInfo property) : base(type)
private readonly StructFunc _propertyFetch;
}
+#if NETCOREAPP
+ ///
+ /// A fetcher that can be used when MakeGenericType isn't available.
+ ///
+ private sealed class ReflectionPropertyFetch : PropertyFetch
+ {
+ private readonly PropertyInfo _property;
+ public ReflectionPropertyFetch(Type type, PropertyInfo property) : base(type)
+ {
+ _property = property;
+ }
+
+ public override object? Fetch(object? obj) => _property.GetValue(obj);
+ }
+
+ ///
+ /// A fetcher that enumerates and formats an IEnumerable when MakeGenericType isn't available.
+ ///
+ private sealed class EnumeratePropertyFetch : PropertyFetch
+ {
+ public EnumeratePropertyFetch(Type type) : base(type) { }
+
+ public override object? Fetch(object? obj)
+ {
+ IEnumerable? enumerable = obj as IEnumerable;
+ Debug.Assert(enumerable is not null);
+
+ // string.Join for a non-generic IEnumerable
+ IEnumerator en = enumerable.GetEnumerator();
+ using (IDisposable? disposable = en as IDisposable)
+ {
+ if (!en.MoveNext())
+ {
+ return string.Empty;
+ }
+
+ object? currentValue = en.Current;
+ string? firstString = currentValue?.ToString();
+
+ // If there's only 1 item, simply return the ToString of that
+ if (!en.MoveNext())
+ {
+ // Only one value available
+ return firstString ?? string.Empty;
+ }
+
+ var result = new ValueStringBuilder(stackalloc char[256]);
+
+ result.Append(firstString);
+
+ do
+ {
+ currentValue = en.Current;
+
+ result.Append(",");
+ if (currentValue != null)
+ {
+ result.Append(currentValue.ToString());
+ }
+ }
+ while (en.MoveNext());
+
+ return result.ToString();
+ }
+ }
+ }
+#endif
+
///
/// A fetcher that returns the result of Activity.Current
///
@@ -1431,17 +1526,17 @@ public EnumeratePropertyFetch(Type type) : base(type) { }
return string.Join(",", (IEnumerable)obj);
}
}
- #endregion
+#endregion
}
private readonly string _propertyName;
private volatile PropertyFetch? _fetchForExpectedType;
- #endregion
+#endregion
}
private readonly string _outputName = null!;
private readonly PropertySpec? _fetches;
- #endregion
+#endregion
}
///
@@ -1454,13 +1549,13 @@ internal sealed class CallbackObserver : IObserver
{
public CallbackObserver(Action callback) { _callback = callback; }
- #region private
+#region private
public void OnCompleted() { }
public void OnError(Exception error) { }
public void OnNext(T value) { _callback(value); }
private readonly Action _callback;
- #endregion
+#endregion
}
// A linked list of IObservable subscriptions (which are IDisposable).
@@ -1477,11 +1572,11 @@ public Subscriptions(IDisposable subscription, Subscriptions? next)
public Subscriptions? Next;
}
- #endregion
+#endregion
private FilterAndTransform? _specs; // Transformation specifications that indicate which sources/events are forwarded.
private FilterAndTransform? _activitySourceSpecs; // ActivitySource Transformation specifications that indicate which sources/events are forwarded.
private ActivityListener? _activityListener;
- #endregion
+#endregion
}
}
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/HttpHandlerDiagnosticListener.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/HttpHandlerDiagnosticListener.cs
index a35ea9ce5807d4..94d4192721ca54 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/HttpHandlerDiagnosticListener.cs
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/HttpHandlerDiagnosticListener.cs
@@ -25,7 +25,6 @@ namespace System.Diagnostics
/// when it sees the System.Net.Http.Desktop source, subscribe to it. This will trigger the
/// initialization of this DiagnosticListener.
///
- [RequiresDynamicCode(WriteRequiresDynamicCode)]
internal sealed class HttpHandlerDiagnosticListener : DiagnosticListener
{
///
@@ -204,7 +203,6 @@ public override void Remove(object key)
/// intercept each new ServicePoint object being added to ServicePointManager.s_ServicePointTable
/// and replace its ConnectionGroupList hashtable field.
///
- [RequiresDynamicCode(WriteRequiresDynamicCode)]
private sealed class ServicePointHashtable : HashtableWrapper
{
public ServicePointHashtable(Hashtable table) : base(table)
@@ -245,7 +243,6 @@ public override object this[object key]
/// intercept each new ConnectionGroup object being added to ServicePoint.m_ConnectionGroupList
/// and replace its m_ConnectionList arraylist field.
///
- [RequiresDynamicCode(WriteRequiresDynamicCode)]
private sealed class ConnectionGroupHashtable : HashtableWrapper
{
public ConnectionGroupHashtable(Hashtable table) : base(table)
@@ -485,7 +482,6 @@ public override void TrimToSize()
/// intercept each new Connection object being added to ConnectionGroup.m_ConnectionList
/// and replace its m_WriteList arraylist field.
///
- [RequiresDynamicCode(WriteRequiresDynamicCode)]
private sealed class ConnectionArrayList : ArrayListWrapper
{
public ConnectionArrayList(ArrayList list) : base(list)
@@ -516,7 +512,6 @@ public override int Add(object value)
/// It also intercepts all HttpWebRequest objects that are about to get removed from
/// Connection.m_WriteList as they have completed the request.
///
- [RequiresDynamicCode(WriteRequiresDynamicCode)]
private sealed class HttpWebRequestArrayList : ArrayListWrapper
{
public HttpWebRequestArrayList(ArrayList list) : base(list)
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/DiagnosticSourceEventSourceTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/DiagnosticSourceEventSourceTests.cs
new file mode 100644
index 00000000000000..fab21b5a7b716c
--- /dev/null
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/DiagnosticSourceEventSourceTests.cs
@@ -0,0 +1,110 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Tracing;
+
+///
+/// Tests that using writing to a DiagnosticSource writes the correct payloads
+/// to the DiagnosticSourceEventSource.
+///
+internal class Program
+{
+ private class TestEventListener : EventListener
+ {
+ public ReadOnlyCollection