11using System ;
22using System . Diagnostics ;
3+ using System . Diagnostics . CodeAnalysis ;
34using System . IO ;
45using System . Linq ;
56using System . Reflection ;
67using System . Runtime . Versioning ;
8+ using BenchmarkDotNet . Helpers ;
79using BenchmarkDotNet . Extensions ;
810using BenchmarkDotNet . Jobs ;
911using BenchmarkDotNet . Portability ;
@@ -47,6 +49,13 @@ public static CoreRuntime CreateForNewVersion(string msBuildMoniker, string disp
4749 return new CoreRuntime ( RuntimeMoniker . NotRecognized , msBuildMoniker , displayName ) ;
4850 }
4951
52+ internal static CoreRuntime GetTargetOrCurrentVersion ( Assembly ? assembly )
53+ // Try to determine the version that the assembly was compiled for.
54+ => FrameworkVersionHelper . GetTargetCoreVersion ( assembly ) is { } version
55+ ? FromVersion ( version , assembly )
56+ // Fallback to the current running version.
57+ : GetCurrentVersion ( ) ;
58+
5059 internal static CoreRuntime GetCurrentVersion ( )
5160 {
5261 if ( ! RuntimeInformation . IsNetCore )
@@ -59,28 +68,24 @@ internal static CoreRuntime GetCurrentVersion()
5968 throw new NotSupportedException ( "Unable to recognize .NET Core version, please report a bug at https://github.com/dotnet/BenchmarkDotNet" ) ;
6069 }
6170
62- return FromVersion ( version ) ;
71+ return FromVersion ( version , null ) ;
6372 }
6473
65- internal static CoreRuntime FromVersion ( Version version )
74+ internal static CoreRuntime FromVersion ( Version version , Assembly ? assembly = null ) => version switch
6675 {
67- switch ( version )
68- {
69- case Version v when v . Major == 2 && v . Minor == 0 : return Core20 ;
70- case Version v when v . Major == 2 && v . Minor == 1 : return Core21 ;
71- case Version v when v . Major == 2 && v . Minor == 2 : return Core22 ;
72- case Version v when v . Major == 3 && v . Minor == 0 : return Core30 ;
73- case Version v when v . Major == 3 && v . Minor == 1 : return Core31 ;
74- case Version v when v . Major == 5 && v . Minor == 0 : return GetPlatformSpecific ( Core50 ) ;
75- case Version v when v . Major == 6 && v . Minor == 0 : return GetPlatformSpecific ( Core60 ) ;
76- case Version v when v . Major == 7 && v . Minor == 0 : return GetPlatformSpecific ( Core70 ) ;
77- case Version v when v . Major == 8 && v . Minor == 0 : return GetPlatformSpecific ( Core80 ) ;
78- case Version v when v . Major == 9 && v . Minor == 0 : return GetPlatformSpecific ( Core90 ) ;
79- case Version v when v . Major == 10 && v . Minor == 0 : return GetPlatformSpecific ( Core10_0 ) ;
80- default :
81- return CreateForNewVersion ( $ "net{ version . Major } .{ version . Minor } ", $ ".NET { version . Major } .{ version . Minor } ") ;
82- }
83- }
76+ { Major : 2 , Minor : 0 } => Core20 ,
77+ { Major : 2 , Minor : 1 } => Core21 ,
78+ { Major : 2 , Minor : 2 } => Core22 ,
79+ { Major : 3 , Minor : 0 } => Core30 ,
80+ { Major : 3 , Minor : 1 } => Core31 ,
81+ { Major : 5 } => GetPlatformSpecific ( Core50 , assembly ) ,
82+ { Major : 6 } => GetPlatformSpecific ( Core60 , assembly ) ,
83+ { Major : 7 } => GetPlatformSpecific ( Core70 , assembly ) ,
84+ { Major : 8 } => GetPlatformSpecific ( Core80 , assembly ) ,
85+ { Major : 9 } => GetPlatformSpecific ( Core90 , assembly ) ,
86+ { Major : 10 } => GetPlatformSpecific ( Core10_0 , assembly ) ,
87+ _ => CreateForNewVersion ( $ "net{ version . Major } .{ version . Minor } ", $ ".NET { version . Major } .{ version . Minor } ") ,
88+ } ;
8489
8590 internal static bool TryGetVersion ( out Version ? version )
8691 {
@@ -220,29 +225,36 @@ internal static bool TryGetVersionFromFrameworkName(string frameworkName, out Ve
220225 // Version.TryParse does not handle thing like 3.0.0-WORD
221226 internal static string GetParsableVersionPart ( string fullVersionName ) => new string ( fullVersionName . TakeWhile ( c => char . IsDigit ( c ) || c == '.' ) . ToArray ( ) ) ;
222227
223- private static CoreRuntime GetPlatformSpecific ( CoreRuntime fallback )
228+ private static CoreRuntime GetPlatformSpecific ( CoreRuntime fallback , Assembly ? assembly )
229+ => TryGetTargetPlatform ( assembly ?? Assembly . GetEntryAssembly ( ) , out var platform )
230+ ? new CoreRuntime ( fallback . RuntimeMoniker , $ "{ fallback . MsBuildMoniker } -{ platform } ", fallback . Name )
231+ : fallback ;
232+
233+ internal static bool TryGetTargetPlatform ( Assembly ? assembly , [ NotNullWhen ( true ) ] out string ? platform )
224234 {
225- // TargetPlatformAttribute is not part of .NET Standard 2.0 so as usuall we have to use some reflection hacks...
235+ platform = null ;
236+
237+ if ( assembly is null )
238+ return false ;
239+
240+ // TargetPlatformAttribute is not part of .NET Standard 2.0 so as usual we have to use some reflection hacks.
226241 var targetPlatformAttributeType = typeof ( object ) . Assembly . GetType ( "System.Runtime.Versioning.TargetPlatformAttribute" , throwOnError : false ) ;
227242 if ( targetPlatformAttributeType is null ) // an old preview version of .NET 5
228- return fallback ;
229-
230- var exe = Assembly . GetEntryAssembly ( ) ;
231- if ( exe is null )
232- return fallback ;
243+ return false ;
233244
234- var attributeInstance = exe . GetCustomAttribute ( targetPlatformAttributeType ) ;
245+ var attributeInstance = assembly . GetCustomAttribute ( targetPlatformAttributeType ) ;
235246 if ( attributeInstance is null )
236- return fallback ;
247+ return false ;
237248
238249 var platformNameProperty = targetPlatformAttributeType . GetProperty ( "PlatformName" ) ;
239250 if ( platformNameProperty is null )
240- return fallback ;
251+ return false ;
241252
242- if ( ! ( platformNameProperty . GetValue ( attributeInstance ) is string platformName ) )
243- return fallback ;
253+ if ( platformNameProperty . GetValue ( attributeInstance ) is not string platformName )
254+ return false ;
244255
245- return new CoreRuntime ( fallback . RuntimeMoniker , $ "{ fallback . MsBuildMoniker } -{ platformName } ", fallback . Name ) ;
256+ platform = platformName ;
257+ return true ;
246258 }
247259 }
248260}
0 commit comments