From 7c8338aedb68503f056ff5dc0b4d71b77dfae20c Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Thu, 21 Mar 2024 02:27:43 -0400 Subject: Lazy compilation --- tomo.c | 97 +++++++++++++++++++++++++++++++++++++++--------------------------- tomo.h | 10 ------- 2 files changed, 58 insertions(+), 49 deletions(-) delete mode 100644 tomo.h diff --git a/tomo.c b/tomo.c index 00aa40f3..62316098 100644 --- a/tomo.c +++ b/tomo.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -12,7 +13,6 @@ #include "builtins/text.h" #include "compile.h" #include "parse.h" -#include "tomo.h" #include "typecheck.h" #include "types.h" @@ -26,6 +26,11 @@ static const char *ldlibs; static const char *ldflags = "-Wl,-rpath '-Wl,$ORIGIN' -L/usr/local/lib"; static const char *cc; +static array_t get_file_dependencies(const char *filename); +static int transpile(const char *filename, bool force_retranspile); +static int compile_object_file(const char *filename, bool force_recompile); +static int run_program(const char *filename, const char *object_files); + int main(int argc, char *argv[]) { mode_e mode = MODE_RUN; @@ -73,18 +78,27 @@ int main(int argc, char *argv[]) cc = getenv("CC"); if (!cc) cc = "tcc"; - int status = transpile(filename, true); - if (status != 0 || mode < MODE_COMPILE) - return status; + if (mode == MODE_TRANSPILE) { + return transpile(filename, true); + } - status = compile_object_file(filename, true); - if (status != 0 || mode < MODE_RUN) - return status; + array_t file_deps = get_file_dependencies(filename); + CORD object_files_cord = CORD_EMPTY; + for (int64_t i = 0; i < file_deps.length; i++) { + const char *dep = *(char**)(file_deps.data + i*file_deps.stride); + compile_object_file(dep, false); + object_files_cord = object_files_cord ? CORD_all(object_files_cord, " ", dep, ".o") : CORD_cat(dep, ".o"); + } - return run_program(filename); + if (mode == MODE_RUN) { + const char *object_files = CORD_to_const_char_star(object_files_cord); + assert(object_files); + return run_program(filename, object_files); + } + return 0; } -static void build_object_dependency_graph(const char *filename, table_t *dependencies) +static void build_file_dependency_graph(const char *filename, table_t *dependencies) { size_t len = strlen(filename); const char *base_filename; @@ -99,14 +113,17 @@ static void build_object_dependency_graph(const char *filename, table_t *depende return; array_t *deps = new(array_t); - const char *obj_file = heap_strf("%s.o", base_filename); - Array__insert(deps, &obj_file, 0, $ArrayInfo(&Text)); + Array__insert(deps, &base_filename, 0, $ArrayInfo(&Text)); Table_str_set(dependencies, base_filename, deps); + transpile(base_filename, false); + const char *to_scan[] = { heap_strf("%s.h", base_filename), heap_strf("%s.c", base_filename), }; + char *file_dir = realpath(filename, NULL); + dirname(file_dir); for (size_t s = 0; s < sizeof(to_scan)/sizeof(to_scan[0]); s++) { file_t *f = load_file(to_scan[s]); if (!f) errx(1, "Couldn't find file: %s", to_scan[s]); @@ -114,14 +131,37 @@ static void build_object_dependency_graph(const char *filename, table_t *depende const char *line = f->text + f->lines[i].offset; const char *prefix = "#include \""; if (strncmp(line, prefix, strlen(prefix)) == 0) { - const char *included = heap_strn(line + strlen(prefix), strcspn(line + strlen(prefix), "\"")); - const char *resolved_header = resolve_path(included, to_scan[s], NULL); - const char *resolved_obj = heap_strf("%.*s.o", strlen(resolved_header)-2, resolved_header); - Array__insert(deps, &resolved_obj, 0, $ArrayInfo(&Text)); - build_object_dependency_graph(resolved_header, dependencies); + char *tmp = realpath(heap_strf("%s/%.*s", file_dir, strcspn(line + strlen(prefix), "\"") - 2, line + strlen(prefix)), NULL); + const char *resolved_file = heap_str(tmp); + free(tmp); + Array__insert(deps, &resolved_file, 0, $ArrayInfo(&Text)); + build_file_dependency_graph(resolved_file, dependencies); } } } + free(file_dir); +} + +array_t get_file_dependencies(const char *filename) +{ + const char *resolved = resolve_path(filename, ".", "."); + + table_t file_dependencies = {}; + build_file_dependency_graph(resolved, &file_dependencies); + table_t dependency_set = {}; + + const TypeInfo unit = {.size=0, .align=0, .tag=CustomInfo}; + const TypeInfo info = {.size=sizeof(table_t), .align=__alignof__(table_t), + .tag=TableInfo, .TableInfo.key=&Text, .TableInfo.value=&unit}; + + for (int64_t i = 1; i <= Table_length(file_dependencies); i++) { + struct { const char *name; array_t *deps; } *entry = Table_entry(file_dependencies, i); + for (int64_t j = 0; j < entry->deps->length; j++) { + const char *dep = *(char**)(entry->deps->data + j*entry->deps->stride); + Table_set(&dependency_set, &dep, &dep, &info); + } + } + return dependency_set.entries; } static bool stale(const char *filename, const char *relative_to) @@ -146,7 +186,6 @@ int transpile(const char *filename, bool force_retranspile) return 0; } - file_t *f = load_file(filename); if (!f) errx(1, "No such file: %s", filename); @@ -214,28 +253,8 @@ int compile_object_file(const char *filename, bool force_recompile) return WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE; } -int run_program(const char *filename) +int run_program(const char *filename, const char *object_files) { - const char *resolved = resolve_path(filename, ".", NULL); - - table_t obj_dependencies = {}; - build_object_dependency_graph(resolved, &obj_dependencies); - table_t obj_files = {}; - for (int64_t i = 1; i <= Table_length(obj_dependencies); i++) { - struct { const char *name; array_t *obj_files; } *entry = Table_entry(obj_dependencies, i); - for (int64_t j = 0; j < entry->obj_files->length; j++) { - const char *obj_name = *(char**)(entry->obj_files->data + j*entry->obj_files->stride); - Table_str_set(&obj_files, obj_name, obj_name); - } - } - CORD object_files_cord = CORD_EMPTY; - for (int64_t i = 1; i <= Table_length(obj_files); i++) { - struct { const char *name, *_; } *entry = Table_entry(obj_files, i); - object_files_cord = object_files_cord ? CORD_all(object_files_cord, " ", entry->name) : entry->name; - } - - const char *object_files = CORD_to_const_char_star(object_files_cord); - assert(object_files); const char *run = streq(cc, "tcc") ? heap_strf("%s | tcc %s %s %s %s -run -", autofmt, cflags, ldflags, ldlibs, object_files) : heap_strf("%s | gcc %s %s %s %s -x c - -o program && ./program", autofmt, cflags, ldflags, ldlibs, object_files); if (verbose) @@ -244,7 +263,7 @@ int run_program(const char *filename) const char *module_name = file_base_name(filename); CORD program = CORD_all( - "#include \n" + "#include \n" "#include \"", filename, ".h\"\n" "\n" "int main(int argc, const char *argv[]) {\n" diff --git a/tomo.h b/tomo.h deleted file mode 100644 index c96c25a0..00000000 --- a/tomo.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -// Compiler interface - -#include - -int transpile(const char *filename, bool force_retranspile); -int compile_object_file(const char *filename, bool force_recompile); -int run_program(const char *filename); - -// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 -- cgit v1.2.3