c part ready to go

This commit is contained in:
Rune
2026-02-22 15:25:43 +01:00
parent 397c0e320c
commit 806f27381a
17 changed files with 674 additions and 43 deletions

134
CxxBuilder/src/Program.bf Normal file
View File

@@ -0,0 +1,134 @@
using System;
using System.IO;
using System.Collections;
using System.Diagnostics;
namespace CxxBuilder;
static class Program
{
[CLink] static extern int32 system(char8*);
public static int Main(String[] args)
{
mixin PrintUsage()
{
Console.WriteLine("""
Simple and fast build tool using clang and ninja.
Usage: $(Var CxxBuilderExe) <patterns...> -- src=<> target=<> builddir=<> output=<> [cflags=<>]
Example: $(Var CxxBuilderExe) **.c vk_*.cpp -- "src=$(ProjectDir)/MyLib/src" target=$(TargetTriple) "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
""");
return 1;
}
StringView src = null, target = null, builddir = null, output = null, cflags = null;
var iter = args.GetEnumerator();
skipPatterns: do
{
for (let arg in iter)
if (arg == "--") break skipPatterns;
PrintUsage!();
}
for (let arg in iter)
{
var parts = arg.Split('=', 2);
StringView key = parts.GetNext().Value;
StringView value;
switch (parts.GetNext())
{
case .Err: PrintUsage!();
case .Ok(out value):
}
key.Trim();
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;
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'");
{
StreamWriter writer = scope .()..Create(scope $"{builddir}/build.ninja");
{
String buffer = scope .(1024);
let currentDir = Directory.GetCurrentDirectory(..scope .(128));
void WriteVarPath(StringView key, StringView value)
{
buffer.Append(key);
buffer.Append(" = ");
Path.GetAbsolutePath(value, currentDir, buffer);
buffer.Append('\n');
}
WriteVarPath("src", src);
WriteVarPath("builddir", builddir);
buffer.AppendF($"""
target = {target}
cflags = {cflags}
""");
writer.Write(buffer);
}
writer.Write("""
\n
cc = clang
ar = ar
rule cc
command = $cc $cflags -target $target -MD -MF $out.d -c -o $out $in
deps = gcc
depfile = $out.d
description = Building $in
rule ar
command = $ar crs $out $in
description = Creating static lib $out
""");
String ar = scope .(1024);
ar.AppendF($"\nbuild $builddir/{output}.{target.Contains("windows") ? "lib" : "a"}: ar");
int pcount = 0;
for (let arg in args)
{
if (arg == "--") break;
pcount++;
}
StringView[] patterns = scope .[pcount];
for (var pattern in ref patterns)
{
pattern = args[@pattern];
}
void HandleMatch(StringView match)
{
writer.Write($"build $builddir/{match}.o: cc $src/{match}\n");
ar.Append(" $builddir/", match, ".o");
}
let abssrc = Path.GetAbsolutePath(src, Directory.GetCurrentDirectory(..scope .(128)), ..scope .(128));
FileMatcher.HandleMatches(patterns, abssrc, scope => HandleMatch);
writer.WriteLine(ar);
}
let ret = system(scope $"ninja -C {builddir}");
if (ret != 0)
Console.WriteLine($"Failed to build {output}");
return ret;
}
}