6 export LANGUAGE="${LANG}"
13 local file_path="${1}"
15 if command -v cygpath >/dev/null
17 if [ "${file_path}" = '-' ]
20 | xargs -0 -n1 -P1 -I{} \
23 cygpath --unix "${file_path}"
26 if [ "${file_path}" = '-' ]
30 printf '%s\n' "${file_path}"
41 sed -e 's/ (0x[0-9a-f]*)$//;s/^.* => //'
44 Multi::excludeLdd () {
45 case "${system_name}" in
47 # - always rely on up-to-date x11 and gl libraries, bundling them will break on future distros
48 # - gtk is not easily bundlable on linux because it looks for harcoded system path to optional
49 # shared libraries like image codecs, theme engines, sound notification system, etc.
50 # so expect user to install gtk first
51 # - since we ask user to instal gtk, we can also ask them to install gtkglext,
52 # which is likely to pull gtk itself, x11 and gl dependencies
53 # - old fontconfig does not work correctly if newer fontconfig configuration is installed
54 # - if gtk and fontconfig is installed, pango and freetype are
55 egrep -v '/libc\.|/libstdc\+\+\.|/libdl\.|/libm\.|/libX|/libxcb|/libGL|/libICE\.|/libSM\.|/libpthread\.' \
56 | egrep -v '/libatk|/libgdk|/libgtk|/libgio|/libglib|/libgmodule|/libgobject|/libcairo|/libpango|/libfontconfig|/libfreetype'
59 egrep -i '\.dll => [A-Z]:\\msys64\\'
74 case "${system_name}" in
79 ntldd --recursive "${exe_file}"
84 Multi::getGtkThemeName () {
85 case "${system_name}" in
95 Multi::getGtkLibName () {
96 case "${system_name}" in
98 echo 'libgtk-x11-2.0.so.0'
101 echo 'libgtk-win32-2.0-0.dll'
106 Multi::getRootPrefix () {
107 local lib_file="${1}"
109 case "${system_name}" in
115 basename "${lib_file}" \
116 | xargs -n1 -P1 which \
122 Multi::getLibPrefix () {
123 local lib_file="${1}"
125 case "${system_name}" in
127 dirname "${lib_file}" \
136 Multi::getGtkDeps () {
137 local lib_prefix="${1}"
138 local gtk_theme_name="${2}"
141 share/themes/${gtk_theme_name}/gtk-2.0
143 ${lib_prefix}/gdk-pixbuf-2.0
144 ${lib_prefix}/gtk-2.0
147 case "${system_name}" in
150 ${lib_prefix}/libatk-bridge-2.0.so.0
151 ${lib_prefix}/libcanberra-0.30
152 ${lib_prefix}/libcanberra.so.0
153 ${lib_prefix}/libcanberra-gtk.so.0
159 Multi::bundleGtkDepsFromFile () {
160 local lib_file="${1}"
162 lib_basename="$(basename "${lib_file}")"
164 gtk_lib_name="$(Multi::getGtkLibName)"
165 if [ "${lib_basename}" = "${gtk_lib_name}" ]
167 root_prefix="$(Multi::getRootPrefix "${lib_file}")"
168 lib_prefix="$(Multi::getLibPrefix "${lib_file}")"
169 gtk_theme_name="$(Multi::getGtkThemeName)"
171 for component_dir in $(Multi::getGtkDeps "${lib_prefix}" "${gtk_theme_name}")
173 bundle_component_dir="$(echo "${component_dir}" | sed -e 's|^'"${lib_prefix}"'|lib|')"
174 if ! [ -e "${bundle_dir}/${bundle_component_dir}" ]
176 mkdir --parents "${bundle_dir}/$(dirname "${bundle_component_dir}")"
178 cp -H -r --preserve=timestamps \
179 "/${root_prefix}/${component_dir}" \
180 "${bundle_dir}/${bundle_component_dir}"
186 Multi::bundleLibFromFile () {
187 local exe_file="${1}"
190 Multi::printLdd "${exe_file}" \
192 | while read lib_file
194 if [ "${lib_file}" = 'not found' ]
196 printf 'ERROR: library not found while bundling %s (but link worked)\n' "${exe_file}" >&2
197 Multi::printLdd "${exe_file}" | grep 'not found'
200 lib_basename="$(basename "${lib_file}")"
202 if [ -f "${lib_dir}/${lib_basename}" ]
207 cp --preserve=timestamps \
209 "${lib_dir}/${lib_basename}"
211 Multi::bundleGtkDepsFromFile "${lib_file}"
216 find "${bundle_dir}/lib" \
221 find "${bundle_dir}/lib" \
226 find "${bundle_dir}/lib" \
229 -exec rmdir --ignore-fail-on-non-empty {} \;
233 local exe_file="${1}"
235 local exe_dir="$(dirname "${exe_file}")"
236 local path_start="$(printf '%s' "${bundle_dir}" | wc -c)"
237 path_start="$((${path_start} + 1))"
239 local exe_subdir="$(echo "${exe_dir}" | cut -c "${path_start}-" | sed -e 's|//*|/|;s|^/||')"
241 local rpath_origin='$ORIGIN'
243 if [ "${exe_subdir}" = '' ]
245 printf '%s/lib\n' "${rpath_origin}"
247 if [ "${exe_subdir}" = 'lib' ]
249 printf '%s\n' "${rpath_origin}"
251 local num_parent_dir="$(echo "${exe_subdir}" | tr '/' '\n' | wc -l)"
254 while [ "${i}" -lt "${num_parent_dir}" ]
256 rpath_subdir="${rpath_subdir}/.."
259 printf '%s%s/lib\n' "${rpath_origin}" "${rpath_subdir}"
265 local exe_file="${1}"
267 local linux_rpath_string=$"$(Linux::getRpath "${exe_file}")"
268 patchelf --set-rpath "${linux_rpath_string}" "${exe_file}"
278 | while read exe_file
280 Linux::patchExe "${exe_file}"
284 Windows::listLibForManifest () {
291 -exec basename {} \; \
293 | xargs -0 -n1 -P1 -I{} \
294 printf ' <file name="{}"/>\n'
297 Windows::writeManifest () {
300 cat > "${manifest_file}" <<-EOF
301 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
302 <assemblyIdentity type="win32" name="lib" version="1.0.0.0"/>
303 $(Windows::listLibForManifest "${lib_dir}")
308 system_name="${1}"; shift
309 bundle_dir="${1}"; shift
313 exe_file="${1}"; shift
316 bundle_dir="$(Common::getPath "${bundle_dir}")"
317 registry_dir="${bundle_dir}/registry"
318 lib_dir="${bundle_dir}/lib"
320 manifest_file="${lib_dir}/lib.manifest"
322 exe_action='Common::noOp'
323 lib_action='Common::noOp'
325 case "${system_name}" in
327 mkdir --parents "${registry_dir}"
328 Common::getPath "${exe_file}" > "${registry_dir}/$(uuidgen)"
332 exe_action='Linux::patchExe'
333 lib_action='Linux::patchLib'
336 lib_action='Windows::writeManifest'
339 printf 'ERROR: unsupported system: %s\n' "${system_name}" >&2
344 mkdir --parents "${lib_dir}"
346 if [ -d "${registry_dir}" ]
348 for registry_entry in "${registry_dir}"/*
350 exe_file="$(cat "${registry_entry}")"
352 Multi::bundleLibFromFile "${exe_file}"
354 "${exe_action}" "${exe_file}"
356 rm "${registry_entry}"
358 "${exe_action}" "${exe_file}"
361 rmdir "${registry_dir}"
364 "${lib_action}" "${lib_dir}"