Fix some relative import issues with compiled modules

This commit is contained in:
Bruce Hill 2025-03-30 14:44:42 -04:00
parent cdbf36b63c
commit 67f0886890
3 changed files with 42 additions and 28 deletions

View File

@ -4391,27 +4391,36 @@ CORD compile_file(env_t *env, ast_t *ast)
"}\n"); "}\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) { switch (ast->tag) {
case Use: { case Use: {
auto use = Match(ast, 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) { switch (use->what) {
case USE_MODULE: { case USE_MODULE: {
return CORD_all("#include <", use->path, "/", use->path, ".h>\n"); return CORD_all("#include <", use->path, "/", use->path, ".h>\n");
} }
case USE_LOCAL: { case USE_LOCAL: {
Path_t path = Path$relative_to(Path$from_str(use->path), Path(".build")); Path_t used_path = Path$from_str(use->path);
Path_t build_dir = Path$with_component(Path$parent(path), Text(".build")); if (used_path.type.$tag == PATH_RELATIVE)
path = Path$with_component(build_dir, Texts(Path$base_name(path), Text(".h"))); used_path = Path$concat(source_dir, used_path);
return CORD_all("#include \"", Path$as_c_string(path), "\"\n"); 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: case USE_HEADER:
if (use->path[0] == '<') { if (use->path[0] == '<') {
return CORD_all("#include ", use->path, "\n"); return CORD_all("#include ", use->path, "\n");
} else { } else {
Path_t path = Path$relative_to(Path$from_str(use->path), Path(".build")); Path_t used_path = Path$from_str(use->path);
return CORD_all("#include \"", Path$as_c_string(path), "\"\n"); 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: default:
return CORD_EMPTY; 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; const char *ns_name = NULL;
ast_t *block = 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"); code_err(ast, "You can't declare a variable with a ", type_to_str(t), " value");
return CORD_all( 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"); "extern ", compile_declaration(t, CORD_cat(namespace_prefix(env, env->namespace), decl_name)), ";\n");
} }
case FunctionDef: { 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); env_t *ns_env = namespace_env(env, ns_name);
CORD header = CORD_EMPTY; CORD header = CORD_EMPTY;
for (ast_list_t *stmt = block ? Match(block, Block)->statements : NULL; stmt; stmt = stmt->next) { 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; return header;
} }
@ -4554,6 +4563,7 @@ CORD compile_statement_namespace_header(env_t *env, ast_t *ast)
typedef struct { typedef struct {
env_t *env; env_t *env;
CORD *header; CORD *header;
Path_t header_path;
} compile_typedef_info_t; } compile_typedef_info_t;
static void _make_typedefs(compile_typedef_info_t *info, ast_t *ast) 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) static void _define_types_and_funcs(compile_typedef_info_t *info, ast_t *ast)
{ {
*info->header = CORD_all(*info->header, *info->header = CORD_all(*info->header,
compile_statement_type_header(info->env, ast), compile_statement_type_header(info->env, info->header_path, ast),
compile_statement_namespace_header(info->env, 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( CORD header = CORD_all(
"#pragma once\n" "#pragma once\n"
"#line 1 ", CORD_quoted(ast->file->filename), "\n", "#line 1 ", CORD_quoted(ast->file->filename), "\n",
"#include <tomo/tomo.h>\n"); "#include <tomo/tomo.h>\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*)_make_typedefs, &info});
visit_topologically(Match(ast, Block)->statements, (Closure_t){.fn=(void*)_define_types_and_funcs, &info}); visit_topologically(Match(ast, Block)->statements, (Closure_t){.fn=(void*)_define_types_and_funcs, &info});

View File

@ -7,17 +7,18 @@
#include <stdio.h> #include <stdio.h>
#include "environment.h" #include "environment.h"
#include "stdlib/datatypes.h"
CORD expr_as_text(CORD expr, type_t *t, CORD color); CORD expr_as_text(CORD expr, type_t *t, CORD color);
CORD compile_file(env_t *env, ast_t *ast); 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_declaration(type_t *t, const char *name);
CORD compile_type(type_t *t); CORD compile_type(type_t *t);
CORD compile(env_t *env, ast_t *ast); CORD compile(env_t *env, ast_t *ast);
CORD compile_namespace_header(env_t *env, const char *ns_name, ast_t *block); 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(env_t *env, ast_t *ast);
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);
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);
CORD compile_type_info(type_t *t); CORD compile_type_info(type_t *t);
CORD compile_cli_arg_call(env_t *env, CORD fn_name, type_t *fn_type); CORD compile_cli_arg_call(env_t *env, CORD fn_name, type_t *fn_type);

View File

@ -297,6 +297,7 @@ typedef struct {
env_t *env; env_t *env;
Table_t *used_imports; Table_t *used_imports;
FILE *output; FILE *output;
Path_t header_path;
} libheader_info_t; } libheader_info_t;
static void _compile_statement_header_for_library(libheader_info_t *info, ast_t *ast) 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); Path_t path = Path$from_str(use->path);
if (!Table$get(*info->used_imports, &path, Table$info(&Path$info, &Path$info))) { 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)); 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_type_header(info->env, info->header_path, ast), info->output);
CORD_put(compile_statement_namespace_header(info->env, ast), info->output); CORD_put(compile_statement_namespace_header(info->env, info->header_path, ast), info->output);
} }
} else { } else {
CORD_put(compile_statement_type_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, 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))) if (Table$get(*visited_files, &path, Table$info(&Path$info, &Bool$info)))
return; return;
@ -357,6 +358,7 @@ static void _compile_file_header_for_library(env_t *env, Path_t path, Table_t *v
.env=module_env, .env=module_env,
.used_imports=used_imports, .used_imports=used_imports,
.output=output, .output=output,
.header_path=header_path,
}; };
// Visit files in topological order: // 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); auto use = Match(ast, Use);
if (use->what == USE_LOCAL) { if (use->what == USE_LOCAL) {
Path_t resolved = Path$resolved(Path$from_str(use->path), Path("./")); 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)); env->libname = Text$as_c_string(escape_lib_name(lib_dir_name));
// Build a "whatever.h" header that loads all the headers: // 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"); FILE *header = fopen(String(lib_dir_name, ".h"), "w");
fputs("#pragma once\n", header); fputs("#pragma once\n", header);
fputs("#include <tomo/tomo.h>\n", header); fputs("#include <tomo/tomo.h>\n", header);
@ -402,7 +405,7 @@ void build_library(Text_t lib_dir_name)
for (int64_t i = 0; i < tm_files.length; i++) { for (int64_t i = 0; i < tm_files.length; i++) {
Path_t f = *(Path_t*)(tm_files.data + i*tm_files.stride); Path_t f = *(Path_t*)(tm_files.data + i*tm_files.stride);
Path_t resolved = Path$resolved(f, Path(".")); 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) if (fclose(header) == -1)
print_err("Failed to write header file: ", lib_dir_name, ".h"); 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) if (verbose)
CORD_printf("Successfully renamed symbols with library prefix!\n"); CORD_printf("Successfully renamed symbols with library prefix!\n");
// unlink(".build/symbol_renames.txt");
if (should_install) { if (should_install) {
char library_directory[PATH_MAX]; char library_directory[PATH_MAX];
getcwd(library_directory, sizeof(library_directory)); 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; break;
} }
case USE_ASM: { 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)); Table$set(to_link, &linker_text, ((Bool_t[1]){1}), Table$info(&Text$info, &Bool$info));
break; 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); 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"); FILE *header = fopen(Path$as_c_string(h_filename), "w");
if (!header) if (!header)