diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json deleted file mode 100644 index 7bd5f9f..0000000 --- a/.config/dotnet-tools.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "version": 1, - "isRoot": true, - "tools": { - "cake.tool": { - "version": "2.2.0", - "commands": [ - "dotnet-cake" - ] - } - } -} \ No newline at end of file diff --git a/BepInEx.sln b/BepInEx.sln index c60101f..356b05d 100644 --- a/BepInEx.sln +++ b/BepInEx.sln @@ -3,11 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.32112.339 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BepInExTests", "BepInExTests\BepInExTests.csproj", "{E7CD429A-D057-48E3-8C51-E5C934E8E07B}" - ProjectSection(ProjectDependencies) = postProject - {4FFBA620-F5ED-47F9-B90C-DAD1316FD9B9} = {4FFBA620-F5ED-47F9-B90C-DAD1316FD9B9} - EndProjectSection -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BepInEx.Preloader.Core", "BepInEx.Preloader.Core\BepInEx.Preloader.Core.csproj", "{15F8BC38-A761-4F93-8903-1B531AC5D9F9}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BepInEx.Unity.Mono", "Runtimes\Unity\BepInEx.Unity.Mono\BepInEx.Unity.Mono.csproj", "{EAE9FAE6-8011-45A3-8B6E-0C7F14210533}" @@ -38,15 +33,12 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{12081C35-76DF-450C-AC83-1E1CB84516AA}" ProjectSection(SolutionItems) = preProject Directory.Build.props = Directory.Build.props - Directory.Build.targets = Directory.Build.targets EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Unity", "Unity", "{BF8F4E07-3B89-4152-89F4-9EF9D4AAA1E0}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BepInEx.Unity.Common", "Runtimes\Unity\BepInEx.Unity.Common\BepInEx.Unity.Common.csproj", "{C32E74A3-C0BD-42DE-9E2F-D033D496ACB9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{8AC60656-4159-4EFA-A43D-B132564697F3}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "IL2CPP", "IL2CPP", "{E4E75C18-4156-4213-A20C-8677EF6B5312}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Doorstop", "Doorstop", "{CE06453E-44E7-4D50-9A68-AA15F4C1C8D1}" @@ -57,6 +49,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Doorstop", "Doorstop", "{CE Runtimes\Unity\Doorstop\run_bepinex_mono.sh = Runtimes\Unity\Doorstop\run_bepinex_mono.sh EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Build", "build\Build.csproj", "{0C38DDF2-EAAA-43FA-BA0A-985636AC6040}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution BepInEx.NetLauncher.Shared\BepInEx.NetLauncher.Shared.projitems*{067bcc8c-fc25-4929-b4f4-c6a5a7496994}*SharedItemsImports = 13 @@ -78,13 +72,6 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8AC60656-4159-4EFA-A43D-B132564697F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8AC60656-4159-4EFA-A43D-B132564697F3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E7CD429A-D057-48E3-8C51-E5C934E8E07B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E7CD429A-D057-48E3-8C51-E5C934E8E07B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E7CD429A-D057-48E3-8C51-E5C934E8E07B}.Release_NetFramework|Any CPU.ActiveCfg = Release|Any CPU - {E7CD429A-D057-48E3-8C51-E5C934E8E07B}.Release_Unity|Any CPU.ActiveCfg = Release|Any CPU - {E7CD429A-D057-48E3-8C51-E5C934E8E07B}.Release|Any CPU.ActiveCfg = Release|Any CPU {15F8BC38-A761-4F93-8903-1B531AC5D9F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {15F8BC38-A761-4F93-8903-1B531AC5D9F9}.Debug|Any CPU.Build.0 = Debug|Any CPU {15F8BC38-A761-4F93-8903-1B531AC5D9F9}.Release_NetFramework|Any CPU.ActiveCfg = Release|Any CPU @@ -154,6 +141,12 @@ Global {C32E74A3-C0BD-42DE-9E2F-D033D496ACB9}.Release_Unity|Any CPU.Build.0 = Debug|Any CPU {C32E74A3-C0BD-42DE-9E2F-D033D496ACB9}.Release|Any CPU.ActiveCfg = Release|Any CPU {C32E74A3-C0BD-42DE-9E2F-D033D496ACB9}.Release|Any CPU.Build.0 = Release|Any CPU + {0C38DDF2-EAAA-43FA-BA0A-985636AC6040}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C38DDF2-EAAA-43FA-BA0A-985636AC6040}.Release_NetFramework|Any CPU.ActiveCfg = Debug|Any CPU + {0C38DDF2-EAAA-43FA-BA0A-985636AC6040}.Release_NetFramework|Any CPU.Build.0 = Debug|Any CPU + {0C38DDF2-EAAA-43FA-BA0A-985636AC6040}.Release_Unity|Any CPU.ActiveCfg = Debug|Any CPU + {0C38DDF2-EAAA-43FA-BA0A-985636AC6040}.Release_Unity|Any CPU.Build.0 = Debug|Any CPU + {0C38DDF2-EAAA-43FA-BA0A-985636AC6040}.Release|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Directory.Build.targets b/Directory.Build.targets deleted file mode 100644 index 42c44a2..0000000 --- a/Directory.Build.targets +++ /dev/null @@ -1,5 +0,0 @@ - - - $(BuildDir)/$(DistributionIdentifier)/ - - diff --git a/Runtimes/NET/BepInEx.NET.CoreCLR/BepInEx.NET.CoreCLR.csproj b/Runtimes/NET/BepInEx.NET.CoreCLR/BepInEx.NET.CoreCLR.csproj index 568de2d..d42685d 100644 --- a/Runtimes/NET/BepInEx.NET.CoreCLR/BepInEx.NET.CoreCLR.csproj +++ b/Runtimes/NET/BepInEx.NET.CoreCLR/BepInEx.NET.CoreCLR.csproj @@ -1,8 +1,11 @@ + BepInEx support library for CoreCLR games netcoreapp3.1 - NET.CoreCLR + $(BuildDir)/NET.CoreCLR + true + false diff --git a/Runtimes/NET/BepInEx.NET.Framework.Launcher/BepInEx.NET.Framework.Launcher.csproj b/Runtimes/NET/BepInEx.NET.Framework.Launcher/BepInEx.NET.Framework.Launcher.csproj index 15b064d..f6aa5ac 100644 --- a/Runtimes/NET/BepInEx.NET.Framework.Launcher/BepInEx.NET.Framework.Launcher.csproj +++ b/Runtimes/NET/BepInEx.NET.Framework.Launcher/BepInEx.NET.Framework.Launcher.csproj @@ -6,7 +6,7 @@ true false x86 - NET.Framework + $(BuildDir)/NET.Framework diff --git a/Runtimes/Unity/BepInEx.Unity.IL2CPP/BepInEx.Unity.IL2CPP.csproj b/Runtimes/Unity/BepInEx.Unity.IL2CPP/BepInEx.Unity.IL2CPP.csproj index 8d7a0aa..299e879 100644 --- a/Runtimes/Unity/BepInEx.Unity.IL2CPP/BepInEx.Unity.IL2CPP.csproj +++ b/Runtimes/Unity/BepInEx.Unity.IL2CPP/BepInEx.Unity.IL2CPP.csproj @@ -4,7 +4,7 @@ net6.0 true true - Unity.IL2CPP + $(BuildDir)/Unity.IL2CPP false diff --git a/Runtimes/Unity/BepInEx.Unity.Mono.Preloader/BepInEx.Unity.Mono.Preloader.csproj b/Runtimes/Unity/BepInEx.Unity.Mono.Preloader/BepInEx.Unity.Mono.Preloader.csproj index 8fcb2df..be4f0f6 100644 --- a/Runtimes/Unity/BepInEx.Unity.Mono.Preloader/BepInEx.Unity.Mono.Preloader.csproj +++ b/Runtimes/Unity/BepInEx.Unity.Mono.Preloader/BepInEx.Unity.Mono.Preloader.csproj @@ -5,7 +5,7 @@ - Unity.IL2CPP + $(BuildDir)/Unity.Mono false diff --git a/Runtimes/Unity/BepInEx.Unity.Mono/BepInEx.Unity.Mono.csproj b/Runtimes/Unity/BepInEx.Unity.Mono/BepInEx.Unity.Mono.csproj index c1e8c71..2cd1157 100644 --- a/Runtimes/Unity/BepInEx.Unity.Mono/BepInEx.Unity.Mono.csproj +++ b/Runtimes/Unity/BepInEx.Unity.Mono/BepInEx.Unity.Mono.csproj @@ -6,7 +6,7 @@ - Unity.Mono + $(BuildDir)/Unity.Mono false diff --git a/build.bat b/build.bat deleted file mode 100644 index 9cecbba..0000000 --- a/build.bat +++ /dev/null @@ -1 +0,0 @@ -powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File %CD%\build.ps1 %* \ No newline at end of file diff --git a/build.cake b/build.cake deleted file mode 100644 index b0cc7bf..0000000 --- a/build.cake +++ /dev/null @@ -1,331 +0,0 @@ -#nullable enable -#addin nuget:?package=Cake.FileHelpers&version=4.0.1 -#addin nuget:?package=SharpZipLib&version=1.3.1 -#addin nuget:?package=Cake.Compression&version=0.2.6 -#addin nuget:?package=Cake.Json&version=6.0.1 -#addin nuget:?package=Newtonsoft.Json&version=13.0.1 -#addin nuget:?package=Cake.Http&version=1.3.0 - -var task = Argument("target", "Build"); // Note: "target" is special Cake argument, don't change -var isBleedingEdge = Argument("bleeding_edge", false); -var buildId = Argument("build_id", 0); -var cleanDependencyCache = Argument("clean_build_cache", false); -var lastBuildCommit = Argument("last_build_commit", ""); -var nugetPushSource = Argument("nuget_push_source", "https://nuget.bepinex.dev/v3/index.json"); -var nugetPushKey = Argument("nuget_push_key", ""); - -var buildVersion = ""; -var currentCommit = RunGit("rev-parse HEAD"); -var currentCommitShort = RunGit("log -n 1 --pretty=\"format:%h\"").Trim(); -var currentBranch = RunGit("rev-parse --abbrev-ref HEAD"); -var latestTag = RunGit("describe --tags --abbrev=0"); - -string RunGit(string command, string separator = "") { - using var process = StartAndReturnProcess("git", new() { Arguments = command, RedirectStandardOutput = true }); - process.WaitForExit(); - return string.Join(separator, process.GetStandardOutput()); -} - -readonly record struct Target(string Abi, string Os, string Cpu, bool NeedsRuntime = false) { - public string Abi { get; } = Abi.Contains('-') ? throw new FormatException($"Target ABI cannot be hyphenated: {Abi}") : Abi; - public string Os { get; } = Os.Contains('-') ? throw new FormatException($"Target OS cannot be hyphenated: {Os}") : Os; - public string Cpu { get; } = Cpu.Contains('-') ? throw new FormatException($"Target CPU cannot be hyphenated: {Cpu}") : Cpu; - - public string RuntimeIdentifier => $"{Os}-{Cpu}"; - - public override string ToString() => $"{Abi}-{Os}-{Cpu}"; - - public bool IsUnix => Os is "unix" or "linux" or "macos"; - - public string LibExt => Os switch { - "macos" => "dylib", - "linux" => "so", - "windows" => "dll", - _ => throw new NotSupportedException($"Target OS {Os} is not supported") - }; - - public string LibPrefix => IsUnix ? "lib" : ""; -} - -var targets = new Target[] { - new("UnityMono", "windows", "x86"), - new("UnityMono", "windows", "x64"), - new("UnityMono", "linux", "x86"), - new("UnityMono", "linux", "x64"), - new("UnityMono", "macos", "x64"), - new("UnityIL2CPP", "windows", "x86", true), - new("UnityIL2CPP", "windows", "x64", true), - new("UnityIL2CPP", "linux", "x64", true), - new("UnityIL2CPP", "macos", "x64", true), - new("NetLauncher", "windows", "any"), -}; - -const string DEP_CACHE_NAME = ".dep_cache"; - -Task("Cleanup") - .Does(() => -{ - Information("Removing old binaries"); - CreateDirectory("./bin"); - CleanDirectory("./bin", fi => { - var cachePath = fi.Path.FullPath.Contains(DEP_CACHE_NAME); - return !cachePath || cleanDependencyCache && cachePath; - }); - - Information("Cleaning up old build objects"); - CleanDirectories(GetDirectories(new GlobPattern("./BepInEx.*/**/bin/"))); - CleanDirectories(GetDirectories(new GlobPattern("./BepInEx.*/**/obj/"))); -}); - -Task("Build") - .IsDependentOn("Cleanup") - .Does(() => -{ - // Used in later phases - buildVersion = FindRegexMatchGroupInFile(File("Directory.Build.props"), @"\([0-9]+\.[0-9]+\.[0-9]+)\<\/VersionPrefix\>", 1, System.Text.RegularExpressions.RegexOptions.None).Value; - - var buildSettings = new DotNetBuildSettings { - Configuration = "Release", - MSBuildSettings = new() // Apparently needed in some versions of CakeBuild - }; - - if (isBleedingEdge) { - buildSettings.MSBuildSettings.Properties["VersionSuffix"] = new[] { $"be.{buildId}" }; - buildSettings.MSBuildSettings.Properties["SourceRevisionId"] = new[] { currentCommit }; - buildSettings.MSBuildSettings.Properties["RepositoryBranch"] = new[] { currentBranch }; - buildVersion += $"-be.{buildId}+{currentCommitShort}"; - } - - foreach (var file in GetFiles("./BepInEx.*/*.csproj")) { - DotNetBuild(file.FullPath, buildSettings); - } -}); - -const string DOORSTOP_VER = "4.0.0-rc.7"; -const string DOTNET_MINI_VER = "6.0.6"; -const string DOORSTOP_PROXY_DLL = "winhttp.dll"; -const string DOBBY_VER = "1.0.0"; - -var depCachePath = Directory($"./bin/{DEP_CACHE_NAME}"); -var doorstopPath = depCachePath + Directory("doorstop"); -var dotnetPath = depCachePath + Directory("dotnet"); -var dobbyPath = depCachePath + Directory("dobby"); - -Task("DownloadDependencies") - .Does(() => -{ - var cacheFile = depCachePath + File("cache.json"); - var cache = FileExists(cacheFile) ? DeserializeJsonFromFile>(cacheFile) : new Dictionary(); - - bool NeedsRedownload(string repo, string curVer) { - if (!cache.TryGetValue(repo, out var ver) || ver != curVer) { - cache[repo] = curVer; - return true; - } - return false; - } - - CreateDirectory(doorstopPath); - CreateDirectory(dotnetPath); - CreateDirectory(dobbyPath); - - if (NeedsRedownload("NeighTools/UnityDoorstop", DOORSTOP_VER)) { - Information("Updating Doorstop"); - var doorstopZipPathWin = depCachePath + File("doorstop_win.zip"); - var doorstopZipPathLinux = depCachePath + File("doorstop_linux.zip"); - var doorstopZipPathMacOs = depCachePath + File("doorstop_macos.zip"); - - DownloadFile($"https://github.com/NeighTools/UnityDoorstop/releases/download/v{DOORSTOP_VER}/doorstop_win_release_{DOORSTOP_VER}.zip", doorstopZipPathWin); - DownloadFile($"https://github.com/NeighTools/UnityDoorstop/releases/download/v{DOORSTOP_VER}/doorstop_linux_release_{DOORSTOP_VER}.zip", doorstopZipPathLinux); - DownloadFile($"https://github.com/NeighTools/UnityDoorstop/releases/download/v{DOORSTOP_VER}/doorstop_macos_release_{DOORSTOP_VER}.zip", doorstopZipPathMacOs); - - CleanDirectory(doorstopPath); - ZipUncompress(doorstopZipPathWin, doorstopPath + Directory("windows")); - ZipUncompress(doorstopZipPathLinux, doorstopPath + Directory("linux")); - ZipUncompress(doorstopZipPathMacOs, doorstopPath + Directory("macos")); - } - - if (NeedsRedownload("BepInEx/Dobby", DOBBY_VER)) { - Information("Updating Dobby"); - var dobbyZipPathWin = depCachePath + File("dobby_win.zip"); - var dobbyZipPathLinux = depCachePath + File("dobby_linux.zip"); - var dobbyZipPathMacOs = depCachePath + File("dobby_macos.zip"); - - DownloadFile($"https://github.com/BepInEx/Dobby/releases/download/v{DOBBY_VER}/dobby-win.zip", dobbyZipPathWin); - DownloadFile($"https://github.com/BepInEx/Dobby/releases/download/v{DOBBY_VER}/dobby-linux.zip", dobbyZipPathLinux); - DownloadFile($"https://github.com/BepInEx/Dobby/releases/download/v{DOBBY_VER}/dobby-macos.zip", dobbyZipPathMacOs); - - CleanDirectory(dobbyPath); - ZipUncompress(dobbyZipPathWin, dobbyPath + Directory("windows")); - ZipUncompress(dobbyZipPathLinux, dobbyPath + Directory("linux")); - ZipUncompress(dobbyZipPathMacOs, dobbyPath + Directory("macos")); - } - - if (NeedsRedownload("BepInEx/dotnet-runtime", DOTNET_MINI_VER)) { - Information("Updating mini-dotnet, this might take a while"); - - var dotnetZipPath = depCachePath + File("dotnet-mini.zip"); - - DownloadFile($"https://github.com/BepInEx/dotnet-runtime/releases/download/{DOTNET_MINI_VER}/mini-coreclr-Release.zip", dotnetZipPath); - - CleanDirectory(dotnetPath); - ZipUncompress(dotnetZipPath, dotnetPath); - } - - SerializeJsonToFile(cacheFile, cache); -}); - -Task("PushNuGet") - .IsDependentOn("Build") - .Does(() => -{ - if (nugetPushSource is null or "") { - Information("NuGet push source is missing"); - return; - } - if (nugetPushKey is null or "") { - Information("NuGet push key is missing"); - return; - } - - foreach (var file in GetFiles("./bin/NuGet/*.nupkg")) { - Information($"Pushing {file}"); - DotNetNuGetPush(file.FullPath, new() { - Source = nugetPushSource, - ApiKey = nugetPushKey, - }); - } -}); - -Task("MakeDist") - .IsDependentOn("Build") - .IsDependentOn("DownloadDependencies") - .Does(() => -{ - var distDir = Directory("./bin/dist"); - - CreateDirectory(distDir); - - var changelog = TransformText("<%commit_count%> commits since <%last_tag%>\r\n\r\nChangelog (excluding merges):\r\n<%commit_log%>") - .WithToken("commit_count", RunGit($"rev-list --count {latestTag}..HEAD")) - .WithToken("last_tag", latestTag) - .WithToken("commit_log", RunGit($"--no-pager log --no-merges --pretty=\"format:* (%h) [%an] %s\" {latestTag}..HEAD", "\r\n")) - .ToString(); - - void PackageBepin(Target target, ConvertableDirectoryPath originDir, ConvertableFilePath? doorstopConfigFile = null) { - Information($"Creating distributions for target \"{target}\"..."); - - string? doorstopTargetPath = null; - ConvertableDirectoryPath? doorstopTargetDir = null; - - if (doorstopConfigFile is not null) { - doorstopTargetDir = doorstopPath + Directory(target.Os) + Directory(target.Cpu); - doorstopTargetPath = $"{doorstopTargetDir + File(target.IsUnix ? "libdoorstop.*" : DOORSTOP_PROXY_DLL)}"; - } - - var distTargetDir = distDir + Directory($"{target}"); - var distBepinDir = distTargetDir + Directory("BepInEx"); - var distDoorstopDir = distTargetDir; - - CreateDirectory(distTargetDir); - CreateDirectory(distDoorstopDir); - CreateDirectory(distBepinDir + Directory("core")); - CreateDirectory(distBepinDir + Directory("plugins")); - CreateDirectory(distBepinDir + Directory("patchers")); - - if (doorstopConfigFile is not null) { - CopyFile(Directory("./doorstop") + doorstopConfigFile, distTargetDir + File(target.IsUnix ? "run_bepinex.sh" : "doorstop_config.ini")); - if (target.IsUnix) { - CopyFiles(new GlobPattern(doorstopTargetPath), distDoorstopDir); - } else { - CopyFile(File(doorstopTargetPath), Directory(distDoorstopDir) + File(DOORSTOP_PROXY_DLL)); - } - CopyFile(doorstopTargetDir + File(".doorstop_version"), distDoorstopDir + File(".doorstop_version")); - - if (target.IsUnix) { - ReplaceTextInFiles(distTargetDir + File("run_bepinex.sh"), "\r\n", "\n"); - } - - if (target.NeedsRuntime) { - CopyDirectory(dotnetPath + Directory(target.RuntimeIdentifier), Directory(distTargetDir) + Directory("dotnet")); - CopyFile(dobbyPath + Directory(target.Os) + File($"{target.LibPrefix}dobby_{target.Cpu}.{target.LibExt}"), distBepinDir + Directory("core") + File($"{target.LibPrefix}dobby.{target.LibExt}")); - } - } - - CopyFiles(new GlobPattern($"{Directory("./bin") + originDir + File("*.*")}"), Directory(distBepinDir) + Directory("core")); - - FileWriteText(distTargetDir + File("changelog.txt"), changelog); - - if (target.Abi is "NetLauncher") { - DeleteFile(Directory(distBepinDir) + Directory("core") + File("BepInEx.NetLauncher.exe.config")); - MoveFiles(new GlobPattern($"{Directory(distBepinDir) + Directory("core") + File("BepInEx.NetLauncher.*")}"), Directory(distTargetDir)); - } - } - - foreach (Target target in targets) { - (ConvertableDirectoryPath originDir, ConvertableFilePath? doorstopConfigFile) = (Directory(target.Abi), null); - if (target.Abi is var abi and ("UnityIL2CPP" or "UnityMono")) { - originDir = Directory(abi is "UnityIL2CPP" ? "IL2CPP" : "UnityMono"); - // TODO: Move config file resolving to Target class - doorstopConfigFile = File( - target.IsUnix ? - (abi is "UnityIL2CPP" ? "run_bepinex_il2cpp.sh" : "run_bepinex_mono.sh") - : (abi is "UnityIL2CPP" ? "doorstop_config_il2cpp.ini" : "doorstop_config_mono.ini") - ); - } - PackageBepin(target, originDir, doorstopConfigFile); - } -}); - -Task("Pack") - .IsDependentOn("MakeDist") - .IsDependentOn("PushNuGet") - .Does(() => -{ - var distDir = Directory("./bin/dist"); - - Information("Packing BepInEx"); - foreach (Target target in targets) { - ZipCompress(distDir + Directory($"{target}"), distDir + File($"BepInEx-{target}-{buildVersion}.zip")); - } - - if(isBleedingEdge) { - var changelog = lastBuildCommit is null or "" ? "" : - TransformText("
    <%changelog%>
") - .WithToken("changelog", RunGit($"--no-pager log --no-merges --pretty=\"format:
  • (%h) [%an] %s
  • \" {lastBuildCommit}..HEAD")) - .ToString(); - - FileWriteText(distDir + File("info.json"), SerializeJsonPretty(new Dictionary { - ["id"] = buildId.ToString(), - ["date"] = DateTime.Now.ToString("o"), - ["changelog"] = changelog, - ["hash"] = currentCommit, - ["short_hash"] = currentCommitShort, - ["artifacts"] = targets.Select(target => { - (string abiName, string abiGamesPrefix) = target.Abi switch { - "NetLauncher" => (".NET Launcher", ".NET Framework/XNA "), - "UnityIL2CPP" => ("Unity IL2CPP", ""), - "UnityMono" => ("Unity Mono", ""), - var abi => (abi, $"{abi} "), - }; - (string osName, string osGamesSuffix) = target.Os switch { - "unix" => ("Linux & macOS", " using GCC"), - "linux" => ("Linux", " using GCC"), - "macos" => ("macOS", ""), - "windows" => ("Windows", ""), - var os => (os, ""), - }; - string cpuOsNameSuffix = target.Cpu switch { - "any" => "", - var cpu => $" {cpu}", - }; - return new Dictionary() { - ["file"] = $"BepInEx-{target}-{buildVersion}.zip", - ["description"] = $"BepInEx {abiName} for {osName}{cpuOsNameSuffix} {abiGamesPrefix}games{osGamesSuffix}", - }; - }).ToArray(), - })); - } -}); - -RunTarget(task); diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000..b08cc59 --- /dev/null +++ b/build.cmd @@ -0,0 +1,7 @@ +:; set -eo pipefail +:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) +:; ${SCRIPT_DIR}/build.sh "$@" +:; exit $? + +@ECHO OFF +powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %* diff --git a/build.ps1 b/build.ps1 index 21821d2..a707719 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,13 +1,2 @@ -$ErrorActionPreference = 'Stop' - -Set-Location -LiteralPath $PSScriptRoot - -$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = '1' -$env:DOTNET_CLI_TELEMETRY_OPTOUT = '1' -$env:DOTNET_NOLOGO = '1' - -dotnet tool restore -if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } - -dotnet cake @args -if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } +dotnet run --project build/Build.csproj -- $args +exit $LASTEXITCODE; \ No newline at end of file diff --git a/build.sh b/build.sh index 1d0e17c..dfd6b85 100755 --- a/build.sh +++ b/build.sh @@ -1,12 +1 @@ -#!/usr/bin/env bash -set -euox pipefail - -cd "$(dirname "${BASH_SOURCE[0]}")" - -export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 -export DOTNET_CLI_TELEMETRY_OPTOUT=1 -export DOTNET_NOLOGO=1 - -dotnet tool restore - -dotnet cake $@ +dotnet run --project ./build/Build.csproj -- "$@" diff --git a/build/Build.csproj b/build/Build.csproj new file mode 100644 index 0000000..755ccc4 --- /dev/null +++ b/build/Build.csproj @@ -0,0 +1,18 @@ + + + Exe + net6 + $(MSBuildProjectDirectory) + false + + + + + + + + + + + + diff --git a/build/BuildDependencies.cs b/build/BuildDependencies.cs deleted file mode 100644 index fd34bf0..0000000 --- a/build/BuildDependencies.cs +++ /dev/null @@ -1,15 +0,0 @@ -static class BuildDependencies -{ - public const string DoorstopVersion = "4.0.0-rc.5"; - public const string DotnetRuntimeVersion = "6.0.6-test"; - public const string DobbyVersion = "1.0.0"; - - public const string DotnetRuntimeZipUrl = - $"https://github.com/BepInEx/dotnet-runtime/releases/download/{DotnetRuntimeVersion}/mini-coreclr-Release.zip"; - - public static string DoorstopZipUrl(string arch) => - $"https://github.com/NeighTools/UnityDoorstop/releases/download/v{DoorstopVersion}/doorstop_{arch}_release_{DoorstopVersion}.zip"; - - public static string DobbyZipUrl(string arch) => - $"https://github.com/BepInEx/Dobby/releases/download/v{DobbyVersion}/dobby-{arch}.zip"; -} diff --git a/build/DependencyCache.cs b/build/DependencyCache.cs index 4b1e4f4..c60e5bf 100644 --- a/build/DependencyCache.cs +++ b/build/DependencyCache.cs @@ -1,14 +1,14 @@ using System; using System.Collections.Generic; using System.IO; -using Nuke.Common.IO; -using static Nuke.Common.IO.SerializationTasks; +using Cake.Core.IO; +using Cake.Json; -readonly record struct DependencyCache(AbsolutePath CacheFile) +readonly record struct DependencyCache(BuildContext Ctx, FilePath CacheFile) { readonly IDictionary cache = - CacheFile.Exists() - ? JsonDeserialize>(File.ReadAllText(CacheFile)) + File.Exists(CacheFile.FullPath) + ? Ctx.DeserializeJsonFromFile>(CacheFile.FullPath) : new Dictionary(); public void Refresh(string name, string key, Action process) @@ -18,5 +18,5 @@ readonly record struct DependencyCache(AbsolutePath CacheFile) cache[name] = key; } - public void Save() => File.WriteAllText(CacheFile, JsonSerialize(cache)); + public void Save() => Ctx.SerializeJsonToPrettyFile(CacheFile.FullPath, cache); } diff --git a/build/DownloadTasks.cs b/build/DownloadTasks.cs index fa767eb..517bf3b 100644 --- a/build/DownloadTasks.cs +++ b/build/DownloadTasks.cs @@ -4,57 +4,69 @@ using System.IO.Compression; using System.Linq; using System.Net.Http; using System.Threading.Tasks; -using Nuke.Common.IO; -using ShellProgressBar; +using Cake.Core; +using Cake.Core.IO; +using Spectre.Console; +using Path = System.IO.Path; static class DownloadTasks { - public static void DownloadFiles(string name, params (string Name, string Url, AbsolutePath Destination)[] files) + public static void DownloadFiles(this ICakeContext ctx, + string name, + params (string Name, string Url, FilePath Destination)[] files) { - using var progress = new ProgressBar(files.Length, $"Downloading {name}"); - Task.WaitAll(files.Select(t => DownloadFile(progress, t.Name, t.Url, t.Destination)).ToArray()); - } - - public static void DownloadZipFiles(string name, params (string Name, string Url, AbsolutePath Destination)[] files) - { - using var progress = new ProgressBar(files.Length, $"Downloading {name}"); - Task.WaitAll(files.Select(async t => + AnsiConsole.Progress().Start(pCtx => { - var zipFilePath = (AbsolutePath) $"{t.Destination}_tmp.zip"; - await DownloadFile(progress, t.Name, t.Url, zipFilePath); - await UnzipFile(progress, t.Name, zipFilePath, t.Destination); - File.Delete(zipFilePath!); - }).ToArray()); + Task.WaitAll(files + .Select(t => DownloadFile(pCtx, t.Name, t.Url, t.Destination)) + .ToArray()); + }); } - static async Task DownloadFile(ProgressBarBase bar, string name, string url, AbsolutePath destination) + public static void DownloadZipFiles(this ICakeContext ctx, + string name, + params (string Name, string Url, DirectoryPath Destination)[] files) + { + AnsiConsole.Progress().Start(pCtx => + { + Task.WaitAll(files.Select(async t => + { + var zipFilePath = $"{t.Destination}_tmp.zip"; + await DownloadFile(pCtx, t.Name, t.Url, zipFilePath); + await UnzipFile(pCtx, t.Name, zipFilePath, t.Destination); + File.Delete(zipFilePath!); + }).ToArray()); + }); + } + + static async Task DownloadFile(ProgressContext pCtx, string name, string url, FilePath destination) { using var client = new HttpClient(); - await using var fs = File.Create(destination); + await using var fs = File.Create(destination.FullPath); var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); if (!response.IsSuccessStatusCode) throw new Exception($"Failed to download {name}"); await using var stream = await response.Content.ReadAsStreamAsync(); - using var childBar = bar.Spawn((int) (response.Content.Headers.ContentLength ?? 1), $"Downloading {name}"); + var bar = pCtx.AddTask($"Downloading {name}", maxValue: (int) (response.Content.Headers.ContentLength ?? 1)); var buffer = new byte[4096]; int read; while ((read = await stream.ReadAsync(buffer)) > 0) { await fs.WriteAsync(buffer.AsMemory(0, read)); - childBar.Tick(childBar.CurrentTick + read); + bar.Increment(read); } } - static async Task UnzipFile(ProgressBarBase bar, string name, AbsolutePath zipFile, AbsolutePath destination) + static async Task UnzipFile(ProgressContext pCtx, string name, FilePath zipFile, DirectoryPath destination) { - using var zip = ZipFile.OpenRead(zipFile); - using var childBar = bar.Spawn((int) zip.Entries.Select(e => e.Length).Sum(), $"Extracting {name}"); + using var zip = ZipFile.OpenRead(zipFile.FullPath); + var bar = pCtx.AddTask($"Extracting {name}", maxValue: (int) zip.Entries.Select(e => e.Length).Sum()); foreach (var entry in zip.Entries) { // Use Path.Combine to ensure the trailing slash is preserved. - var fullPath = Path.Combine(destination, entry.FullName); + var fullPath = Path.Combine(destination.FullPath, entry.FullName); var fileName = Path.GetFileName(fullPath); if (string.IsNullOrEmpty(fileName)) { @@ -70,7 +82,7 @@ static class DownloadTasks while ((read = await stream.ReadAsync(buffer)) > 0) { await fs.WriteAsync(buffer.AsMemory(0, read)); - childBar.Tick(childBar.CurrentTick + read); + bar.Increment(read); } } } diff --git a/build/GitTasks.cs b/build/GitTasks.cs new file mode 100644 index 0000000..d793567 --- /dev/null +++ b/build/GitTasks.cs @@ -0,0 +1,12 @@ +using Cake.Common; +using Cake.Core; + +static class GitTasks +{ + public static string Git(this ICakeContext ctx, string args, string separator = "") + { + using var process = ctx.StartAndReturnProcess("git", new() { Arguments = args, RedirectStandardOutput = true }); + process.WaitForExit(); + return string.Join(separator, process.GetStandardOutput()); + } +} diff --git a/build/Program.cs b/build/Program.cs new file mode 100644 index 0000000..8fa95fa --- /dev/null +++ b/build/Program.cs @@ -0,0 +1,338 @@ +#pragma warning disable CS1591 +// ReSharper disable ClassNeverInstantiated.Global +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using Cake.Common; +using Cake.Common.IO; +using Cake.Common.Tools.DotNet; +using Cake.Common.Tools.DotNet.Build; +using Cake.Common.Tools.DotNet.NuGet.Push; +using Cake.Core; +using Cake.Core.Diagnostics; +using Cake.Core.IO; +using Cake.Frosting; +using Cake.Git; +using Cake.Json; +using Microsoft.Build.Definition; +using Microsoft.Build.Evaluation; + +return new CakeHost() + .UseContext() + .Run(args); + +public class BuildContext : FrostingContext +{ + public const string DoorstopVersion = "4.0.0-rc.5"; + public const string DotnetRuntimeVersion = "6.0.6-test"; + public const string DobbyVersion = "1.0.0"; + + public const string DotnetRuntimeZipUrl = + $"https://github.com/BepInEx/dotnet-runtime/releases/download/{DotnetRuntimeVersion}/mini-coreclr-Release.zip"; + + internal readonly DistributionTarget[] Distributions = + { + new("Unity.Mono", "win-x86"), + new("Unity.Mono", "win-x64"), + new("Unity.Mono", "linux-x86"), + new("Unity.Mono", "linux-x64"), + new("Unity.Mono", "macos-x64"), + new("Unity.IL2CPP", "win-x86"), + new("Unity.IL2CPP", "win-x64"), + new("Unity.IL2CPP", "linux-x64"), + new("Unity.IL2CPP", "macos-x64"), + new("NET.Framework", "win-x64"), + new("NET.CoreCLR", "win-x64") + }; + + + public BuildContext(ICakeContext ctx) + : base(ctx) + { + RootDirectory = ctx.Environment.WorkingDirectory.GetParent(); + OutputDirectory = RootDirectory.Combine("bin"); + CacheDirectory = OutputDirectory.Combine(".dep_cache"); + DistributionDirectory = OutputDirectory.Combine("dist"); + var props = Project.FromFile(RootDirectory.CombineWithFilePath("Directory.Build.props").FullPath, + new ProjectOptions()); + VersionPrefix = props.GetPropertyValue("VersionPrefix"); + CurrentCommit = ctx.GitLogTip(RootDirectory); + + BleedingEdge = ctx.Argument("bleeding-edge", false); + BuildId = ctx.Argument("build-id", -1); + LastBuildCommit = ctx.Argument("last-build-commit", ""); + NugetApiKey = ctx.Argument("nuget-api-key", ""); + NugetSource = ctx.Argument("nuget-source", "https://nuget.bepinex.dev/v3/index.json"); + } + + public bool BleedingEdge { get; } + public int BuildId { get; } + public string LastBuildCommit { get; } + public string NugetApiKey { get; } + public string NugetSource { get; } + + public DirectoryPath RootDirectory { get; } + public DirectoryPath OutputDirectory { get; } + public DirectoryPath CacheDirectory { get; } + public DirectoryPath DistributionDirectory { get; } + + public string VersionPrefix { get; } + public GitCommit CurrentCommit { get; } + + public string BuildPackageVersion => + $"{VersionPrefix}{(BleedingEdge ? $"-be.{BuildId}+{this.GitShortenSha(RootDirectory, CurrentCommit)}" : "")}"; + + public static string DoorstopZipUrl(string arch) => + $"https://github.com/NeighTools/UnityDoorstop/releases/download/v{DoorstopVersion}/doorstop_{arch}_release_{DoorstopVersion}.zip"; + + public static string DobbyZipUrl(string arch) => + $"https://github.com/BepInEx/Dobby/releases/download/v{DobbyVersion}/dobby-{arch}.zip"; +} + +[TaskName("Clean")] +public sealed class CleanTask : FrostingTask +{ + public override void Run(BuildContext ctx) + { + ctx.CreateDirectory(ctx.OutputDirectory); + ctx.CleanDirectory(ctx.OutputDirectory, + f => !f.Path.FullPath.Contains(".dep_cache")); + + ctx.Log.Information("Cleaning up old build objects"); + ctx.CleanDirectories(ctx.RootDirectory.Combine("**/BepInEx.*/**/bin").FullPath); + ctx.CleanDirectories(ctx.RootDirectory.Combine("**/BepInEx.*/**/obj").FullPath); + } +} + +[TaskName("Compile")] +[IsDependentOn(typeof(CleanTask))] +public sealed class CompileTask : FrostingTask +{ + public override void Run(BuildContext ctx) + { + var buildSettings = new DotNetBuildSettings + { + Configuration = "Release" + }; + if (ctx.BleedingEdge) + { + buildSettings.MSBuildSettings = new() + { + VersionSuffix = $"be.{ctx.BuildId}", + Properties = + { + ["SourceRevisionId"] = new[] { ctx.CurrentCommit.Sha }, + ["RepositoryBranch"] = new[] { ctx.GitBranchCurrent(ctx.RootDirectory).FriendlyName } + } + }; + } + + ctx.DotNetBuild(ctx.RootDirectory.FullPath, buildSettings); + } +} + +[TaskName("DownloadDependencies")] +public sealed class DownloadDependenciesTask : FrostingTask +{ + public override void Run(BuildContext ctx) + { + ctx.Log.Information("Downloading dependencies"); + ctx.CreateDirectory(ctx.CacheDirectory); + + var cache = new DependencyCache(ctx, ctx.CacheDirectory.CombineWithFilePath("cache.json")); + + cache.Refresh("NeighTools/UnityDoorstop", BuildContext.DoorstopVersion, () => + { + ctx.Log.Information($"Downloading Doorstop {BuildContext.DoorstopVersion}"); + var doorstopDir = ctx.CacheDirectory.Combine("doorstop"); + ctx.CreateDirectory(doorstopDir); + ctx.CleanDirectory(doorstopDir); + var archs = new[] { "win", "linux", "macos" }; + var versions = archs + .Select(a => ($"Doorstop ({a})", + BuildContext.DoorstopZipUrl(a), + doorstopDir.Combine($"doorstop_{a}"))) + .ToArray(); + ctx.DownloadZipFiles($"Doorstop {BuildContext.DoorstopVersion}", versions); + }); + + cache.Refresh("BepInEx/Dobby", BuildContext.DobbyVersion, () => + { + ctx.Log.Information($"Downloading Dobby {BuildContext.DobbyVersion}"); + var dobbyDir = ctx.CacheDirectory.Combine("dobby"); + ctx.CreateDirectory(dobbyDir); + ctx.CleanDirectory(dobbyDir); + var archs = new[] { "win", "linux", "macos" }; + var versions = archs + .Select(a => ($"Dobby ({a})", BuildContext.DobbyZipUrl(a), dobbyDir.Combine($"dobby_{a}"))) + .ToArray(); + ctx.DownloadZipFiles($"Dobby {BuildContext.DobbyVersion}", versions); + }); + + cache.Refresh("BepInEx/dotnet_runtime", BuildContext.DotnetRuntimeVersion, () => + { + ctx.Log.Information($"Downloading dotnet runtime {BuildContext.DotnetRuntimeVersion}"); + var dotnetDir = ctx.CacheDirectory.Combine("dotnet"); + ctx.CreateDirectory(dotnetDir); + ctx.CleanDirectory(dotnetDir); + ctx.DownloadZipFiles($"dotnet-runtime {BuildContext.DotnetRuntimeVersion}", + ("dotnet runtime", BuildContext.DotnetRuntimeZipUrl, dotnetDir)); + }); + + cache.Save(); + } +} + +[TaskName("MakeDist")] +[IsDependentOn(typeof(CompileTask))] +[IsDependentOn(typeof(DownloadDependenciesTask))] +public sealed class MakeDistTask : FrostingTask +{ + public override void Run(BuildContext ctx) + { + ctx.CreateDirectory(ctx.DistributionDirectory); + ctx.CleanDirectory(ctx.DistributionDirectory); + + var latestTag = ctx.Git("describe --tags --abbrev=0"); + var changelog = new StringBuilder() + .AppendLine( + $"{ctx.Git($"rev-list --count {latestTag}..HEAD")} changes since {latestTag}") + .AppendLine() + .AppendLine("Changelog (excluding merge commits):") + .AppendLine(ctx.Git( + $"--no-pager log --no-merges --pretty=\"format:* (%h) [%an] %s\" {latestTag}..HEAD", + Environment.NewLine)) + .ToString(); + + + foreach (var dist in ctx.Distributions) + { + ctx.Log.Information($"Creating distribution {dist.Target}"); + var targetDir = ctx.DistributionDirectory.Combine(dist.Target); + ctx.CreateDirectory(targetDir); + ctx.CleanDirectory(targetDir); + + var bepInExDir = targetDir.Combine("BepInEx"); + var bepInExCoreDir = bepInExDir.Combine("core"); + ctx.CreateDirectory(bepInExDir); + ctx.CreateDirectory(bepInExCoreDir); + ctx.CreateDirectory(bepInExDir.Combine("plugins")); + ctx.CreateDirectory(bepInExDir.Combine("patchers")); + + File.WriteAllText(targetDir.CombineWithFilePath("changelog.txt").FullPath, changelog); + foreach (var filePath in ctx.GetFiles(ctx.OutputDirectory.Combine(dist.DistributionIdentifier) + .Combine("*.*").FullPath)) + ctx.CopyFileToDirectory(filePath, bepInExCoreDir); + + if (dist.Engine == "Unity") + { + var doorstopPath = + ctx.CacheDirectory.Combine("doorstop").Combine($"doorstop_{dist.Os}").Combine(dist.Arch); + foreach (var filePath in ctx.GetFiles(doorstopPath.Combine($"*.{dist.DllExtension}").FullPath)) + ctx.CopyFileToDirectory(filePath, targetDir); + ctx.CopyFileToDirectory(doorstopPath.CombineWithFilePath(".doorstop_version"), targetDir); + var (doorstopConfigFile, doorstopConfigDistName) = dist.Os switch + { + "win" => ($"doorstop_config_{dist.Runtime.ToLower()}.ini", + "doorstop_config.ini"), + "linux" or "macos" => ($"run_bepinex_{dist.Runtime.ToLower()}.sh", + "run_bepinex.sh"), + var _ => throw new + NotSupportedException( + $"Doorstop is not supported on {dist.Os}") + }; + ctx.CopyFile(ctx.RootDirectory.Combine("Runtimes").Combine("Unity").Combine("Doorstop").CombineWithFilePath(doorstopConfigFile), + targetDir.CombineWithFilePath(doorstopConfigDistName)); + + if (dist.Runtime == "IL2CPP") + { + ctx.CopyFile(ctx.CacheDirectory.Combine("dobby").Combine($"dobby_{dist.Os}").CombineWithFilePath($"{dist.DllPrefix}dobby_{dist.Arch}.{dist.DllExtension}"), + bepInExCoreDir.CombineWithFilePath($"{dist.DllPrefix}dobby.{dist.DllExtension}")); + ctx.CopyDirectory(ctx.CacheDirectory.Combine("dotnet").Combine(dist.RuntimeIndentifier), + targetDir.Combine("dotnet")); + } + } + + if (dist.DistributionIdentifier == "NET.Framework") + { + ctx.DeleteFile(bepInExCoreDir.CombineWithFilePath("BepInEx.NET.Framework.Launcher.exe.config")); + foreach (var filePath in ctx.GetFiles(bepInExCoreDir.Combine("BepInEx.NET.*").FullPath)) + ctx.MoveFileToDirectory(filePath, targetDir); + } + + if (dist.DistributionIdentifier == "NET.CoreCLR") + foreach (var filePath in ctx.GetFiles(bepInExCoreDir.Combine("BepInEx.NET.CoreCLR.*").FullPath)) + ctx.MoveFileToDirectory(filePath, targetDir); + } + } +} + +[TaskName("PushNuGet")] +public sealed class PushNuGetTask : FrostingTask +{ + public override bool ShouldRun(BuildContext ctx) => !string.IsNullOrWhiteSpace(ctx.NugetApiKey); + + public override void Run(BuildContext ctx) + { + var nugetPath = ctx.OutputDirectory.Combine("NuGet"); + var settings = new DotNetNuGetPushSettings + { + Source = ctx.NugetSource, + ApiKey = ctx.NugetApiKey + }; + foreach (var pkg in ctx.GetFiles(ctx.OutputDirectory.Combine("*.nupkg").FullPath)) + ctx.DotNetNuGetPush(pkg, settings); + } +} + +[TaskName("Publish")] +[IsDependentOn(typeof(MakeDistTask))] +[IsDependentOn(typeof(PushNuGetTask))] +public sealed class PublishTask : FrostingTask +{ + public override void Run(BuildContext ctx) + { + ctx.Log.Information("Packing BepInEx"); + + foreach (var dist in ctx.Distributions) + { + var targetZipName = $"BepInEx-{dist.Target}-{ctx.BuildPackageVersion}.zip"; + ctx.Log.Information($"Packing {targetZipName}"); + ctx.Zip(ctx.DistributionDirectory.Combine(dist.Target), + ctx.DistributionDirectory + .CombineWithFilePath(targetZipName)); + } + + + var changeLog = ""; + if (!string.IsNullOrWhiteSpace(ctx.LastBuildCommit)) + { + var changeLogContents = + ctx.Git($"--no-pager log --no-merges --pretty=\"format:
  • (%h) [%an] %s
  • \" {ctx.LastBuildCommit}..HEAD", + "\n"); + changeLog = $"
      {changeLogContents}
    "; + } + + ctx.SerializeJsonToPrettyFile(ctx.DistributionDirectory.CombineWithFilePath("info.json"), + new Dictionary + { + ["id"] = ctx.BuildId.ToString(), + ["date"] = DateTime.Now.ToString("o"), + ["changelog"] = changeLog, + ["hash"] = ctx.CurrentCommit.Sha, + ["short_hash"] = ctx.GitShortenSha(ctx.RootDirectory, ctx.CurrentCommit), + ["artifacts"] = ctx.Distributions.Select(d => new Dictionary + { + ["file"] = $"BepInEx-{d.Target}-{ctx.BuildPackageVersion}.zip", + ["description"] = + $"BepInEx {d.Engine} ({d.Runtime}) for {d.ClearOsName} ({d.Arch}) games" + }).ToArray() + }); + } +} + +[TaskName("Default")] +[IsDependentOn(typeof(CompileTask))] +public class DefaultTask : FrostingTask { }