add tool
This commit is contained in:
124
src/BuildTool.bf
Normal file
124
src/BuildTool.bf
Normal file
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace CxxBuildTool;
|
||||
|
||||
static class CxxBuildTool
|
||||
{
|
||||
public static void CMake(StringView sourceDir, StringView buildDir, StringView cmakeFlags = "", StringView clangFlags = "")
|
||||
{
|
||||
if (!File.Exists(scope $"{buildDir}/CMakeCache.txt"))
|
||||
{
|
||||
StringView buildType;
|
||||
String flags = scope .(64);
|
||||
switch ((Compiler.Options.OptLevel)Compiler.Options.OptimizationLevel)
|
||||
{
|
||||
case .Og, .OgPlus:
|
||||
buildType = "RelWithDebInfo";
|
||||
flags.Append("-O2");
|
||||
default:
|
||||
buildType = "Release";
|
||||
flags.Append('-');
|
||||
_.ToString(flags);
|
||||
}
|
||||
flags.Append(" --target=", Compiler.Options.TargetTriple);
|
||||
RunCommand("cmake", scope $"-S {sourceDir} -B {buildDir} {cmakeFlags} -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE={buildType
|
||||
} -DCMAKE_C_FLAGS=\"{clangFlags} {flags}\" -DCMAKE_CXX_FLAGS=\"{clangFlags} {flags}\"");
|
||||
}
|
||||
|
||||
RunCommand("cmake", scope $"--build {buildDir}");
|
||||
}
|
||||
|
||||
public static void Ninja(StringView sourceDir, StringView buildDir, StringView projectName, StringView clangFlags, params Span<StringView> sourceFiles)
|
||||
{
|
||||
String ninja = scope .(1024);
|
||||
ninja.AppendF($"""
|
||||
src = {sourceDir}
|
||||
builddir = {buildDir}
|
||||
cflags = {clangFlags} --target={Compiler.Options.TargetTriple}
|
||||
""");
|
||||
switch ((Compiler.Options.OptLevel)Compiler.Options.OptimizationLevel)
|
||||
{
|
||||
case .Og, .OgPlus:
|
||||
ninja.Append(" -O2 -g");
|
||||
default:
|
||||
ninja.Append(" -");
|
||||
_.ToString(ninja);
|
||||
}
|
||||
ninja.Append("""
|
||||
|
||||
|
||||
cc = clang
|
||||
ar = llvm-ar
|
||||
|
||||
rule cc
|
||||
command = $cc $cflags -MD -MF $out.d -c $in -o $out
|
||||
depfile = $out.d
|
||||
deps = gcc
|
||||
description = Building $in
|
||||
|
||||
rule ar
|
||||
command = $ar crs $out $in
|
||||
description = Linking $out
|
||||
|
||||
|
||||
""");
|
||||
for (let src in sourceFiles)
|
||||
ninja.Append("build $builddir/", src, ".o: cc $src/", src, "\n");
|
||||
ninja.Append("\nbuild $builddir/", projectName,
|
||||
((Compiler.Options.PlatformType)Compiler.Options.Platform == .Windows) ? ".lib" : ".a",
|
||||
": ar");
|
||||
for (let src in sourceFiles)
|
||||
ninja.Append(" $builddir/", src, ".o");
|
||||
ninja.Append('\n');
|
||||
|
||||
Directory.CreateDirectory(buildDir);
|
||||
File.WriteAllText(scope $"{buildDir}/build.ninja", ninja);
|
||||
RunCommand("ninja", scope $"-C {buildDir}");
|
||||
}
|
||||
|
||||
static void RunCommand(StringView cmd, StringView args)
|
||||
{
|
||||
let startInfo = scope ProcessStartInfo();
|
||||
startInfo.SetFileName(cmd);
|
||||
startInfo.SetArguments(args);
|
||||
startInfo.UseShellExecute = false;
|
||||
startInfo.RedirectStandardOutput = true;
|
||||
startInfo.RedirectStandardError = true;
|
||||
startInfo.CreateNoWindow = true;
|
||||
|
||||
let proc = scope SpawnedProcess();
|
||||
Runtime.Assert(proc.Start(startInfo) case .Ok, "starting command failed");
|
||||
|
||||
FileStream output = scope .();
|
||||
FileStream error = scope .();
|
||||
proc.AttachStandardOutput(output);
|
||||
proc.AttachStandardError(error);
|
||||
|
||||
String str = scope .();
|
||||
Span<uint8> buffer = uint8[1024]();
|
||||
StringView bufferView = *(.)&buffer;
|
||||
while (!proc.HasExited || !output.IsEmpty || !error.IsEmpty)
|
||||
{
|
||||
while (output.TryRead(buffer) case .Ok(let val) && val > 0)
|
||||
str.Append(bufferView[..<val]);
|
||||
if (!str.IsEmpty)
|
||||
{
|
||||
Console.Write(str);
|
||||
str.Clear();
|
||||
}
|
||||
while (error.TryRead(buffer) case .Ok(let val) && val > 0)
|
||||
str.Append(bufferView[..<val]);
|
||||
if (!str.IsEmpty)
|
||||
{
|
||||
Console.Write(str);
|
||||
str.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
Runtime.Assert(proc.ExitCode == 0, "command failed");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user