From 7f525588cb1e5f1b56e79e4c0407b909b4b5ff52 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Mon, 17 Mar 2025 20:17:37 -0400 Subject: [PATCH] Move to using a .build/ folder for generated files instead of foo.tm.c in the same folder --- .gitignore | 1 + Makefile | 2 +- README.md | 4 ++-- compile.c | 15 +++++++++++---- tomo.c | 50 ++++++++++++++++++++++++++++++++------------------ 5 files changed, 47 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 1a2f8c8..fd59728 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.build *.o *.so *.tm.c diff --git a/Makefile b/Makefile index f7305c6..04a9398 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ test: $(TESTS) @echo -e '\x1b[32;7m ALL TESTS PASSED! \x1b[m' clean: - rm -f tomo *.o stdlib/*.o libtomo.so test/*.tm.{c,h,o,testresult} examples/**/*.tm.{c,h,o} examples/*.tm.{c,h,o} + rm -rf tomo *.o stdlib/*.o libtomo.so test/*.tm.testresult test/.build examples/.build examples/*/.build %: %.md pandoc --lua-filter=.pandoc/bold-code.lua -s $< -t man -o $@ diff --git a/README.md b/README.md index e798356..730613d 100644 --- a/README.md +++ b/README.md @@ -121,13 +121,13 @@ Compile a Tomo file into an object file: ```bash tomo -c foo.tm -# Output: foo.tm.o +# Output: .build/foo.tm.o ``` Transpile a Tomo file into a C header and source file: ```bash tomo -t foo.tm -# Outputs: foo.tm.h foo.tm.c +# Outputs: .build/foo.tm.h .build/foo.tm.c ``` ## Installing diff --git a/compile.c b/compile.c index b2bb9aa..84d4836 100644 --- a/compile.c +++ b/compile.c @@ -14,6 +14,7 @@ #include "environment.h" #include "stdlib/integers.h" #include "stdlib/nums.h" +#include "stdlib/paths.h" #include "stdlib/patterns.h" #include "stdlib/text.h" #include "stdlib/util.h" @@ -4214,8 +4215,10 @@ CORD compile_top_level_code(env_t *env, ast_t *ast) switch (ast->tag) { case Use: { auto use = Match(ast, Use); - if (use->what == USE_C_CODE) - return CORD_all("#include \"", use->path, "\"\n"); + if (use->what == USE_C_CODE) { + Path_t path = Path$relative_to(Path$from_str(use->path), Path(".build")); + return CORD_all("#include \"", Path$as_c_string(path), "\"\n"); + } return CORD_EMPTY; } case Declare: { @@ -4387,8 +4390,12 @@ CORD compile_statement_type_header(env_t *env, ast_t *ast) case USE_MODULE: { return CORD_all("#include <", use->path, "/", use->path, ".h>\n"); } - case USE_LOCAL: - return CORD_all("#include \"", use->path, ".h\"\n"); + case USE_LOCAL: { + Path_t path = Path$relative_to(Path$from_str(use->path), Path(".build")); + Path_t build_dir = Path$with_component(Path$parent(path), Text(".build")); + path = Path$with_component(build_dir, Texts(Path$base_name(path), Text(".h"))); + return CORD_all("#include \"", Path$as_c_string(path), "\"\n"); + } case USE_HEADER: if (use->path[0] == '<') return CORD_all("#include ", use->path, "\n"); diff --git a/tomo.c b/tomo.c index 10fbac8..534faff 100644 --- a/tomo.c +++ b/tomo.c @@ -1,5 +1,6 @@ // The main program that runs compilation #include +#include #include #include #include @@ -209,6 +210,16 @@ Text_t escape_lib_name(Text_t lib_name) return Text$replace(lib_name, Pattern("{1+ !alphanumeric}"), Text("_"), Pattern(""), false); } +static Path_t build_file(Path_t path, const char *extension) +{ + Path_t build_dir = Path$with_component(Path$parent(path), Text(".build")); + if (mkdir(Path$as_c_string(build_dir), 0777) != 0) { + if (errno != EEXIST) + err(1, "Could not make .build directory"); + } + return Path$with_component(build_dir, Texts(Path$base_name(path), Text$from_str(extension))); +} + typedef struct { env_t *env; Table_t *used_imports; @@ -225,7 +236,7 @@ static void _compile_statement_header_for_library(libheader_info_t *info, ast_t if (use->what == USE_LOCAL) return; - Text_t path = Text$from_str(use->path); + Path_t path = Path$from_str(use->path); if (!Table$get(*info->used_imports, &path, Table$info(&Path$info, &Path$info))) { Table$set(info->used_imports, &path, ((Bool_t[1]){1}), Table$info(&Text$info, &Bool$info)); CORD_put(compile_statement_type_header(info->env, ast), info->output); @@ -324,12 +335,12 @@ void build_library(Text_t lib_dir_name) errx(1, "Failed to write header file: %k.h", &lib_dir_name); // Build up a list of symbol renamings: - unlink("symbol_renames.txt"); + unlink(".build/symbol_renames.txt"); FILE *prog; for (int64_t i = 0; i < tm_files.length; i++) { Path_t f = *(Path_t*)(tm_files.data + i*tm_files.stride); - prog = run_cmd("nm -Ug -fjust-symbols '%s.o' | sed -n 's/_\\$\\(.*\\)/\\0 _$%s$\\1/p' >>symbol_renames.txt", - Path$as_c_string(f), CORD_to_const_char_star(env->libname)); + prog = run_cmd("nm -Ug -fjust-symbols '%s' | sed -n 's/_\\$\\(.*\\)/\\0 _$%s$\\1/p' >>.build/symbol_renames.txt", + Path$as_c_string(build_file(f, ".o")), CORD_to_const_char_star(env->libname)); int status = pclose(prog); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) errx(WEXITSTATUS(status), "Failed to create symbol rename table with `nm` and `sed`"); @@ -347,12 +358,12 @@ void build_library(Text_t lib_dir_name) if (verbose) printf("\x1b[2mCompiled to lib%k.so\x1b[m\n", &lib_dir_name); - prog = run_cmd("objcopy --redefine-syms=symbol_renames.txt 'lib%k.so'", &lib_dir_name); + prog = run_cmd("objcopy --redefine-syms=.build/symbol_renames.txt 'lib%k.so'", &lib_dir_name); status = pclose(prog); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) errx(WEXITSTATUS(status), "Failed to run `objcopy` to add library prefix to symbols"); - prog = run_cmd("patchelf --rename-dynamic-symbols symbol_renames.txt 'lib%k.so'", &lib_dir_name); + prog = run_cmd("patchelf --rename-dynamic-symbols .build/symbol_renames.txt 'lib%k.so'", &lib_dir_name); status = pclose(prog); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) errx(WEXITSTATUS(status), "Failed to run `patchelf` to rename dynamic symbols with library prefix"); @@ -360,7 +371,7 @@ void build_library(Text_t lib_dir_name) if (verbose) CORD_printf("Successfully renamed symbols with library prefix!\n"); - unlink("symbol_renames.txt"); + // unlink(".build/symbol_renames.txt"); if (should_install) { char *library_directory = get_current_dir_name(); @@ -440,7 +451,7 @@ void compile_files(env_t *env, Array_t to_compile, bool only_compile_arguments, if (object_files) { for (int64_t i = 0; i < dependency_files.entries.length; i++) { Path_t path = *(Path_t*)(dependency_files.entries.data + i*dependency_files.entries.stride); - path = Path$with_extension(path, Text(".o"), false); + path = build_file(path, ".o"); Array$insert(object_files, &path, I(0), sizeof(Path_t)); } } @@ -457,7 +468,7 @@ void build_file_dependency_graph(Path_t path, Table_t *to_compile, Table_t *to_l if (Table$get(*to_compile, &path, Table$info(&Path$info, &Bool$info))) return; - bool stale = is_stale(Path$with_extension(path, Text(".o"), false), path); + bool stale = is_stale(build_file(path, ".o"), path); Table$set(to_compile, &path, &stale, Table$info(&Path$info, &Bool$info)); assert(Text$equal_values(Path$extension(path, true), Text("tm"))); @@ -477,7 +488,7 @@ void build_file_dependency_graph(Path_t path, Table_t *to_compile, Table_t *to_l switch (use->what) { case USE_LOCAL: { Path_t resolved = Path$resolved(Path$from_str(use->path), Path$parent(path)); - if (!stale && is_stale(Path$with_extension(path, Text(".o"), false), resolved)) { + if (!stale && is_stale(build_file(path, ".o"), resolved)) { stale = true; Table$set(to_compile, &path, &stale, Table$info(&Path$info, &Bool$info)); } @@ -493,7 +504,8 @@ void build_file_dependency_graph(Path_t path, Table_t *to_compile, Table_t *to_l Array_t children = Path$glob(Path$from_str(heap_strf("%s/.local/share/tomo/installed/%s/*.tm", getenv("HOME"), use->path))); for (int64_t i = 0; i < children.length; i++) { Path_t *child = (Path_t*)(children.data + i*children.stride); - build_file_dependency_graph(*child, to_compile, to_link); + Table_t discarded = {.fallback=to_compile}; + build_file_dependency_graph(*child, &discarded, to_link); } break; } @@ -503,8 +515,8 @@ void build_file_dependency_graph(Path_t path, Table_t *to_compile, Table_t *to_l break; } case USE_ASM: { - Text_t lib = Text$from_str(use->path); - Table$set(to_link, &lib, ((Bool_t[1]){1}), Table$info(&Text$info, &Bool$info)); + Text_t linker_text = Path$as_text(&use->path, false, &Path$info); + Table$set(to_link, &linker_text, ((Bool_t[1]){1}), Table$info(&Text$info, &Bool$info)); break; } default: case USE_HEADER: break; @@ -525,7 +537,7 @@ bool is_stale(Path_t path, Path_t relative_to) void transpile_header(env_t *base_env, Path_t path, bool force_retranspile) { - Path_t h_filename = Path$with_extension(path, Text(".h"), false); + Path_t h_filename = build_file(path, ".h"); if (!force_retranspile && !is_stale(h_filename, path)) return; @@ -538,6 +550,8 @@ void transpile_header(env_t *base_env, Path_t path, bool force_retranspile) CORD h_code = compile_file_header(module_env, ast); FILE *header = fopen(Path$as_c_string(h_filename), "w"); + if (!header) + errx(1, "Failed to open header file: %s", Path$as_c_string(h_filename)); CORD_put(h_code, header); if (fclose(header) == -1) errx(1, "Failed to write header file: %s", Path$as_c_string(h_filename)); @@ -551,7 +565,7 @@ void transpile_header(env_t *base_env, Path_t path, bool force_retranspile) void transpile_code(env_t *base_env, Path_t path, bool force_retranspile) { - Path_t c_filename = Path$with_extension(path, Text(".c"), false); + Path_t c_filename = build_file(path, ".c"); if (!force_retranspile && !is_stale(c_filename, path)) return; @@ -598,9 +612,9 @@ void transpile_code(env_t *base_env, Path_t path, bool force_retranspile) void compile_object_file(Path_t path, bool force_recompile) { - Path_t obj_file = Path$with_extension(path, Text(".o"), false); - Path_t c_file = Path$with_extension(path, Text(".c"), false); - Path_t h_file = Path$with_extension(path, Text(".h"), false); + Path_t obj_file = build_file(path, ".o"); + Path_t c_file = build_file(path, ".c"); + Path_t h_file = build_file(path, ".h"); if (!force_recompile && !is_stale(obj_file, path) && !is_stale(obj_file, c_file) && !is_stale(obj_file, h_file)) {