From 0f440ff390b13186dc1a6872bd63a7b4713d71f2 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Tue, 14 Nov 2023 10:18:23 -0700 Subject: [PATCH] find boot files relative to the executable by default Building on recent support for "%x" everywhere, the change here makes the default boot-file search path "%x:%x/../lib/csv%v/%m:%x/../../boot/%m" which searches in the immediate directory, then in the place relative to the executable's install location to reach installed boot files, and then relative to the workarea executable to reach workarea boot files. More precisely, the middle path in the default takes into account the configured bin and lib target directories. As a result of this change, it's much easier to run a just-built executable before installing it, and installing to a non-system directory produces something that you can move around in the filesystem. As a further step to make things work in the default way, `configure` now supports `--prefix` as an alias for `--installprefix`. The `--installabsolute` flag uses the old default search path, which is absolute relative to the target installation directory. --- BUILDING | 11 +++++++---- boot/pb/scheme.h | 3 ++- c/build.zuo | 20 ++++++++++++++++---- c/main.c | 4 ++-- c/scheme.c | 18 ++++++++++++------ configure | 10 ++++++++++ csug/foreign.stex | 32 +++++++++++++++++++++++--------- csug/use.stex | 2 +- release_notes/release_notes.stex | 6 ++++-- s/mkheader.ss | 3 ++- 10 files changed, 79 insertions(+), 30 deletions(-) diff --git a/BUILDING b/BUILDING index f1b846b32..203fd8f4b 100644 --- a/BUILDING +++ b/BUILDING @@ -182,14 +182,17 @@ The makefile supports several targets: Runs the build Chez Scheme without installing. - Alternatively, you can run the executable directly and tell it - where to find boot files, either by setting `SCHEMEHEAPDIRS` as + Alternatively, you can run the executable directly as + + /bin//scheme + + If you have configured with `--installabsolute`, running without + installing requires either `SCHEMEHEAPDIRS` as env SCHEMEHEAPDIRS=/boot/ \ /bin//scheme - or through the `-B` command-line flag, which requires absolute - paths: + or using the `-B` command-line flag: /bin//scheme \ -B /boot//petite.boot \ diff --git a/boot/pb/scheme.h b/boot/pb/scheme.h index a2db6f4dd..23ea0a45f 100644 --- a/boot/pb/scheme.h +++ b/boot/pb/scheme.h @@ -228,8 +228,9 @@ EXPORT const char * Skernel_version(void); EXPORT void Sretain_static_relocation(void); EXPORT void Sset_verbose(int); EXPORT void Sscheme_init(void (*)(void)); +EXPORT void Sregister_boot_executable_relative_file(const char *, const char *); EXPORT void Sregister_boot_file(const char *); -EXPORT void Sregister_boot_direct_file(const char *); +EXPORT void Sregister_boot_relative_file(const char *); EXPORT void Sregister_boot_file_fd(const char *, int fd); EXPORT void Sregister_boot_file_fd_region(const char *, int fd, iptr offset, iptr len, int close_after); EXPORT void Sregister_heap_file(const char *); diff --git a/c/build.zuo b/c/build.zuo index a92875cbe..549bd1f09 100644 --- a/c/build.zuo +++ b/c/build.zuo @@ -69,7 +69,8 @@ (define c-config-file (at-dir "config.h")) (define c-config-keys - '(disablecurses disablex11 enablelibffi alwaysUseBootFile preloadBootFiles)) + '(disablecurses disablex11 enablelibffi alwaysUseBootFile preloadBootFiles relativeBootFiles + InstallBin InstallLib)) ;; sources for "kernel.o": (define kernel-src-files @@ -420,9 +421,20 @@ (line (and (equal? (hash-ref config 'enablelibffi #f) "yes") "#define ENABLE_LIBFFI")) (line (and (not (for-windows? config)) - (let ([s (hash-ref config 'InstallLib #f)]) - (and s - (~a "#define DEFAULT_HEAP_PATH \"" s "/csv%v/%m\""))))) + (or (and (equal? (hash-ref config 'relativeBootFiles #f) "yes") + (let* ([bin (hash-ref config 'InstallBin #f)] + [lib (hash-ref config 'InstallLib #f)] + [rel (or (and bin lib (find-relative-path bin lib)) + ".")] + [x-rel (if (relative-path? rel) + (build-raw-path "%x" rel) + rel)]) + (~a "#define DEFAULT_HEAP_PATH \"%x:" + (build-raw-path x-rel "csv%v/%m") + ":%x/../../boot/%m\""))) + (let ([s (hash-ref config 'InstallLib #f)]) + (and s + (~a "#define DEFAULT_HEAP_PATH \"" s "/csv%v/%m\"")))))) (line (let ([alwaysUseBootFile (or (and (not (equal? (hash-ref config 'alwaysUseBootFile "") ""))) (infer-always-use-boot-file preload-files))]) diff --git a/c/main.c b/c/main.c index 7d92a4358..56c770790 100644 --- a/c/main.c +++ b/c/main.c @@ -128,13 +128,13 @@ int main(int argc, const char *argv[]) { (void) fprintf(stderr,"%s requires argument\n", arg); exit(1); } - Sregister_boot_file(argv[n]); + Sregister_boot_executable_relative_file(execpath, argv[n]); } else if (strcmp(arg,"-B") == 0 || strcmp(arg,"--Boot") == 0) { if (++n == argc) { (void) fprintf(stderr,"%s requires argument\n", arg); exit(1); } - Sregister_boot_direct_file(argv[n]); + Sregister_boot_relative_file(argv[n]); } else if (strcmp(arg,"--eedisable") == 0) { #ifdef FEATURE_EXPEDITOR expeditor_enable = 0; diff --git a/c/scheme.c b/c/scheme.c index 8b0077c42..e85f9a337 100644 --- a/c/scheme.c +++ b/c/scheme.c @@ -508,6 +508,7 @@ static char *get_defaultheapdirs() { #else /* not WIN32: */ #define SEARCHPATHSEP ':' #define PATHSEP '/' +/* `DEFAULT_HEAP_PATH` is normally defined in the generated "config.h" */ #ifndef DEFAULT_HEAP_PATH #define DEFAULT_HEAP_PATH "/usr/lib/csv%v/%m:/usr/local/lib/csv%v/%m" #endif @@ -1083,17 +1084,22 @@ static void check_boot_file_state(const char *who) { extern void Sregister_boot_file(const char *name) { check_boot_file_state("Sregister_boot_file"); - find_boot("", name, "", 0, -1, 1); + find_boot("scheme", name, "", 0, -1, 1); } -extern void Sregister_boot_direct_file(const char *name) { - check_boot_file_state("Sregister_boot_direct_file"); - find_boot("", name, "", 1, -1, 1); +extern void Sregister_boot_executable_relative_file(const char* execpath, const char *name) { + check_boot_file_state("Sregister_executable_relative_boot_file"); + find_boot(execpath, name, "", 0, -1, 1); +} + +extern void Sregister_boot_relative_file(const char *name) { + check_boot_file_state("Sregister_boot_relative_file"); + find_boot(NULL, name, "", 1, -1, 1); } extern void Sregister_boot_file_fd(const char *name, int fd) { check_boot_file_state("Sregister_boot_file_fd"); - find_boot("", name, "", 1, fd, 1); + find_boot(NULL, name, "", 1, fd, 1); } extern void Sregister_boot_file_fd_region(const char *name, @@ -1101,7 +1107,7 @@ extern void Sregister_boot_file_fd_region(const char *name, iptr offset, iptr len, int close_after) { - check_boot_file_state("Sregister_boot_file_fd"); + check_boot_file_state("Sregister_boot_file_fd_region"); if (strlen(name) >= BOOT_PATH_MAX) { fprintf(stderr, "boot-file path is too long %s\n", name); diff --git a/configure b/configure index 8f9eec91f..b66d268dd 100755 --- a/configure +++ b/configure @@ -60,6 +60,7 @@ installreleasenotes="" installschemename="scheme" installpetitename="petite" installscriptname="scheme-script" +relativeBootFiles=yes cflagsset=no disablex11=no disablecurses=no @@ -263,6 +264,9 @@ while [ $# != 0 ] ; do --installprefix=*) installprefix=`echo $1 | sed -e 's/^--installprefix=//'` ;; + --prefix=*) + installprefix=`echo $1 | sed -e 's/^--prefix=//'` + ;; --installlib=*) installlib=`echo $1 | sed -e 's/^--installlib=//'` ;; @@ -296,6 +300,9 @@ while [ $# != 0 ] ; do --installscriptname=*) installscriptname=`echo $1 | sed -e 's/^--installscriptname=//'` ;; + --installabsolute) + relativeBootFiles=no + ;; --toolprefix=*) toolprefix=`echo $1 | sed -e 's/^--toolprefix=//'` CC="${toolprefix}${CC}" @@ -562,6 +569,7 @@ if [ "$help" = "yes" ]; then echo " --libkernel build libkernel.a (the default)" echo " --kernelobj build kernel.o instead of libkernel.a" echo " --installprefix= final installation root ($installprefix)" + echo " --prefix= alias for --installprefix" echo " --installbin= bin directory ($installbin)" echo " --installlib= lib directory ($installlib)" echo " --installman= manpage directory ($installman)" @@ -575,6 +583,7 @@ if [ "$help" = "yes" ]; then echo " --installschemename= install scheme as ($installschemename)" echo " --installpetitename= install petite as ($installpetitename)" echo " --installscriptname= install scheme-script as ($installscriptname)" + echo " --installabsolute disable relative boot-file search" echo " --toolprefix= prefix tool (compiler, linker, ...) names" echo " --boot=- build from prepared variant (e.g., pbchunk)" echo " --emboot=\" ...\" additional boot s with emscripten" @@ -1047,6 +1056,7 @@ disablex11=$disablex11 enablelibffi=$libffi preloadBootFiles=$preloadBootFiles alwaysUseBootFile=$alwaysUseBootFile +relativeBootFiles=$relativeBootFiles InstallBin=$installbin InstallLib=$installlib diff --git a/csug/foreign.stex b/csug/foreign.stex index 32c1eca6b..816dc9a24 100644 --- a/csug/foreign.stex +++ b/csug/foreign.stex @@ -3093,8 +3093,10 @@ program. \cfunction{void}{Sscheme_init}{void (*\var{abnormal}_\var{exit})(void)} \cfunction{void}{Sset_verbose}{int \var{v}} \cfunction{void}{Sregister_boot_file}{const char *\var{name}} +\cfunctTwo{void}{Sregister_boot_executable_relative_file}{const char *\var{execpath},}{const char *\var{name}} +\cfunction{void}{Sregister_boot_relative_file}{const char *\var{name}} \cfunction{void}{Sregister_boot_file_fd}{const char *\var{name}, int \var{fd}} -\cfunctTwo{void}{Sregister_boot_file_fd_segment}{const char *\var{name}, int \var{fd},}{iptr \var{offset}, iptr \var{len}, int \var{close}_\var{after}} +\cfunctTwo{void}{Sregister_boot_file_fd_region}{const char *\var{name}, int \var{fd},}{iptr \var{offset}, iptr \var{len}, int \var{close}_\var{after}} \cfunction{void}{Sbuild_heap}{const char *\var{exec}, void (*\var{custom}_\var{init})(void)} \cfunction{void}{Senable_expeditor}{const char *\var{history}_\var{file}} \cfunction{void}{Sretain_static_relocation}{void} @@ -3125,13 +3127,24 @@ values of \var{v} and off when \var{v} is zero. In verbose mode, the system displays a trace of the search process for subsequently registered boot files. -\scheme{Sregister_boot_file} searches for -the named boot file and -register it for loading, while \scheme{Sregister_boot_file_fd} -provides a specific boot file as a file descriptor. -When only a boot file name is provided, the file is opened but not loaded until the heap is built via -\scheme{Sbuild_heap}. When a file descriptor is provided, the given file name -is used only for error reporting. +\scheme{Sregister_boot_file} searches for a boot file and registers it +for loading. If the given boot file path is absolute or starts with +a \scheme{.} or \scheme{..} path element, then the path is +used relative to the current directory; otherwise, the boot file is +found through a search as described in +Section~\ref{SECTUSECOMMANDLINE}, and \scheme{"scheme"} is assumed as +the executable name for resolving a \scheme{"%x"} escape when the +executable path is not otherwise available from the operating system. +\scheme{Sregister_boot_executable_relative_file} is similar, but +accepts a path to the executable instead of assuming +\scheme{"scheme"}, so it should be preferred when using a boot file +path that may be resolved relative to the executable. +\scheme{Sregister_boot_relative_file} always treats a relative path +as relative to the current directory, so the executable path is not needed. +In all of those cases, the boot file is opened but not loaded until the heap is built via +\scheme{Sbuild_heap}. \scheme{Sregister_boot_file_fd} provides a specific boot file as a file descriptor, +the given file name is used only for error reporting, and the file descriptor +is not read until until the heap is built via \scheme{Sbuild_heap}. For the first boot file registered only, the system also searches for the boot files upon which the named file depends, either directly or indirectly. @@ -3153,7 +3166,8 @@ called. files. \var{exec} is assumed to be the name of or path to the executable image and is used when no boot files have been registered as -the base name for the boot-file search process. +both the base name for the boot-file search process and the executable +name for finding boot files relative to the executable. \var{exec} may be null only if one or more boot files have been registered. \scheme{\var{custom}_\var{init}} must be a (possibly null) pointer to diff --git a/csug/use.stex b/csug/use.stex index 5b29aa415..06bc3840a 100644 --- a/csug/use.stex +++ b/csug/use.stex @@ -1837,7 +1837,7 @@ arguments for which search tracing is desired. Ordinarily, the search for boot files is limited to a set of -installation directories, but this may be overridden by setting +installation directories relative to the executable, but this may be overridden by setting the environment variable \index{\scheme{SCHEMEHEAPDIRS}}\scheme{SCHEMEHEAPDIRS}. \scheme{SCHEMEHEAPDIRS} should be a colon-separated list of directories, listed in the order in which they should be searched. diff --git a/release_notes/release_notes.stex b/release_notes/release_notes.stex index 5e6557432..53f54d483 100644 --- a/release_notes/release_notes.stex +++ b/release_notes/release_notes.stex @@ -768,10 +768,12 @@ The \scheme{enable-error-source-expression} parameter determines whether error messages that become embedded in code can refer to the original source file's path. -\subsection{Portable boot files (9.9.9)} +\subsection{Executable-relative boot files (9.9.9)} When searching for boot files, the two-character escape sequence -``\scheme{%x}'' is now supported on more platforms. +``\scheme{%x}'' is now supported on more platforms. By default, Chez +Scheme is configured to use this facility to find boot files relative +to the executable, even when installed. \subsection{New conversions from Scheme to C signed and unsigned integers (9.6.4)} diff --git a/s/mkheader.ss b/s/mkheader.ss index de66c5704..9dc1d69eb 100644 --- a/s/mkheader.ss +++ b/s/mkheader.ss @@ -452,7 +452,8 @@ (export "void" "Sset_verbose" "(int)") (export "void" "Sscheme_init" "(void (*)(void))") (export "void" "Sregister_boot_file" "(const char *)") - (export "void" "Sregister_boot_direct_file" "(const char *)") + (export "void" "Sregister_boot_executable_relative_file" "(const char *, const char *)") + (export "void" "Sregister_boot_relative_file" "(const char *)") (export "void" "Sregister_boot_file_fd" "(const char *, int fd)") (export "void" "Sregister_boot_file_fd_region" "(const char *, int fd, iptr offset, iptr len, int close_after)") (export "void" "Sregister_heap_file" "(const char *)")