pmake/src/js/core.js

245 lines
5.2 KiB
JavaScript
Raw Normal View History

2026-05-09 16:20:44 +09:00
if(!Array.prototype.includes) {
Array.prototype.includes = function(v) {
for(var i = 0; i < this.length; i++) {
if(this[i] == v) return true;
}
return false;
};
}
if(!Array.prototype.flat) {
Array.prototype.flat = function() {
const flat = function(acc, cur) {
return acc.concat(cur);
};
return this.reduce(flat, []);
};
}
2026-05-08 05:18:35 +09:00
const pmake = {
2026-05-08 19:07:45 +09:00
VERSION : "0.0",
2026-05-09 03:16:12 +09:00
compilers : {},
options : {},
2026-05-09 16:20:44 +09:00
options_category : {},
2026-05-09 03:16:12 +09:00
projects : []
2026-05-08 05:18:35 +09:00
};
2026-05-09 03:16:12 +09:00
pmake.inherit = function(base, call) {
2026-05-09 16:20:44 +09:00
const func = (function() {
base.apply(this, arguments);
if(call) call.apply(this, arguments);
});
2026-05-08 05:18:35 +09:00
Object.setPrototypeOf(func.prototype, base.prototype);
return func;
};
2026-05-08 05:35:07 +09:00
pmake.inherited = function(base, parent) {
2026-05-08 05:18:35 +09:00
var proto = base.prototype;
2026-05-08 05:35:07 +09:00
while(proto) {
2026-05-08 05:18:35 +09:00
if(proto == parent.prototype) return true;
proto = Object.getPrototypeOf(proto);
}
return false;
2026-05-08 05:35:07 +09:00
};
2026-05-08 05:18:35 +09:00
2026-05-09 16:20:44 +09:00
pmake.register = function(target) {
if(target instanceof pmake.Compiler) {
pmake.compilers[target.target] = target;
} else if(target instanceof pmake.Option) {
if(!pmake.options_category[target.category]) pmake.options_category[target.category] = {};
2026-05-09 03:16:12 +09:00
2026-05-09 16:20:44 +09:00
pmake.options_category[target.category][target.target] = target;
pmake.options[target.target] = target;
} else if(target instanceof pmake.Project) {
pmake.projects.push(target);
2026-05-09 03:16:12 +09:00
}
};
2026-05-09 16:20:44 +09:00
pmake.resolveProjects = function(arr, if_str) {
2026-05-09 03:16:12 +09:00
var r = [];
2026-05-09 03:16:20 +09:00
for(var i = 0; i < arr.length; i++) {
2026-05-09 16:20:44 +09:00
var proj = arr[i];
if((typeof proj) == "string" && pmake.projects[proj]) {
proj = pmake.projects[proj];
}
if(proj instanceof pmake.Project) {
r = r.concat(pmake.resolveProjects(proj.libraries));
r.push(proj);
} else if((typeof proj) == "string" && if_str) {
r.push(if_str(proj));
2026-05-09 03:16:12 +09:00
}
2026-05-08 05:18:35 +09:00
}
2026-05-09 03:16:12 +09:00
2026-05-09 16:20:44 +09:00
r = r.filter(function(item, pos) {
return r.indexOf(item) == pos;
});
2026-05-09 03:16:12 +09:00
return r;
};
2026-05-09 16:20:44 +09:00
pmake.isCxx = function(src) {
return src.endsWith(".cc") || src.endsWith(".cxx") || src.endsWith(".cpp");
};
pmake.includes = function(target) {
function includes(x) {
return x.includes;
}
const targets = pmake.resolveProjects(target.libraries);
return targets.map(includes).flat();
};
pmake.libs = function(target, if_str) {
function libs(x) {
if(x instanceof pmake.LibraryProject) {
return x.libraries.concat([ pmake.compiler.output(x) ]);
} else if((typeof x) == "string") {
return [ x ];
}
return [];
}
const targets = pmake.resolveProjects(target.libraries, if_str);
return targets.map(libs).flat();
};
2026-05-09 03:16:12 +09:00
(function() {
2026-05-09 16:20:44 +09:00
const Compiler = function() {
this.prefix = "";
};
Compiler.prototype.output = function(target) {
if((typeof target) == "string") {
if(target.endsWith(".c")) return target.replace(/\.c$/, ".o");
} else if(target instanceof pmake.LibraryProject) {
return "lib" + target.output + ".a";
} else if(target instanceof pmake.ExecutableProject) {
return target.output;
}
return target.output;
};
const POSIXCompiler = pmake.inherit(Compiler, function(target) {
this.ar = "ar";
this.cc = "cc";
this.cxx = "c++";
});
2026-05-09 03:16:12 +09:00
2026-05-09 16:20:44 +09:00
POSIXCompiler.prototype.compile = function(target, obj, src) {
function add_i(x) {
return "-I" + x;
}
2026-05-09 16:39:35 +09:00
const includes = pmake.includes(target).map(add_i).join(" ");
const flags = includes + " -c -o " + obj + " " + src;
2026-05-09 16:20:44 +09:00
if(src.endsWith(".c")) {
2026-05-09 16:39:35 +09:00
return this.prefix + this.cc + " " + flags;
2026-05-09 16:20:44 +09:00
} else if(is_cxx(src)) {
2026-05-09 16:39:35 +09:00
return this.prefix + this.cxx + " " + flags;
2026-05-09 16:20:44 +09:00
}
return "";
2026-05-09 16:39:35 +09:00
};
2026-05-09 16:20:44 +09:00
2026-05-09 16:39:35 +09:00
POSIXCompiler.prototype.link = function(target, files) {
2026-05-09 16:20:44 +09:00
if(target instanceof pmake.LibraryProject) {
return this.prefix + this.ar + " rcs " + this.output(target) + " " + files.join(" ");
} else if(target instanceof pmake.ExecutableProject) {
var c = "";
var cxx = target.sources.filter(pmake.isCxx);
if(!cxx || cxx.length == 0) {
c = this.prefix + this.cc;
} else {
c = this.prefix + this.cxx;
}
function add_l(x) {
return "-l" + x;
}
return this.prefix + c + " -o " + this.output(target) + " " + files.join(" ") + " " + pmake.libs(target, add_l).join(" ");
}
return "";
}
2026-05-09 03:16:12 +09:00
const Option = function() {};
const Project = function(target) {
2026-05-09 03:16:20 +09:00
this.target = target;
2026-05-09 16:20:44 +09:00
this.sources = [];
this.includes = [];
2026-05-09 03:16:12 +09:00
this.libraries = [];
2026-05-09 16:20:44 +09:00
this.output = target;
2026-05-08 05:35:07 +09:00
};
2026-05-08 05:18:35 +09:00
2026-05-09 03:16:12 +09:00
Project.prototype.generate = function() {
2026-05-08 19:07:45 +09:00
};
2026-05-09 16:20:44 +09:00
const LibraryProject = pmake.inherit(Project, function(target) {
});
const ExecutableProject = pmake.inherit(Project, function(target) {
});
const InterfaceProject = pmake.inherit(Project, function(target) {
});
2026-05-09 03:16:12 +09:00
const File = function(filename, mode) {
this.fp = fs.open(filename, mode);
2026-05-08 19:07:45 +09:00
};
2026-05-09 03:16:12 +09:00
File.prototype.write = function(string) {
fs.write(this.fp, string);
};
File.prototype.close = function() {
fs.close(this.fp);
};
2026-05-09 16:20:44 +09:00
pmake.Compiler = Compiler;
pmake.POSIXCompiler = POSIXCompiler;
pmake.Option = Option;
pmake.Project = Project;
pmake.LibraryProject = LibraryProject;
pmake.ExecutableProject = ExecutableProject;
pmake.InterfaceProject = InterfaceProject;
pmake.File = File;
2026-05-09 03:16:12 +09:00
})();
/*** Option ***/
(function() {
const Compiler = new pmake.Option();
Compiler.category = "General";
Compiler.target = "compiler";
Compiler.description = "Choose a compiler set; one of:";
Compiler.option = "VALUE";
Compiler.options = function() {
return Object.keys(pmake.compilers);
};
2026-05-09 16:20:44 +09:00
Compiler.action = function(value) {
pmake.compiler = pmake.compilers[value];
};
2026-05-09 03:16:12 +09:00
pmake.register(Compiler);
})();