aboutsummaryrefslogtreecommitdiff
path: root/src/tomo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tomo.c')
-rw-r--r--src/tomo.c106
1 files changed, 70 insertions, 36 deletions
diff --git a/src/tomo.c b/src/tomo.c
index 1517259e..b8588566 100644
--- a/src/tomo.c
+++ b/src/tomo.c
@@ -69,12 +69,6 @@ static const char *paths_str(List_t paths) {
return Text$as_c_string(result);
}
-#ifdef __APPLE__
-#define SHARED_SUFFIX ".dylib"
-#else
-#define SHARED_SUFFIX ".so"
-#endif
-
static OptionalBool_t verbose = false, quiet = false, show_version = false, show_prefix = false, clean_build = false,
source_mapping = true, should_install = false;
@@ -151,7 +145,6 @@ int main(int argc, char *argv[]) {
if (stat(compiler_path, &compiler_stat) != 0) err(1, "Could not find age of compiler");
#endif
- ldlibs = Texts(ldlibs, " -ltomo@", TOMO_VERSION);
#ifdef __OpenBSD__
ldlibs = Texts(ldlibs, Text(" -lexecinfo"));
#endif
@@ -268,7 +261,8 @@ int main(int argc, char *argv[]) {
cflags = Texts(cflags, Text(" -Wno-parentheses-equality"));
}
- ldflags = Texts("-Wl,-rpath,'", TOMO_PATH, "/lib' ", ldflags);
+ ldflags =
+ Texts("-Wl,-rpath,'", TOMO_PATH, "/lib' ", ldflags, " -ffunction-sections -fdata-sections -Wl,--gc-sections");
#ifdef __APPLE__
cflags = Texts(cflags, Text(" -I/opt/homebrew/include"));
@@ -397,6 +391,32 @@ int main(int argc, char *argv[]) {
run_files = normalize_tm_paths(run_files);
+ if (run_files.length == 0 && format_files.length == 0 && format_files_inplace.length == 0 && parse_files.length == 0
+ && transpile_files.length == 0 && compile_objects.length == 0 && compile_executables.length == 0
+ && run_files.length == 0 && uninstall_libraries.length == 0 && libraries.length == 0) {
+ Path_t path = Path$from_str(String("~/.local/tomo/state/tomo@", TOMO_VERSION, "/run.tm"));
+ path = Path$expand_home(path);
+ Path$create_directory(Path$parent(path), 0755, true);
+ if (!Path$exists(path)) {
+ Path$write(path,
+ Text("# This is a handy Tomo REPL-like runner\n" //
+ "# Normally you would run `tomo ./file.tm` to run a script\n" //
+ "# See `tomo --help` for full usage\n" //
+ "\n" //
+ "func main()\n" //
+ " # Put your code here:\n" //
+ " pass\n" //
+ "\n" //
+ "# Save and exit to run\n"),
+ 0644);
+ }
+ List$insert(&run_files, &path, I(0), sizeof(path));
+ const char *editor = getenv("EDITOR");
+ if (!editor || editor[0] == '\0') editor = "vim";
+ int status = system(String(editor, " ", path));
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) return 1;
+ }
+
// Compile runnable files in parallel, then execute in serial:
for (int64_t i = 0; i < (int64_t)run_files.length; i++) {
Path_t path = *(Path_t *)(run_files.data + i * run_files.stride);
@@ -481,28 +501,16 @@ void build_library(Path_t lib_dir) {
compile_files(env, tm_files, &object_files, &extra_ldlibs, COMPILE_OBJ);
Text_t lib_name = get_library_name(lib_dir);
- Path_t shared_lib = Path$child(lib_dir, Texts(Text("lib"), lib_name, Text(SHARED_SUFFIX)));
- if (!is_stale_for_any(shared_lib, object_files, false)) {
- if (verbose) whisper("Unchanged: ", shared_lib);
- return;
+ Path_t archive = Path$child(lib_dir, Texts(Text("lib"), lib_name, ".a"));
+ if (is_stale_for_any(archive, object_files, false)) {
+ FILE *prog = run_cmd("ar -rcs '", archive, "' ", paths_str(object_files));
+ if (!prog) print_err("Failed to run `ar`");
+ int status = pclose(prog);
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) exit(EXIT_FAILURE);
+ if (!quiet) print("Compiled static library:\t", Path$relative_to(archive, Path$current_dir()));
+ } else {
+ if (verbose) whisper("Unchanged: ", archive);
}
-
- FILE *prog = run_cmd(cc, " -O", optimization, " ", cflags, " ", ldflags, " ", ldlibs, " ", list_text(extra_ldlibs),
-#ifdef __APPLE__
- " -Wl,-install_name,@rpath/'lib", lib_name, SHARED_SUFFIX,
- "'"
-#else
- " -Wl,-soname,'lib", lib_name, SHARED_SUFFIX,
- "'"
-#endif
- " -shared ",
- paths_str(object_files), " -o '", shared_lib, "'");
-
- if (!prog) print_err("Failed to run C compiler: ", cc);
- int status = pclose(prog);
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) exit(EXIT_FAILURE);
-
- if (!quiet) print("Compiled library:\t", Path$relative_to(shared_lib, Path$current_dir()));
}
void install_library(Path_t lib_dir) {
@@ -519,11 +527,11 @@ void install_library(Path_t lib_dir) {
}
// If we have `debugedit` on this system, use it to remap the debugging source information
// to point to the installed version of the source file. Otherwise, fail silently.
- if (verbose) whisper("Updating debug symbols for ", dest, "/lib", lib_name, SHARED_SUFFIX);
+ if (verbose) whisper("Updating debug symbols for ", dest, "/lib", lib_name, ".a");
int result = system(String(as_owner, "debugedit -b ", lib_dir, " -d '", dest,
"'"
" '",
- dest, "/lib", lib_name, SHARED_SUFFIX,
+ dest, "/lib", lib_name, ".a",
"' "
">/dev/null 2>/dev/null"));
(void)result;
@@ -689,9 +697,8 @@ void build_file_dependency_graph(Path_t path, Table_t *to_compile, Table_t *to_l
case USE_MODULE: {
module_info_t mod = get_used_module_info(stmt_ast);
const char *full_name = mod.version ? String(mod.name, "@", mod.version) : mod.name;
- Text_t lib = Texts("-Wl,-rpath,'", TOMO_PATH, "/lib/tomo@", TOMO_VERSION, "/", Text$from_str(full_name),
- "' '", TOMO_PATH, "/lib/tomo@", TOMO_VERSION, "/", Text$from_str(full_name), "/lib",
- Text$from_str(full_name), SHARED_SUFFIX "'");
+ Text_t lib = Texts(TOMO_PATH, "/lib/tomo@", TOMO_VERSION, "/", Text$from_str(full_name), "/lib",
+ Text$from_str(full_name), ".a");
Table$set(to_link, &lib, NULL, Table$info(&Text$info, &Void$info));
List_t children = Path$glob(
@@ -917,8 +924,35 @@ Path_t compile_executable(env_t *base_env, Path_t path, Path_t exe_path, List_t
Path_t runner_file = build_file(path, ".runner.c");
Path$write(runner_file, program, 0644);
- FILE *runner = run_cmd(cc, " ", cflags, " -O", optimization, " ", ldflags, " ", ldlibs, " ",
- list_text(extra_ldlibs), " ", paths_str(object_files), " ", runner_file, " -o ", exe_path);
+ // .a archive files need to go later in the positional order:
+ List_t archives = EMPTY_LIST;
+ for (int64_t i = 0; i < (int64_t)extra_ldlibs.length;) {
+ Text_t *lib = (Text_t *)(extra_ldlibs.data + i * extra_ldlibs.stride);
+ if (Text$ends_with(*lib, Text(".a"), NULL)) {
+ List$insert(&archives, lib, I(0), sizeof(Text_t));
+ List$remove_at(&extra_ldlibs, I(i + 1), I(1), sizeof(Text_t));
+ } else {
+ i += 1;
+ }
+ }
+
+ FILE *runner = run_cmd(cc, " ",
+ // C flags:
+ cflags, " -O", optimization, " ",
+ // Linker flags and dynamically linked shared libraries:
+ ldflags, " ", ldlibs, " ", list_text(extra_ldlibs), " ",
+ // Object files:
+ paths_str(object_files), " ",
+ // Input file:
+ runner_file,
+ // Statically linked archive files (must come after runner):
+ // Libraries are grouped to allow for circular dependencies among
+ // the libraries that are used.
+ " -Wl,--start-group ", list_text(archives), " -Wl,--end-group ",
+ // Tomo static library:
+ TOMO_PATH, "/lib/libtomo@", TOMO_VERSION, ".a",
+ // Output file:
+ " -o ", exe_path);
if (show_codegen.length > 0) {
FILE *out = run_cmd(show_codegen);