Build an application bundle on macOS
All checks were successful
Alpine 3.22 Success
Arch Linux Success
Arch Linux AUR Success
Debian Bookworm Success
Fedora 39 Success
OpenBSD 7.8 Success
openSUSE 15.5 Success

This is far from done, but nonetheless constitutes a big improvement.

macOS application bundles are more or less necessary for:
 - showing a nice icon;
 - having spawned off instances actually be brought to the foreground;
 - file associations (yet files currently do not open properly);
 - having a reasonable method of distribution.

Also resolving a bunch of minor issues:
 - The context menu had duplicate items,
   and might needlessly end up with (null) labels.
This commit is contained in:
2025-11-08 18:47:51 +01:00
parent a7ff9f220d
commit 690e60cd74
8 changed files with 440 additions and 23 deletions

View File

@@ -2,7 +2,7 @@ fiv
=== ===
'fiv' is a slightly unconventional, general-purpose image browser and viewer 'fiv' is a slightly unconventional, general-purpose image browser and viewer
for Linux and Windows (macOS still has major issues). for Linux and Windows (macOS also kind of works).
image::docs/fiv.webp["Screenshot of both the browser and the viewer"] image::docs/fiv.webp["Screenshot of both the browser and the viewer"]
@@ -91,6 +91,14 @@ _mingw-w64-lcms2_ with the following change:
sed -i 's/meson setup /&-Dfastfloat=true /' PKGCONFIG sed -i 's/meson setup /&-Dfastfloat=true /' PKGCONFIG
macOS
~~~~~
Support for this operating system isn't as good.
If you install Homebrew, you can get an application bundle with:
$ sh -e macos-configure.sh builddir
$ meson install -C builddir
Documentation Documentation
------------- -------------
For information concerning usage, refer to link:docs/fiv.html[the user guide], For information concerning usage, refer to link:docs/fiv.html[the user guide],

View File

@@ -380,8 +380,11 @@ append_opener(GtkWidget *menu, GAppInfo *opener, const OpenContext *template)
ctx->app_info = opener; ctx->app_info = opener;
// On Linux, this prefers the obsoleted X-GNOME-FullName. // On Linux, this prefers the obsoleted X-GNOME-FullName.
gchar *name = const char *display_name = g_app_info_get_display_name(opener);
g_strdup_printf("Open With %s", g_app_info_get_display_name(opener)); // Ironically, GIO reads CFBundleName and can't read CFBundleDisplayName.
if (!display_name)
display_name = g_app_info_get_executable(opener);
gchar *name = g_strdup_printf("Open With %s", display_name);
// It's documented that we can touch the child, if we want to use markup. // It's documented that we can touch the child, if we want to use markup.
#if 0 #if 0
@@ -503,8 +506,6 @@ fiv_context_menu_new(GtkWidget *widget, GFile *file)
GAppInfo *default_ = GAppInfo *default_ =
g_app_info_get_default_for_type(ctx->content_type, FALSE); g_app_info_get_default_for_type(ctx->content_type, FALSE);
GList *recommended = g_app_info_get_recommended_for_type(ctx->content_type);
GList *fallback = g_app_info_get_fallback_for_type(ctx->content_type);
GtkWidget *menu = gtk_menu_new(); GtkWidget *menu = gtk_menu_new();
if (default_) { if (default_) {
@@ -513,6 +514,7 @@ fiv_context_menu_new(GtkWidget *widget, GFile *file)
GTK_MENU_SHELL(menu), gtk_separator_menu_item_new()); GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
} }
GList *recommended = g_app_info_get_recommended_for_type(ctx->content_type);
for (GList *iter = recommended; iter; iter = iter->next) { for (GList *iter = recommended; iter; iter = iter->next) {
if (!default_ || !g_app_info_equal(iter->data, default_)) if (!default_ || !g_app_info_equal(iter->data, default_))
append_opener(menu, iter->data, ctx); append_opener(menu, iter->data, ctx);
@@ -525,6 +527,10 @@ fiv_context_menu_new(GtkWidget *widget, GFile *file)
GTK_MENU_SHELL(menu), gtk_separator_menu_item_new()); GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
} }
// The implementation returns the same data for both,
// we'd have to filter out the recommended ones from here.
#ifndef __APPLE__
GList *fallback = g_app_info_get_fallback_for_type(ctx->content_type);
for (GList *iter = fallback; iter; iter = iter->next) { for (GList *iter = fallback; iter; iter = iter->next) {
if (!default_ || !g_app_info_equal(iter->data, default_)) if (!default_ || !g_app_info_equal(iter->data, default_))
append_opener(menu, iter->data, ctx); append_opener(menu, iter->data, ctx);
@@ -536,6 +542,7 @@ fiv_context_menu_new(GtkWidget *widget, GFile *file)
gtk_menu_shell_append( gtk_menu_shell_append(
GTK_MENU_SHELL(menu), gtk_separator_menu_item_new()); GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
} }
#endif
GtkWidget *item = gtk_menu_item_new_with_label("Open With..."); GtkWidget *item = gtk_menu_item_new_with_label("Open With...");
g_signal_connect_data(item, "activate", G_CALLBACK(on_chooser_activate), g_signal_connect_data(item, "activate", G_CALLBACK(on_chooser_activate),

168
fiv.c
View File

@@ -73,6 +73,138 @@ slist_to_strv(GSList *slist)
return strv; return strv;
} }
// --- macOS utilities ---------------------------------------------------------
#ifdef __APPLE__
#include <CoreFoundation/CoreFoundation.h>
static gchar *
cfurlref_to_path(CFURLRef urlref)
{
CFStringRef path = CFURLCopyFileSystemPath(urlref, kCFURLPOSIXPathStyle);
if (!path)
return NULL;
CFIndex size = CFStringGetMaximumSizeForEncoding(
CFStringGetLength(path), kCFStringEncodingUTF8) + 1;
gchar *string = g_malloc(size);
Boolean ok = CFStringGetCString(path, string, size, kCFStringEncodingUTF8);
CFRelease(path);
if (!ok) {
g_free(string);
return NULL;
}
return string;
}
static gchar *
get_application_bundle_path(void)
{
gchar *result = NULL;
CFBundleRef bundle = CFBundleGetMainBundle();
if (!bundle)
goto fail_1;
// When launched from outside a bundle, it will make up one,
// but these paths will then be equal.
CFURLRef bundle_url = CFBundleCopyBundleURL(bundle);
if (!bundle_url)
goto fail_1;
CFURLRef resources_url = CFBundleCopyResourcesDirectoryURL(bundle);
if (!resources_url)
goto fail_2;
if (!CFEqual(bundle_url, resources_url))
result = cfurlref_to_path(bundle_url);
CFRelease(resources_url);
fail_2:
CFRelease(bundle_url);
fail_1:
return result;
}
static gchar *
prepend_path_string(const gchar *prepended, const gchar *original)
{
if (!prepended)
return g_strdup(original ? original : "");
if (!original || !*original)
return g_strdup(prepended);
GHashTable *seen = g_hash_table_new(g_str_hash, g_str_equal);
GPtrArray *unique = g_ptr_array_new();
g_ptr_array_add(unique, (gpointer) prepended);
g_hash_table_add(seen, (gpointer) prepended);
gchar **components = g_strsplit(original, ":", -1);
for (gchar **p = components; *p; p++) {
if (g_hash_table_contains(seen, *p))
continue;
g_ptr_array_add(unique, *p);
g_hash_table_add(seen, *p);
}
g_ptr_array_add(unique, NULL);
gchar *result = g_strjoinv(":", (gchar **) unique->pdata);
g_hash_table_destroy(seen);
g_ptr_array_free(unique, TRUE);
g_strfreev(components);
return result;
}
// We reuse foreign dependencies, so we need to prevent them from loading
// any system-wide files, and point them in the right direction.
static void
adjust_environment(void)
{
gchar *bundle_dir = get_application_bundle_path();
if (!bundle_dir)
return;
gchar *contents_dir = g_build_filename(bundle_dir, "Contents", NULL);
gchar *macos_dir = g_build_filename(contents_dir, "MacOS", NULL);
gchar *resources_dir = g_build_filename(contents_dir, "Resources", NULL);
gchar *datadir = g_build_filename(resources_dir, "share", NULL);
gchar *libdir = g_build_filename(resources_dir, "lib", NULL);
g_free(bundle_dir);
gchar *new_path = prepend_path_string(macos_dir, g_getenv("PATH"));
g_setenv("PATH", new_path, TRUE);
g_free(new_path);
const gchar *data_dirs = g_getenv("XDG_DATA_DIRS");
gchar *new_data_dirs = data_dirs && *data_dirs
? prepend_path_string(datadir, data_dirs)
: prepend_path_string(datadir, "/usr/local/share:/usr/share");
g_setenv("XDG_DATA_DIRS", new_data_dirs, TRUE);
g_free(new_data_dirs);
gchar *schemas_dir = g_build_filename(datadir, "glib-2.0", "schemas", NULL);
g_setenv("GSETTINGS_SCHEMA_DIR", schemas_dir, TRUE);
g_free(schemas_dir);
gchar *gdk_pixbuf_module_file =
g_build_filename(libdir, "gdk-pixbuf-2.0", "loaders.cache", NULL);
g_setenv("GDK_PIXBUF_MODULE_FILE", gdk_pixbuf_module_file, TRUE);
g_free(gdk_pixbuf_module_file);
// GTK+ is smart enough to also consider application bundles,
// but let there be a single source of truth.
g_setenv("GTK_EXE_PREFIX", resources_dir, TRUE);
g_free(libdir);
g_free(datadir);
g_free(resources_dir);
g_free(macos_dir);
g_free(contents_dir);
}
#endif
// --- Keyboard shortcuts ------------------------------------------------------ // --- Keyboard shortcuts ------------------------------------------------------
// Fuck XML, this can be easily represented in static structures. // Fuck XML, this can be easily represented in static structures.
// Though it would be nice if the accelerators could be customized. // Though it would be nice if the accelerators could be customized.
@@ -1092,8 +1224,21 @@ on_next(void)
static gchar ** static gchar **
build_spawn_argv(const char *uri) build_spawn_argv(const char *uri)
{ {
// Because we only pass URIs, there is no need to prepend "--" here.
GPtrArray *a = g_ptr_array_new(); GPtrArray *a = g_ptr_array_new();
#ifdef __APPLE__
// Otherwise we would always launch ourselves in the background.
gchar *bundle_dir = get_application_bundle_path();
if (bundle_dir) {
g_ptr_array_add(a, g_strdup("open"));
g_ptr_array_add(a, g_strdup("-a"));
g_ptr_array_add(a, bundle_dir);
// At least with G_APPLICATION_NON_UNIQUE, this is necessary:
g_ptr_array_add(a, g_strdup("-n"));
g_ptr_array_add(a, g_strdup("--args"));
}
#endif
// Because we only pass URIs, there is no need to prepend "--" after this.
if (!a->len)
g_ptr_array_add(a, g_strdup(PROJECT_NAME)); g_ptr_array_add(a, g_strdup(PROJECT_NAME));
// Process-local VFS URIs need to be resolved to globally accessible URIs. // Process-local VFS URIs need to be resolved to globally accessible URIs.
@@ -1403,15 +1548,24 @@ on_window_state_event(G_GNUC_UNUSED GtkWidget *widget,
static void static void
show_help_contents(void) show_help_contents(void)
{ {
gchar *filename = g_strdup_printf("%s.html", PROJECT_NAME);
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
gchar *prefix = g_win32_get_package_installation_directory_of_module(NULL); gchar *prefix = g_win32_get_package_installation_directory_of_module(NULL);
#elif defined __APPLE__
gchar *prefix = get_application_bundle_path();
if (!prefix) {
show_error_dialog(g_error_new(
G_FILE_ERROR, G_FILE_ERROR_FAILED, "Cannot locate bundle"));
return;
}
#else
gchar *prefix = g_strdup(PROJECT_PREFIX);
#endif
gchar *filename = g_strdup_printf("%s.html", PROJECT_NAME);
gchar *path = g_build_filename(prefix, PROJECT_DOCDIR, filename, NULL); gchar *path = g_build_filename(prefix, PROJECT_DOCDIR, filename, NULL);
g_free(prefix); g_free(prefix);
#else
gchar *path = g_build_filename(PROJECT_DOCDIR, filename, NULL);
#endif
g_free(filename); g_free(filename);
GError *error = NULL; GError *error = NULL;
gchar *uri = g_filename_to_uri(path, NULL, &error); gchar *uri = g_filename_to_uri(path, NULL, &error);
g_free(path); g_free(path);
@@ -2640,6 +2794,10 @@ main(int argc, char *argv[])
{}, {},
}; };
#ifdef __APPLE__
adjust_environment();
#endif
// We never get the ::open signal, thanks to G_OPTION_ARG_FILENAME_ARRAY. // We never get the ::open signal, thanks to G_OPTION_ARG_FILENAME_ARRAY.
GtkApplication *app = gtk_application_new(NULL, G_APPLICATION_NON_UNIQUE); GtkApplication *app = gtk_application_new(NULL, G_APPLICATION_NON_UNIQUE);
g_application_set_option_context_parameter_string( g_application_set_option_context_parameter_string(

52
macos-Info.plist.in Normal file
View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>@ProjectName@</string>
<key>CFBundleIdentifier</key>
<string>@ProjectNS@@ProjectName@</string>
<key>CFBundleName</key>
<string>@ProjectName@</string>
<key>CFBundleIconFile</key>
<string>@ProjectName@.icns</string>
<key>CFBundleShortVersionString</key>
<string>@ProjectVersion@</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<!-- Although mostly static, this should eventually be generated. -->
<!-- In particular, we should expand image/x-dcraw, -->
<!-- using information we can collect from shared-mime-info. -->
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>Image File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Default</string>
<key>LSItemContentTypes</key>
<array>
<string>com.apple.icns</string>
<string>com.apple.quicktime-image</string>
<string>com.compuserve.gif</string>
<string>com.microsoft.bmp</string>
<string>com.microsoft.ico</string>
<string>org.webmproject.webp</string>
<string>public.avif</string>
<string>public.heic</string>
<string>public.heif</string>
<string>public.jpeg</string>
<string>public.png</string>
<string>public.svg-image</string>
<string>public.tiff</string>
<string>public.xbitmap-image</string>
</array>
</dict>
</array>
</dict>
</plist>

25
macos-configure.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/sh -e
# macos-configure.sh: set up a Homebrew-based macOS build
#
# Meson has no special support for macOS application bundles whatsoever.
#
# gtk-mac-bundler doesn't do anything particularly miraculous,
# and it doesn't directly support Homebrew.
#
# It would be cleaner and more reproducible to set up a special HOMEBREW_PREFIX,
# though right now we're happy to build an app bundle at all.
#
# It would also allow us to make a custom Little CMS build that includes
# the fast float plugin, which is a bit of a big deal.
# TODO: exiftool (Perl is part of macOS, at least for now)
HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_ASK=1 brew install
coreutils meson pkgconf shared-mime-info adwaita-icon-theme \
gtk+3 jpeg-xl libavif libheif libraw librsvg little-cms2 webp
sourcedir=$(grealpath "${2:-$(dirname "$0")}")
builddir=$(grealpath "${1:-builddir}")
appdir=$builddir/fiv.app
meson setup --buildtype=debugoptimized --prefix="$appdir" \
--bindir=Contents/MacOS --libdir=Contents/Resources/lib \
--datadir=Contents/Resources/share "$builddir" "$sourcedir"

115
macos-install.sh Executable file
View File

@@ -0,0 +1,115 @@
#!/bin/sh -e
export LC_ALL=C
cd "$MESON_INSTALL_DESTDIR_PREFIX"
# Input: Half-baked application bundle linked against Homebrew.
# Output: Portable application bundle.
source=/opt/homebrew
bindir=Contents/MacOS
libdir=Contents/Resources/lib
datadir=Contents/Resources/share
mkdir -p "$datadir"/glib-2.0/schemas
cp -p "$source"/share/glib-2.0/schemas/org.gtk.Settings.* \
"$datadir"/glib-2.0/schemas
mkdir -p "$datadir"/icons
cp -pRL "$source"/share/icons/Adwaita "$datadir/"icons
mkdir -p "$datadir"/icons/hicolor
cp -p "$source"/share/icons/hicolor/index.theme "$datadir"/icons/hicolor
mkdir -p "$datadir/mime"
# GIO doesn't use the database on macOS, this subset is for us.
find "$source"/share/mime/ -maxdepth 1 -type f -exec cp -p {} "$datadir"/mime \;
# Copy binaries we directly or indirectly depend on.
#
# Homebrew is a bit chaotic in that some libraries are linked against locations
# in /opt/homebrew/Cellar, and some against /opt/homebrew/opt symlinks.
# We'll process things in such a way that it does not matter.
#
# As a side note, libraries in /usr/lib are now actually being served from
# a shared cache by the dynamic linker and aren't visible on the filesystem.
# There is an alternative to "otool -L" which can see them but it isn't
# particularly nicer to parse: "dyld_info -dependents/-linked_dylibs".
rm -rf "$libdir"
mkdir -p "$libdir"
pixbufdir=$libdir/gdk-pixbuf-2.0
loadersdir=$pixbufdir/loaders
cp -RL "$source"/lib/gdk-pixbuf-2.0/* "$pixbufdir"
# Fix a piece of crap loader that needs to be special.
svg=$loadersdir/libpixbufloader_svg.so
rm -f "$loadersdir"/libpixbufloader_svg.dylib
otool -L "$svg" | grep -o '@rpath/[^ ]*' | while IFS= read -r bad
do install_name_tool -change "$bad" "$source/lib/$(basename "$bad")" "$svg"
done
GDK_PIXBUF_MODULEDIR=$loadersdir gdk-pixbuf-query-loaders \
| sed "s,$libdir,@rpath," > "$pixbufdir/loaders.cache"
gtkdir=$libdir/gtk-3.0
printbackendsdir=$gtkdir/printbackends
cp -RL "$source"/lib/gtk-3.0/* "$gtkdir"
# TODO: Figure out how to make gtk-query-immodules-3.0 pick up exactly
# what it needs to. So far I'm not sure if this is at all even useful.
rm -rf "$gtkdir"/immodules*
find "$bindir" "$loadersdir" "$printbackendsdir" -type f -maxdepth 1 | awk '
function collect(binary, command, line) {
if (seen[binary]++)
return
command = "otool -L \"" binary "\""
while ((command | getline line) > 0)
if (match(line, /^\t\/opt\/.+ \(/))
collect(substr(line, RSTART + 1, RLENGTH - 3))
close(command)
} {
collect($0)
delete seen[$0]
} END {
for (library in seen)
print library
}
' | while IFS= read -r binary
do test -f "$libdir/$(basename "$binary")" || cp "$binary" "$libdir"
done
# Now redirect all binaries to internal linking.
# A good overview of how this works is "man dyld" and:
# https://itwenty.me/posts/01-understanding-rpath/
rewrite() {
otool -L "$1" | sed -n 's,^\t\(.*\) (.*,\1,p' | grep '^/opt/' \
| while IFS= read -r lib
do install_name_tool -change "$lib" "@rpath/$(basename "$lib")" "$1"
done
}
find "$bindir" -type f -maxdepth 1 | while IFS= read -r binary
do
install_name_tool -add_rpath @executable_path/../Resources/lib "$binary"
rewrite "$binary"
done
find "$libdir" -type f \( -name '*.so' -o -name '*.dylib' \) \
| while IFS= read -r binary
do
chmod 644 "$binary"
install_name_tool -id "@rpath/${binary#$libdir/}" "$binary"
rewrite "$binary"
# Discard pointless @loader_path/../lib and absolute Homebrew paths.
otool -l "$binary" | awk '
$1 == "cmd" { command = $2 }
command == "LC_RPATH" && $1 == "path" { print $2 }
' | xargs -R 1 -I % install_name_tool -delete_rpath % "$binary"
# Replace freshly invalidated code signatures with ad-hoc ones.
codesign --force --sign - "$binary"
done
glib-compile-schemas "$datadir"/glib-2.0/schemas
# This may speed up program start-up a little bit.
gtk-update-icon-cache "$datadir"/icons/Adwaita

22
macos-svg2icns.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/bin/sh -e
# macos-svg2icns.sh: convert an SVG to the macOS .icns format
if [ $# -ne 2 ]
then
echo >&2 "Usage: $0 INPUT.svg OUTPUT.icns"
exit 2
fi
svg=$1 icns=$2 tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
iconset="$tmpdir/$(basename "$icns" .icns).iconset"
mkdir -p "$iconset"
for size in 16 32 128 256 512
do
size2x=$((size * 2))
rsvg-convert --output="$iconset/icon_${size}x${size}.png" \
--width=$size --height=$size "$svg"
rsvg-convert --output="$iconset/icon_${size}x${size}@2x.png" \
--width=$size2x --height=$size2x "$svg"
done
iconutil -c icns -o "$icns" "$iconset"

View File

@@ -18,6 +18,8 @@ add_project_arguments(
#endif #endif
win32 = host_machine.system() == 'windows' win32 = host_machine.system() == 'windows'
macos = host_machine.system() == 'darwin' \
and host_machine.subsystem() == 'macos'
# The likelihood of this being installed is nearly zero. Enable the wrap. # The likelihood of this being installed is nearly zero. Enable the wrap.
libjpegqs = dependency('libjpegqs', required : get_option('libjpegqs'), libjpegqs = dependency('libjpegqs', required : get_option('libjpegqs'),
@@ -97,15 +99,20 @@ docdir = get_option('datadir') / 'doc' / meson.project_name()
application_ns = 'name.janouch.' application_ns = 'name.janouch.'
application_url = 'https://janouch.name/p/' + meson.project_name() application_url = 'https://janouch.name/p/' + meson.project_name()
rawconf = configuration_data({
'ProjectName' : meson.project_name(),
'ProjectVersion' : meson.project_version(),
'ProjectNS' : application_ns,
'ProjectURL' : application_url,
})
conf = configuration_data() conf = configuration_data()
conf.set_quoted('PROJECT_NAME', meson.project_name()) conf.set_quoted('PROJECT_NAME', meson.project_name())
conf.set_quoted('PROJECT_VERSION', '@VCS_TAG@') conf.set_quoted('PROJECT_VERSION', '@VCS_TAG@')
conf.set_quoted('PROJECT_NS', application_ns) conf.set_quoted('PROJECT_NS', application_ns)
conf.set_quoted('PROJECT_URL', application_url) conf.set_quoted('PROJECT_URL', application_url)
conf.set_quoted('PROJECT_DOCDIR', get_option('prefix') / docdir) conf.set_quoted('PROJECT_PREFIX', get_option('prefix'))
if win32
conf.set_quoted('PROJECT_DOCDIR', docdir) conf.set_quoted('PROJECT_DOCDIR', docdir)
endif
conf.set('HAVE_JPEG_QS', libjpegqs.found()) conf.set('HAVE_JPEG_QS', libjpegqs.found())
conf.set('HAVE_LCMS2', lcms2.found()) conf.set('HAVE_LCMS2', lcms2.found())
@@ -147,6 +154,15 @@ if win32
output : 'fiv.ico', input : icon_png_list, output : 'fiv.ico', input : icon_png_list,
command : [icotool, '-c', '-o', '@OUTPUT@', '@INPUT@']) command : [icotool, '-c', '-o', '@OUTPUT@', '@INPUT@'])
rc += windows.compile_resources('fiv.rc', depends : icon_ico) rc += windows.compile_resources('fiv.rc', depends : icon_ico)
elif macos
# Meson is really extremely brain-dead and retarded.
# There is no real reason why this would have to be a shell script.
svg2icns = find_program('macos-svg2icns.sh')
icon_icns = custom_target('fiv.icns',
output : 'fiv.icns', input : 'fiv.svg',
command : [svg2icns, '@INPUT@', '@OUTPUT@'],
install : true,
install_dir : 'Contents/Resources')
endif endif
gnome = import('gnome') gnome = import('gnome')
@@ -220,7 +236,6 @@ endforeach
# For the purposes of development: make the program find its GSettings schemas. # For the purposes of development: make the program find its GSettings schemas.
gnome.compile_schemas(depend_files : files(gsettings_schemas)) gnome.compile_schemas(depend_files : files(gsettings_schemas))
gnome.post_install(glib_compile_schemas : true, gtk_update_icon_cache : true)
# Meson is broken on Windows and removes the backslashes, so this ends up empty. # Meson is broken on Windows and removes the backslashes, so this ends up empty.
symbolics = run_command(find_program('sed', required : false, disabler : true), symbolics = run_command(find_program('sed', required : false, disabler : true),
@@ -256,7 +271,26 @@ install_data('fiv.svg',
install_subdir('docs', install_subdir('docs',
install_dir : docdir, strip_directory : true) install_dir : docdir, strip_directory : true)
if not win32 if macos
# We're going all in on application bundles, seeing as it doesn't make
# much sense to install the application as in the block below.
#
# macOS has other mechanisms we can use to launch the JPEG cropper,
# or the reverse search utilities.
configure_file(
input : 'macos-Info.plist.in',
output : 'Info.plist',
configuration : rawconf,
install : true,
install_dir : 'Contents')
meson.add_install_script('macos-install.sh')
elif not win32
gnome.post_install(
glib_compile_schemas : true,
gtk_update_icon_cache : true,
)
asciidoctor = find_program('asciidoctor', required : false) asciidoctor = find_program('asciidoctor', required : false)
a2x = find_program('a2x', required : false) a2x = find_program('a2x', required : false)
if not asciidoctor.found() and not a2x.found() if not asciidoctor.found() and not a2x.found()
@@ -357,11 +391,7 @@ elif meson.is_cross_build()
wxs = configure_file( wxs = configure_file(
input : 'fiv.wxs.in', input : 'fiv.wxs.in',
output : 'fiv.wxs', output : 'fiv.wxs',
configuration : configuration_data({ configuration : rawconf,
'ProjectName' : meson.project_name(),
'ProjectVersion' : meson.project_version(),
'ProjectURL' : application_url,
}),
) )
msi = meson.project_name() + '-' + meson.project_version() + \ msi = meson.project_name() + '-' + meson.project_version() + \
'-' + host_machine.cpu() + '.msi' '-' + host_machine.cpu() + '.msi'