Support loading shared libraries
This commit is contained in:
parent
217eb51280
commit
5757a5023c
@ -2330,10 +2330,10 @@ CORD compile_statement_header(env_t *env, ast_t *ast)
|
||||
case Use: {
|
||||
auto use = Match(ast, Use);
|
||||
const char *path = use->raw_path;
|
||||
if (strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) {
|
||||
return CORD_all("#include \"", path, ".h\"\n");
|
||||
if (strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || strncmp(path, "~/", 2) == 0 || strncmp(path, "/", 1) == 0) {
|
||||
return CORD_all("#include \"", path, ".tm.h\"\n");
|
||||
} else {
|
||||
return CORD_all("#include <", path, ".h>\n");
|
||||
return CORD_all("#include <tomo/lib", path, ".h>\n");
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
2
parse.c
2
parse.c
@ -2017,7 +2017,7 @@ PARSER(parse_use) {
|
||||
size_t path_len = strcspn(pos, " \t\r\n;");
|
||||
if (path_len < 1)
|
||||
parser_err(ctx, start, pos, "There is no filename here to use");
|
||||
char *path = heap_strf("%.*s.tm", (int)path_len, pos);
|
||||
char *path = heap_strn(pos, path_len);
|
||||
pos += path_len;
|
||||
while (match(&pos, ";")) continue;
|
||||
return NewAST(ctx->file, start, pos, Use, .raw_path=path);
|
||||
|
29
tomo.c
29
tomo.c
@ -78,6 +78,7 @@ int main(int argc, char *argv[])
|
||||
errx(1, "Couldn't set printf specifier");
|
||||
|
||||
setenv("TOMO_IMPORT_PATH", "~/.local/src/tomo:.", 0);
|
||||
setenv("TOMO_LIB_PATH", "~/.local/lib/tomo:.", 0);
|
||||
|
||||
CORD home = ENV_CORD("HOME");
|
||||
autofmt = ENV_CORD("AUTOFMT");
|
||||
@ -103,7 +104,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
cflags = ENV_CORD("CFLAGS");
|
||||
if (!cflags)
|
||||
cflags = CORD_all(cconfig, " ", optimization, " -fPIC -ggdb -I./include -I'", home, "/.local/include/tomo' -D_DEFAULT_SOURCE");
|
||||
cflags = CORD_all(cconfig, " ", optimization, " -fPIC -ggdb -I./include -I'", home, "/.local/include' -D_DEFAULT_SOURCE");
|
||||
|
||||
ldflags = CORD_all("-Wl,-rpath='$ORIGIN',-rpath='", home, "/.local/lib/tomo' -L. -L'", home, "/.local/lib/tomo'");
|
||||
|
||||
@ -174,6 +175,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// For shared objects, link up all the object files into one .so file:
|
||||
if (mode == MODE_COMPILE_SHARED_OBJ) {
|
||||
// Build a "libwhatever.h" header that loads all the headers:
|
||||
const char *h_filename = heap_strf("lib%s.h", libname);
|
||||
FILE *h_file = fopen(h_filename, "w");
|
||||
if (!h_file)
|
||||
@ -181,11 +183,21 @@ int main(int argc, char *argv[])
|
||||
fputs("#pragma once\n", h_file);
|
||||
for (int i = after_flags; i < argc; i++) {
|
||||
const char *filename = argv[i];
|
||||
fprintf(h_file, "#include <%s/%s.h>\n", libname, filename);
|
||||
fprintf(h_file, "#include \"../../src/tomo/%s/%s.h\"\n", libname, filename);
|
||||
}
|
||||
if (fclose(h_file))
|
||||
errx(1, "Failed to close file: %s", h_filename);
|
||||
|
||||
// Also output a "libwhatever.files" file that lists the .tm files it used:
|
||||
const char *files_filename = heap_strf("lib%s.files", libname);
|
||||
FILE *files_file = fopen(files_filename, "w");
|
||||
if (!files_file)
|
||||
errx(1, "Couldn't open file: %s", files_filename);
|
||||
for (int i = after_flags; i < argc; i++)
|
||||
fprintf(files_file, "%s\n", argv[i]);
|
||||
if (fclose(files_file))
|
||||
errx(1, "Failed to close file: %s", files_filename);
|
||||
|
||||
CORD outfile = CORD_all("lib", libname, ".so");
|
||||
FILE *prog = CORD_RUN(cc, " ", cflags, " ", ldflags, " ", ldlibs, " -Wl,-soname=", outfile, " -shared ", object_files, " -o ", outfile);
|
||||
status = pclose(prog);
|
||||
@ -255,20 +267,19 @@ void build_file_dependency_graph(const char *filename, table_t *to_compile, tabl
|
||||
use_path = Match(decl->value, Use)->raw_path;
|
||||
}
|
||||
if (!use_path) continue;
|
||||
const char *import;
|
||||
if (use_path[0] == '/' || strncmp(use_path, "~/", 2) == 0 || strncmp(use_path, "./", 2) == 0 || strncmp(use_path, "../", 3) == 0) {
|
||||
import = resolve_path(use_path, filename, "");
|
||||
if (!import) errx(1, "Couldn't resolve path: %s", use_path);
|
||||
const char *path = resolve_path(use_path, filename, "");
|
||||
const char *path = resolve_path(heap_strf("%s.tm", use_path), filename, "");
|
||||
if (!path) errx(1, "Couldn't resolve import: %s", use_path);
|
||||
if (Table$str_get(*to_compile, path))
|
||||
continue;
|
||||
Table$str_set(to_compile, path, path);
|
||||
build_file_dependency_graph(path, to_compile, to_link);
|
||||
} else {
|
||||
import = resolve_path(use_path, filename, getenv("TOMO_IMPORT_PATH"));
|
||||
const char *lib = heap_strf("-l%.*s", strlen(use_path)-strlen(".tm"), use_path);
|
||||
const char *libfile = resolve_path(heap_strf("%s/lib%s.so", use_path, use_path), filename, getenv("TOMO_IMPORT_PATH"));
|
||||
if (!libfile) errx(1, "Couldn't resolve path: %s", use_path);
|
||||
const char *lib = heap_strf("-l%s", use_path);
|
||||
Table$str_set(to_link, lib, lib);
|
||||
}
|
||||
build_file_dependency_graph(import, to_compile, to_link);
|
||||
}
|
||||
free(file_dir);
|
||||
}
|
||||
|
51
typecheck.c
51
typecheck.c
@ -110,16 +110,51 @@ static env_t *load_module(env_t *env, ast_t *use_ast)
|
||||
if (module_env)
|
||||
return module_env;
|
||||
|
||||
const char *resolved_path = resolve_path(use->raw_path, use_ast->file->filename, getenv("TOMO_IMPORT_PATH"));
|
||||
if (!resolved_path)
|
||||
code_err(use_ast, "No such file exists: \"%s\"", use->raw_path);
|
||||
if (strncmp(use->raw_path, "/", 1) == 0 || strncmp(use->raw_path, "./", 2) == 0
|
||||
|| strncmp(use->raw_path, "../", 3) == 0 || strncmp(use->raw_path, "~/", 2) == 0) {
|
||||
const char *path = heap_strf("%s.tm", use->raw_path);
|
||||
const char *resolved_path = resolve_path(path, use_ast->file->filename, use_ast->file->filename);
|
||||
if (!resolved_path)
|
||||
code_err(use_ast, "No such file exists: \"%s\"", path);
|
||||
|
||||
file_t *f = load_file(resolved_path);
|
||||
if (!f) errx(1, "No such file: %s", resolved_path);
|
||||
file_t *f = load_file(resolved_path);
|
||||
if (!f) errx(1, "No such file: %s", resolved_path);
|
||||
|
||||
ast_t *ast = parse_file(f, NULL);
|
||||
if (!ast) errx(1, "Could not compile!");
|
||||
return load_module_env(env, ast);
|
||||
ast_t *ast = parse_file(f, NULL);
|
||||
if (!ast) errx(1, "Could not compile!");
|
||||
return load_module_env(env, ast);
|
||||
} else {
|
||||
const char *files_filename = heap_strf("%s/lib%s.files", use->raw_path, use->raw_path);
|
||||
const char *resolved_path = resolve_path(files_filename, use_ast->file->filename, getenv("TOMO_IMPORT_PATH"));
|
||||
if (!resolved_path)
|
||||
code_err(use_ast, "No such library exists: \"lib%s.files\"", use->raw_path);
|
||||
file_t *files_f = load_file(resolved_path);
|
||||
if (!files_f) errx(1, "Couldn't open file: %s", resolved_path);
|
||||
|
||||
env = fresh_scope(env);
|
||||
env->imports = new(table_t);
|
||||
for (int64_t i = 1; i <= files_f->num_lines; i++) {
|
||||
const char *line = get_line(files_f, i);
|
||||
line = heap_strn(line, strcspn(line, "\r\n"));
|
||||
if (!line || line[0] == '\0') continue;
|
||||
const char *tm_path = resolve_path(line, resolved_path, ".");
|
||||
if (!tm_path) errx(1, "Couldn't find library %s dependency: %s", use->raw_path, line);
|
||||
|
||||
file_t *tm_f = load_file(tm_path);
|
||||
if (!tm_f) errx(1, "No such file: %s", tm_path);
|
||||
|
||||
ast_t *ast = parse_file(tm_f, NULL);
|
||||
if (!ast) errx(1, "Could not compile!");
|
||||
env_t *subenv = load_module_env(env, ast);
|
||||
for (int64_t j = 0; j < subenv->locals->entries.length; j++) {
|
||||
struct {
|
||||
const char *name; binding_t *binding;
|
||||
} *entry = subenv->locals->entries.data + j*subenv->locals->entries.stride;
|
||||
set_binding(env, entry->name, entry->binding);
|
||||
}
|
||||
}
|
||||
return env;
|
||||
}
|
||||
}
|
||||
|
||||
void prebind_statement(env_t *env, ast_t *statement)
|
||||
|
Loading…
Reference in New Issue
Block a user