diff --git a/Cake.Recipe/Content/build.cake b/Cake.Recipe/Content/build.cake index 482b9115..7e57f6a1 100644 --- a/Cake.Recipe/Content/build.cake +++ b/Cake.Recipe/Content/build.cake @@ -106,6 +106,7 @@ Teardown((context, buildVersion) => BuildParameters.Tasks.ShowInfoTask = Task("Show-Info") .Does(() => { + Information("Build Platform: {0}", BuildParameters.Platform); Information("Target: {0}", BuildParameters.Target); Information("Configuration: {0}", BuildParameters.Configuration); Information("PrepareLocalRelease: {0}", BuildParameters.PrepareLocalRelease); diff --git a/Cake.Recipe/Content/buildPlatform.cake b/Cake.Recipe/Content/buildPlatform.cake new file mode 100644 index 00000000..8d3df56b --- /dev/null +++ b/Cake.Recipe/Content/buildPlatform.cake @@ -0,0 +1,233 @@ +using System.Runtime.InteropServices; + +public class BuildPlatform +{ + protected ICakeContext context; + + public BuildPlatform(ICakeContext context) + { + this.context = context; + SystemVersion = System.Environment.OSVersion.Version.ToString(); + SystemName = RuntimeInformation.OSDescription.Trim(); + OperatingSystem = context.Environment.Platform.Family; + SystemArchitecture = RuntimeInformation.OSArchitecture.ToString(); + } + + public PlatformFamily OperatingSystem { get; private set; } + public string SystemName { get; private set; } + public string SystemDistro { get; protected set; } = ""; + public string SystemDistroId { get; protected set; } = ""; + public string SystemVersion { get; protected set; } + public string SystemArchitecture { get; private set; } + + public static BuildPlatform Create(ICakeContext context) + { + BuildPlatform result; + if (context.Environment.Platform.Family != PlatformFamily.Linux) + { + result = new BuildPlatform(context); + } + else + { + result = new LinuxBuildPlatform(context); + } + + return result; + } + + public virtual void CopyLibGit2Binaries(params string[] globbingPatterns) + { + } + + public virtual void PatchGitLib2ConfigFiles(string globbingPattern = "**/LibGit2Sharp.dll.config") + { + } + + public override string ToString() + { + if (!string.IsNullOrEmpty(SystemDistro)) + { + return string.Format("{0} {1} ({2})", SystemDistro, SystemVersion, SystemArchitecture); + } + else if (OperatingSystem == PlatformFamily.Windows) + { + // Windows have the system version in the SystemName + return string.Format("{0} ({1})", SystemName, SystemArchitecture); + } + else + { + return string.Format("{0} {1} ({2})", SystemName, SystemVersion, SystemArchitecture); + } + } +} + +public class LinuxBuildPlatform : BuildPlatform +{ + public LinuxBuildPlatform(ICakeContext context) + : base(context) + { + SetSystemInformation(); + } + + public override void CopyLibGit2Binaries(params string[] globbingPatterns) + { + var addinPath = GetAddinPath(context); + var copyToFiles = context.GetFiles(globbingPatterns.Select(g => addinPath.CombineWithFilePath(g).ToString()).ToArray()); + + string libgit2Path = GetLibGit2Path(context); + + if (String.IsNullOrEmpty(libgit2Path)) + { + return; + } + + foreach (var file in copyToFiles) + { + if (context.FileExists(file)) + { + context.DeleteFile(file); + } + context.Verbose("Copying system library from '{0}' to '{1}'", libgit2Path, file); + context.CopyFile(libgit2Path, file); + } + } + + public override void PatchGitLib2ConfigFiles(string globbingPattern = "**/LibGit2Sharp.dll.config") + { + var toolPath = context.Configuration.GetToolPath(".", context.Environment); + var configFiles = context.GetFiles(toolPath.CombineWithFilePath(globbingPattern).ToString()); + + var libgit2Path = GetLibGit2Path(context); + + if (String.IsNullOrEmpty(libgit2Path)) + { + return; + } + + // This is a workaround for Ubuntu 18.04 especially. + // as gitversion will fail if we add a dllmap to the system + // libgit2 library. + var relativeExpected = "lib/"; + if (!string.IsNullOrEmpty(SystemDistroId)) + { + if (!string.IsNullOrEmpty(SystemVersion) + && Version.TryParse(SystemVersion, out _)) + { + relativeExpected += string.Format("{0}.{1}-{2}", + SystemDistroId, + SystemVersion, + SystemArchitecture); + } + else + { + relativeExpected += string.Format("{0}-{1}", + SystemDistroId, + SystemArchitecture); + } + } + + foreach (var config in configFiles) + { + if (!relativeExpected.Equals("lib/")) + { + var parent = config.GetDirectory(); + var expectedPath = parent.Combine(relativeExpected); + if (context.DirectoryExists(expectedPath)) + { + continue; + } + } + + var xml = System.Xml.Linq.XDocument.Load(config.ToString()); + + if (xml.Element("configuration").Elements("dllmap").All(e => e.Attribute("target").Value != libgit2Path)) + { + var dllName = xml.Element("configuration").Elements("dllmap").First(e => e.Attribute("os").Value == "linux").Attribute("dll").Value; + xml.Element("configuration") + .Add(new System.Xml.Linq.XElement("dllmap", + new System.Xml.Linq.XAttribute("os", "linux"), + new System.Xml.Linq.XAttribute("dll", dllName), + new System.Xml.Linq.XAttribute("target", libgit2Path))); + + context.Information($"Patching '{config}' to use fallback system path on Linux..."); + xml.Save(config.ToString()); + } + } + } + + // Shamelessly stolen from + private static DirectoryPath GetAddinPath(ICakeContext context) + { + var addinPath = context.Configuration.GetValue("Paths_Addins"); + if (!string.IsNullOrEmpty(addinPath)) + { + return new DirectoryPath(addinPath).MakeAbsolute(context.Environment); + } + + var toolPath = context.Configuration.GetToolPath(".", context.Environment); + return toolPath.Combine("Addins").Collapse(); + } + + private static string GetLibGit2Path(ICakeContext context) + { + var possiblePaths = new[] { + "/usr/lib*/libgit2.so*", + "/usr/lib/*/libgit2.so*" + }; + + foreach (var path in possiblePaths) { + var file = context.GetFiles(path).FirstOrDefault(); + if (file != null && !string.IsNullOrEmpty(file.ToString())) { + return file.ToString(); + } + } + + return null; + } + + private void SetSystemInformation() + { + string file; + if (context.FileExists("/etc/lsb-release")) + { + file = "/etc/lsb-release"; + } + else if (context.FileExists("/etc/os-release")) + { + file = "/etc/os-release"; + } + else + { + return; + } + + var lines = System.IO.File.ReadAllLines(file); + var details = lines.Where(l => !string.IsNullOrEmpty(l)) + .Select(l => l.Split('=')) + .Where(s => s.Length == 2) + .ToDictionary(s => s[0].ToUpperInvariant(), s => s[1]); + + if (details.ContainsKey("DISTRIB_ID")) + { + SystemDistroId = SystemDistro = details["DISTRIB_ID"]; + } + else if(details.ContainsKey("ID")) + { + SystemDistroId = details["ID"]; + } + + if (details.ContainsKey("NAME")) + { + SystemDistro = details["NAME"]; + } + + if (details.ContainsKey("DISTRIB_RELEASE")) + { + SystemVersion = details["DISTRIB_RELEASE"]; + } + else if (details.ContainsKey("BUILD_ID")) + { + SystemVersion = details["BUILD_ID"]; + } + } +} \ No newline at end of file diff --git a/Cake.Recipe/Content/gitversion.cake b/Cake.Recipe/Content/gitversion.cake index a522b2d6..d5a59b2c 100644 --- a/Cake.Recipe/Content/gitversion.cake +++ b/Cake.Recipe/Content/gitversion.cake @@ -51,9 +51,7 @@ public class BuildVersion if (BuildParameters.ShouldCalculateVersion) { - if (BuildParameters.BuildAgentOperatingSystem != PlatformFamily.Windows) { - PatchGitLibConfigFiles(context); - } + BuildParameters.Platform.PatchGitLib2ConfigFiles("**/GitVersion*/**/LibGit2Sharp.dll.config"); context.Information("Calculating Semantic Version..."); if (!BuildParameters.IsLocalBuild || BuildParameters.IsPublishBuild || BuildParameters.IsReleaseBuild || BuildParameters.PrepareLocalRelease) @@ -125,46 +123,4 @@ public class BuildVersion AssemblySemVer = assemblySemVer?.ToLowerInvariant() }; } - - private static void PatchGitLibConfigFiles(ICakeContext context) - { - var configFiles = context.GetFiles("./tools/**/LibGit2Sharp.dll.config"); - var libgitPath = GetLibGit2Path(context); - if (string.IsNullOrEmpty(libgitPath)) { return; } - - foreach (var config in configFiles) { - var xml = System.Xml.Linq.XDocument.Load(config.ToString()); - - if (xml.Element("configuration").Elements("dllmap") - .All(e => e.Attribute("target").Value != libgitPath)) { - - var dllName = xml.Element("configuration").Elements("dllmap").First(e => e.Attribute("os").Value == "linux").Attribute("dll").Value; - xml.Element("configuration") - .Add(new System.Xml.Linq.XElement("dllmap", - new System.Xml.Linq.XAttribute("os", "linux"), - new System.Xml.Linq.XAttribute("dll", dllName), - new System.Xml.Linq.XAttribute("target", libgitPath))); - - context.Information($"Patching '{config}' to use fallback system path on Linux..."); - xml.Save(config.ToString()); - } - } - } - - private static string GetLibGit2Path(ICakeContext context) - { - var possiblePaths = new[] { - "/usr/lib*/libgit2.so*", - "/usr/lib/*/libgit2.so*" - }; - - foreach (var path in possiblePaths) { - var file = context.GetFiles(path).FirstOrDefault(); - if (file != null && !string.IsNullOrEmpty(file.ToString())) { - return file.ToString(); - } - } - - return null; - } } diff --git a/Cake.Recipe/Content/parameters.cake b/Cake.Recipe/Content/parameters.cake index fb4b6d81..d9471f30 100644 --- a/Cake.Recipe/Content/parameters.cake +++ b/Cake.Recipe/Content/parameters.cake @@ -18,7 +18,8 @@ public static class BuildParameters public static string Configuration { get; private set; } public static Cake.Core.Configuration.ICakeConfiguration CakeConfiguration { get; private set; } public static bool IsLocalBuild { get; private set; } - public static PlatformFamily BuildAgentOperatingSystem { get; private set; } + public static PlatformFamily BuildAgentOperatingSystem => Platform.OperatingSystem; + public static BuildPlatform Platform { get; private set; } public static bool IsRunningOnAppVeyor { get; private set; } public static bool IsRunningOnTravisCI { get; private set; } public static bool IsPullRequest { get; private set; } @@ -420,6 +421,11 @@ public static class BuildParameters PreferredBuildAgentOperatingSystem = preferredBuildAgentOperatingSystem; PreferredBuildProviderType = preferredBuildProviderType; + Platform = BuildPlatform.Create(context); + + Platform.CopyLibGit2Binaries("**/netstandard*/**/libgit2*.so", "**/linux-x64/libgit2*.so"); + Platform.PatchGitLib2ConfigFiles(); + BuildProvider = GetBuildProvider(context, buildSystem); EmailRecipient = emailRecipient; @@ -553,8 +559,6 @@ public static class BuildParameters ); TreatWarningsAsErrors = treatWarningsAsErrors; - BuildAgentOperatingSystem = context.Environment.Platform.Family; - GitHub = GetGitHubCredentials(context); MicrosoftTeams = GetMicrosoftTeamsCredentials(context); Email = GetEmailCredentials(context);