From aabcd5f9b279ab8a0dd034def3d32a90b0acccb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Sat, 11 Apr 2026 17:28:04 +0200 Subject: [PATCH] Build Box2D with BuildTool --- GlitchyEngine/vendor/box2D | 2 +- bin/BuildTool/BuildInfo.cs | 17 ++ bin/BuildTool/BuildTool.cs | 157 +----------------- bin/BuildTool/Module.cs | 11 ++ bin/BuildTool/Modules/AllModule.cs | 13 ++ bin/BuildTool/Modules/BeefWorkspaceModule.cs | 27 +++ bin/BuildTool/Modules/Box2DModule.cs | 72 ++++++++ .../Modules/GlitchyEngineHelperModule.cs | 31 ++++ bin/BuildTool/Modules/ScriptCoreModule.cs | 29 ++++ bin/BuildTool/Modules/SetupNethostModule.cs | 39 +++++ 10 files changed, 243 insertions(+), 155 deletions(-) create mode 100644 bin/BuildTool/BuildInfo.cs create mode 100644 bin/BuildTool/Module.cs create mode 100644 bin/BuildTool/Modules/AllModule.cs create mode 100644 bin/BuildTool/Modules/BeefWorkspaceModule.cs create mode 100644 bin/BuildTool/Modules/Box2DModule.cs create mode 100644 bin/BuildTool/Modules/GlitchyEngineHelperModule.cs create mode 100644 bin/BuildTool/Modules/ScriptCoreModule.cs create mode 100644 bin/BuildTool/Modules/SetupNethostModule.cs diff --git a/GlitchyEngine/vendor/box2D b/GlitchyEngine/vendor/box2D index c6528c4..0e6010c 160000 --- a/GlitchyEngine/vendor/box2D +++ b/GlitchyEngine/vendor/box2D @@ -1 +1 @@ -Subproject commit c6528c4fcb016c0c1f1cfc4fe5cff859fba7578b +Subproject commit 0e6010c93f4a3d04f5bfa499a20563842aeaf5be diff --git a/bin/BuildTool/BuildInfo.cs b/bin/BuildTool/BuildInfo.cs new file mode 100644 index 0000000..860e50f --- /dev/null +++ b/bin/BuildTool/BuildInfo.cs @@ -0,0 +1,17 @@ +namespace BuildTool; + +class BuildInfo +{ + public WorkingDirectoryHistory WorkingDirectory; + public bool ForceRebuild; + public bool BuildDebug; + public bool BuildRelease; + + public BuildInfo(WorkingDirectoryHistory workingDirectory, bool forceRebuild, bool buildDebug, bool buildRelease) + { + WorkingDirectory = workingDirectory; + ForceRebuild = forceRebuild; + BuildDebug = buildDebug; + BuildRelease = buildRelease; + } +} diff --git a/bin/BuildTool/BuildTool.cs b/bin/BuildTool/BuildTool.cs index ddfd9c6..c473cf3 100644 --- a/bin/BuildTool/BuildTool.cs +++ b/bin/BuildTool/BuildTool.cs @@ -2,163 +2,12 @@ using System.Diagnostics; using SimpleExec; using Spectre.Console; -using static SimpleExec.Command; +using BuildTool.Modules; + using Command = System.CommandLine.Command; namespace BuildTool; -class BuildInfo -{ - public WorkingDirectoryHistory WorkingDirectory; - public bool ForceRebuild; - public bool BuildDebug; - public bool BuildRelease; - - public BuildInfo(WorkingDirectoryHistory workingDirectory, bool forceRebuild, bool buildDebug, bool buildRelease) - { - WorkingDirectory = workingDirectory; - ForceRebuild = forceRebuild; - BuildDebug = buildDebug; - BuildRelease = buildRelease; - } -} - -class SetupNethostModule : Module -{ - public static readonly string ModuleName = "SetupNethost"; - - public override string Name => ModuleName; - - public override List DependencyTypes => []; - - public override async Task Run(BuildInfo buildInfo) - { - buildInfo.WorkingDirectory.NavigateFromWorkspaceRoot("GlitchyEngine/vendor/NetHostBeef"); - - string targetPath = buildInfo.WorkingDirectory.GetRelativePath("./NetHostBeef/nethost/"); - - if (buildInfo.ForceRebuild || !Directory.Exists(targetPath)) - { - if (Directory.Exists(targetPath)) - { - Console.WriteLine("Removing existing nethost directory..."); - Directory.Delete(targetPath, true); - Console.WriteLine("Done."); - } - - Console.WriteLine("Donwloading nethost..."); - await RunAsync("powershell", "./downloadNethost.ps1"); - Console.WriteLine("Done."); - } - else - { - Console.WriteLine("Nethost already exists. Use --force-rebuild to force download."); - } - - return true; - } -} - -class ScriptCoreModule : Module -{ - public static readonly string ModuleName = "ScriptCore"; - - public override string Name => ModuleName; - - public override List DependencyTypes => [typeof(SetupNethostModule), typeof(BeefWorkspaceModule)]; - - public override async Task Run(BuildInfo buildInfo) - { - string projectFile = Path.Join(buildInfo.WorkingDirectory.WorkspaceRoot, "ScriptCore/ScriptCore.csproj"); - - if (buildInfo.BuildDebug) - { - await RunAsync("dotnet", $"build \"{projectFile}\" -c Debug"); - } - - if (buildInfo.BuildRelease) - { - await RunAsync("dotnet", $"build \"{projectFile}\" -c Release"); - } - - return true; - } -} - -class GlitchyEngineHelperModule : Module -{ - public static readonly string ModuleName = "GlitchyEngineHelper"; - - public override string Name => ModuleName; - - public override List DependencyTypes => []; - - public override async Task Run(BuildInfo buildInfo) - { - buildInfo.WorkingDirectory.NavigateFromWorkspaceRoot("GlitchyEngineHelper"); - - if (buildInfo.BuildDebug) - { - await RunAsync("cmake", "--preset x64-debug"); - await RunAsync("cmake", "--build --preset x64-debug"); - } - - if (buildInfo.BuildRelease) - { - await RunAsync("cmake", "--preset x64-release"); - await RunAsync("cmake", "--build --preset x64-release"); - } - - return true; - } -} - -class BeefWorkspaceModule : Module -{ - public static readonly string ModuleName = "BeefWorkspace"; - - public override string Name => ModuleName; - - public override List DependencyTypes => [typeof(GlitchyEngineHelperModule)]; - - public override async Task Run(BuildInfo buildInfo) - { - if (buildInfo.BuildDebug) - { - await RunAsync("beefbuild", $"-workspace={buildInfo.WorkingDirectory.WorkspaceRoot} -config=debug"); - } - - if (buildInfo.BuildRelease) - { - await RunAsync("beefbuild", $"-workspace={buildInfo.WorkingDirectory.WorkspaceRoot} -config=release"); - } - - return true; - } -} - -class AllModule : Module -{ - public static readonly string ModuleName = "All"; - public override string Name => ModuleName; - public override List DependencyTypes => [typeof(BeefWorkspaceModule), typeof(ScriptCoreModule)]; - - public override Task Run(BuildInfo buildInfo) - { - return Task.FromResult(true); - } -} - -abstract class Module -{ - public abstract string Name { get; } - - public List Dependencies { get; } = new(); - public abstract List DependencyTypes { get; } - - public abstract Task Run(BuildInfo buildInfo); -} - class Program { /// @@ -229,7 +78,7 @@ class Program static async Task Main(string[] args) { - List modules = [new BeefWorkspaceModule(), new GlitchyEngineHelperModule(), new ScriptCoreModule(), new SetupNethostModule(), new AllModule()]; + List modules = [new BeefWorkspaceModule(), new GlitchyEngineHelperModule(), new ScriptCoreModule(), new SetupNethostModule(), new Box2DModule(), new AllModule()]; // Find dependencies foreach (Module module in modules) diff --git a/bin/BuildTool/Module.cs b/bin/BuildTool/Module.cs new file mode 100644 index 0000000..5e6b5ed --- /dev/null +++ b/bin/BuildTool/Module.cs @@ -0,0 +1,11 @@ +namespace BuildTool; + +abstract class Module +{ + public abstract string Name { get; } + + public List Dependencies { get; } = new(); + public abstract List DependencyTypes { get; } + + public abstract Task Run(BuildInfo buildInfo); +} diff --git a/bin/BuildTool/Modules/AllModule.cs b/bin/BuildTool/Modules/AllModule.cs new file mode 100644 index 0000000..6e8d859 --- /dev/null +++ b/bin/BuildTool/Modules/AllModule.cs @@ -0,0 +1,13 @@ +namespace BuildTool.Modules; + +class AllModule : Module +{ + public static readonly string ModuleName = "All"; + public override string Name => ModuleName; + public override List DependencyTypes => [typeof(BeefWorkspaceModule), typeof(ScriptCoreModule)]; + + public override Task Run(BuildInfo buildInfo) + { + return Task.FromResult(true); + } +} diff --git a/bin/BuildTool/Modules/BeefWorkspaceModule.cs b/bin/BuildTool/Modules/BeefWorkspaceModule.cs new file mode 100644 index 0000000..c4739e8 --- /dev/null +++ b/bin/BuildTool/Modules/BeefWorkspaceModule.cs @@ -0,0 +1,27 @@ +using static SimpleExec.Command; + +namespace BuildTool.Modules; + +class BeefWorkspaceModule : Module +{ + public static readonly string ModuleName = "BeefWorkspace"; + + public override string Name => ModuleName; + + public override List DependencyTypes => [typeof(GlitchyEngineHelperModule), typeof(Box2DModule)]; + + public override async Task Run(BuildInfo buildInfo) + { + if (buildInfo.BuildDebug) + { + await RunAsync("beefbuild", $"-workspace={buildInfo.WorkingDirectory.WorkspaceRoot} -config=debug"); + } + + if (buildInfo.BuildRelease) + { + await RunAsync("beefbuild", $"-workspace={buildInfo.WorkingDirectory.WorkspaceRoot} -config=release"); + } + + return true; + } +} diff --git a/bin/BuildTool/Modules/Box2DModule.cs b/bin/BuildTool/Modules/Box2DModule.cs new file mode 100644 index 0000000..03709a8 --- /dev/null +++ b/bin/BuildTool/Modules/Box2DModule.cs @@ -0,0 +1,72 @@ +using SimpleExec; +using static SimpleExec.Command; + +namespace BuildTool.Modules; + +class Box2DModule : Module +{ + public static readonly string ModuleName = "Box2D"; + + public override string Name => ModuleName; + + public override List DependencyTypes => []; + + public override async Task Run(BuildInfo buildInfo) + { + // Locate MSBuild.exe before doing any work — fail fast with a clear error. + string msbuildPath = await LocateMSBuildAsync(); + + // Generate Visual Studio 2022 project files. Must be invoked from box2D/scripts so + // that genie picks up scripts/genie.lua (defines solution "box2d"). The original + // build_windows_vs2022.cmd runs genie from submodules/bx — that picks up bx's own + // genie.lua and only generates bx.sln, which is not what we want. + buildInfo.WorkingDirectory.NavigateFromWorkspaceRoot("GlitchyEngine/vendor/box2D/scripts"); + + string geniePath = Path.Combine("..", "submodules", "bx", "tools", "bin", "windows", "genie.exe"); + await RunAsync(geniePath, "--with-windows=10.0 vs2022"); + + buildInfo.WorkingDirectory.NavigateFromWorkspaceRoot("GlitchyEngine/vendor/box2D"); + + string solutionPath = Path.Combine(".build", "projects", "vs2022", "box2d.sln"); + string target = buildInfo.ForceRebuild ? "-t:Rebuild" : "-t:Build"; + + if (buildInfo.BuildDebug) + { + await RunAsync(msbuildPath, $"\"{solutionPath}\" {target} -p:Platform=x64 -p:Configuration=Debug -m -verbosity:minimal"); + } + + if (buildInfo.BuildRelease) + { + await RunAsync(msbuildPath, $"\"{solutionPath}\" {target} -p:Platform=x64 -p:Configuration=Release -m -verbosity:minimal"); + } + + return true; + } + + /// + /// Locates MSBuild.exe via vswhere (shipped with any Visual Studio 2017+ install). + /// + private static async Task LocateMSBuildAsync() + { + string programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); + string vswherePath = Path.Combine(programFilesX86, "Microsoft Visual Studio", "Installer", "vswhere.exe"); + + if (!File.Exists(vswherePath)) + { + throw new Exception($"Could not find vswhere.exe at '{vswherePath}'. Is Visual Studio 2017 or newer installed?"); + } + + (string stdout, _) = await ReadAsync(vswherePath, + "-latest -products * -requires Microsoft.Component.MSBuild -find MSBuild\\**\\Bin\\MSBuild.exe"); + + string msbuildPath = stdout.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + .FirstOrDefault() ?? ""; + + if (string.IsNullOrWhiteSpace(msbuildPath) || !File.Exists(msbuildPath)) + { + throw new Exception("vswhere could not locate MSBuild.exe. Make sure the 'MSBuild' component is installed with Visual Studio."); + } + + return msbuildPath; + } +} diff --git a/bin/BuildTool/Modules/GlitchyEngineHelperModule.cs b/bin/BuildTool/Modules/GlitchyEngineHelperModule.cs new file mode 100644 index 0000000..3128b13 --- /dev/null +++ b/bin/BuildTool/Modules/GlitchyEngineHelperModule.cs @@ -0,0 +1,31 @@ +using static SimpleExec.Command; + +namespace BuildTool.Modules; + +class GlitchyEngineHelperModule : Module +{ + public static readonly string ModuleName = "GlitchyEngineHelper"; + + public override string Name => ModuleName; + + public override List DependencyTypes => []; + + public override async Task Run(BuildInfo buildInfo) + { + buildInfo.WorkingDirectory.NavigateFromWorkspaceRoot("GlitchyEngineHelper"); + + if (buildInfo.BuildDebug) + { + await RunAsync("cmake", "--preset x64-debug"); + await RunAsync("cmake", "--build --preset x64-debug"); + } + + if (buildInfo.BuildRelease) + { + await RunAsync("cmake", "--preset x64-release"); + await RunAsync("cmake", "--build --preset x64-release"); + } + + return true; + } +} diff --git a/bin/BuildTool/Modules/ScriptCoreModule.cs b/bin/BuildTool/Modules/ScriptCoreModule.cs new file mode 100644 index 0000000..ff7216c --- /dev/null +++ b/bin/BuildTool/Modules/ScriptCoreModule.cs @@ -0,0 +1,29 @@ +using SimpleExec; + +namespace BuildTool.Modules; + +class ScriptCoreModule : Module +{ + public static readonly string ModuleName = "ScriptCore"; + + public override string Name => ModuleName; + + public override List DependencyTypes => [typeof(SetupNethostModule), typeof(BeefWorkspaceModule)]; + + public override async Task Run(BuildInfo buildInfo) + { + string projectFile = Path.Join(buildInfo.WorkingDirectory.WorkspaceRoot, "ScriptCore/ScriptCore.csproj"); + + if (buildInfo.BuildDebug) + { + await Command.RunAsync("dotnet", $"build \"{projectFile}\" -c Debug"); + } + + if (buildInfo.BuildRelease) + { + await Command.RunAsync("dotnet", $"build \"{projectFile}\" -c Release"); + } + + return true; + } +} \ No newline at end of file diff --git a/bin/BuildTool/Modules/SetupNethostModule.cs b/bin/BuildTool/Modules/SetupNethostModule.cs new file mode 100644 index 0000000..6241f61 --- /dev/null +++ b/bin/BuildTool/Modules/SetupNethostModule.cs @@ -0,0 +1,39 @@ +using static SimpleExec.Command; + +namespace BuildTool.Modules; + +class SetupNethostModule : Module +{ + public static readonly string ModuleName = "SetupNethost"; + + public override string Name => ModuleName; + + public override List DependencyTypes => []; + + public override async Task Run(BuildInfo buildInfo) + { + buildInfo.WorkingDirectory.NavigateFromWorkspaceRoot("GlitchyEngine/vendor/NetHostBeef"); + + string targetPath = buildInfo.WorkingDirectory.GetRelativePath("./NetHostBeef/nethost/"); + + if (buildInfo.ForceRebuild || !Directory.Exists(targetPath)) + { + if (Directory.Exists(targetPath)) + { + Console.WriteLine("Removing existing nethost directory..."); + Directory.Delete(targetPath, true); + Console.WriteLine("Done."); + } + + Console.WriteLine("Donwloading nethost..."); + await RunAsync("powershell", "./downloadNethost.ps1"); + Console.WriteLine("Done."); + } + else + { + Console.WriteLine("Nethost already exists. Use --force-rebuild to force download."); + } + + return true; + } +}