From 67f088689019bfc3c731f8157e50c560fabddb04 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sun, 30 Mar 2025 14:44:42 -0400 Subject: [PATCH] Fix some relative import issues with compiled modules --- src/compile.c | 38 ++++++++++++++++++++++++-------------- src/compile.h | 7 ++++--- src/tomo.c | 25 ++++++++++++++----------- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/src/compile.c b/src/compile.c index aa4ddac..abccc59 100644 --- a/src/compile.c +++ b/src/compile.c @@ -4391,27 +4391,36 @@ CORD compile_file(env_t *env, ast_t *ast) "}\n"); } -CORD compile_statement_type_header(env_t *env, ast_t *ast) +CORD compile_statement_type_header(env_t *env, Path_t header_path, ast_t *ast) { switch (ast->tag) { case Use: { auto use = Match(ast, Use); + Path_t source_path = Path$from_str(ast->file->filename); + Path_t source_dir = Path$parent(source_path); + char cwd[PATH_MAX]; + getcwd(cwd, sizeof(cwd)); + Path_t build_dir = Path$resolved(Path$parent(header_path), Path(cwd)); switch (use->what) { case USE_MODULE: { return CORD_all("#include <", use->path, "/", 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"); + Path_t used_path = Path$from_str(use->path); + if (used_path.type.$tag == PATH_RELATIVE) + used_path = Path$concat(source_dir, used_path); + Path_t used_build_dir = Path$with_component(Path$parent(used_path), Text(".build")); + Path_t used_header_path = Path$with_component(used_build_dir, Texts(Path$base_name(used_path), Text(".h"))); + return CORD_all("#include \"", Path$as_c_string(Path$relative_to(used_header_path, build_dir)), "\"\n"); } case USE_HEADER: if (use->path[0] == '<') { return CORD_all("#include ", use->path, "\n"); } else { - Path_t path = Path$relative_to(Path$from_str(use->path), Path(".build")); - return CORD_all("#include \"", Path$as_c_string(path), "\"\n"); + Path_t used_path = Path$from_str(use->path); + if (used_path.type.$tag == PATH_RELATIVE) + used_path = Path$concat(source_dir, used_path); + return CORD_all("#include \"", Path$as_c_string(Path$relative_to(used_path, build_dir)), "\"\n"); } default: return CORD_EMPTY; @@ -4440,7 +4449,7 @@ CORD compile_statement_type_header(env_t *env, ast_t *ast) } } -CORD compile_statement_namespace_header(env_t *env, ast_t *ast) +CORD compile_statement_namespace_header(env_t *env, Path_t header_path, ast_t *ast) { const char *ns_name = NULL; ast_t *block = NULL; @@ -4496,7 +4505,7 @@ CORD compile_statement_namespace_header(env_t *env, ast_t *ast) code_err(ast, "You can't declare a variable with a ", type_to_str(t), " value"); return CORD_all( - compile_statement_type_header(env, decl->value), + compile_statement_type_header(env, header_path, decl->value), "extern ", compile_declaration(t, CORD_cat(namespace_prefix(env, env->namespace), decl_name)), ";\n"); } case FunctionDef: { @@ -4546,7 +4555,7 @@ CORD compile_statement_namespace_header(env_t *env, ast_t *ast) env_t *ns_env = namespace_env(env, ns_name); CORD header = CORD_EMPTY; for (ast_list_t *stmt = block ? Match(block, Block)->statements : NULL; stmt; stmt = stmt->next) { - header = CORD_all(header, compile_statement_namespace_header(ns_env, stmt->ast)); + header = CORD_all(header, compile_statement_namespace_header(ns_env, header_path, stmt->ast)); } return header; } @@ -4554,6 +4563,7 @@ CORD compile_statement_namespace_header(env_t *env, ast_t *ast) typedef struct { env_t *env; CORD *header; + Path_t header_path; } compile_typedef_info_t; static void _make_typedefs(compile_typedef_info_t *info, ast_t *ast) @@ -4581,18 +4591,18 @@ static void _make_typedefs(compile_typedef_info_t *info, ast_t *ast) static void _define_types_and_funcs(compile_typedef_info_t *info, ast_t *ast) { *info->header = CORD_all(*info->header, - compile_statement_type_header(info->env, ast), - compile_statement_namespace_header(info->env, ast)); + compile_statement_type_header(info->env, info->header_path, ast), + compile_statement_namespace_header(info->env, info->header_path, ast)); } -CORD compile_file_header(env_t *env, ast_t *ast) +CORD compile_file_header(env_t *env, Path_t header_path, ast_t *ast) { CORD header = CORD_all( "#pragma once\n" "#line 1 ", CORD_quoted(ast->file->filename), "\n", "#include \n"); - compile_typedef_info_t info = {.env=env, .header=&header}; + compile_typedef_info_t info = {.env=env, .header=&header, .header_path=header_path}; visit_topologically(Match(ast, Block)->statements, (Closure_t){.fn=(void*)_make_typedefs, &info}); visit_topologically(Match(ast, Block)->statements, (Closure_t){.fn=(void*)_define_types_and_funcs, &info}); diff --git a/src/compile.h b/src/compile.h index 4256ab5..ae9e510 100644 --- a/src/compile.h +++ b/src/compile.h @@ -7,17 +7,18 @@ #include #include "environment.h" +#include "stdlib/datatypes.h" CORD expr_as_text(CORD expr, type_t *t, CORD color); CORD compile_file(env_t *env, ast_t *ast); -CORD compile_file_header(env_t *env, ast_t *ast); +CORD compile_file_header(env_t *env, Path_t header_path, ast_t *ast); CORD compile_declaration(type_t *t, const char *name); CORD compile_type(type_t *t); CORD compile(env_t *env, ast_t *ast); CORD compile_namespace_header(env_t *env, const char *ns_name, ast_t *block); CORD compile_statement(env_t *env, ast_t *ast); -CORD compile_statement_type_header(env_t *env, ast_t *ast); -CORD compile_statement_namespace_header(env_t *env, ast_t *ast); +CORD compile_statement_type_header(env_t *env, Path_t header_path, ast_t *ast); +CORD compile_statement_namespace_header(env_t *env, Path_t header_path, ast_t *ast); CORD compile_type_info(type_t *t); CORD compile_cli_arg_call(env_t *env, CORD fn_name, type_t *fn_type); diff --git a/src/tomo.c b/src/tomo.c index 255332f..3a73707 100644 --- a/src/tomo.c +++ b/src/tomo.c @@ -297,6 +297,7 @@ typedef struct { env_t *env; Table_t *used_imports; FILE *output; + Path_t header_path; } libheader_info_t; static void _compile_statement_header_for_library(libheader_info_t *info, ast_t *ast) @@ -312,12 +313,12 @@ static void _compile_statement_header_for_library(libheader_info_t *info, ast_t 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); - CORD_put(compile_statement_namespace_header(info->env, ast), info->output); + CORD_put(compile_statement_type_header(info->env, info->header_path, ast), info->output); + CORD_put(compile_statement_namespace_header(info->env, info->header_path, ast), info->output); } } else { - CORD_put(compile_statement_type_header(info->env, ast), info->output); - CORD_put(compile_statement_namespace_header(info->env, ast), info->output); + CORD_put(compile_statement_type_header(info->env, info->header_path, ast), info->output); + CORD_put(compile_statement_namespace_header(info->env, info->header_path, ast), info->output); } } @@ -342,7 +343,7 @@ static void _make_typedefs_for_library(libheader_info_t *info, ast_t *ast) } } -static void _compile_file_header_for_library(env_t *env, Path_t path, Table_t *visited_files, Table_t *used_imports, FILE *output) +static void _compile_file_header_for_library(env_t *env, Path_t header_path, Path_t path, Table_t *visited_files, Table_t *used_imports, FILE *output) { if (Table$get(*visited_files, &path, Table$info(&Path$info, &Bool$info))) return; @@ -357,6 +358,7 @@ static void _compile_file_header_for_library(env_t *env, Path_t path, Table_t *v .env=module_env, .used_imports=used_imports, .output=output, + .header_path=header_path, }; // Visit files in topological order: @@ -369,7 +371,7 @@ static void _compile_file_header_for_library(env_t *env, Path_t path, Table_t *v auto use = Match(ast, Use); if (use->what == USE_LOCAL) { Path_t resolved = Path$resolved(Path$from_str(use->path), Path("./")); - _compile_file_header_for_library(env, resolved, visited_files, used_imports, output); + _compile_file_header_for_library(env, header_path, resolved, visited_files, used_imports, output); } } @@ -394,6 +396,7 @@ void build_library(Text_t lib_dir_name) env->libname = Text$as_c_string(escape_lib_name(lib_dir_name)); // Build a "whatever.h" header that loads all the headers: + Path_t header_path = Path$resolved(Path$from_str(String(lib_dir_name, ".h")), Path$from_str(".")); FILE *header = fopen(String(lib_dir_name, ".h"), "w"); fputs("#pragma once\n", header); fputs("#include \n", header); @@ -402,7 +405,7 @@ void build_library(Text_t lib_dir_name) for (int64_t i = 0; i < tm_files.length; i++) { Path_t f = *(Path_t*)(tm_files.data + i*tm_files.stride); Path_t resolved = Path$resolved(f, Path(".")); - _compile_file_header_for_library(env, resolved, &visited_files, &used_imports, header); + _compile_file_header_for_library(env, header_path, resolved, &visited_files, &used_imports, header); } if (fclose(header) == -1) print_err("Failed to write header file: ", lib_dir_name, ".h"); @@ -445,8 +448,6 @@ void build_library(Text_t lib_dir_name) if (verbose) CORD_printf("Successfully renamed symbols with library prefix!\n"); - // unlink(".build/symbol_renames.txt"); - if (should_install) { char library_directory[PATH_MAX]; getcwd(library_directory, sizeof(library_directory)); @@ -601,7 +602,9 @@ void build_file_dependency_graph(Path_t path, Table_t *to_compile, Table_t *to_l break; } case USE_ASM: { - Text_t linker_text = Text$from_str(use->path); + Path_t asm_path = Path$from_str(use->path); + asm_path = Path$concat(Path$parent(path), asm_path); + Text_t linker_text = Path$as_text(&asm_path, NULL, &Path$info); Table$set(to_link, &linker_text, ((Bool_t[1]){1}), Table$info(&Text$info, &Bool$info)); break; } @@ -637,7 +640,7 @@ void transpile_header(env_t *base_env, Path_t path) env_t *module_env = load_module_env(base_env, ast); - CORD h_code = compile_file_header(module_env, ast); + CORD h_code = compile_file_header(module_env, Path$resolved(h_filename, Path$from_str(".")), ast); FILE *header = fopen(Path$as_c_string(h_filename), "w"); if (!header)