aboutsummaryrefslogtreecommitdiff
path: root/src/compile.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-03-30 14:44:42 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-03-30 14:44:42 -0400
commit67f088689019bfc3c731f8157e50c560fabddb04 (patch)
treee1fa1ce523545eab7ede7f6d3924ba3d2ccd71bf /src/compile.c
parentcdbf36b63c9250c132b1fafb46b7881b4a263217 (diff)
Fix some relative import issues with compiled modules
Diffstat (limited to 'src/compile.c')
-rw-r--r--src/compile.c38
1 files changed, 24 insertions, 14 deletions
diff --git a/src/compile.c b/src/compile.c
index aa4ddac9..abccc599 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 <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*)_define_types_and_funcs, &info});