aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/nightly.yml19
-rwxr-xr-xAppImage/curses.yml5
-rwxr-xr-xAppImage/gtk.yml5
-rw-r--r--TODO5
-rw-r--r--configure.ac17
-rwxr-xr-xdebian/rules9
-rw-r--r--distribute.mk.in5
-rw-r--r--src/file-utils.c85
-rw-r--r--src/file-utils.h12
-rw-r--r--src/interface-gtk/interface.c32
-rw-r--r--src/main.c23
11 files changed, 153 insertions, 64 deletions
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index 4a6bc53..52c5425 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -218,9 +218,11 @@ jobs:
mkdir build-wingui build-wincon
(cd build-wingui
../configure --with-interface=pdcurses-gui --enable-html-manual --program-prefix=g \
+ --with-scitecodatadir=. \
PDCURSES_LIBS="-lpdcurses_wingui -lgdi32 -lcomdlg32 -lwinmm")
(cd build-wincon
../configure --with-interface=pdcurses --enable-html-manual \
+ --with-scitecodatadir=. \
PDCURSES_LIBS="-lpdcurses_wincon -lgdi32 -lwinmm")
- name: make
@@ -244,9 +246,10 @@ jobs:
run: |
mkdir temp-bin/
cd temp-bin/
- cp /mingw32/bin/{gsciteco.exe,sciteco.exe,grosciteco.tes,tedoc.tes} ./
- cp -r /mingw32/share/sciteco/{lib,*.tmac} ./
- cp /mingw32/share/sciteco/sample.teco_ini .teco_ini
+ cp -r /mingw32/bin/{gsciteco.exe,sciteco.exe,grosciteco.tes,tedoc.tes} ./
+ # datadir is relative to bindir
+ cp -r /mingw32/bin/{lib,*.tmac} ./
+ cp /mingw32/bin/sample.teco_ini .teco_ini
cp -r /mingw32/share/doc/sciteco/* ./
cp ../COPYING ../ChangeLog ./
cp /mingw32/bin/gspawn-win32-helper*.exe ./
@@ -300,7 +303,8 @@ jobs:
LDFLAGS: -flto
run: |
autoreconf -i
- ./configure --with-interface=gtk --enable-html-manual
+ ./configure --with-interface=gtk --enable-html-manual \
+ --with-scitecodatadir=.
- name: make
run: make -j 2
@@ -317,11 +321,12 @@ jobs:
mkdir temp-bin
cd temp-bin
cp /mingw32/bin/{sciteco.exe,grosciteco.tes,tedoc.tes} ./
- cp -r /mingw32/share/sciteco/{lib,*.tmac} ./
+ # datadir is relative to bindir
+ cp -r /mingw32/bin/{lib,*.tmac} ./
# FIXME: Maybe there should be a separate win32/.teco_ini with
# a few pre-enabled settings?
- cp /mingw32/share/sciteco/sample.teco_ini .teco_ini
- cp /mingw32/share/sciteco/fallback.css .teco_css
+ cp /mingw32/bin/sample.teco_ini .teco_ini
+ cp /mingw32/bin/fallback.css .teco_css
cp -r /mingw32/share/doc/sciteco/* ./
cp ../COPYING ../ChangeLog ./
cp /mingw32/bin/gspawn-win32-helper*.exe ./
diff --git a/AppImage/curses.yml b/AppImage/curses.yml
index 2989a39..edf9fd0 100755
--- a/AppImage/curses.yml
+++ b/AppImage/curses.yml
@@ -1,10 +1,5 @@
app: sciteco-curses
-# We currently use paths hardcoded at build-time.
-# Alternatively, it would be possible to customize the AppRun script or
-# add a wrapper that sets $SCITECOPATH.
-union: true
-
ingredients:
packages:
- sciteco-curses
diff --git a/AppImage/gtk.yml b/AppImage/gtk.yml
index d49e308..ea233db 100755
--- a/AppImage/gtk.yml
+++ b/AppImage/gtk.yml
@@ -1,10 +1,5 @@
app: sciteco-gtk
-# We currently use paths hardcoded at build-time.
-# Alternatively, it would be possible to customize the AppRun script or
-# add a wrapper that sets $SCITECOPATH.
-union: true
-
ingredients:
packages:
- sciteco-gtk
diff --git a/TODO b/TODO
index cb4fc7a..d38ada7 100644
--- a/TODO
+++ b/TODO
@@ -466,11 +466,6 @@ Features:
* Get into mentors.debian.net. First step to being adopted
into the Debian repositories.
* Get meta-rhaberkorn into https://layers.openembedded.org
- * Linux: Relocatable binaries instead of hardcoding the library path.
- This makes it possible to run builds installed via
- `make install DESTDIR=...` and will aid in creating AppImages.
- Currently we have to define "union: true" and consequently
- the root directory is not what we would expect.
* sample.teco_ini: Support opening files on certain lines
(filename:line).
Theoretically, this could also be added to the <EB> syntax,
diff --git a/configure.ac b/configure.ac
index 870b7b0..a82eb1d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -173,9 +173,12 @@ AC_CHECK_FUNCS([memset setlocale strchr strrchr fstat sscanf], , [
# glib defines G_OS_UNIX instead...
case $host in
*-*-linux* | *-*-*bsd* | *-*-darwin* | *-*-cygwin* | *-*-haiku*)
- AC_CHECK_FUNCS([realpath fchown dup dup2 getpid open read kill mmap], , [
+ AC_CHECK_FUNCS([realpath readlink fchown dup dup2 getpid open read kill mmap], , [
AC_MSG_ERROR([Missing libc function])
])
+ AC_SEARCH_LIBS(dladdr, [dl], , [
+ AC_MSG_ERROR([No library providing dladdr()!])
+ ])
;;
esac
@@ -183,10 +186,17 @@ esac
# Config options
#
+# NOTE: This can be relative to the binary location for relocateable builds.
AC_ARG_WITH(scitecodatadir,
AS_HELP_STRING([--with-scitecodatadir=PATH],
[Installation directory of data [default=DATADIR/sciteco]]),
- [scitecodatadir=$withval], [scitecodatadir=$datadir/$PACKAGE])
+ [scitecodatadir_rel=$withval], [scitecodatadir_rel=$datadir/$PACKAGE])
+AC_SUBST(scitecodatadir_rel)
+# The Automake installation directory needs to be absolute, though:
+case "$scitecodatadir_rel" in
+/*) scitecodatadir="$scitecodatadir_rel";;
+*) scitecodatadir="$bindir/$scitecodatadir_rel";;
+esac
AC_SUBST(scitecodatadir)
# SciTECO library macro directory
scitecolibdir=$scitecodatadir/lib
@@ -194,8 +204,7 @@ AC_SUBST(scitecolibdir)
# These paths can be changed at install-time and
# should not be written into config.h:
-AM_CPPFLAGS="$AM_CPPFLAGS -D'SCITECODATADIR=\"\$(scitecodatadir)\"' \
- -D'SCITECOLIBDIR=\"\$(scitecolibdir)\"'"
+AM_CPPFLAGS="$AM_CPPFLAGS -D'SCITECODATADIR=\"\$(scitecodatadir_rel)\"'"
# FIXME: It does not really make sense to have this configurable.
# It would make more sense to allow linking against an externally-provided
diff --git a/debian/rules b/debian/rules
index fb1d65e..8b8ad11 100755
--- a/debian/rules
+++ b/debian/rules
@@ -31,11 +31,15 @@ endif
build build-arch build-indep: build-curses-stamp build-gtk-stamp;
+# NOTE: The datadir will be relative to the binary location at runtime.
+# This makes the binary relocateable, which is important when creating
+# AppImages from the Debian packages.
build-curses-stamp:
dh_testdir
rm -rf build-curses
dh_auto_configure -Bbuild-curses -- \
- --with-interface=ncurses
+ --with-interface=ncurses \
+ --with-scitecodatadir=../share/sciteco
dh_auto_build -Bbuild-curses
dh_auto_test -Bbuild-curses
touch $@
@@ -47,7 +51,8 @@ build-gtk-stamp:
rm -rf build-gtk
dh_auto_configure -Bbuild-gtk -- \
--program-prefix=g \
- --with-interface=gtk
+ --with-interface=gtk \
+ --with-scitecodatadir=../share/sciteco
# NOTE: Since the Gtk+ version of SciTECO is called during the build,
# we need an XServer which may be missing on the build server.
# That's why we use xvfb.
diff --git a/distribute.mk.in b/distribute.mk.in
index 0d6942c..4eb9b91 100644
--- a/distribute.mk.in
+++ b/distribute.mk.in
@@ -110,6 +110,7 @@ mingw-binary : @PACKAGE@-@PACKAGE_VERSION@-win32.zip
PKG_CONFIG_LIBDIR=/usr/i686-w64-mingw32/lib/pkgconfig \
./configure --host=i686-w64-mingw32 build=i386-pc-linux-gnu \
--prefix=/usr \
+ --with-scitecodatadir=. \
--enable-static-executables \
--disable-dependency-tracking \
--with-interface=$(MINGW_UI) \
@@ -122,11 +123,11 @@ mingw-binary : @PACKAGE@-@PACKAGE_VERSION@-win32.zip
install-strip DESTDIR=`pwd`/temp-install
rm -rf $(SCITECO_DIR)/
mkdir temp-bin/
- cp -r temp-install/usr/bin/* temp-install/usr/share/sciteco/* \
+ cp -r temp-install/usr/bin/* \
temp-install/usr/share/doc/sciteco/* \
temp-bin/
cp @srcdir@/win32.teco_ini temp-bin/.teco_ini || \
- cp temp-install/usr/share/sciteco/sample.teco_ini \
+ cp temp-install/usr/bin/sample.teco_ini \
temp-bin/.teco_ini
cp @srcdir@/COPYING @srcdir@/ChangeLog temp-bin/
rm -rf temp-install/
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.
*
diff --git a/src/file-utils.h b/src/file-utils.h
index 4ee59e6..e974e2f 100644
--- a/src/file-utils.h
+++ b/src/file-utils.h
@@ -68,6 +68,18 @@ teco_file_normalize_path(gchar *path)
gboolean teco_file_is_visible(const gchar *path);
+/**
+ * Get absolute path of the program executable.
+ *
+ * This may return the current working directory on
+ * unsupported platforms.
+ *
+ * @return Newly-allocated path.
+ */
+gchar *teco_file_get_program_path(void);
+
+gchar *teco_file_get_datadir(void);
+
gchar *teco_file_expand_path(const gchar *path);
/**
diff --git a/src/interface-gtk/interface.c b/src/interface-gtk/interface.c
index 3121b05..829310a 100644
--- a/src/interface-gtk/interface.c
+++ b/src/interface-gtk/interface.c
@@ -51,6 +51,7 @@
#include "sciteco.h"
#include "error.h"
#include "string-utils.h"
+#include "file-utils.h"
#include "cmdline.h"
#include "qreg.h"
#include "ring.h"
@@ -1124,6 +1125,8 @@ teco_interface_event_loop(GError **error)
}
g_assert(scitecoconfig.data != NULL);
+ g_autofree gchar *datadir = teco_file_get_datadir();
+
/*
* Initialize the CSS variable provider and the CSS provider
* for the included fallback.css.
@@ -1138,14 +1141,7 @@ teco_interface_event_loop(GError **error)
if (!g_file_test(user_css_file, G_FILE_TEST_IS_REGULAR)) {
/* use fallback CSS */
g_free(user_css_file);
- /*
- * FIXME: See above for icons.
- */
-#ifdef G_OS_WIN32
- user_css_file = g_build_filename(scitecoconfig.data, "fallback.css", NULL);
-#else
- user_css_file = g_build_filename(SCITECODATADIR, "fallback.css", NULL);
-#endif
+ user_css_file = g_build_filename(datadir, "fallback.css", NULL);
}
GtkCssProvider *user_css_provider = gtk_css_provider_new();
@@ -1170,15 +1166,10 @@ teco_interface_event_loop(GError **error)
/*
* FIXME: This is necessary so that the icon themes are found in the same
* directory as sciteco.exe.
- * This fails of course when $SCITECOCONFIG is changed.
- * We should perhaps always use the absolute path of sciteco.exe.
- * If you want to install SciTECO differently, you can still set
- * $XDG_DATA_DIRS.
- *
- * FIXME FIXME FIXME: This is also currently broken.
*/
- //g_autofree char *theme_path = g_build_filename(scitecoconfig.data, "icons");
- //gtk_icon_theme_prepend_search_path(gtk_icon_theme_get_default(), theme_path);
+ g_autofree gchar *program_path = teco_file_get_program_path();
+ g_autofree gchar *theme_path = g_build_filename(program_path, "icons", NULL);
+ gtk_icon_theme_prepend_search_path(gtk_icon_theme_get_default(), theme_path);
#else
/*
* Load icons for the GTK window.
@@ -1186,17 +1177,16 @@ teco_interface_event_loop(GError **error)
* as a resource will be used by default.
*/
static const gchar *icon_files[] = {
- SCITECODATADIR G_DIR_SEPARATOR_S "sciteco-48.png",
- SCITECODATADIR G_DIR_SEPARATOR_S "sciteco-32.png",
- SCITECODATADIR G_DIR_SEPARATOR_S "sciteco-16.png"
+ "sciteco-48.png", "sciteco-32.png", "sciteco-16.png"
};
GList *icon_list = NULL;
for (gint i = 0; i < G_N_ELEMENTS(icon_files); i++) {
- GdkPixbuf *icon_pixbuf = gdk_pixbuf_new_from_file(icon_files[i], NULL);
+ g_autofree gchar *icon_file = g_build_filename(datadir, icon_files[i], NULL);
+ GdkPixbuf *icon_pixbuf = gdk_pixbuf_new_from_file(icon_file, NULL);
/* fail silently if there's a problem with one of the icons */
- if (icon_pixbuf)
+ if (G_LIKELY(icon_pixbuf != NULL))
icon_list = g_list_append(icon_list, icon_pixbuf);
}
diff --git a/src/main.c b/src/main.c
index 45149e6..e2c6b9e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -77,15 +77,15 @@ volatile sig_atomic_t teco_interrupted = FALSE;
* program's directory.
*/
static inline gchar *
-teco_get_default_config_path(const gchar *program)
+teco_get_default_config_path(void)
{
- return g_path_get_dirname(program);
+ return teco_file_get_program_path();
}
#elif defined(G_OS_UNIX) && !defined(__HAIKU__)
static inline gchar *
-teco_get_default_config_path(const gchar *program)
+teco_get_default_config_path(void)
{
return g_strdup(g_get_home_dir());
}
@@ -99,7 +99,7 @@ teco_get_default_config_path(const gchar *program)
* with config files.
*/
static inline gchar *
-teco_get_default_config_path(const gchar *program)
+teco_get_default_config_path(void)
{
return g_strdup(g_get_user_config_dir());
}
@@ -210,7 +210,7 @@ teco_process_options(gchar ***argv)
}
static void
-teco_initialize_environment(const gchar *program)
+teco_initialize_environment(void)
{
g_autoptr(GError) error = NULL;
gchar *abs_path;
@@ -252,14 +252,11 @@ teco_initialize_environment(const gchar *program)
/*
* Initialize $SCITECOCONFIG and $SCITECOPATH
*/
- g_autofree gchar *default_configpath = teco_get_default_config_path(program);
+ g_autofree gchar *default_configpath = teco_get_default_config_path();
g_setenv("SCITECOCONFIG", default_configpath, FALSE);
-#ifdef G_OS_WIN32
- g_autofree gchar *default_scitecopath = g_build_filename(default_configpath, "lib", NULL);
- g_setenv("SCITECOPATH", default_scitecopath, FALSE);
-#else
- g_setenv("SCITECOPATH", SCITECOLIBDIR, FALSE);
-#endif
+ g_autofree gchar *datadir = teco_file_get_datadir();
+ g_autofree gchar *default_libdir = g_build_filename(datadir, "lib", NULL);
+ g_setenv("SCITECOPATH", default_libdir, FALSE);
/*
* $SCITECOCONFIG and $SCITECOPATH may still be relative.
@@ -389,7 +386,7 @@ main(int argc, char **argv)
/* current working directory ("$") */
teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_workingdir_new());
/* environment defaults and registers */
- teco_initialize_environment(argv_utf8[0]);
+ teco_initialize_environment();
teco_qreg_table_t local_qregs;
teco_qreg_table_init(&local_qregs, TRUE);