From fa90624c843b959aed47a6441dc4c79b92059d61 Mon Sep 17 00:00:00 2001 From: Rune Date: Thu, 5 Mar 2026 17:02:04 +0100 Subject: [PATCH] Stop using fatal errors --- .gitignore | 1 + BeefSpace_Lock.toml | 6 --- CxxBuilder/src/FileMatcher.bf | 29 +++++++++---- CxxBuilder/src/Program.bf | 79 ++++++++++++++++++++++++++--------- 4 files changed, 82 insertions(+), 33 deletions(-) delete mode 100644 BeefSpace_Lock.toml diff --git a/.gitignore b/.gitignore index 2cfe158..e05f8c7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ build recovery BeefSpace_User.toml +BeefSpace_Lock.toml clang-c.h diff --git a/BeefSpace_Lock.toml b/BeefSpace_Lock.toml deleted file mode 100644 index b772165..0000000 --- a/BeefSpace_Lock.toml +++ /dev/null @@ -1,6 +0,0 @@ -FileVersion = 1 - -[Locks."Clang-C.git".Git] -URL = "https://git.unicon-gmbh.de/BeefBindings/Clang-C.git" -Tag = "" -Hash = "a64e7a0cac26e4844385b87e595e27e95b46e5a0" diff --git a/CxxBuilder/src/FileMatcher.bf b/CxxBuilder/src/FileMatcher.bf index ec72560..7d704f6 100644 --- a/CxxBuilder/src/FileMatcher.bf +++ b/CxxBuilder/src/FileMatcher.bf @@ -7,7 +7,13 @@ namespace CxxBuilder; static class FileMatcher { - public static void HandleMatches(Span patterns, StringView directory, delegate void(StringView match) callback) + public enum Error + { + ExpectedEscapeSequence, + CharacterClassNotClosed, + } + + public static Result HandleMatches(Span patterns, StringView directory, delegate void(StringView match) callback) { Runtime.Assert(Directory.Exists(directory), scope $"No such directory {directory}"); void Dir(StringView dir) @@ -38,13 +44,14 @@ static class FileMatcher } } Dir(directory); + return .Ok; } - public static bool IsMatch(StringView pattern, StringView path) + public static Result IsMatch(StringView pattern, StringView path) { var pattern, path; - bool Matches(StringView pattern, char8 c) + Result Matches(StringView pattern, char8 c) { if (pattern.IsEmpty) return false; @@ -56,7 +63,7 @@ static class FileMatcher return !Path.IsDirectorySeparatorChar(c); case '?': return true; case '\\': - Runtime.Assert(pattern.Length > 1, "Expected escape sequence"); + if (pattern.Length <= 1) return .Err(.ExpectedEscapeSequence); return c == pattern[1]; case '/': return Path.IsDirectorySeparatorChar(c); case '[': @@ -64,13 +71,14 @@ static class FileMatcher char8 Next() { if (pattern.Length <= ++i) - Runtime.FatalError("Character class not closed"); + return (.)7; return pattern[i]; } bool negated = false; char8 current; switch (Next()) { + case (.)7: return .Err(.CharacterClassNotClosed); case '^', '!': negated = true; fallthrough; case '\\': current = Next(); case ']': return false; @@ -100,7 +108,12 @@ static class FileMatcher { if (path.IsEmpty) return true; if (pattern.IsEmpty) return false; - if (!Matches(pattern, path[0])) return false; + switch (Matches(pattern, path[0])) + { + case .Err: return _; + case .Ok(false): return false; + case .Ok: + } switch (pattern[0]) { case '*': @@ -114,8 +127,8 @@ static class FileMatcher defer { pattern = lazy; } while (true) { - if (IsMatch(lazy, path)) continue reduce; - if (!Matches(pattern, path[0])) continue reduce; + if (Try!(IsMatch(lazy, path))) continue reduce; + if (!Try!(Matches(pattern, path[0]))) continue reduce; path.RemoveFromStart(1); if (path.IsEmpty) return lazy.IsEmpty; } diff --git a/CxxBuilder/src/Program.bf b/CxxBuilder/src/Program.bf index 4dcdce9..883c746 100644 --- a/CxxBuilder/src/Program.bf +++ b/CxxBuilder/src/Program.bf @@ -16,24 +16,45 @@ static class Program Console.WriteLine(""" Simple and fast build tool using clang and ninja. - Usage: $(Var CxxBuilderExe) -- src=<> target=<> builddir=<> output=<> [cflags=<>] - Example: $(Var CxxBuilderExe) **.c vk_*.cpp -- "src=$(ProjectDir)/MyLib/src" target=$(TargetTriple) "builddir=$(BuildDir)" output=MyLib cflags=-Isome/dir + Usage: $(Var CxxBuilderExe) [] -- src=<> target=<> config=<> builddir=<> output=<> [cflags=<>] + Example: $(Var CxxBuilderExe) **.c vk_*.cpp -- "src=$(ProjectDir)/MyLib/src" target=$(TargetTriple) config=$(Configuration) "builddir=$(BuildDir)" output=MyLib cflags=-Isome/dir - src - The source dir, all patterns are rooted here - target - the llvm target triple passed to clang - builddir - contains build artifacts and ninja files - output - the name of the output object archive $builddir/$output.lib on windows and $builddir/$output.a elsewhere - cflags - additional flags passed to clang + --template - TODO + --cmake - builds $src/CMakeLists.txt to build, patterns and output are ignored + + $src - The source dir, all patterns are rooted here + $target - the llvm target triple passed to clang + $config - the build configuration + $builddir - contains build artifacts and ninja files + $output - the name of the output object archive $builddir/$output.lib on windows and $builddir/$output.a elsewhere + $cflags - additional flags passed to clang """); return 1; } - StringView src = null, target = null, builddir = null, output = null, cflags = null; + mixin Assert(bool condition, StringView str) + { + if (!condition) + { + Console.WriteLine(str); + return 1; + } + } + + enum { Default, CMake, Template } mode = .Default; + StringView src = null, target = null, config = null, builddir = null, output = null, cflags = null; var iter = args.GetEnumerator(); skipPatterns: do { for (let arg in iter) + { if (arg == "--") break skipPatterns; + if (arg == "--cmake") + { + Assert!(mode == .Default, "Conflicting options"); + mode = .CMake; + } + } PrintUsage!(); } for (let arg in iter) @@ -50,20 +71,24 @@ static class Program value.Trim(); switch (key) { - case "src": Runtime.Assert(src.IsNull, "Duplicate var 'src'"); src = value; - case "target": Runtime.Assert(target.IsNull, "Duplicate var 'target'"); target = value; - case "builddir": Runtime.Assert(builddir.IsNull, "Duplicate var 'builddir'"); builddir = value; - case "output": Runtime.Assert(output.IsNull, "Duplicate var 'output'"); output = value; - case "cflags": Runtime.Assert(cflags.IsNull, "Duplicate var 'cflags'"); cflags = value; + case "src": Assert!(src.IsNull, "Duplicate var 'src'"); src = value; + case "target": Assert!(target.IsNull, "Duplicate var 'target'"); target = value; + case "config": Assert!(config.IsNull, "Duplicate var 'config'"); config = value; + case "builddir": Assert!(builddir.IsNull, "Duplicate var 'builddir'"); builddir = value; + case "output": Assert!(output.IsNull, "Duplicate var 'output'"); output = value; + case "cflags": Assert!(cflags.IsNull, "Duplicate var 'cflags'"); cflags = value; default: PrintUsage!(); } } - Runtime.Assert(!src.IsNull, "Missing var 'src'"); - Runtime.Assert(!target.IsNull, "Missing var 'target'"); - Runtime.Assert(!builddir.IsNull, "Missing var 'builddir'"); - Runtime.Assert(!builddir.IsNull, "Missing var 'output'"); + Assert!(!src.IsNull, "Missing var 'src'"); + Assert!(!target.IsNull, "Missing var 'target'"); + Assert!(!config.IsNull, "Missing var 'config'"); + Assert!(!builddir.IsNull, "Missing var 'builddir'"); + Assert!(!output.IsNull || mode == .CMake, "Missing var 'output'"); + switch (mode) { + case .Default: StreamWriter writer = scope .()..Create(scope $"{builddir}/build.ninja"); { String buffer = scope .(1024); @@ -79,7 +104,7 @@ static class Program WriteVarPath("builddir", builddir); buffer.AppendF($""" target = {target} - cflags = {cflags} + cflags = {(config == "Release") ? "-O2" : "-O2 -g"} {cflags} """); writer.Write(buffer); } @@ -121,9 +146,25 @@ static class Program ar.Append(" $builddir/", match, ".o"); } let abssrc = Path.GetAbsolutePath(src, Directory.GetCurrentDirectory(..scope .(128)), ..scope .(128)); - FileMatcher.HandleMatches(patterns, abssrc, scope => HandleMatch); + if (FileMatcher.HandleMatches(patterns, abssrc, scope => HandleMatch) case .Err(let err)) + { + Console.WriteLine($"Syntax Error in Pattern: {err}"); + return 1; + } writer.WriteLine(ar); + case .CMake: +#if !DEBUG + if (File.Exists(scope $"{builddir}/build.ninja")) + break; +#endif + String cmd = scope .(512); + cmd.Append("cmake -S \"", src, "\" -B \"", builddir, "\" -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ "); + cmd.Append("-DCMAKE_C_FLAGS=\"-target ", target, " ", cflags, "\" -DCMAKE_CXX_FLAGS=\"-target ", target, " ", cflags, "\" -DCMAKE_BUILD_TYPE="); + if (config == "Release") cmd.Append("Release"); + else cmd.Append("RelWithDebInfo"); + Assert!(system(cmd) == 0, "Build file generation failed"); + case .Template: //TODO } let ret = system(scope $"ninja -C {builddir}");