From 8a915d0e2c233debad68de2156fe1fb2ab145c68 Mon Sep 17 00:00:00 2001 From: Mattias Karlsson Date: Tue, 17 Sep 2019 17:28:44 +0200 Subject: [PATCH] Refactored Runtime Framework detection --- .../Fixtures/ScriptRunnerFixture.cs | 3 +- src/Cake.Core.Tests/Unit/CakeRuntimeTests.cs | 18 +++++++- src/Cake.Core/Polyfill/EnvironmentHelper.cs | 27 +++++++++++- src/Cake.Core/Scripting/IScriptConventions.cs | 6 +++ src/Cake.Core/Scripting/ScriptConventions.cs | 43 ++++++++++++++++++- src/Cake.Core/Scripting/ScriptRunner.cs | 5 ++- .../Cake.Core/Scripting/DefineDirective.cake | 39 ++++++++++++++++- tests/integration/setup.cake | 5 ++- 8 files changed, 138 insertions(+), 8 deletions(-) diff --git a/src/Cake.Core.Tests/Fixtures/ScriptRunnerFixture.cs b/src/Cake.Core.Tests/Fixtures/ScriptRunnerFixture.cs index f87ee8525d..c82a17019f 100644 --- a/src/Cake.Core.Tests/Fixtures/ScriptRunnerFixture.cs +++ b/src/Cake.Core.Tests/Fixtures/ScriptRunnerFixture.cs @@ -57,9 +57,10 @@ public ScriptRunnerFixture(string fileName = "/Working/build.cake") Engine = Substitute.For(); Engine.CreateSession(Arg.Any()).Returns(Session); + var runtime = new CakeRuntime(); ScriptAnalyzer = new ScriptAnalyzer(FileSystem, Environment, Log, new[] { new FileLoadDirectiveProvider(Globber, Log) }); ScriptProcessor = Substitute.For(); - ScriptConventions = new ScriptConventions(FileSystem, AssemblyLoader); + ScriptConventions = new ScriptConventions(FileSystem, AssemblyLoader, runtime); var context = Substitute.For(); context.Environment.Returns(c => Environment); diff --git a/src/Cake.Core.Tests/Unit/CakeRuntimeTests.cs b/src/Cake.Core.Tests/Unit/CakeRuntimeTests.cs index b08bf91a92..7a30c4bd53 100644 --- a/src/Cake.Core.Tests/Unit/CakeRuntimeTests.cs +++ b/src/Cake.Core.Tests/Unit/CakeRuntimeTests.cs @@ -26,7 +26,23 @@ public void Should_Return_Correct_Result_For_CoreClr() var framework = runtime.BuiltFramework; // Then - Assert.Equal(".NETStandard,Version=v2.0", framework.FullName); +#if NETFRAMEWORK + Assert.Equal(".NETFramework,Version=v4.6.1", +#elif !NETCOREAPP + Assert.Equal(".NETStandard,Version=v2.0", +#else + Assert.Equal(".NETCoreApp,Version=v" + +#endif +#if NETCOREAPP2_0 + "2.0", +#elif NETCOREAPP2_1 + "2.1", +#elif NETCOREAPP2_2 + "2.2", +#elif NETCOREAPP3_0 + "3.0", +#endif + framework.FullName); } } diff --git a/src/Cake.Core/Polyfill/EnvironmentHelper.cs b/src/Cake.Core/Polyfill/EnvironmentHelper.cs index e01a735c78..cd241b6ac7 100644 --- a/src/Cake.Core/Polyfill/EnvironmentHelper.cs +++ b/src/Cake.Core/Polyfill/EnvironmentHelper.cs @@ -4,6 +4,8 @@ using System; #if NETCORE +using System.Linq; +using System.Reflection; using System.Runtime.InteropServices; #endif using System.Runtime.Versioning; @@ -15,7 +17,9 @@ internal static class EnvironmentHelper #if !NETCORE private static bool? _isRunningOnMac; #else + private static readonly FrameworkName NetStandardFramework = new FrameworkName(".NETStandard,Version=v2.0"); private static bool? _isCoreClr; + private static FrameworkName netCoreAppFramwork; #endif public static bool Is64BitOperativeSystem() @@ -119,7 +123,28 @@ public static Runtime GetRuntime() public static FrameworkName GetBuiltFramework() { #if NETCORE - return new FrameworkName(".NETStandard,Version=v2.0"); + if (netCoreAppFramwork != null) + { + return netCoreAppFramwork; + } + + var assemblyPath = typeof(System.Runtime.GCSettings)?.GetTypeInfo()?.Assembly?.CodeBase; + + if (string.IsNullOrEmpty(assemblyPath)) + { + return NetStandardFramework; + } + + var netCoreAppVersion = string.Concat(assemblyPath.Skip(assemblyPath.IndexOf("Microsoft.NETCore.App") + 22).Take(3)); + + if (string.IsNullOrEmpty(netCoreAppVersion)) + { + return NetStandardFramework; + } + + return netCoreAppFramwork = Version.TryParse(netCoreAppVersion, out var version) + ? new FrameworkName(".NETCoreApp", version) + : NetStandardFramework; #else return new FrameworkName(".NETFramework,Version=v4.6.1"); #endif diff --git a/src/Cake.Core/Scripting/IScriptConventions.cs b/src/Cake.Core/Scripting/IScriptConventions.cs index 2467a93391..c58e2a6091 100644 --- a/src/Cake.Core/Scripting/IScriptConventions.cs +++ b/src/Cake.Core/Scripting/IScriptConventions.cs @@ -25,5 +25,11 @@ public interface IScriptConventions /// The root to where to find Cake related assemblies. /// A list containing all default assemblies. IReadOnlyList GetDefaultAssemblies(DirectoryPath root); + + /// + /// Gets the default defines. + /// + /// A list containing all default defines. + IReadOnlyList GetDefaultDefines(); } } \ No newline at end of file diff --git a/src/Cake.Core/Scripting/ScriptConventions.cs b/src/Cake.Core/Scripting/ScriptConventions.cs index 31aa6096e2..b34c8db310 100644 --- a/src/Cake.Core/Scripting/ScriptConventions.cs +++ b/src/Cake.Core/Scripting/ScriptConventions.cs @@ -18,16 +18,19 @@ public sealed class ScriptConventions : IScriptConventions { private readonly IFileSystem _fileSystem; private readonly IAssemblyLoader _loader; + private readonly ICakeRuntime _runtime; /// /// Initializes a new instance of the class. /// /// The file system. /// The assembly loader. - public ScriptConventions(IFileSystem fileSystem, IAssemblyLoader loader) + /// The Cake runtime. + public ScriptConventions(IFileSystem fileSystem, IAssemblyLoader loader, ICakeRuntime runtime) { _fileSystem = fileSystem; _loader = loader; + _runtime = runtime; } /// @@ -106,6 +109,44 @@ public IReadOnlyList GetDefaultAssemblies(DirectoryPath root) return result.ToArray(); } + /// + /// Gets the default defines. + /// + /// A list containing all default defines. + public IReadOnlyList GetDefaultDefines() + { + return new[] + { + "#define CAKE", + _runtime.IsCoreClr ? "#define NETCOREAPP" : "#define NETFRAMEWORK", + $"#define {GetFrameworkDefine()}" + }; + } + + private string GetFrameworkDefine() + { + switch (_runtime.BuiltFramework.FullName) + { + case ".NETFramework,Version=v4.6.1": + return "NET461"; + + case ".NETCoreApp,Version=v2.0": + return "NETCOREAPP2_0"; + + case ".NETCoreApp,Version=v2.1": + return "NETCOREAPP2_1"; + + case ".NETCoreApp,Version=v2.2": + return "NETCOREAPP2_2"; + + case ".NETCoreApp,Version=v3.0": + return "NETCOREAPP3_0"; + + default: + return "NETSTANDARD2_0"; + } + } + private List LoadCakeAssemblies(DirectoryPath root) { var result = new List(); diff --git a/src/Cake.Core/Scripting/ScriptRunner.cs b/src/Cake.Core/Scripting/ScriptRunner.cs index cefde3c0ee..a2ee3db166 100644 --- a/src/Cake.Core/Scripting/ScriptRunner.cs +++ b/src/Cake.Core/Scripting/ScriptRunner.cs @@ -206,8 +206,11 @@ public void Run(IScriptHost host, FilePath scriptPath, IDictionary(result.Defines, StringComparer.Ordinal); + defines.AddRange(_conventions.GetDefaultDefines()); + // Execute the script. - var script = new Script(result.Namespaces, result.Lines, aliases, result.UsingAliases, result.UsingStaticDirectives, result.Defines); + var script = new Script(result.Namespaces, result.Lines, aliases, result.UsingAliases, result.UsingStaticDirectives, defines); session.Execute(script); } diff --git a/tests/integration/Cake.Core/Scripting/DefineDirective.cake b/tests/integration/Cake.Core/Scripting/DefineDirective.cake index 4bd15e733f..3690c6b5fb 100644 --- a/tests/integration/Cake.Core/Scripting/DefineDirective.cake +++ b/tests/integration/Cake.Core/Scripting/DefineDirective.cake @@ -26,8 +26,45 @@ Task("Cake.Core.Scripting.DefineDirective.NotDefined") Assert.False(bar); }); +Task("Cake.Core.Scripting.DefineDirective.Runtime") + .Does(context => +{ +#if NETFRAMEWORK + Assert.Equal(".NETFramework,Version=v4.6.1", +#elif !NETCOREAPP + Assert.Equal(".NETStandard,Version=v2.0", +#else + Assert.Equal(".NETCoreApp,Version=v" + +#endif +#if NETCOREAPP2_0 + "2.0", +#elif NETCOREAPP2_1 + "2.1", +#elif NETCOREAPP2_2 + "2.2", +#elif NETCOREAPP3_0 + "3.0", +#endif + context.Environment.Runtime.BuiltFramework.FullName); +}); + +Task("Cake.Core.Scripting.DefineDirective.Cake") + .Does(() => +{ + bool cake; +#if (CAKE) + cake = true; +#else + cake = false; +#endif + Assert.True(cake); +}); + + ////////////////////////////////////////////////////////////////////////////// Task("Cake.Core.Scripting.DefineDirective") .IsDependentOn("Cake.Core.Scripting.DefineDirective.Defined") - .IsDependentOn("Cake.Core.Scripting.DefineDirective.NotDefined"); \ No newline at end of file + .IsDependentOn("Cake.Core.Scripting.DefineDirective.NotDefined") + .IsDependentOn("Cake.Core.Scripting.DefineDirective.Runtime") + .IsDependentOn("Cake.Core.Scripting.DefineDirective.Cake"); \ No newline at end of file diff --git a/tests/integration/setup.cake b/tests/integration/setup.cake index 039454c2c9..054881f263 100644 --- a/tests/integration/setup.cake +++ b/tests/integration/setup.cake @@ -17,11 +17,12 @@ Setup(setupContext => // Output information from setup task setupContext.Log.Information( Verbosity.Quiet, - "Performing setup initated by {0} ({1} tasks to be executed beginning with {2}, performing {3} build)", + "Performing setup initated by {0} ({1} tasks to be executed beginning with {2}, performing {3} build on {4})", setupContext.TargetTask?.Name, setupContext.TasksToExecute?.Count, setupContext.TasksToExecute?.Select(task => task.Name).FirstOrDefault(), - BuildSystem.Provider + BuildSystem.Provider, + setupContext.Environment.Runtime.BuiltFramework ); // Perform artifact cleanup