diff --git a/.gitignore b/.gitignore index 0c9cf5b..a5e023e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,8 @@ *.o *.lib *.a -/Makefile -/*.make +Makefile +*.make /src/compiler/*.c /src/system/*.c /src/js/*.c diff --git a/GNUmakefile b/GNUmakefile index 8946410..1a15ef2 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -69,7 +69,7 @@ mk/js.mk: mk: mk/js.mk format: - clang-format --verbose -i src/*/*.js `find src -name "*.c" -or -name "*.h"` + clang-format --verbose -i `find pmake.js external src "(" -name "*.c" -or -name "*.h" -or -name "*.js" ")" -and -not -name "duk*" -and -not -name "stb_*.h"` maint: rm -f mk/*.mk diff --git a/external/duktape/pmake.js b/external/duktape/pmake.js new file mode 100644 index 0000000..76b91b8 --- /dev/null +++ b/external/duktape/pmake.js @@ -0,0 +1,11 @@ +function main() { + const duktape = new pmake.LibraryProject("duktape"); + duktape.sources = fs.glob("*.c"); + duktape.includes = [ "." ]; + + if(pmake.system.target == "Unix") { + duktape.libraries = [ "m" ]; + } + + pmake.register(duktape); +} diff --git a/pmake.js b/pmake.js index 0318219..8b2678d 100644 --- a/pmake.js +++ b/pmake.js @@ -16,15 +16,7 @@ function main() { generate("src/system/*.js"); generate("src/js/*.js"); - const Duktape = new pmake.LibraryProject("Duktape"); - Duktape.output = "duktape"; - Duktape.sources = fs.glob("external/duktape/*.c"); - Duktape.includes = [ "external/duktape" ]; - Duktape.libdirs = ["a"]; - - if(pmake.system.target == "Unix") { - Duktape.libraries = [ "m" ]; - } + pmake.subdirectory("external/duktape"); const stb = new pmake.InterfaceProject("stb"); stb.includes = [ "external/stb" ]; @@ -32,7 +24,7 @@ function main() { const PMake = new pmake.ExecutableProject("PMake"); PMake.output = "pmake"; PMake.sources = fs.glob("src/*.c", "src/compiler/*.c", "src/system/*.c", "src/js/*.c"); - PMake.libraries = [ Duktape, stb ]; + PMake.libraries = [ "duktape", stb ]; pmake.register(PMake); } diff --git a/src/js.c b/src/js.c index 49bd7b0..098dde7 100644 --- a/src/js.c +++ b/src/js.c @@ -30,6 +30,24 @@ static void js_win32_init(void) { duk_put_prop_string(js_ctx, 0, "WIN32"); } +static void js_pmake_subdirectory_main(const char* name) { + duk_eval_string(js_ctx, "main();"); +} + +static duk_ret_t js_pmake_subdirectory(duk_context* self) { + const char* s = duk_to_string(self, 0); + char cwd[1024]; + + getcwd(cwd, 1024); + if(chdir(s) != 0) return 0; + + js_run("pmake.js", js_pmake_subdirectory_main); + + chdir(cwd); + + return 0; +} + int js_init(int argc, char** argv) { int st; @@ -47,6 +65,11 @@ int js_init(int argc, char** argv) { return 1; } + duk_get_prop_string(js_ctx, 0, "pmake"); + duk_push_c_function(js_ctx, js_pmake_subdirectory, 1); + duk_put_prop_string(js_ctx, -2, "subdirectory"); + duk_pop(js_ctx); + #define X(name, prefix) \ if(duk_peval_lstring(js_ctx, prefix##_##name, prefix##_##name##_len) != 0) { \ printf("JS error: %s: %s\n", #prefix "/" #name ".js", duk_safe_to_string(js_ctx, -1)); \ @@ -56,7 +79,7 @@ int js_init(int argc, char** argv) { X(postinit, js); - if((st = js_run("pmake.js")) != 0) return st; + if((st = js_run("pmake.js", NULL)) != 0) return st; X(cmdline, js); #undef X @@ -64,16 +87,21 @@ int js_init(int argc, char** argv) { return 0; } -int js_run(const char* file) { +int js_run(const char* file, void (*call)(const char*)) { FILE* f; char* buffer; int len; + char name[512]; + int i; + char js[1024]; if((f = fopen(file, "rb")) == NULL) { printf("No PMake script (pmake.js) found!\n"); return 1; } + sprintf(name, "main_%d", (int)rand()); + fseek(f, 0, SEEK_END); len = ftell(f); fseek(f, 0, SEEK_SET); @@ -81,6 +109,9 @@ int js_run(const char* file) { buffer = malloc(len); fread(buffer, 1, len, f); + sprintf(js, "var %s;\nif(this.main){\n %s = main;\n delete main;}\n", name, name); + duk_eval_string(js_ctx, js); + if(duk_peval_lstring(js_ctx, buffer, len) != 0) { printf("JS error: %s: %s\n", file, duk_safe_to_string(js_ctx, -1)); @@ -90,6 +121,11 @@ int js_run(const char* file) { return 1; } + if(call != NULL) call(name); + + sprintf(js, "if(%s) main = %s;", name, name); + duk_eval_string(js_ctx, js); + free(buffer); fclose(f); diff --git a/src/js/cmdline.js b/src/js/cmdline.js index 51d3cd9..6177c7b 100644 --- a/src/js/cmdline.js +++ b/src/js/cmdline.js @@ -73,6 +73,10 @@ for(var i = 1; i < ARGV.length; i++) { main(); (function() { +function makefile(target) { + return target.base + "/" + target.target + ".make"; +} + function make(output) { const targets = pmake.resolveProjects(pmake.projects); @@ -101,21 +105,25 @@ function make(output) { for(var i = 0; i < targets.length; i++) { 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(" @cd " + targets[i].base + " ; $(MAKE) $(MAKEARGS) -f " + makefile(targets[i]) + "\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"); + mk.write(" @cd " + targets[i].base + " ; $(MAKE) $(MAKEARGS) -f " + makefile(targets[i]) + " clean\n"); } mk.write("\n"); mk.write("distclean: clean\n"); - mk.write(" $(SILENT)rm -f *.make Makefile\n"); + mk.write(" $(SILENT)rm -f Makefile\n"); + for(var i = 0; i < targets.length; i++) { + mk.write(" $(SILENT)rm -f " + makefile(targets[i]) + "\n"); + } } else { function target_filter(x) { - return x.target == output.replace(/\.make$/, ""); + const p = output.replace(/\.make$/, "").split("/"); + return x.target == p[p.length - 1]; } const self = targets.filter(target_filter)[0]; @@ -150,6 +158,6 @@ function make(output) { make("Makefile"); const targets = pmake.resolveProjects(pmake.projects); for(var i = 0; i < targets.length; i++) { - make(targets[i].target + ".make"); + make(makefile(targets[i])); } })(); diff --git a/src/js/core.js b/src/js/core.js index f5fb7c8..8d36d59 100644 --- a/src/js/core.js +++ b/src/js/core.js @@ -72,8 +72,12 @@ pmake.resolveProjects = function(arr, if_str) { for(var i = 0; i < arr.length; i++) { var proj = arr[i]; - if((typeof proj) == "string" && pmake.projects[proj]) { - proj = pmake.projects[proj]; + function filter_project(x) { + return x.target == proj; + } + + if((typeof proj) == "string" && pmake.projects.filter(filter_project)[0]) { + proj = pmake.projects.filter(filter_project)[0]; } if(proj instanceof pmake.Project) { @@ -95,26 +99,36 @@ pmake.isCxx = function(src) { return src.endsWith(".cc") || src.endsWith(".cxx") || src.endsWith(".cpp"); }; +pmake.pathTransform = function(target) { + return function(x) { + if(x == "." || x == ".." || x.startsWith("./") || x.startsWith("../")) { + return target.base + "/" + x; + } else { + return x; + } + }; +}; + pmake.includes = function(target) { function includes(x) { - return x.includes; + return x.includes.map(pmake.pathTransform(x)); } const targets = pmake.resolveProjects(target.libraries); - return targets.map(includes).flat(); + return target.includes.concat(targets.map(includes).flat()); }; -pmake.libdirs = function(target, if_str) { +pmake.libdirs = function(target) { function libdirs(x) { if(x instanceof pmake.LibraryProject) { - return x.libdirs; + return x.libdirs.map(pmake.pathTransform(x)); } return []; } - const targets = pmake.resolveProjects(target.libraries, if_str); + const targets = pmake.resolveProjects(target.libraries); return target.libdirs.concat(targets.map(libdirs).flat()); }; @@ -122,7 +136,7 @@ pmake.libdirs = function(target, if_str) { pmake.libs = function(target, if_str) { function libs(x) { if(x instanceof pmake.LibraryProject) { - const r = pmake.resolveProjects(x.libraries, if_str).concat([ pmake.compiler.output(x) ]); + const r = pmake.resolveProjects(x.libraries, if_str).concat([ x.base + "/" + pmake.compiler.output(x) ]); return r; } else if((typeof x) == "string") { @@ -236,6 +250,7 @@ const Project = function(target) { this.libdirs = []; this.libraries = []; this.output = target; + this.base = fs.cwd(); }; Project.prototype.generate = function() { diff --git a/src/js_fs.c b/src/js_fs.c index 948e5a4..80b176a 100644 --- a/src/js_fs.c +++ b/src/js_fs.c @@ -95,6 +95,15 @@ static duk_ret_t js_fs_close(duk_context* self) { return 0; } +static duk_ret_t js_fs_cwd(duk_context* self) { + char path[1024]; + + getcwd(path, 1024); + duk_push_string(self, path); + + return 1; +} + void js_fs_init(void) { int obj; @@ -112,5 +121,8 @@ void js_fs_init(void) { duk_push_c_function(js_ctx, js_fs_close, 1); duk_put_prop_string(js_ctx, obj, "close"); + duk_push_c_function(js_ctx, js_fs_cwd, 0); + duk_put_prop_string(js_ctx, obj, "cwd"); + duk_put_prop_string(js_ctx, 0, "fs"); } diff --git a/src/pmake.h b/src/pmake.h index 5659416..9978e87 100644 --- a/src/pmake.h +++ b/src/pmake.h @@ -7,6 +7,12 @@ #include #include +#ifdef _WIN32 +#include +#else +#include +#endif + #include #include @@ -21,7 +27,7 @@ JS; /* js.c */ extern duk_context* js_ctx; int js_init(int argc, char** argv); -int js_run(const char* file); +int js_run(const char* file, void (*call)(const char*)); void js_uninit(void); /* js_*.c */