X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=library-bundler;h=d5a439716aa88b950d24cd85b165a7a5e196faf2;hp=0ef9567c3c4a91896c6b35e3ddeaad7e2a4e846a;hb=1c5f9677125c9f218810c148b2e41911ebc7a9e7;hpb=2a499e0cea34582a9cb47d581c302edd49202fce diff --git a/library-bundler b/library-bundler index 0ef9567c..d5a43971 100755 --- a/library-bundler +++ b/library-bundler @@ -1,7 +1,9 @@ #! /usr/bin/env bash +set -e + Common::noOp () { - printf '' + true } Common::getPath () { @@ -24,7 +26,8 @@ Common::getPath () { else printf '%s\n' "${file_path}" fi - fi + fi \ + | sed -e 's|/*$||' } Common::grepLdd () { @@ -37,6 +40,18 @@ Common::stripLdd () { Multi::excludeLdd () { case "${system_name}" in + 'linux') + # - always rely on up-to-date x11 and gl libraries, bundling them will break on future distros + # - gtk is not easily bundlable on linux because it looks for harcoded system path to optional + # shared libraries like image codecs, theme engines, sound notification system, etc. + # so expect user to install gtk first + # - since we ask user to instal gtk, we can also ask them to install gtkglext, + # which is likely to pull gtk itself, x11 and gl dependencies + # - old fontconfig does not work correctly if newer fontconfig configuration is installed + # - if gtk and fontconfig is installed, pango and freetype are + egrep -v '/libc\.|/libstdc\+\+\.|/libdl\.|/libm\.|/libX|/libxcb|/libGL|/libICE\.|/libSM\.|/libpthread\.' \ + | egrep -v '/libatk|/libgdk|/libgtk|/libgio|/libglib|/libgmodule|/libgobject|/libcairo|/libpango|/libfontconfig|/libfreetype' + ;; 'windows') egrep -i '\.dll => [A-Z]:\\msys64\\' \ ;; @@ -54,6 +69,9 @@ Multi::printLdd () { local exe_file="${1}" case "${system_name}" in + 'linux') + ldd "${exe_file}" + ;; 'windows') ntldd --recursive "${exe_file}" ;; @@ -62,6 +80,9 @@ Multi::printLdd () { Multi::getGtkThemeName () { case "${system_name}" in + 'linux') + echo 'Adwaita' + ;; 'windows') echo 'MS-Windows' ;; @@ -70,6 +91,9 @@ Multi::getGtkThemeName () { Multi::getGtkLibName () { case "${system_name}" in + 'linux') + echo 'libgtk-x11-2.0.so.0' + ;; 'windows') echo 'libgtk-win32-2.0-0.dll' ;; @@ -80,9 +104,13 @@ Multi::getRootPrefix () { local lib_file="${1}" case "${system_name}" in + 'linux') + echo "${lib_file}" \ + | cut -f2 -d'/' + ;; 'windows') basename "${lib_file}" \ - | xargs -n1 -P 1 which \ + | xargs -n1 -P1 which \ | cut -f2 -d'/' ;; esac @@ -92,12 +120,39 @@ Multi::getLibPrefix () { local lib_file="${1}" case "${system_name}" in + 'linux') + dirname "${lib_file}" \ + | cut -f3- -d'/' + ;; 'windows') echo 'lib' ;; esac } +Multi::getGtkDeps () { + local lib_prefix="${1}" + local gtk_theme_name="${2}" + + cat <<-EOF + share/themes/${gtk_theme_name}/gtk-2.0 + share/icons/hicolor + ${lib_prefix}/gdk-pixbuf-2.0 + ${lib_prefix}/gtk-2.0 + EOF + + case "${system_name}" in + 'linux') + cat <<-EOF + ${lib_prefix}/libatk-bridge-2.0.so.0 + ${lib_prefix}/libcanberra-0.30 + ${lib_prefix}/libcanberra.so.0 + ${lib_prefix}/libcanberra-gtk.so.0 + EOF + ;; + esac +} + Multi::bundleGtkDepsFromFile () { local lib_file="${1}" @@ -110,19 +165,16 @@ Multi::bundleGtkDepsFromFile () { lib_prefix="$(Multi::getLibPrefix "${lib_file}")" gtk_theme_name="$(Multi::getGtkThemeName)" - for component_dir in \ - 'share/themes/'"${gtk_theme_name}"'/gtk-2.0' \ - 'share/icons/hicolor' \ - "${lib_prefix}"'/gdk-pixbuf-2.0' \ - "${lib_prefix}"'/gtk-2.0' + for component_dir in $(Multi::getGtkDeps "${lib_prefix}" "${gtk_theme_name}") do - if ! [ -d "${bundle_dir}/${component_dir}" ] + bundle_component_dir="$(echo "${component_dir}" | sed -e 's|^'"${lib_prefix}"'|lib|')" + if ! [ -e "${bundle_dir}/${bundle_component_dir}" ] then - mkdir --parents "${bundle_dir}/$(dirname "${component_dir}")" + mkdir --parents "${bundle_dir}/$(dirname "${bundle_component_dir}")" - cp -r --preserve=timestamps \ + cp -H -r --preserve=timestamps \ "/${root_prefix}/${component_dir}" \ - "${bundle_dir}/${component_dir}" + "${bundle_dir}/${bundle_component_dir}" fi done fi @@ -137,7 +189,7 @@ Multi::bundleLibFromFile () { do lib_basename="$(basename "${lib_file}")" - if [ -f "${bundle_dir}/${lib_basename}" ] + if [ -f "${lib_dir}/${lib_basename}" ] then continue fi @@ -162,11 +214,63 @@ Multi::cleanUp () { -exec rm {} \; find "${bundle_dir}/lib" \ - -type d \ -depth \ + -type d \ -exec rmdir --ignore-fail-on-non-empty {} \; } +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 +} + Windows::listLibForManifest () { local lib_dir="${1}" @@ -193,14 +297,19 @@ Windows::writeManifest () { system_name="${1}"; shift bundle_dir="${1}"; shift -exe_file="${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" -rpath_string='@executable_path:lib' +manifest_file="${lib_dir}/lib.manifest" +exe_action='Common::noOp' lib_action='Common::noOp' case "${system_name}" in @@ -209,6 +318,10 @@ case "${system_name}" in Common::getPath "${exe_file}" > "${registry_dir}/$(uuidgen)" exit ;; + 'linux') + exe_action='Linux::patchExe' + lib_action='Linux::patchLib' + ;; 'windows') lib_action='Windows::writeManifest' ;; @@ -231,6 +344,8 @@ then "${exe_action}" "${exe_file}" rm "${registry_entry}" + + "${exe_action}" "${exe_file}" done rmdir "${registry_dir}"