diff --git a/Cargo.lock b/Cargo.lock index c7007fdf46298b293abeb3baae3c789f501a6567..59c91994bba6a44be11f3b9b277cb3aed096db05 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -213,6 +213,15 @@ dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "core-foundation" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "core-foundation-sys" version = "0.2.3" @@ -221,6 +230,11 @@ dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "core-foundation-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "crc" version = "1.8.1" @@ -414,6 +428,14 @@ dependencies = [ "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fractal-mac-wrapper" +version = "0.1.0" +dependencies = [ + "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -1963,7 +1985,9 @@ dependencies = [ "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" "checksum comrak 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "17a5772ca33e3ec805360145413ccb60e0256b504919d3c7d38bfb844cd0dc75" "checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67" +"checksum core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7caa6cb9e76ddddbea09a03266d6b3bc98cd41e9fb9b017c473e7cca593ec25" "checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d" +"checksum core-foundation-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2a53cce0ddcf7e7e1f998738d757d5a3bf08bf799a180e50ebe50d298f52f5a" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum crossbeam-deque 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c1bdc73742c36f7f35ebcda81dbb33a7e0d33757d03a06d9ddca762712ec5ea2" "checksum crossbeam-epoch 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9b4e2817eb773f770dcb294127c011e22771899c21d18fce7dd739c0b9832e81" diff --git a/Cargo.toml b/Cargo.toml index eac6d25e987d82110eaa3040f2ddbcfa31e3ed44..fa30b6a899c25d5e50582fc1c699e904bedd4bbe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "fractal-api", "fractal-gtk", + "fractal-mac-wrapper" ] [patch.crates-io] diff --git a/fractal-gtk/res/Info.plist.in b/fractal-gtk/res/Info.plist.in new file mode 100644 index 0000000000000000000000000000000000000000..02f627c96cb553672bb704edd8686aab34d1697b --- /dev/null +++ b/fractal-gtk/res/Info.plist.in @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + fractal + CFBundleIconFile + fractal.icns + CFBundleIdentifier + com.gnome.Fractal + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Fractal + CFBundlePackageType + APPL + CFBundleShortVersionString + @VERSION@ + CFBundleVersion + @VERSION@ + NSHighResolutionCapable + + + + diff --git a/fractal-gtk/res/icons/hicolor/128x128/org.gnome.Fractal.png b/fractal-gtk/res/icons/fractal.iconset/icon_128x128.png similarity index 100% rename from fractal-gtk/res/icons/hicolor/128x128/org.gnome.Fractal.png rename to fractal-gtk/res/icons/fractal.iconset/icon_128x128.png diff --git a/fractal-gtk/res/icons/fractal.iconset/icon_128x128@2x.png b/fractal-gtk/res/icons/fractal.iconset/icon_128x128@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f6094db63f814b4fad7abb752e0e26c8cb3161f4 Binary files /dev/null and b/fractal-gtk/res/icons/fractal.iconset/icon_128x128@2x.png differ diff --git a/fractal-gtk/res/icons/fractal.iconset/icon_16x16.png b/fractal-gtk/res/icons/fractal.iconset/icon_16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..2a5c8ea0b06cf0cc355ff549b823cd834692eaff Binary files /dev/null and b/fractal-gtk/res/icons/fractal.iconset/icon_16x16.png differ diff --git a/fractal-gtk/res/icons/fractal.iconset/icon_16x16@2x.png b/fractal-gtk/res/icons/fractal.iconset/icon_16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bc53dada14de4c7e22fb77b7f17b6ac6c4bf088f Binary files /dev/null and b/fractal-gtk/res/icons/fractal.iconset/icon_16x16@2x.png differ diff --git a/fractal-gtk/res/icons/hicolor/256x256/org.gnome.Fractal.png b/fractal-gtk/res/icons/fractal.iconset/icon_256x256.png similarity index 100% rename from fractal-gtk/res/icons/hicolor/256x256/org.gnome.Fractal.png rename to fractal-gtk/res/icons/fractal.iconset/icon_256x256.png diff --git a/fractal-gtk/res/icons/fractal.iconset/icon_256x256@2x.png b/fractal-gtk/res/icons/fractal.iconset/icon_256x256@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f35d55298df78a1409e990042bf56b03a18f388f Binary files /dev/null and b/fractal-gtk/res/icons/fractal.iconset/icon_256x256@2x.png differ diff --git a/fractal-gtk/res/icons/fractal.iconset/icon_32x32.png b/fractal-gtk/res/icons/fractal.iconset/icon_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..d7681cd99f843ae0f517550eba49faa196619a8c Binary files /dev/null and b/fractal-gtk/res/icons/fractal.iconset/icon_32x32.png differ diff --git a/fractal-gtk/res/icons/fractal.iconset/icon_32x32@2x.png b/fractal-gtk/res/icons/fractal.iconset/icon_32x32@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e7bd5f0b93aa89dcc743c2f18777c95dba709890 Binary files /dev/null and b/fractal-gtk/res/icons/fractal.iconset/icon_32x32@2x.png differ diff --git a/fractal-gtk/res/icons/fractal.iconset/icon_512x512.png b/fractal-gtk/res/icons/fractal.iconset/icon_512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..9b9c991912242c8bdc9570576e20845ab312419a Binary files /dev/null and b/fractal-gtk/res/icons/fractal.iconset/icon_512x512.png differ diff --git a/fractal-gtk/res/icons/fractal.iconset/icon_512x512@2x.png b/fractal-gtk/res/icons/fractal.iconset/icon_512x512@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4b639741423856cc64aeed4a2075a31020f1cc5f Binary files /dev/null and b/fractal-gtk/res/icons/fractal.iconset/icon_512x512@2x.png differ diff --git a/fractal-gtk/res/icons/hicolor/128x128/apps/org.gnome.Fractal.png b/fractal-gtk/res/icons/hicolor/128x128/apps/org.gnome.Fractal.png new file mode 100644 index 0000000000000000000000000000000000000000..85f64f419509631cae25f8a16dec50e8d738221e Binary files /dev/null and b/fractal-gtk/res/icons/hicolor/128x128/apps/org.gnome.Fractal.png differ diff --git a/fractal-gtk/res/icons/hicolor/256x256/apps/org.gnome.Fractal.png b/fractal-gtk/res/icons/hicolor/256x256/apps/org.gnome.Fractal.png new file mode 100644 index 0000000000000000000000000000000000000000..a4b3e54718f9402880c9ad7af1de9b6bc4cf629e Binary files /dev/null and b/fractal-gtk/res/icons/hicolor/256x256/apps/org.gnome.Fractal.png differ diff --git a/fractal-gtk/res/icons/meson.build b/fractal-gtk/res/icons/meson.build index eff6e4b5301b0538c29054cbb241b85722b8263a..ff3d15b523ef0ed526e7abe606d54d67da7b3171 100644 --- a/fractal-gtk/res/icons/meson.build +++ b/fractal-gtk/res/icons/meson.build @@ -1 +1,13 @@ install_subdir('hicolor', install_dir: icondir) + +# Install the mac icon only if we are building a .app bundle for macOS +iconutil = find_program('iconutil', required: mac_bundle) + +if iconutil.found() + icns = custom_target('mac-icns', + input : 'fractal.iconset', + output : 'fractal.icns', + command : [iconutil, '-c', 'icns', '-o', '@OUTPUT@', '@INPUT@'], + install : mac_bundle, + install_dir : datadir) +endif diff --git a/fractal-gtk/res/meson.build b/fractal-gtk/res/meson.build index d050c6f1c058ffac8475e57b711102117438393a..3296d3861f6666c2148e431f57faf5d14a7e90c9 100644 --- a/fractal-gtk/res/meson.build +++ b/fractal-gtk/res/meson.build @@ -1,4 +1,17 @@ subdir('icons') -install_data('org.gnome.Fractal.desktop', install_dir : datadir + '/applications') -install_data('org.gnome.Fractal.appdata.xml', install_dir : datadir + '/appdata') +appdata = configure_file(input : 'org.gnome.Fractal.appdata.xml.in', + output : 'org.gnome.Fractal.appdata.xml', + configuration : conf) + +infoplist = configure_file(input : 'Info.plist.in', + output : 'Info.plist', + configuration : conf) + + +if host_machine.system() == 'linux' or host_machine.system() == 'bsd' + install_data('org.gnome.Fractal.desktop', install_dir : datadir + '/applications') + install_data(appdata, install_dir : datadir + '/appdata') +elif host_machine.system() == 'darwin' and mac_bundle + install_data(infoplist, install_dir : get_option('prefix') + '/Contents') +endif diff --git a/fractal-gtk/res/org.gnome.Fractal.appdata.xml b/fractal-gtk/res/org.gnome.Fractal.appdata.xml.in similarity index 95% rename from fractal-gtk/res/org.gnome.Fractal.appdata.xml rename to fractal-gtk/res/org.gnome.Fractal.appdata.xml.in index 3cc163c102d43b570892f98406a395970479cc1e..fc3bb001e1be5127e23331da02165343c85041b2 100644 --- a/fractal-gtk/res/org.gnome.Fractal.appdata.xml +++ b/fractal-gtk/res/org.gnome.Fractal.appdata.xml.in @@ -2,7 +2,7 @@ org.gnome.Fractal.desktop Fractal - GPL-3.0 + @LICENSE@ CC0-1.0 Daniel GarcĂ­a Moreno Matrix group messaging app @@ -18,7 +18,7 @@ - + danigm@wadobo.com diff --git a/fractal-mac-wrapper/Cargo.toml b/fractal-mac-wrapper/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..e907277007edb4f57d6fd1fc26576ec055d5d311 --- /dev/null +++ b/fractal-mac-wrapper/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "fractal-mac-wrapper" +version = "0.1.0" +authors = ["Quentin Gliech "] + +[dependencies] +libc = "0.2" +core-foundation = "0.6" diff --git a/fractal-mac-wrapper/src/main.rs b/fractal-mac-wrapper/src/main.rs new file mode 100644 index 0000000000000000000000000000000000000000..3c1d70d32fe3c4182452c7750d401338fd8b5492 --- /dev/null +++ b/fractal-mac-wrapper/src/main.rs @@ -0,0 +1,43 @@ +extern crate core_foundation; +extern crate libc; + +use core_foundation::bundle::CFBundle; +use libc::execv; +use std::ffi::CString; +use std::ptr; + +fn main() { + // Get the URL of the executable inside the bundle and build the other paths relative to this. + // + // Ideally, we would use CFBundleCopyResourcesDirectoryURL and + // CFBundleCopyAuxiliaryExecutableURL to get the paths to the Resources directory and the + // fractal binary, but core_foundation_sys doesn't expose them for now. + let bundle = CFBundle::main_bundle(); + let url = bundle.executable_url().unwrap(); + + let mut path = url.to_path().unwrap(); + path.pop(); + + // Construct the argument for execv + let program = CString::new(format!("{}/fractal", path.to_str().unwrap())).unwrap(); + let args = vec![program.as_ptr(), ptr::null()]; + + // Inject the needed environment variables + path.pop(); + let env = vec![ + ("GDK_PIXBUF_MODULE_FILE", "Resources/gdk-loaders.cache"), + ("GTK_IM_MODULE_FILE", "Resources/gtk.immodules"), + ("XDG_DATA_DIRS", "Resources"), + ("XDG_CONFIG_DIRS", "Resources"), + ]; + + for (key, val) in env { + let val = format!("{}/{}", path.to_str().unwrap(), val); + std::env::set_var(key, val); + } + + // Execute the real `fractal` + unsafe { + execv(program.as_ptr(), args.as_ptr()); + }; +} diff --git a/meson.build b/meson.build index 23bb6d108f544898c24f168953687e0ff6ba8d1f..f32d7197a6e380ad1b270f366e762d164511b215 100644 --- a/meson.build +++ b/meson.build @@ -1,21 +1,25 @@ project( 'fractal', 'rust', version: '0.1.28', - license: 'GPLv3', + license: 'GPL-3.0-only', ) fractal_version = meson.project_version() -version_array = fractal_version.split('.') -fractal_major_version = version_array[0].to_int() -fractal_minor_version = version_array[1].to_int() -fractal_version_micro = version_array[2].to_int() +build_date = run_command('date', '+%Y-%m-%d').stdout().strip() -fractal_prefix = get_option('prefix') -fractal_bindir = join_paths(fractal_prefix, get_option('bindir')) +conf = configuration_data() +conf.set('VERSION', fractal_version) +conf.set('LICENSE', meson.project_license()[0]) +conf.set('BUILD_DATE', build_date) +mac_bundle = get_option('mac_bundle') datadir = get_option('datadir') icondir = join_paths(datadir, 'icons') +if mac_bundle and host_machine.system() != 'darwin' + error('Can\'t build a mac bundle if the target machine isn\'t darwin') +endif + subdir('fractal-gtk/res') cargo = find_program('cargo', required: false) @@ -24,18 +28,41 @@ cargo_vendor = find_program('cargo-vendor', required: false) cargo_script = find_program('scripts/cargo.sh') grabber = find_program('scripts/grabber.sh') cargo_release = find_program('scripts/release.sh') +create_mac_bundle = find_program('scripts/create-mac-bundle.sh') c = run_command(grabber) sources = c.stdout().strip().split('\n') -cargo_release = custom_target('cargo-build', +fractal = custom_target('cargo-build', build_by_default: true, input: sources, output: ['fractal'], install: true, - install_dir: fractal_bindir, + install_dir: get_option('bindir'), command: [cargo_script, '@CURRENT_SOURCE_DIR@', '@OUTPUT@']) run_target('release', command: ['scripts/release.sh', meson.project_name() + '-' + fractal_version ]) + +if mac_bundle + brew = find_program('brew', required: true) + pkg_config = find_program('pkg-config', required: true) + install_name_tool = find_program('install_name_tool', required: true) + glib_compile_schemas = find_program('glib-compile-schemas', required: true) + gtk_query_immodules = find_program('gtk-query-immodules-3.0', required: true) + + fractal_mac_wrapper = custom_target('cargo-build-mac-wrapper', + build_by_default: true, + input: sources, + output: ['fractal-mac-wrapper'], + install: true, + install_dir: get_option('bindir'), + command: [cargo_script, '@CURRENT_SOURCE_DIR@', '@OUTPUT@', 'fractal-mac-wrapper']) + + meson.add_install_script( + create_mac_bundle.path(), + join_paths(get_option('prefix'), get_option('bindir'), 'fractal'), + get_option('prefix') + ) +endif diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000000000000000000000000000000000000..5e12bfea074e605386cb268a42d1cb1fbfdf12b5 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1 @@ +option('mac_bundle', type : 'boolean', value : false, description : 'Set true if you are building a .app bundle for macOS') diff --git a/scripts/build-mac.sh b/scripts/build-mac.sh new file mode 100755 index 0000000000000000000000000000000000000000..1658ef0fc84e5ac9952f5273e537f91bba9834c9 --- /dev/null +++ b/scripts/build-mac.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +# This scripts configures meson for creating a .app bundle for macOS. +# +# scripts/build-mac.sh /tmp/Fractal.app _mac +# ninja -C _mac install +# open /tmp/Fractal.app + +if [ $# -lt 2 ]; then + echo "usage: $0 /path/to/Fractal.app [meson options]" >&2 + exit 1 +fi + +APP_BUNDLE=$1 +shift + +meson \ + --prefix $APP_BUNDLE \ + --bindir Contents/MacOS \ + --libdir Contents/Frameworks \ + --datadir Contents/Resources \ + -Dmac_bundle=true \ + $@ diff --git a/scripts/cargo.sh b/scripts/cargo.sh index 901d0df630132a9381ef0a4ce33af68b8862b6c1..ae7998ff1753ae093d34244e4cdc54e979479ba8 100755 --- a/scripts/cargo.sh +++ b/scripts/cargo.sh @@ -1,12 +1,17 @@ #!/bin/sh -export CARGO_HOME=$1/target/cargo-home +SOURCE=$1 +TARGET=$2 +PACKAGE=${3:-"fractal-gtk"} +export CARGO_HOME=$SOURCE/target/cargo-home + +set -x if [[ $DEBUG = true ]] then echo "DEBUG MODE" - cargo build --manifest-path $1/Cargo.toml -p fractal-gtk && cp $1/target/debug/fractal-gtk $2 + cargo build --manifest-path $SOURCE/Cargo.toml -p $PACKAGE && cp $SOURCE/target/debug/$PACKAGE $TARGET else echo "RELEASE MODE" - cargo build --manifest-path $1/Cargo.toml --release -p fractal-gtk && cp $1/target/release/fractal-gtk $2 + cargo build --manifest-path $SOURCE/Cargo.toml --release -p $PACKAGE && cp $SOURCE/target/release/$PACKAGE $TARGET fi diff --git a/scripts/create-mac-bundle.sh b/scripts/create-mac-bundle.sh new file mode 100755 index 0000000000000000000000000000000000000000..27c1e8a91800a86b614286f184dbe23080ca503c --- /dev/null +++ b/scripts/create-mac-bundle.sh @@ -0,0 +1,111 @@ +#!/bin/sh +# +# This scripts is used to bundle all the dependencies in a .app bundle for macOS. +# It is called by meson if the `mac_bundle` option is set to true. + +if [ $# -ne 2 ]; then + echo "usage: $0 /path/to/Fractal.app/Contents/MacOS/fractal /path/to/Fractal.app" >&2 + exit 1 +fi + +# Useful for debugging, but meson doesn't eat the outputs of install scripts +#set -eux +set -eu + +BINARY="$1" +APP_BUNDLE="$2" + +CONTENTS="$APP_BUNDLE/Contents" + +FRAMEWORKS="$CONTENTS/Frameworks" # Where all the libraries live +RESOURCES="$CONTENTS/Resources" # Where all the resources are + +mkdir -p $FRAMEWORKS $RESOURCES + +# List of library that where already copied and fixed +DONE="" + +# Copy and fix a dependency +copy_and_fix () { + OLD_PATH="$1" + LIB_NAME=`basename $OLD_PATH` + NEW_PATH="$FRAMEWORKS/$LIB_NAME" + if echo "$DONE" | grep -q $LIB_NAME; then return; fi + + cp $OLD_PATH $NEW_PATH + chmod u+w $NEW_PATH + install_name_tool -change "$OLD_PATH" "$LIB_NAME" "$NEW_PATH" + install_name_tool -id "@rpath/$LIB_NAME" "$NEW_PATH" + + DONE="$DONE $LIB_NAME" + fix "$NEW_PATH" +} + +# Fix a lib or binary by searching all it's dependencies, copying them inside +# the Frameworks directory, fix the library search path and recursivly fix it's +# dependencies +fix () { + LIBS="`otool -L "$1" | grep '\(local\|opt\)' | awk '{ print $1 }'`" + + for LIB in $LIBS; do + install_name_tool -change "$LIB" "@rpath/`basename $LIB`" "$1" + copy_and_fix "$LIB" + done +} + +install_name_tool -add_rpath "@executable_path/../Frameworks" "$BINARY" || echo "Executable already has 'Frameworks' in his @rpath" +fix $BINARY + +# GTK Input modules stuff +GTK_VERSION=`pkg-config gtk+-3.0 --variable gtk_binary_version` +GTK_PREFIX=`pkg-config gtk+-3.0 --variable prefix` + +for LIB in `gtk-query-immodules-3.0 | grep .so | sed 's/"//g'`; do + copy_and_fix $LIB +done + +gtk-query-immodules-3.0 \ + | sed "s|$GTK_PREFIX/lib/gtk-3.0/$GTK_VERSION/immodules/|@rpath/|g" \ + | sed "s|$GTK_PREFIX/shareaa/locale|@executable_path/../Resources/locale|g" \ + > $RESOURCES/gtk.immodules + + +# GDK Pixbuf modules things +GDK_PIXBUF_PREFIX=`pkg-config gdk-pixbuf-2.0 --variable prefix` +GDK_PIXBUF_VERSION=`pkg-config gdk-pixbuf-2.0 --variable gdk_pixbuf_binary_version` + +for LIB in `pkg-config gdk-pixbuf-2.0 --variable=gdk_pixbuf_moduledir`/*.so; do + copy_and_fix $LIB +done + +gdk-pixbuf-query-loaders \ + | sed "s|$GDK_PIXBUF_PREFIX/lib/gdk-pixbuf-2.0/$GDK_PIXBUF_VERSION/loaders/|@rpath/|g" \ + > $RESOURCES/gdk-loaders.cache + + +# Compile the GLib schemas +mkdir -p $RESOURCES/glib-2.0/schemas +glib-compile-schemas --targetdir=$RESOURCES/glib-2.0/schemas "`brew --prefix gtk+3`/share/glib-2.0/schemas" + + +# Copy the theme and icons +mkdir -p $RESOURCES/icons +cp -a `brew --prefix adwaita-icon-theme`/share/icons/* $RESOURCES/icons +cp -a `brew --prefix hicolor-icon-theme`/share/icons/* $RESOURCES/icons + +mkdir -p $RESOURCES/themes/Mac +cp -a `brew --prefix gtk+3`/share/themes/Mac/* $RESOURCES/themes/Mac + + +# Create the GTK settings file +mkdir -p $RESOURCES/etc/gtk-3.0 +cat > $RESOURCES/etc/gtk-3.0/settings.ini << EOF +[Settings] +gtk-theme-name=Adwaita +EOF + + +# Copy mime database +mkdir -p $RESOURCES/mime +cp -a $(pkg-config shared-mime-info --variable=prefix)/share/mime/mime.cache \ + $RESOURCES/mime