Port Cakebuild script to Cake.Frosting

This commit is contained in:
ghorsington committed 2022-08-14 17:19:09 +03:00
1 parent f7857c7994
commit 008f835e80
19 files changed
+437 -440

No files matched your search

-12
View File
@@ -1,12 +0,0 @@
{
"version": 1,
"isRoot": true,
"tools": {
"cake.tool": {
"version": "2.2.0",
"commands": [
"dotnet-cake"
]
}
}
}
+8 -15
View File
@@ -3,11 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.0.32112.339 VisualStudioVersion = 17.0.32112.339
MinimumVisualStudioVersion = 10.0.40219.1 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}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BepInEx.Preloader.Core", "BepInEx.Preloader.Core\BepInEx.Preloader.Core.csproj", "{15F8BC38-A761-4F93-8903-1B531AC5D9F9}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BepInEx.Unity.Mono", "Runtimes\Unity\BepInEx.Unity.Mono\BepInEx.Unity.Mono.csproj", "{EAE9FAE6-8011-45A3-8B6E-0C7F14210533}" 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}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{12081C35-76DF-450C-AC83-1E1CB84516AA}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
Directory.Build.props = Directory.Build.props Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
EndProjectSection EndProjectSection
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Unity", "Unity", "{BF8F4E07-3B89-4152-89F4-9EF9D4AAA1E0}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Unity", "Unity", "{BF8F4E07-3B89-4152-89F4-9EF9D4AAA1E0}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BepInEx.Unity.Common", "Runtimes\Unity\BepInEx.Unity.Common\BepInEx.Unity.Common.csproj", "{C32E74A3-C0BD-42DE-9E2F-D033D496ACB9}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BepInEx.Unity.Common", "Runtimes\Unity\BepInEx.Unity.Common\BepInEx.Unity.Common.csproj", "{C32E74A3-C0BD-42DE-9E2F-D033D496ACB9}"
EndProject 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}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "IL2CPP", "IL2CPP", "{E4E75C18-4156-4213-A20C-8677EF6B5312}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Doorstop", "Doorstop", "{CE06453E-44E7-4D50-9A68-AA15F4C1C8D1}" 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 Runtimes\Unity\Doorstop\run_bepinex_mono.sh = Runtimes\Unity\Doorstop\run_bepinex_mono.sh
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Build", "build\Build.csproj", "{0C38DDF2-EAAA-43FA-BA0A-985636AC6040}"
EndProject
Global Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution GlobalSection(SharedMSBuildProjectFiles) = preSolution
BepInEx.NetLauncher.Shared\BepInEx.NetLauncher.Shared.projitems*{067bcc8c-fc25-4929-b4f4-c6a5a7496994}*SharedItemsImports = 13 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 Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution 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.ActiveCfg = Debug|Any CPU
{15F8BC38-A761-4F93-8903-1B531AC5D9F9}.Debug|Any CPU.Build.0 = 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 {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_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.ActiveCfg = Release|Any CPU
{C32E74A3-C0BD-42DE-9E2F-D033D496ACB9}.Release|Any CPU.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
-5
View File
@@ -1,5 +0,0 @@
<Project>
<PropertyGroup Condition="'$(DistributionIdentifier)' != ''">
<OutDir>$(BuildDir)/$(DistributionIdentifier)/</OutDir>
</PropertyGroup>
</Project>
@@ -1,8 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>BepInEx support library for CoreCLR games</Description>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<DistributionIdentifier>NET.CoreCLR</DistributionIdentifier> <OutputPath>$(BuildDir)/NET.CoreCLR</OutputPath>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -6,7 +6,7 @@
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<DistributionIdentifier>NET.Framework</DistributionIdentifier> <OutputPath>$(BuildDir)/NET.Framework</OutputPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\BepInEx.Core\BepInEx.Core.csproj"/> <ProjectReference Include="..\..\..\BepInEx.Core\BepInEx.Core.csproj"/>
@@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DistributionIdentifier>Unity.IL2CPP</DistributionIdentifier> <OutputPath>$(BuildDir)/Unity.IL2CPP</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -5,7 +5,7 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net35'"> <PropertyGroup Condition="'$(TargetFramework)' == 'net35'">
<!-- Output only net35 version to distribution; netstadnard is only used for generating NuGet package --> <!-- Output only net35 version to distribution; netstadnard is only used for generating NuGet package -->
<DistributionIdentifier>Unity.IL2CPP</DistributionIdentifier> <OutputPath>$(BuildDir)/Unity.Mono</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -6,7 +6,7 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net35'"> <PropertyGroup Condition="'$(TargetFramework)' == 'net35'">
<!-- Output only net35 version to distribution; netstadnard is only used for generating NuGet package --> <!-- Output only net35 version to distribution; netstadnard is only used for generating NuGet package -->
<DistributionIdentifier>Unity.Mono</DistributionIdentifier> <OutputPath>$(BuildDir)/Unity.Mono</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
-1
View File
@@ -1 +0,0 @@
powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File %CD%\build.ps1 %*
-331
View File
@@ -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"), @"\<VersionPrefix\>([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<Dictionary<string, string>>(cacheFile) : new Dictionary<string, string>();
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("<ul><%changelog%></ul>")
.WithToken("changelog", RunGit($"--no-pager log --no-merges --pretty=\"format:<li>(<code>%h</code>) [%an] %s</li>\" {lastBuildCommit}..HEAD"))
.ToString();
FileWriteText(distDir + File("info.json"), SerializeJsonPretty(new Dictionary<string, object> {
["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<string, object>() {
["file"] = $"BepInEx-{target}-{buildVersion}.zip",
["description"] = $"BepInEx {abiName} for {osName}{cpuOsNameSuffix} {abiGamesPrefix}games{osGamesSuffix}",
};
}).ToArray(),
}));
}
});
RunTarget(task);
+7
View File
@@ -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" %*
+2 -13
View File
@@ -1,13 +1,2 @@
$ErrorActionPreference = 'Stop' dotnet run --project build/Build.csproj -- $args
exit $LASTEXITCODE;
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 }
+1 -12
View File
@@ -1,12 +1 @@
#!/usr/bin/env bash dotnet run --project ./build/Build.csproj -- "$@"
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 $@
+18
View File
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6</TargetFramework>
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Cake.Frosting" Version="2.2.0"/>
<PackageReference Include="Cake.Git" Version="2.0.0"/>
<PackageReference Include="Cake.Incubator" Version="7.0.0"/>
<PackageReference Include="Cake.Json" Version="7.0.1"/>
<PackageReference Include="Microsoft.Build" Version="17.2.0"/>
</ItemGroup>
<ItemGroup>
<Content Include="$(SolutionDir)/.github/workflows/*.yml" LinkBase="ci"/>
</ItemGroup>
</Project>
-15
View File
@@ -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";
}
+6 -6
View File
@@ -1,14 +1,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Nuke.Common.IO; using Cake.Core.IO;
using static Nuke.Common.IO.SerializationTasks; using Cake.Json;
readonly record struct DependencyCache(AbsolutePath CacheFile) readonly record struct DependencyCache(BuildContext Ctx, FilePath CacheFile)
{ {
readonly IDictionary<string, string> cache = readonly IDictionary<string, string> cache =
CacheFile.Exists() File.Exists(CacheFile.FullPath)
? JsonDeserialize<Dictionary<string, string>>(File.ReadAllText(CacheFile)) ? Ctx.DeserializeJsonFromFile<Dictionary<string, string>>(CacheFile.FullPath)
: new Dictionary<string, string>(); : new Dictionary<string, string>();
public void Refresh(string name, string key, Action process) public void Refresh(string name, string key, Action process)
@@ -18,5 +18,5 @@ readonly record struct DependencyCache(AbsolutePath CacheFile)
cache[name] = key; cache[name] = key;
} }
public void Save() => File.WriteAllText(CacheFile, JsonSerialize(cache)); public void Save() => Ctx.SerializeJsonToPrettyFile(CacheFile.FullPath, cache);
} }
+37 -25
View File
@@ -4,57 +4,69 @@ using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Nuke.Common.IO; using Cake.Core;
using ShellProgressBar; using Cake.Core.IO;
using Spectre.Console;
using Path = System.IO.Path;
static class DownloadTasks 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}"); AnsiConsole.Progress().Start(pCtx =>
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 =>
{ {
var zipFilePath = (AbsolutePath) $"{t.Destination}_tmp.zip"; Task.WaitAll(files
await DownloadFile(progress, t.Name, t.Url, zipFilePath); .Select(t => DownloadFile(pCtx, t.Name, t.Url, t.Destination))
await UnzipFile(progress, t.Name, zipFilePath, t.Destination); .ToArray());
File.Delete(zipFilePath!); });
}).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(); 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); var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
throw new Exception($"Failed to download {name}"); throw new Exception($"Failed to download {name}");
await using var stream = await response.Content.ReadAsStreamAsync(); 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]; var buffer = new byte[4096];
int read; int read;
while ((read = await stream.ReadAsync(buffer)) > 0) while ((read = await stream.ReadAsync(buffer)) > 0)
{ {
await fs.WriteAsync(buffer.AsMemory(0, read)); 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 zip = ZipFile.OpenRead(zipFile.FullPath);
using var childBar = bar.Spawn((int) zip.Entries.Select(e => e.Length).Sum(), $"Extracting {name}"); var bar = pCtx.AddTask($"Extracting {name}", maxValue: (int) zip.Entries.Select(e => e.Length).Sum());
foreach (var entry in zip.Entries) foreach (var entry in zip.Entries)
{ {
// Use Path.Combine to ensure the trailing slash is preserved. // 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); var fileName = Path.GetFileName(fullPath);
if (string.IsNullOrEmpty(fileName)) if (string.IsNullOrEmpty(fileName))
{ {
@@ -70,7 +82,7 @@ static class DownloadTasks
while ((read = await stream.ReadAsync(buffer)) > 0) while ((read = await stream.ReadAsync(buffer)) > 0)
{ {
await fs.WriteAsync(buffer.AsMemory(0, read)); await fs.WriteAsync(buffer.AsMemory(0, read));
childBar.Tick(childBar.CurrentTick + read); bar.Increment(read);
} }
} }
} }
+12
View File
@@ -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());
}
}
+338
View File
@@ -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<BuildContext>()
.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<BuildContext>
{
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<BuildContext>
{
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<BuildContext>
{
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<BuildContext>
{
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<BuildContext>
{
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<BuildContext>
{
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:<li>(<code>%h</code>) [%an] %s</li>\" {ctx.LastBuildCommit}..HEAD",
"\n");
changeLog = $"<ul>{changeLogContents}</ul>";
}
ctx.SerializeJsonToPrettyFile(ctx.DistributionDirectory.CombineWithFilePath("info.json"),
new Dictionary<string, object>
{
["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<string, string>
{
["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 { }