wip
This commit is contained in:
parent
6ae9cf6e1e
commit
ae7ff555d9
5 changed files with 250 additions and 31 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,5 +1,6 @@
|
|||
/pmake*
|
||||
*.o
|
||||
*.a
|
||||
/Makefile
|
||||
/*.make
|
||||
/src/compiler/*.c
|
||||
|
|
|
|||
|
|
@ -4,5 +4,8 @@ const GCC = new pmake.POSIXCompiler();
|
|||
GCC.target = "GCC";
|
||||
GCC.description = "GCC/Clang";
|
||||
|
||||
GCC.cc = "gcc";
|
||||
GCC.cxx = "g++";
|
||||
|
||||
pmake.register(GCC);
|
||||
})();
|
||||
|
|
|
|||
8
src/js.c
8
src/js.c
|
|
@ -34,13 +34,13 @@ int js_init(int argc, char** argv) {
|
|||
js_fs_init();
|
||||
|
||||
if(duk_peval_lstring(js_ctx, js_core, js_core_len) != 0) {
|
||||
printf("error: js/core.js: %s\n", duk_safe_to_string(js_ctx, -1));
|
||||
printf("JS error: js/core.js: %s\n", duk_safe_to_string(js_ctx, -1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define X(name, prefix) \
|
||||
if(duk_peval_lstring(js_ctx, prefix##_##name, prefix##_##name##_len) != 0) { \
|
||||
printf("error: %s: %s\n", #prefix "/" #name ".js", duk_safe_to_string(js_ctx, -1)); \
|
||||
printf("JS error: %s: %s\n", #prefix "/" #name ".js", duk_safe_to_string(js_ctx, -1)); \
|
||||
return 1; \
|
||||
}
|
||||
JS;
|
||||
|
|
@ -49,7 +49,7 @@ int js_init(int argc, char** argv) {
|
|||
if((st = js_run("pmake.js")) != 0) return st;
|
||||
|
||||
if(duk_peval_lstring(js_ctx, js_cmdline, js_cmdline_len) != 0) {
|
||||
printf("error: js/cmdline.js: %s\n", duk_safe_to_string(js_ctx, -1));
|
||||
printf("JS error: js/cmdline.js: %s\n", duk_safe_to_string(js_ctx, -1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ int js_run(const char* file) {
|
|||
fread(buffer, 1, len, f);
|
||||
|
||||
if(duk_peval_lstring(js_ctx, buffer, len) != 0) {
|
||||
printf("error: %s: %s\n", file, duk_safe_to_string(js_ctx, -1));
|
||||
printf("JS error: %s: %s\n", file, duk_safe_to_string(js_ctx, -1));
|
||||
|
||||
free(buffer);
|
||||
fclose(f);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
const PADDING = 24;
|
||||
|
||||
pmake.compiler = pmake.compilers["GCC"];
|
||||
|
||||
for(var i = 1; i < ARGV.length; i++) {
|
||||
if(ARGV[i] == "--help") {
|
||||
var keys;
|
||||
|
|
@ -48,35 +50,104 @@ for(var i = 1; i < ARGV.length; i++) {
|
|||
}
|
||||
process.exit(0);
|
||||
} else if(ARGV[i].startsWith("--")) {
|
||||
console.log("Error: invalid option '" + ARGV[i].substr(2) + "'");
|
||||
process.exit(1);
|
||||
var args = ARGV[i].split("=");
|
||||
|
||||
args[0] = args[0].substr(2);
|
||||
|
||||
if(pmake.options[args[0]]) {
|
||||
var opts = pmake.options[args[0]].options;
|
||||
|
||||
if(opts) {
|
||||
if((typeof opts) == "function") opts = opts();
|
||||
}
|
||||
|
||||
if(opts && !args[1]) {
|
||||
console.log("Error: no value specified for option '" + args[0] + "'");
|
||||
process.exit(1);
|
||||
} else if(opts && !opts.includes(args[1])) {
|
||||
console.log("Error: invalid value '" + args[1] + "' for option '" + args[0] + "'");
|
||||
process.exit(1);
|
||||
} else if(opts) {
|
||||
pmake.options[args[0]].action(args[1]);
|
||||
} else {
|
||||
pmake.options[args[0]].action();
|
||||
}
|
||||
} else {
|
||||
console.log("Error: invalid option '" + args[0] + "'");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(function() {
|
||||
function make(output) {
|
||||
const targets = pmake.resolveProjects(pmake.projects);
|
||||
|
||||
function target_map(x) {
|
||||
return x.target;
|
||||
}
|
||||
|
||||
var mk = new pmake.File(output, "w");
|
||||
|
||||
mk.write("# This file was auto-generated. Do not edit manually!\n");
|
||||
mk.write("\n");
|
||||
mk.write("SILENT = @\n");
|
||||
mk.write("RM = rm -f\n");
|
||||
mk.write("\n");
|
||||
mk.write(".PHONY: all clean\n");
|
||||
|
||||
if(output == "Makefile") {
|
||||
var targets = pmake.resolveProjects(pmake.projects);
|
||||
mk.write(".PHONY: " + targets.map(target_map).join(" ") + "\n");
|
||||
mk.write("\n");
|
||||
|
||||
mk.write("MAKEARGS$(.TARGET) = --no-print-directory");
|
||||
mk.write("\n");
|
||||
|
||||
mk.write("all: " + pmake.projects.map(target_map).join(" ") + "\n");
|
||||
mk.write("\n");
|
||||
|
||||
for(var i = 0; i < targets.length; i++) {
|
||||
mk.write(targets[i].target + ":\n");
|
||||
mk.write(" @$(MAKE) -f " + targets[i].target + ".make\n");
|
||||
mk.write(targets[i].target + ": " + pmake.resolveProjects(targets[i].libraries).map(target_map).join(" ") + "\n");
|
||||
mk.write(" @$(MAKE) $(MAKEARGS) -f " + targets[i].target + ".make\n");
|
||||
mk.write("\n");
|
||||
}
|
||||
|
||||
mk.write("clean:\n");
|
||||
for(var i = 0; i < targets.length; i++) {
|
||||
mk.write(" @$(MAKE) $(MAKEARGS) -f " + targets[i].target + ".make clean\n");
|
||||
}
|
||||
} else {
|
||||
function target_filter(x) {
|
||||
return x.target == output.replace(/\.make$/, "");
|
||||
}
|
||||
|
||||
const self = targets.filter(target_filter)[0];
|
||||
const objs = self.sources.map(pmake.compiler.output);
|
||||
|
||||
mk.write("\n");
|
||||
|
||||
mk.write("all: " + pmake.compiler.output(self) + "\n");
|
||||
mk.write("\n");
|
||||
|
||||
mk.write(pmake.compiler.output(self) + ": " + objs.join(" ") + "\n");
|
||||
mk.write(" " + pmake.compiler.link(self, objs) + "\n");
|
||||
mk.write("\n");
|
||||
|
||||
for(var i = 0; i < objs.length; i++) {
|
||||
mk.write(objs[i] + ": " + self.sources[i] + "\n");
|
||||
mk.write(" " + pmake.compiler.compile(self, objs[i], self.sources[i]) + "\n");
|
||||
mk.write("\n");
|
||||
}
|
||||
|
||||
mk.write("clean: \n");
|
||||
mk.write(" $(SILENT)$(RM) " + pmake.compiler.output(self) + " *.o *.exe *.a *.lib *.so *.dll\n");
|
||||
}
|
||||
|
||||
mk.close();
|
||||
}
|
||||
|
||||
make("Makefile");
|
||||
var targets = pmake.resolveProjects(pmake.projects);
|
||||
const targets = pmake.resolveProjects(pmake.projects);
|
||||
for(var i = 0; i < targets.length; i++) {
|
||||
make(targets[i].target + ".make");
|
||||
}
|
||||
|
|
|
|||
188
src/js/core.js
188
src/js/core.js
|
|
@ -1,12 +1,37 @@
|
|||
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, []);
|
||||
};
|
||||
}
|
||||
|
||||
const pmake = {
|
||||
VERSION : "0.0",
|
||||
compilers : {},
|
||||
options : {},
|
||||
options_category : {},
|
||||
projects : []
|
||||
};
|
||||
|
||||
pmake.inherit = function(base, call) {
|
||||
const func = (function() {});
|
||||
const func = (function() {
|
||||
base.apply(this, arguments);
|
||||
|
||||
if(call) call.apply(this, arguments);
|
||||
});
|
||||
|
||||
Object.setPrototypeOf(func.prototype, base.prototype);
|
||||
|
||||
|
|
@ -25,47 +50,159 @@ pmake.inherited = function(base, parent) {
|
|||
return false;
|
||||
};
|
||||
|
||||
pmake.register = function(base) {
|
||||
if(base instanceof pmake.Compiler) {
|
||||
pmake.compilers[base.target] = base;
|
||||
} else if(base instanceof pmake.Option) {
|
||||
if(!pmake.options[base.category]) pmake.options[base.category] = {};
|
||||
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] = {};
|
||||
|
||||
pmake.options[base.category][base.target] = base;
|
||||
} else if(base instanceof pmake.Project) {
|
||||
pmake.projects.push(base);
|
||||
pmake.options_category[target.category][target.target] = target;
|
||||
pmake.options[target.target] = target;
|
||||
} else if(target instanceof pmake.Project) {
|
||||
pmake.projects.push(target);
|
||||
}
|
||||
};
|
||||
|
||||
pmake.resolveProjects = function(arr) {
|
||||
pmake.resolveProjects = function(arr, if_str) {
|
||||
var r = [];
|
||||
|
||||
for(var i = 0; i < arr.length; i++) {
|
||||
if(arr[i] instanceof pmake.Project) {
|
||||
r = r.concat(pmake.resolveProjects(arr[i].libraries));
|
||||
r.push(arr[i]);
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
r = r.filter(function(item, pos) {
|
||||
return r.indexOf(item) == pos;
|
||||
});
|
||||
|
||||
return r;
|
||||
};
|
||||
|
||||
(function() {
|
||||
const Compiler = function() {};
|
||||
pmake.isCxx = function(src) {
|
||||
return src.endsWith(".cc") || src.endsWith(".cxx") || src.endsWith(".cpp");
|
||||
};
|
||||
|
||||
const POSIXCompiler = pmake.inherit(Compiler);
|
||||
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();
|
||||
};
|
||||
|
||||
(function() {
|
||||
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++";
|
||||
});
|
||||
|
||||
POSIXCompiler.prototype.compile = function(target, obj, src) {
|
||||
function add_i(x) {
|
||||
return "-I" + x;
|
||||
}
|
||||
|
||||
const includes = pmake.includes(target).map(add_i)
|
||||
|
||||
if(includes.length > 0) includes = " " + includes.join(" ");
|
||||
|
||||
if(src.endsWith(".c")) {
|
||||
return this.prefix + this.cc + includes + " -c -o " + obj + " " + src;
|
||||
} else if(is_cxx(src)) {
|
||||
return this.prefix + this.cxx + includes + " -c -o " + obj + " " + src;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
POSIXCompiler.prototype.link = function(target, files) {
|
||||
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 "";
|
||||
}
|
||||
|
||||
const Option = function() {};
|
||||
|
||||
const Project = function(target) {
|
||||
this.target = target;
|
||||
this.files = [];
|
||||
this.sources = [];
|
||||
this.includes = [];
|
||||
this.libraries = [];
|
||||
this.output = target;
|
||||
};
|
||||
|
||||
Project.prototype.generate = function() {
|
||||
};
|
||||
|
||||
const LibraryProject = pmake.inherit(Project, function(target) {
|
||||
});
|
||||
|
||||
const ExecutableProject = pmake.inherit(Project, function(target) {
|
||||
});
|
||||
|
||||
const InterfaceProject = pmake.inherit(Project, function(target) {
|
||||
});
|
||||
|
||||
const File = function(filename, mode) {
|
||||
this.fp = fs.open(filename, mode);
|
||||
};
|
||||
|
|
@ -78,11 +215,14 @@ File.prototype.close = function() {
|
|||
fs.close(this.fp);
|
||||
};
|
||||
|
||||
pmake.Compiler = Compiler;
|
||||
pmake.POSIXCompiler = POSIXCompiler;
|
||||
pmake.Option = Option;
|
||||
pmake.Project = Project;
|
||||
pmake.File = File;
|
||||
pmake.Compiler = Compiler;
|
||||
pmake.POSIXCompiler = POSIXCompiler;
|
||||
pmake.Option = Option;
|
||||
pmake.Project = Project;
|
||||
pmake.LibraryProject = LibraryProject;
|
||||
pmake.ExecutableProject = ExecutableProject;
|
||||
pmake.InterfaceProject = InterfaceProject;
|
||||
pmake.File = File;
|
||||
})();
|
||||
|
||||
/*** Option ***/
|
||||
|
|
@ -98,5 +238,9 @@ Compiler.options = function() {
|
|||
return Object.keys(pmake.compilers);
|
||||
};
|
||||
|
||||
Compiler.action = function(value) {
|
||||
pmake.compiler = pmake.compilers[value];
|
||||
};
|
||||
|
||||
pmake.register(Compiler);
|
||||
})();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue