diff --git a/automation/meson.build b/automation/meson.build
index fff6b45c1405075fa49aa74444cea0b4a6437cb6..043d40c8c8986b4d9c9c947f29673b95b4e48826 100644
--- a/automation/meson.build
+++ b/automation/meson.build
@@ -1,4 +1,4 @@
-automation_dir = get_option('datadir') / 'aegisub' / 'automation'
+automation_dir = dataroot / 'automation'
 
 install_data(
     'autoload/cleantags-autoload.lua',
diff --git a/meson.build b/meson.build
index be8feb3d5012b3b45da25f1f9f1c21646f59cdd2..cf9cfe66eb770391ed89dfa0f627f744233315ab 100644
--- a/meson.build
+++ b/meson.build
@@ -26,7 +26,19 @@ version_h = custom_target('git_version.h',
                           build_always_stale: true, # has internal check whether target file will be refreshed
                           output: ['git_version.h', 'git_version.xml'])
 
-dataroot = get_option('prefix') / get_option('datadir') / 'aegisub'
+if host_machine.system() == 'darwin' and get_option('build_osx_bundle')
+    prefix = meson.current_build_dir() / 'Aegisub.app' / 'Contents'
+    bindir = prefix / 'MacOS'
+    datadir = prefix / 'SharedSupport'
+    localedir = prefix / 'Resources'
+else
+    prefix = get_option('prefix')
+    bindir = prefix / get_option('bindir')
+    datadir = prefix / get_option('datadir')
+    localedir = prefix / get_option('localedir')
+endif
+docdir = prefix / 'doc'
+dataroot = datadir / 'aegisub'
 add_project_arguments('-DP_DATA="@0@"'.format(dataroot), language: 'cpp')
 
 if host_machine.system() == 'windows'
diff --git a/meson_options.txt b/meson_options.txt
index fa24825cc0a36b2c6591c8fa5e1b34444699902e..c003fbc1dc99335aabdaa6e21a4a11113ebf062b 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -22,3 +22,5 @@ option('credit', type: 'string', value: '', description: 'Build credit shown in
 option('enable_update_checker', type: 'boolean', value: false, description: 'Enable the update checker')
 option('update_server', type: 'string', value: 'updates.aegisub.org', description: 'Server to use for the update checker')
 option('update_url', type: 'string', value: '/trunk', description: 'Base path to use for the update checker')
+
+option('build_osx_bundle', type: 'boolean', value: 'false', description: 'Package Aegisub.app on OSX')
diff --git a/packages/meson.build b/packages/meson.build
index f2a02902c91cc56c9e98891f041dc0b9b2b72ed3..41676bfb2371376ccaa13f2f1ea3fa0ca895d918 100644
--- a/packages/meson.build
+++ b/packages/meson.build
@@ -2,6 +2,12 @@ conf_pkg = configuration_data()
 
 if host_machine.system() == 'windows'
 elif host_machine.system() == 'darwin'
+    # temporary hack until version.sh generates this properly
+    run_command('cp', meson.source_root() / 'tools' / 'osx-bundle.sed', meson.build_root())
+    fontconfig_conf = run_command('pkg-config', '--variable=confdir', 'fontconfig').stdout().strip()
+    run_target('osx-bundle',
+               command: ['../tools/osx-bundle.sh', meson.source_root(), meson.build_root(), 'wx-config', fontconfig_conf, '',
+                         get_option('build_osx_bundle') ? 'TRUE' : 'FALSE'])
 else
     conf_pkg.set('AEGISUB_COMMAND', 'aegisub')
 
@@ -15,7 +21,7 @@ else
                     type: 'desktop',
                     po_dir: '../po',
                     install: true,
-                    install_dir: join_paths(get_option('datadir'), 'applications'))
+                    install_dir: datadir / 'applications')
 
     aegisub_logos = ['16x16.png', '22x22.png', '24x24.png', '32x32.png', '48x48.png', '64x64.png', 'scalable.svg']
 
@@ -23,6 +29,6 @@ else
         dir = s.split('.')[0]
         ext = s.split('.')[1]
         install_data('desktop' / dir / 'aegisub.' + ext,
-                     install_dir: get_option('datadir') / 'icons' / 'hicolor' / dir / 'apps')
+                     install_dir: datadir / 'icons' / 'hicolor' / dir / 'apps')
     endforeach
 endif
diff --git a/tools/osx-bundle.sed.in b/packages/osx_bundle/osx-bundle.sed.in
similarity index 100%
rename from tools/osx-bundle.sed.in
rename to packages/osx_bundle/osx-bundle.sed.in
diff --git a/po/meson.build b/po/meson.build
index 5d61f0efcc11a9750e61dea8df79ad6c7fd05741..5aae381d118bdc3d76f83ef162c742f8f3d1db9d 100644
--- a/po/meson.build
+++ b/po/meson.build
@@ -1,2 +1,4 @@
 i18n = import('i18n')
-i18n.gettext('aegisub')
+# This is currently busted on OSX
+i18n.gettext('aegisub',
+	         install_dir: localedir)
diff --git a/src/meson.build b/src/meson.build
index 7e5dc7788fbb41e4f2d1b4dc79c8f3feb54cea9f..1238f6dea3bcb59c9f19ed3d7558e6959d2f5a63 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -220,5 +220,6 @@ aegisub = executable('aegisub', aegisub_src, version_h, acconf,
                      cpp_pch: aegisub_cpp_pch,
                      c_pch: aegisub_c_pch,
                      install: true,
+                     install_dir: bindir,
                      dependencies: deps,
                      gui_app: true)
diff --git a/tools/osx-bundle.sh b/tools/osx-bundle.sh
index eb82b554f01994d4ab4ef91aa80e0c36f5b6f2a8..dbec657d8c086f6c7bead28ef364481262b4fa36 100755
--- a/tools/osx-bundle.sh
+++ b/tools/osx-bundle.sh
@@ -2,22 +2,25 @@
 
 set -e
 
-PKG_DIR=Aegisub.app
-SKEL_DIR="packages/osx_bundle"
-AEGISUB_BIN="${1}"
-SRCDIR=`pwd`
-HOME_DIR=`echo ~`
-WX_PREFIX=`${2} --prefix`
-FONTCONFIG_CONF_DIR="${3}"
-
-if ! test -d packages/osx_bundle; then
-  echo
-  echo "Make sure you're in the toplevel source directory"
+SRC_DIR="${1}"
+BUILD_DIR="${2}"
+WX_PREFIX=`${3} --prefix`
+FONTCONFIG_CONF_DIR="${4}"
+DICT_DIR="${5}"
+MESON_BUILD_OSX_BUNDLE="${6}"
+
+if [ "${MESON_BUILD_OSX_BUNDLE}" != "TRUE" ]; then
+  echo "Project not built with \`build_osx_bundle\`"
+  echo "Please run \`meson configure -Dbuild_osx_bundle=true\` and rebuild"
   exit 1
 fi
 
+PKG_DIR="${BUILD_DIR}/Aegisub.app"
+SKEL_DIR="${SRC_DIR}/packages/osx_bundle"
+
 if test -d "${PKG_DIR}"; then
   rm -rf "${PKG_DIR}"
+  echo "Removing old Aegisub.app"
 fi
 
 echo
@@ -31,41 +34,34 @@ mkdir -v "${PKG_DIR}/Contents/SharedSupport/dictionaries"
 
 echo
 echo "---- Copying Skel Files ----"
-if ! test -f "tools/osx-bundle.sed"; then
+if ! test -f "${BUILD_DIR}/osx-bundle.sed"; then
   echo
-  echo "NOT FOUND: tools/osx-bundle.sed"
+  echo "NOT FOUND: ${BUILD_DIR}/osx-bundle.sed"
   exit 1
 fi
 
 # used by osx-bundle.sed
-find po -name *.po | sed 's/.*\/\(.*\)\.po/        <string>\1<\/string>/; s/RS/YU/' > languages
+find "${SRC_DIR}/po" -name *.po | sed 's/.*\/\(.*\)\.po/        <string>\1<\/string>/; s/RS/YU/' > "${BUILD_DIR}/languages"
 
-find ${SKEL_DIR} -type f -not -regex ".*.svn.*"
-cp ${SKEL_DIR}/Contents/Resources/*.icns "${PKG_DIR}/Contents/Resources"
-cat ${SKEL_DIR}/Contents/Info.plist | sed -f tools/osx-bundle.sed > "${PKG_DIR}/Contents/Info.plist"
+#find "${SKEL_DIR}" -type f -not -regex ".*.svn.*"
+cp -v ${SKEL_DIR}/Contents/Resources/*.icns "${PKG_DIR}/Contents/Resources"
+cat "${SKEL_DIR}/Contents/Info.plist" | sed -f "${BUILD_DIR}/osx-bundle.sed" > "${PKG_DIR}/Contents/Info.plist"
 
-rm languages
+rm "${BUILD_DIR}/languages"
 
 echo
 echo "---- Installing files ----"
-make install \
-	DESTDIR="${PKG_DIR}/Contents" \
-	P_DATA="/SharedSupport" \
-	P_DOC="/SharedSupport/doc" \
-	P_LOCALE="/Resources" \
-	P_BINDIR="/MacOS"
+CURRENT_DIR=`pwd`
+cd ${BUILD_DIR}
+ninja install
+cd ${CURRENT_DIR}
 
 echo
 echo "---- Copying dictionaries ----"
-if test -z "${DICT_DIR}"; then
-  DICT_DIR="${HOME_DIR}/dict"
-fi
-
-if test -d "${DICT_DIR}"; then
-  cp -v ${DICT_DIR}/* "${PKG_DIR}/Contents/SharedSupport/dictionaries"
+if test -f "${DICT_DIR}"; then
+  cp -v "${DICT_DIR}/*" "${PKG_DIR}/Contents/SharedSupport/dictionaries"
 else
-  echo "WARNING: Dictionaries not found, please set $$DICT_DIR to a directiory"
-  echo "         where the *.aff and *.dic files can be found"
+  echo "Specified dictionary directory ${DICT_DIR} not found!"
 fi
 
 echo
@@ -74,14 +70,15 @@ echo "---- Copying Aegisub locale files ----"
 # internal so we don't need an aegisub.mo file.
 mkdir -vp "${PKG_DIR}/Contents/Resources/en.lproj"
 
+# FIXME
 # 10.8 wants sr_YU rather than sr_RS
-mv "${PKG_DIR}/Contents/Resources/sr_RS.lproj" "${PKG_DIR}/Contents/Resources/sr_YU.lproj"
-mv "${PKG_DIR}/Contents/Resources/sr_RS@latin.lproj" "${PKG_DIR}/Contents/Resources/sr_YU@latin.lproj"
+#mv "${PKG_DIR}/Contents/Resources/sr_RS.lproj" "${PKG_DIR}/Contents/Resources/sr_YU.lproj"
+#mv "${PKG_DIR}/Contents/Resources/sr_RS@latin.lproj" "${PKG_DIR}/Contents/Resources/sr_YU@latin.lproj"
 
 echo
 echo "---- Copying WX locale files ----"
 
-for i in `ls -1 po/*.mo|sed "s|po/\(.*\).mo|\1|"`; do
+for i in `ls -1 ${SRC_DIR}/po/*.mo|sed "s|po/\(.*\).mo|\1|"`; do
   WX_MO="${WX_PREFIX}/share/locale/${i}/LC_MESSAGES/wxstd.mo"
 
   if ! test -f "${WX_MO}"; then
@@ -95,10 +92,9 @@ for i in `ls -1 po/*.mo|sed "s|po/\(.*\).mo|\1|"`; do
   fi
 done
 
-
 echo
-echo "---- Libraries ----"
-python tools/osx-fix-libs.py "${PKG_DIR}/Contents/MacOS/aegisub" || exit $?
+echo "---- Fixing libraries ----"
+sudo python "${SRC_DIR}/tools/osx-fix-libs.py" "${PKG_DIR}/Contents/MacOS/aegisub" || exit $?
 
 echo
-echo "Done Creating \"${PKG_DIR}\""
+echo "Done creating \"${PKG_DIR}\""