Add new --generator argument and a generator for ninja files

This commit is contained in:
Hedy88 2026-08-10 22:46:50 +01:00
commit 097b273c5d
No known key found for this signature in database
4 changed files with 176 additions and 4 deletions

3
.gitignore vendored
View file

@ -4,7 +4,10 @@
*.lib
*.a
Makefile
*.ninja
*.make
/src/compiler/*.c
/src/system/*.c
/src/js/*.c
compile_commands.json
.cache/

View file

@ -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]));
}
}
})();

View file

@ -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);
})();

View file

@ -1,4 +1,5 @@
pmake.setCompiler("GCC");
pmake.generator = "make";
if(WIN32) {
pmake.setSystem("Windows");