From 0e0808bce2160eb1382a2cf9499d943d4e51bdf4 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Tue, 15 Apr 2025 16:52:55 -0400 Subject: Add configuration script to choose install paths and default C compiler and bake those into the compiled Tomo code --- .gitignore | 1 + Makefile | 26 +++++++++++++++++++++----- configure.sh | 44 ++++++++++++++++++++++++++++++++++++++++++++ lib/commands/commands.tm | 6 +++--- lib/patterns/patterns.c | 1 + src/compile.c | 2 +- src/stdlib/stacktrace.c | 6 +++--- src/tomo.c | 36 ++++++++++++++++++------------------ src/typecheck.c | 2 +- 9 files changed, 93 insertions(+), 31 deletions(-) create mode 100755 configure.sh diff --git a/.gitignore b/.gitignore index 34f62c11..9a8cb004 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/config.mk /examples/*/* !/examples/*.* !/examples/*/*.* diff --git a/Makefile b/Makefile index b76f4053..8b4f291a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,13 @@ -PREFIX=$(HOME)/.local +# Run ./configure.sh to choose installation locations: +ifeq ($(wildcard config.mk),) +all: config.mk + $(MAKE) all +config.mk: configure.sh + ./configure.sh +else + +include config.mk + VERSION=0.0.1 CC=cc CCONFIG=-std=c2x -fPIC \ @@ -41,7 +50,8 @@ OSFLAGS != case $(OS) in *BSD|Darwin) echo '-D_BSD_SOURCE';; Linux) echo '-D_GNU EXTRA= G=-ggdb O=-Og -CFLAGS=$(CCONFIG) $(INCLUDE_DIRS) $(EXTRA) $(CWARN) $(G) $(O) $(OSFLAGS) $(LTO) +CFLAGS=$(CCONFIG) $(INCLUDE_DIRS) $(EXTRA) $(CWARN) $(G) $(O) $(OSFLAGS) $(LTO) \ + -DTOMO_HOME='"$(TOMO_HOME)"' -DTOMO_PREFIX='"$(PREFIX)"' -DDEFAULT_C_COMPILER='"$(DEFAULT_C_COMPILER)"' CFLAGS_PLACEHOLDER="$$(printf '\033[2m\033[m\n')" LDLIBS=-lgc -lcord -lm -lunistring -lgmp LIBTOMO_FLAGS=-shared @@ -65,7 +75,7 @@ COMPILER_OBJS=$(patsubst %.c,%.o,$(wildcard src/*.c)) STDLIB_OBJS=$(patsubst %.c,%.o,$(wildcard src/stdlib/*.c)) TESTS=$(patsubst test/%.tm,test/results/%.tm.testresult,$(wildcard test/*.tm)) -all: build/$(LIB_FILE) build/$(AR_FILE) build/tomo +all: config.mk build/$(LIB_FILE) build/$(AR_FILE) build/tomo build/tomo: $(STDLIB_OBJS) $(COMPILER_OBJS) @mkdir -p build @@ -85,7 +95,10 @@ build/$(AR_FILE): $(STDLIB_OBJS) tags: ctags src/*.[ch] src/stdlib/*.[ch] -%.o: %.c src/ast.h src/environment.h src/types.h +config.mk: configure.sh + ./configure.sh + +%.o: %.c src/ast.h src/environment.h src/types.h config.mk @echo $(CC) $(CFLAGS_PLACEHOLDER) -c $< -o $@ @$(CC) $(CFLAGS) -c $< -o $@ @@ -131,7 +144,8 @@ check-gcc: install-files: build/tomo build/$(LIB_FILE) build/$(AR_FILE) @if ! echo "$$PATH" | tr ':' '\n' | grep -qx "$(PREFIX)/bin"; then \ - printf "\033[31;1mError: '$(PREFIX)' is not in your \$$PATH variable!\033[m\n" >&2; \ + echo $$PATH; \ + printf "\033[31;1mError: '$(PREFIX)/bin' is not in your \$$PATH variable!\033[m\n" >&2; \ printf "\033[31;1mSpecify a different prefix with 'make PREFIX=... install'\033[m\n" >&2; \ printf "\033[31;1mor add the following line to your .profile:\033[m\n" >&2; \ printf "\n\033[1mexport PATH=\"$(PREFIX):\$$PATH\"\033[m\n\n" >&2; \ @@ -152,5 +166,7 @@ install: install-files install-libs uninstall: rm -rvf "$(PREFIX)/bin/tomo" "$(PREFIX)/include/tomo" "$(PREFIX)/lib/$(LIB_FILE)" "$(PREFIX)/lib/$(AR_FILE)" "$(PREFIX)/share/tomo"; +endif + .SUFFIXES: .PHONY: all clean install install-files install-libs uninstall test tags examples deps check-gcc diff --git a/configure.sh b/configure.sh new file mode 100755 index 00000000..9ad06fb0 --- /dev/null +++ b/configure.sh @@ -0,0 +1,44 @@ +#!/bin/env bash + +# if [ "$1" = '--lazy' -a ! -f 'config.mk' ]; then +# echo "Already configured!" +# exit 0 +# fi + +error() { + printf "\033[31;1m%s\033[m\n" "$@" + exit 1 +} + +default_prefix='/usr/local' +if echo "$PATH" | tr ':' '\n' | grep -qx "$HOME/.local/bin"; then + default_prefix="~/.local" +fi + +printf '\033[1mChoose where to install Tomo (default: %s):\033[m ' "$default_prefix" +read PREFIX +if [ -z "$PREFIX" ]; then PREFIX="$default_prefix"; fi +PREFIX="${PREFIX/#\~/$HOME}" + +if ! echo "$PATH" | tr ':' '\n' | grep -qx "$PREFIX/bin"; then + error "Your \$PATH does not include this prefix, so you won't be able to run tomo!" \ + "Please put this in your .profile or .bashrc: export PATH=\"$PREFIX:\$PATH\"" +fi + +default_home="~/.local/share/tomo" +printf '\033[1mChoose where to install Tomo libraries (default: %s):\033[m ' "$default_home" +read TOMO_HOME +if [ -z "$TOMO_HOME" ]; then TOMO_HOME="$default_home"; fi +TOMO_HOME="${TOMO_HOME/#\~/$HOME}" + +default_cc="cc" +printf '\033[1mChoose which C compiler to use by default (default: %s):\033[m ' "$default_cc" +read DEFAULT_C_COMPILER +if [ -z "$DEFAULT_C_COMPILER" ]; then DEFAULT_C_COMPILER="$default_home"; fi +DEFAULT_C_COMPILER="${DEFAULT_C_COMPILER/#\~/$HOME}" + +cat <config.mk +PREFIX=$PREFIX +TOMO_HOME=$TOMO_HOME +DEFAULT_C_COMPILER=$DEFAULT_C_COMPILER +END diff --git a/lib/commands/commands.tm b/lib/commands/commands.tm index aeadda4f..a5ce607a 100644 --- a/lib/commands/commands.tm +++ b/lib/commands/commands.tm @@ -18,10 +18,10 @@ enum ExitType(Exited(status:Int32), Signaled(signal:Int32), Failed) struct ProgramResult(output:[Byte], errors:[Byte], exit_type:ExitType) func or_fail(r:ProgramResult, message:Text?=none -> ProgramResult) when r.exit_type is Exited(status) - if status == 0 - return r + if status != 0 + fail(message or "Program failed: $r") else fail(message or "Program failed: $r") - fail(message or "Program failed: $r") + return r func output_text(r:ProgramResult, trim_newline=yes -> Text?) when r.exit_type is Exited(status) diff --git a/lib/patterns/patterns.c b/lib/patterns/patterns.c index 5cb02ffa..04cc9c0e 100644 --- a/lib/patterns/patterns.c +++ b/lib/patterns/patterns.c @@ -504,6 +504,7 @@ static int64_t match_pat(TextIter_t *state, int64_t index, pat_t pat) default: errx(1, "Invalid pattern"); } errx(1, "Unreachable"); + return 0; } static pat_t parse_next_pat(TextIter_t *state, int64_t *index) diff --git a/src/compile.c b/src/compile.c index 052fe309..766da09d 100644 --- a/src/compile.c +++ b/src/compile.c @@ -1888,7 +1888,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast) return with_source_info(env, ast, CORD_all("_$", name, "$$initialize();\n")); } else if (use->what == USE_MODULE) { glob_t tm_files; - if (glob(String("~/.local/share/tomo/installed/", use->path, "/[!._0-9]*.tm"), GLOB_TILDE, NULL, &tm_files) != 0) + if (glob(String(TOMO_HOME"/installed/", use->path, "/[!._0-9]*.tm"), GLOB_TILDE, NULL, &tm_files) != 0) code_err(ast, "Could not find library"); CORD initialization = CORD_EMPTY; diff --git a/src/stdlib/stacktrace.c b/src/stdlib/stacktrace.c index 0ae4915e..798da218 100644 --- a/src/stdlib/stacktrace.c +++ b/src/stdlib/stacktrace.c @@ -72,8 +72,8 @@ static void _print_stack_frame(FILE *out, const char *cwd, const char *install_d fprintf(out, USE_COLOR ? "\033[1mIn \033[33m%s()\033[37m" : "In %s()", function_display); if (filename) { if (install_dir[0] && strncmp(filename, install_dir, strlen(install_dir)) == 0) - fprintf(out, USE_COLOR ? " in library \033[35m~/.local/share/tomo/installed/%s:%d" : " in library ~/.local/share/tomo/installed/%s:%d", - filename + strlen(install_dir), lineno); + fprintf(out, USE_COLOR ? " in library \033[35m%s:%d" : " in library %s:%d", + filename, lineno); else fprintf(out, USE_COLOR ? " in \033[35m%s:%d" : " in %s:%d", filename, lineno); } @@ -97,7 +97,7 @@ public void print_stacktrace(FILE *out, int offset) cwd[cwd_len++] = '/'; cwd[cwd_len] = '\0'; - const char *install_dir = String(getenv("HOME"), "/.local/share/tomo/installed/"); + const char *install_dir = TOMO_HOME"/installed/"; static void *stack[1024]; int64_t size = (int64_t)backtrace(stack, sizeof(stack)/sizeof(stack[0])); diff --git a/src/tomo.c b/src/tomo.c index 0a75497f..f47f1934 100644 --- a/src/tomo.c +++ b/src/tomo.c @@ -67,12 +67,12 @@ static OptionalText_t " -D_BSD_SOURCE" #endif " -DGC_THREADS" - " -I$HOME/.local/include -I$HOME/.local/share/tomo/installed -I/usr/local/include"), - ldlibs = Text("-lgc -lm -lgmp -lunistring -ltomo"), - ldflags = Text("-Wl,-rpath,'$ORIGIN',-rpath,$HOME/.local/share/tomo/lib,-rpath,$HOME/.local/lib,-rpath,/usr/local/lib " - "-L$HOME/.local/lib -L$HOME/.local/share/tomo/lib -L/usr/local/lib"), + " -I'" TOMO_PREFIX "/include' -I'" TOMO_HOME "/installed' -I/usr/local/include"), + ldlibs = Text("-lgc -lm -lgmp -lunistring '"TOMO_PREFIX"'/lib/libtomo.so"), + ldflags = Text("-Wl,-rpath,'$ORIGIN',-rpath,'" TOMO_HOME "/lib',-rpath,/usr/local/lib " + "-L'" TOMO_HOME "/lib' -L/usr/local/lib"), optimization = Text("2"), - cc = Text("cc"); + cc = Text(DEFAULT_C_COMPILER); static const char *SHARED_SUFFIX = #ifdef __APPLE__ @@ -128,7 +128,7 @@ int main(int argc, char *argv[]) // Run a tool: if ((streq(argv[1], "-r") || streq(argv[1], "--run")) && argc >= 3) { if (strcspn(argv[2], "/;$") == strlen(argv[2])) { - const char *program = String(getenv("HOME"), "/.local/share/tomo/installed/", argv[2], "/", argv[2]); + const char *program = String("'"TOMO_HOME"'/installed/", argv[2], "/", argv[2]); execv(program, &argv[2]); } print_err("This is not an installed tomo program: \033[31;1m", argv[2], "\033[m"); @@ -145,9 +145,9 @@ int main(int argc, char *argv[]) " --verbose|-v: verbose output\n" " --quiet|-q: quiet output\n" " --install|-I: install the executable or library\n" - " --c-compiler : the C compiler to use (default: cc)\n" + " --c-compiler : the C compiler to use (default: "DEFAULT_C_COMPILER")\n" " --optimization|-O : set optimization level\n" - " --run|-r: run a program from ~/.local/share/tomo/installed\n" + " --run|-r: run a program from " TOMO_HOME "/installed\n" ); Text_t help = Texts(Text("\x1b[1mtomo\x1b[m: a compiler for the Tomo programming language"), Text("\n\n"), usage); tomo_parse_args( @@ -199,7 +199,7 @@ int main(int argc, char *argv[]) for (int64_t i = 0; i < uninstall.length; i++) { Text_t *u = (Text_t*)(uninstall.data + i*uninstall.stride); - system(String("rm -rvf ~/.local/share/tomo/installed/", *u, " ~/.local/share/tomo/lib/lib", *u, SHARED_SUFFIX)); + system(String("rm -rvf '"TOMO_HOME"'/installed/", *u, " '"TOMO_HOME"'/lib/lib", *u, SHARED_SUFFIX)); print("Uninstalled ", *u); } @@ -282,7 +282,7 @@ int main(int argc, char *argv[]) for (int64_t i = 0; i < files.length; i++) { Path_t path = *(Path_t*)(files.data + i*files.stride); Path_t exe = Path$with_extension(path, Text(""), true); - system(String("cp -v '", exe, "' ~/.local/bin/")); + system(String("cp -v '", exe, "' '"TOMO_PREFIX"'/bin/")); } } return 0; @@ -494,22 +494,22 @@ void build_library(Text_t lib_dir_name) if (should_install) { char library_directory[PATH_MAX]; getcwd(library_directory, sizeof(library_directory)); - const char *dest = String(getenv("HOME"), "/.local/share/tomo/installed/", lib_dir_name); + const char *dest = String(TOMO_HOME"/installed/", lib_dir_name); if (!streq(library_directory, dest)) { system(String("rm -rf '", dest, "'")); system(String("mkdir -p '", dest, "'")); system(String("cp -r * '", dest, "/'")); } - system("mkdir -p ~/.local/share/tomo/lib/"); + system("mkdir -p '"TOMO_HOME"'/lib/"); system(String("ln -f -s ../installed/'", lib_dir_name, "'/lib'", lib_dir_name, SHARED_SUFFIX, - "' ~/.local/share/tomo/lib/lib'", lib_dir_name, SHARED_SUFFIX, "'")); + "' '"TOMO_HOME"'/lib/lib'", lib_dir_name, SHARED_SUFFIX, "'")); // 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. system(String("debugedit -b ", library_directory, - " -d ~/.local/share/tomo/installed/", lib_dir_name, - " ~/.local/share/tomo/installed/", lib_dir_name, "/lib", lib_dir_name, ".so" + " -d '"TOMO_HOME"'/installed/", lib_dir_name, + " '"TOMO_HOME"'/installed/", lib_dir_name, "/lib", lib_dir_name, ".so" " 2>/dev/null >/dev/null")); - print("Installed \033[1m", lib_dir_name, "\033[m to ~/.local/share/tomo/installed"); + print("Installed \033[1m", lib_dir_name, "\033[m to "TOMO_HOME"/installed"); } } @@ -624,10 +624,10 @@ void build_file_dependency_graph(Path_t path, Table_t *to_compile, Table_t *to_l break; } case USE_MODULE: { - Text_t lib = Text$format("'%s/.local/share/tomo/installed/%s/lib%s%s'", getenv("HOME"), use->path, use->path, SHARED_SUFFIX); + Text_t lib = Text$format("'%s/installed/%s/lib%s%s'", TOMO_HOME, use->path, use->path, SHARED_SUFFIX); Table$set(to_link, &lib, ((Bool_t[1]){1}), Table$info(&Text$info, &Bool$info)); - List_t children = Path$glob(Path$from_str(String(getenv("HOME"), "/.local/share/tomo/installed/", use->path, "/*.tm"))); + List_t children = Path$glob(Path$from_str(String(TOMO_HOME"/installed/", use->path, "/*.tm"))); for (int64_t i = 0; i < children.length; i++) { Path_t *child = (Path_t*)(children.data + i*children.stride); Table_t discarded = {.fallback=to_compile}; diff --git a/src/typecheck.c b/src/typecheck.c index 58b74739..83b715cf 100644 --- a/src/typecheck.c +++ b/src/typecheck.c @@ -181,7 +181,7 @@ static env_t *load_module(env_t *env, ast_t *module_ast) } case USE_MODULE: { glob_t tm_files; - if (glob(String("~/.local/share/tomo/installed/", use->path, "/[!._0-9]*.tm"), GLOB_TILDE, NULL, &tm_files) != 0) + if (glob(String(TOMO_HOME"/installed/", use->path, "/[!._0-9]*.tm"), GLOB_TILDE, NULL, &tm_files) != 0) code_err(module_ast, "Could not find library"); env_t *module_env = fresh_scope(env); -- cgit v1.2.3