From 097b273c5ded4c9f71a106e348fd351a90802d32 Mon Sep 17 00:00:00 2001 From: Hedy88 Date: Mon, 10 Aug 2026 22:46:50 +0100 Subject: [PATCH] Add new --generator argument and a generator for ninja files --- .gitignore | 3 + src/js/cmdline.js | 151 +++++++++++++++++++++++++++++++++++++++++++-- src/js/core.js | 25 ++++++++ src/js/postinit.js | 1 + 4 files changed, 176 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index a5e023e..f7c8d57 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,10 @@ *.lib *.a Makefile +*.ninja *.make /src/compiler/*.c /src/system/*.c /src/js/*.c +compile_commands.json +.cache/ \ No newline at end of file diff --git a/src/js/cmdline.js b/src/js/cmdline.js index 3886775..1ba9388 100644 --- a/src/js/cmdline.js +++ b/src/js/cmdline.js @@ -185,9 +185,152 @@ function make(output) { mk.close(); } -make("Makefile"); -const targets = pmake.resolveProjects(pmake.projects); -for(var i = 0; i < targets.length; i++) { - make(makefile(targets[i])); +function ninjafile(target) { + return target.base + "/" + target.target + ".ninja"; } + +function ninja(output) { + const targets = pmake.resolveProjects(pmake.projects); + + var nk = new pmake.File(output, "w"); + + nk.write("# This file was auto-generated. Do not edit manually!\n"); + nk.write("\n"); + + if(output == "build.ninja") { + nk.write("rule cleantool\n"); + nk.write(" command = ninja -t clean\n"); + nk.write("\n"); + + nk.write("rule rm\n"); + nk.write(" command = rm -f $in\n"); + nk.write("\n"); + + for(var i = 0; i < targets.length; i++) { + nk.write("subninja " + targets[i].base + "/" + targets[i].target + ".ninja\n"); + } + nk.write("\n"); + + nk.write("build all: phony "); + for(var i = 0; i < targets.length; i++) { + if(targets[i] instanceof pmake.InterfaceProject) continue; + nk.write(targets[i].base + "/" + pmake.compiler.output(targets[i]) + " "); + } + nk.write("\n\n"); + + nk.write("default all\n"); + nk.write("\n"); + + nk.write("build clean: cleantool\n"); + nk.write("\n"); + + var distcleanFiles = ["build.ninja"]; + for(var i = 0; i < targets.length; i++) { + distcleanFiles.push(targets[i].base + "/" + targets[i].target + ".ninja"); + } + + nk.write("build distclean_files: rm " + distcleanFiles.join(" ") + "\n"); + nk.write("build distclean: phony clean distclean_files\n"); + } else { + function target_filter(x) { + const p = output.replace(/\.ninja$/, "").split("/"); + return x.target == p[p.length - 1]; + } + + const self = targets.filter(target_filter)[0]; + const objs = self.sources.map(pmake.compiler.output).map(function(x) { return self.base + "/" + x; }); + const sources = self.sources.map(function(x) { return self.base + "/" + x; }); + + function add_I(x) { + return "-I" + x; + } + + function add_L(x) { + return "-L" + x; + } + + function add_l(x) { + return "-l" + x; + } + + const incflags = pmake.includes(self).map(add_I).join(" "); + + nk.write("rule cc\n"); + nk.write(" command = $cc $incs -c -o $out $in\n"); + nk.write(" deps = gcc\n"); + nk.write(" depfile = $out.d\n"); + nk.write("\n"); + + nk.write("rule cxx\n"); + nk.write(" command = $cxx $incs -c -o $out $in\n"); + nk.write(" deps = gcc\n"); + nk.write(" depfile = $out.d\n"); + nk.write("\n"); + + if(pmake.compiler.rc) { + nk.write("rule rc\n"); + nk.write(" command = $rc -O coff $in $out\n"); + nk.write("\n"); + } + + nk.write("rule ar\n"); + nk.write(" command = $ar rcs $out $in\n"); + nk.write("\n"); + + nk.write("rule link\n"); + nk.write(" command = $cxx $libdirs -o $out $in $libs\n"); + nk.write("\n"); + + for(var i = 0; i < objs.length; i++) { + if(self.sources[i].endsWith(".rc")) { + nk.write("build " + objs[i] + ": rc " + sources[i] + "\n"); + nk.write(" rc = " + pmake.compiler.rc + "\n"); + } else if(pmake.isCxx(self.sources[i])) { + nk.write("build " + objs[i] + ": cxx " + sources[i] + "\n"); + nk.write(" cc = " + pmake.compiler.cxx + "\n"); + nk.write(" incs = " + incflags + "\n"); + } else { + nk.write("build " + objs[i] + ": cc " + sources[i] + "\n"); + nk.write(" cc = " + pmake.compiler.cc + "\n"); + nk.write(" incs = " + incflags + "\n"); + } + nk.write("\n"); + } + + const output_path = self.base + "/" + pmake.compiler.output(self); + + if(!(self instanceof pmake.InterfaceProject)) { + const libpaths = pmake.libs(self, null, true); + const libs = pmake.libs(self, add_l, true); + + if(self instanceof pmake.LibraryProject) { + nk.write("build " + output_path + ": ar " + objs.join(" ") + "\n"); + nk.write(" ar = " + pmake.compiler.ar + "\n"); + } else { + nk.write("build " + output_path + ": link " + objs.join(" ") + (libpaths.length ? " | " + libpaths.join(" ") : "") + "\n"); + nk.write(" cxx = " + pmake.compiler.cxx + "\n"); + nk.write(" libdirs = " + pmake.libdirs(self).map(add_L).join(" ") + "\n"); + nk.write(" libs = " + libs.join(" ") + "\n"); + } + nk.write("\n"); + } + } + + nk.close(); +} + +if(!pmake.generator || pmake.generator == "make") { + make("Makefile"); + const targets = pmake.resolveProjects(pmake.projects); + for(var i = 0; i < targets.length; i++) { + make(makefile(targets[i])); + } +} else if(pmake.generator == "ninja") { + ninja("build.ninja"); + const targets = pmake.resolveProjects(pmake.projects); + for(var i = 0; i < targets.length; i++) { + ninja(ninjafile(targets[i])); + } +} + })(); diff --git a/src/js/core.js b/src/js/core.js index 210cb04..b5f3485 100644 --- a/src/js/core.js +++ b/src/js/core.js @@ -347,6 +347,31 @@ System.action = function(value) { pmake.setSystem(value); }; +const Generator = new pmake.Option("generator=VALUE"); +Generator.category = "General"; +Generator.description = "Choose a generator; one of:"; + +Generator.options = function() { + return [ "make", "ninja" ]; +}; + +Generator.action = function(value) { + pmake.generator = value; +}; + +const Generator = new pmake.Option("generator=VALUE"); +Generator.category = "General"; +Generator.description = "Choose a build file generator; one of:"; + +Generator.options = function() { + return ["make", "ninja"]; +}; + +Generator.action = function(value) { + pmake.generator = value; +}; + pmake.register(Compiler); pmake.register(System); +pmake.register(Generator); })(); diff --git a/src/js/postinit.js b/src/js/postinit.js index 4ed70a3..c254834 100644 --- a/src/js/postinit.js +++ b/src/js/postinit.js @@ -1,4 +1,5 @@ pmake.setCompiler("GCC"); +pmake.generator = "make"; if(WIN32) { pmake.setSystem("Windows");