From dc78d1fc9ae8c6644121fa2d8a8661b737f7c1af Mon Sep 17 00:00:00 2001 From: nub31 Date: Fri, 17 Oct 2025 16:22:57 +0200 Subject: [PATCH] Add ability to include o/a files directly --- compiler/NubLang.CLI/Program.cs | 84 +++++++++++++++++++++++++++++++-- examples/raylib/makefile | 7 +-- 2 files changed, 81 insertions(+), 10 deletions(-) diff --git a/compiler/NubLang.CLI/Program.cs b/compiler/NubLang.CLI/Program.cs index 00b9cab..ef86376 100644 --- a/compiler/NubLang.CLI/Program.cs +++ b/compiler/NubLang.CLI/Program.cs @@ -8,7 +8,10 @@ using NubLang.Syntax; var diagnostics = new List(); var syntaxTrees = new List(); -foreach (var file in args) +var nubFiles = args.Where(x => Path.GetExtension(x) == ".nub"); +var objectFiles = args.Where(x => Path.GetExtension(x) is ".o" or ".a"); + +foreach (var file in nubFiles) { var tokenizer = new Tokenizer(file, File.ReadAllText(file)); tokenizer.Tokenize(); @@ -59,14 +62,85 @@ var cFilePath = Path.Combine(".build", "out.c"); File.WriteAllText(cFilePath, c); -using var process = Process.Start("gcc", ["-ffreestanding", "-nostartfiles", "-std=c23", "-g", "-c", "-o", Path.Combine(".build", "out.o"), cFilePath]); +using var compileProcess = Process.Start("gcc", [ + "-ffreestanding", "-nostartfiles", "-std=c23", + "-g", "-lm", + "-c", "-o", Path.Combine(".build", "out.o"), + cFilePath, +]); -process.WaitForExit(); +compileProcess.WaitForExit(); -if (process.ExitCode != 0) +if (compileProcess.ExitCode != 0) { - Console.Error.WriteLine($"gcc failed with exit code {process.ExitCode}"); + Console.Error.WriteLine($"gcc failed with exit code {compileProcess.ExitCode}"); return 1; } +if (moduleRepository.Modules().TryGetValue("main", out var mainModule)) +{ + var mainFunction = mainModule + .Functions(true) + .FirstOrDefault(x => x.ExternSymbol == "main"); + + if (mainFunction is { ExternSymbol: not null }) + { + var runtime = $""" + .intel_syntax noprefix + + .text + .globl _start + _start: + mov rdi, rsp # Pass stack pointer to main (argv-like) + call {mainFunction.ExternSymbol} + mov rdi, rax # Move return value into rdi + mov rax, 60 # syscall: exit + syscall + + """; + + var runtimePath = Path.Combine(".build", "runtime.s"); + File.WriteAllText(runtimePath, runtime); + + using var assembleProcess = Process.Start(new ProcessStartInfo("as", ["-c", runtimePath, "-o", Path.Combine(".build", "runtime.o")])); + if (assembleProcess == null) return 1; + + if (assembleProcess.ExitCode != 0) + { + Console.Error.WriteLine($"gcc failed with exit code {assembleProcess.ExitCode}"); + return 1; + } + + if (assembleProcess.ExitCode != 0) return 1; + + using var linkProcess = Process.Start(new ProcessStartInfo("gcc", [ + "-ffreestanding", "-nostartfiles", "-std=c23", + "-g", "-lm", + "-o", Path.Combine(".build", "out"), + Path.Combine(".build", "out.o"), + Path.Combine(".build", "runtime.o"), + ..objectFiles + ])); + + if (linkProcess == null) return 1; + linkProcess.WaitForExit(); + + if (linkProcess.ExitCode != 0) + { + Console.Error.WriteLine($"gcc failed with exit code {linkProcess.ExitCode}"); + return 1; + } + + Console.WriteLine("Build successful: .build/out"); + } + else + { + Console.WriteLine("No main function found in module main, skipping link step"); + } +} +else +{ + Console.WriteLine("No main function found in module main, skipping link step"); +} + return 0; \ No newline at end of file diff --git a/examples/raylib/makefile b/examples/raylib/makefile index a9d5449..d3b41fa 100644 --- a/examples/raylib/makefile +++ b/examples/raylib/makefile @@ -1,8 +1,5 @@ -out: .build/out.o - gcc -nostartfiles -lm -o out x86_64.s .build/out.o raylib-5.5_linux_amd64/lib/libraylib.a - -.build/out.o: main.nub generated/raylib.nub - nubc main.nub generated/raylib.nub +out: main.nub generated/raylib.nub + nubc main.nub generated/raylib.nub raylib-5.5_linux_amd64/lib/libraylib.a clean: @rm -r .build 2>/dev/null || true