+ fi
+}
+
+Multi::bundleLibFromFile () {
+ local exe_file="${1}"
+ local lib_file
+
+ Multi::printLdd "${exe_file}" \
+ | Multi::filterLib \
+ | while read lib_file
+ do
+ if [ "${lib_file}" = 'not found' ]
+ then
+ printf 'ERROR: library not found while bundling %s (but link worked)\n' "${exe_file}" >&2
+ Multi::printLdd "${exe_file}" | grep 'not found'
+ exit 1
+ fi
+ lib_basename="$(basename "${lib_file}")"
+
+ if [ -f "${lib_dir}/${lib_basename}" ]
+ then
+ continue
+ fi
+
+ _cp \
+ "${lib_file}" \
+ "${lib_dir}/${lib_basename}"
+
+ Multi::bundleGtkDepsFromFile "${lib_file}"
+
+ case "${system_name}" in
+ 'macos')
+ Multi::bundleLibFromFile "${lib_file}"
+ ;;
+ esac
+ done
+}
+
+Multi::cleanUp () {
+ find "${bundle_dir}/lib" \
+ -type f \
+ -name '*.a' \
+ -exec rm -f {} \;
+
+ find "${bundle_dir}/lib" \
+ -type f \
+ -name '*.h' \
+ -exec rm -f {} \;
+
+ find "${bundle_dir}/lib" \
+ -depth \
+ -type d \
+ -exec rmdir {} \; \
+ || true
+}
+
+Linux::getRpath () {
+ local exe_file="${1}"
+
+ local exe_dir="$(dirname "${exe_file}")"
+ local path_start="$(printf '%s' "${bundle_dir}" | wc -c)"
+ path_start="$((${path_start} + 1))"
+
+ local exe_subdir="$(echo "${exe_dir}" | cut -c "${path_start}-" | _sed -e 's|//*|/|;s|^/||')"
+
+ local rpath_origin='$ORIGIN'
+
+ if [ "${exe_subdir}" = '' ]
+ then
+ printf '%s/lib\n' "${rpath_origin}"
+ else
+ if [ "${exe_subdir}" = 'lib' ]
+ then
+ printf '%s\n' "${rpath_origin}"
+ else
+ local num_parent_dir="$(echo "${exe_subdir}" | tr '/' '\n' | wc -l)"
+ local rpath_subdir
+ local i=0
+ while [ "${i}" -lt "${num_parent_dir}" ]
+ do
+ rpath_subdir="${rpath_subdir}/.."
+ i="$((${i} + 1))"
+ done
+ printf '%s%s/lib\n' "${rpath_origin}" "${rpath_subdir}"
+ fi
+ fi
+}
+
+Linux::patchExe () {
+ local exe_file="${1}"
+
+ local linux_rpath_string=$"$(Linux::getRpath "${exe_file}")"
+ patchelf --set-rpath "${linux_rpath_string}" "${exe_file}"
+}
+
+Linux::patchLib () {
+ local lib_dir="${1}"
+ local exe_file
+
+ find "${lib_dir}" \
+ -type f \
+ -name '*.so*' \
+ | while read exe_file
+ do
+ Linux::patchExe "${exe_file}"
+ done
+}
+
+Darwin::patchExe () {
+ local exe_file="${1}"
+
+ Multi::printLdd "${exe_file}" \
+ | Multi::filterLib \
+ | while read lib_file
+ do
+ new_path="$(echo "${lib_file}" | _sed -e 's|^/.*/lib/|@executable_path/lib/|')"
+ id_name="$(echo "${lib_file}" | _sed -e 's|.*/||g')"
+ chmod u+w,go-w "${exe_file}"
+ install_name_tool -change "${lib_file}" "${new_path}" "${exe_file}"
+ install_name_tool -id "${id_name}" "${exe_file}"
+ done
+}
+
+Darwin::patchLib () {
+ local lib_dir="${1}"
+ local exe_file
+
+ find "${lib_dir}" \
+ -type f \
+ \( \
+ -name '*.dylib' \
+ -o -name '*.so' \
+ \) \
+ | while read exe_file
+ do
+ Darwin::patchExe "${exe_file}"
+ chmod ugo-x "${exe_file}"
+ done
+}
+
+Windows::listLibForManifest () {
+ local lib_dir="${1}"
+
+ find "${lib_dir}" \
+ -maxdepth 1 \
+ -type f \
+ -name '*.dll' \
+ -exec basename {} \; \
+ | tr '\n' '\0' \
+ | xargs -0 -n1 -P1 -I{} \
+ printf ' <file name="{}"/>\n'
+}
+
+Windows::writeManifest () {
+ local lib_dir="${1}"
+
+ cat > "${manifest_file}" <<-EOF
+ <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <assemblyIdentity type="win32" name="lib" version="1.0.0.0"/>
+ $(Windows::listLibForManifest "${lib_dir}")
+ </assembly>
+ EOF
+}
+
+system_name="${1}"; shift
+bundle_dir="${1}"; shift
+
+if ! [ -z "${1}" ]
+then
+ exe_file="${1}"; shift
+fi
+
+bundle_dir="$(Common::getPath "${bundle_dir}")"
+registry_dir="${bundle_dir}/registry"
+lib_dir="${bundle_dir}/lib"
+
+manifest_file="${lib_dir}/lib.manifest"
+
+exe_action='Common::noOp'
+lib_action='Common::noOp'
+
+case "${system_name}" in
+ 'register')
+ mkdir -p "${registry_dir}"
+ Common::getPath "${exe_file}" > "${registry_dir}/$(uuidgen)"
+ exit
+ ;;
+ 'linux')
+ exe_action='Linux::patchExe'
+ lib_action='Linux::patchLib'
+ ;;
+ 'windows')
+ lib_action='Windows::writeManifest'
+ ;;
+ 'macos')
+ exe_action='Darwin::patchExe'
+ lib_action='Darwin::patchLib'