diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2024-11-05 01:29:53 +0300 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2024-11-05 12:32:04 +0300 |
commit | 9cce7d263ea3f2984a619cdfcb54d264c6a4c51d (patch) | |
tree | 363314a72aa4fc3fda435086c8deb522aef247ec /src/file-utils.c | |
parent | 36c7526d60319289954bb0b49e9f4cb2c6dfe9da (diff) | |
download | sciteco-9cce7d263ea3f2984a619cdfcb54d264c6a4c51d.tar.gz |
fully support relocatable binaries, improving AppImages
* You can now specify `--with-scitecodatadir` as a relative path,
that will be interpreted relative to the binary's location.
* Win32 binaries already were relocatable, but this was a Windows-specific
hack. Win32 binaries are now built with `--with-scitecodatadir=.`
since everything is in a single directory.
* Ubuntu packages are now also built `--with-scitecodatadir=../share/sciteco`.
This is not crucial for ordinary installations, but is meant for AppImage creation.
* Since AppImages are now built from relocatable packages,
we no longer need the unionfs-workaround from pkg2appimage.
This should fix the strange root contents when autocompleting in
AppImage builds.
* This might also fix the appimage.github.io CI issues.
I assume that because I could reproduce the issue on FreeBSD's
Linuxulator in dependence of pkg2appimage's "union"-setting.
See https://github.com/AppImage/appimage.github.io/pull/3402
* Determining the binary location actually turned out be hard and
very platform-dependant. There are now implementations for Windows
(which could also read argv[0]), Linux and generic UNIX (which
works on FreeBSD, but I am not sure about the others).
I believe this could also be useful on Mac OS to create app bundles,
but this needs to be tested - currently the Mac OS binaries are
installed into fixed locations and don't use relocation.
Diffstat (limited to 'src/file-utils.c')
-rw-r--r-- | src/file-utils.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/file-utils.c b/src/file-utils.c index 3f8f721..b7e5418 100644 --- a/src/file-utils.c +++ b/src/file-utils.c @@ -19,6 +19,7 @@ #include "config.h" #endif +#define _GNU_SOURCE #include <limits.h> #include <stdlib.h> #include <string.h> @@ -35,6 +36,10 @@ #include <glib.h> #include <glib/gstdio.h> +#ifdef G_OS_UNIX +#include <dlfcn.h> +#endif + #include "sciteco.h" #include "qreg.h" #include "interface.h" @@ -179,6 +184,86 @@ teco_file_is_visible(const gchar *path) #endif /* !G_OS_WIN32 */ +#ifdef G_OS_WIN32 + +gchar * +teco_file_get_program_path(void) +{ + TCHAR buf[MAX_PATH]; + if (!GetModuleFileNameW(NULL, buf, G_N_ELEMENTS(buf)) + return g_get_current_dir(); + g_autofree gchar *exe = g_utf16_to_utf8(buf, -1, NULL, NULL, NULL); + return g_path_get_dirname(exe); +} + +#elif defined(__linux__) + +gchar * +teco_file_get_program_path(void) +{ + gchar buf[PATH_MAX]; + ssize_t len = readlink("/proc/self/exe", buf, sizeof(buf)-1); + if (G_UNLIKELY(len < 0)) + /* almost certainly wrong */ + return g_get_current_dir(); + buf[len] = '\0'; + + return g_path_get_dirname(buf); +} + +#elif defined(G_OS_UNIX) + +/* + * At least works on FreeBSD, even though it also has + * sysctl(KERN_PROC_PATHNAME). + * We assume it works on all other UNIXes as well. + */ +gchar * +teco_file_get_program_path(void) +{ + Dl_info info; + return dladdr(teco_file_get_program_path, &info) + ? g_path_get_dirname(info.dli_fname) : g_get_current_dir(); +} + +#else /* !G_OS_WIN32 && !__linux__ && !G_OS_UNIX */ + +/* + * This is almost guaranteed to be wrong, + * meaning that SciTECO cannot be made relocatable on these platforms. + * It may be worth evaluating argv[0] on these platforms. + */ +gchar * +teco_file_get_program_path(void) +{ + return g_get_current_dir(); +} + +#endif + +/** + * Get the datadir. + * + * By default it is hardcoded to an absolute path at + * build time. + * However, you can also build relocateable binaries + * where the datadir is relative to the program's executable. + * + * @note Beginning with glib v2.58, we could directly use + * g_canonicalize_filename(). + */ +gchar * +teco_file_get_datadir(void) +{ + if (g_path_is_absolute(SCITECODATADIR)) + return g_strdup(SCITECODATADIR); + + /* relocateable binary - datadir is relative to binary */ + g_autofree gchar *program_path = teco_file_get_program_path(); + g_autofree gchar *datadir = g_build_filename(program_path, SCITECODATADIR, NULL); + return teco_file_get_absolute_path(datadir); +} + /** * Perform tilde expansion on a file name or path. * |