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 bundle built-in libraries
48 # - always rely on up-to-date x11 and gl libraries, bundling them will break on future distros
49 # - gtk is not easily bundlable on linux because it looks for harcoded system path to optional
50 # shared libraries like image codecs, theme engines, sound notification system, etc.
51 # so expect user to install gtk first
52 # - since we ask user to instal gtk, we can also ask them to install gtkglext,
53 # which is likely to pull gtk itself, x11 and gl dependencies
54 # - old fontconfig does not work correctly if newer fontconfig configuration is installed
55 # - if gtk and fontconfig is installed, pango and freetype are
59 if echo "${ldd_line}" | egrep '/builtins/'
62 elif echo "${ldd_line}" \
63 | egrep -q '/libc\.|/libstdc\+\+\.|/libdl\.|/libm\.|/libX|/libxcb|/libGL|/libICE\.|/libSM\.|/libpthread\.'
66 elif echo "${ldd_line}" \
67 | egrep -q '/libatk|/libgdk|/libgtk|/libgio|/libglib|/libgmodule|/libgobject|/libcairo|/libpango|/libfontconfig|/libfreetype'
76 egrep -i '\.dll => [A-Z]:\\msys64\\'
91 case "${system_name}" in
96 ntldd --recursive "${exe_file}"
101 Multi::getGtkThemeName () {
102 case "${system_name}" in
112 Multi::getGtkLibName () {
113 case "${system_name}" in
115 echo 'libgtk-x11-2.0.so.0'
118 echo 'libgtk-win32-2.0-0.dll'
123 Multi::getRootPrefix () {
124 local lib_file="${1}"
126 case "${system_name}" in
132 basename "${lib_file}" \
133 | xargs -n1 -P1 which \
139 Multi::getLibPrefix () {
140 local lib_file="${1}"
142 case "${system_name}" in
144 dirname "${lib_file}" \
153 Multi::getGtkDeps () {
154 local lib_prefix="${1}"
155 local gtk_theme_name="${2}"
158 share/themes/${gtk_theme_name}/gtk-2.0
160 ${lib_prefix}/gdk-pixbuf-2.0
161 ${lib_prefix}/gtk-2.0
164 case "${system_name}" in
167 ${lib_prefix}/libatk-bridge-2.0.so.0
168 ${lib_prefix}/libcanberra-0.30
169 ${lib_prefix}/libcanberra.so.0
170 ${lib_prefix}/libcanberra-gtk.so.0
176 Multi::bundleGtkDepsFromFile () {
177 local lib_file="${1}"
179 lib_basename="$(basename "${lib_file}")"
181 gtk_lib_name="$(Multi::getGtkLibName)"
182 if [ "${lib_basename}" = "${gtk_lib_name}" ]
184 root_prefix="$(Multi::getRootPrefix "${lib_file}")"
185 lib_prefix="$(Multi::getLibPrefix "${lib_file}")"
186 gtk_theme_name="$(Multi::getGtkThemeName)"
188 for component_dir in $(Multi::getGtkDeps "${lib_prefix}" "${gtk_theme_name}")
190 bundle_component_dir="$(echo "${component_dir}" | sed -e 's|^'"${lib_prefix}"'|lib|')"
191 if ! [ -e "${bundle_dir}/${bundle_component_dir}" ]
193 mkdir --parents "${bundle_dir}/$(dirname "${bundle_component_dir}")"
195 cp -H -r --preserve=timestamps \
196 "/${root_prefix}/${component_dir}" \
197 "${bundle_dir}/${bundle_component_dir}"
203 Multi::bundleLibFromFile () {
204 local exe_file="${1}"
207 Multi::printLdd "${exe_file}" \
209 | while read lib_file
211 if [ "${lib_file}" = 'not found' ]
213 printf 'ERROR: library not found while bundling %s (but link worked)\n' "${exe_file}" >&2
214 Multi::printLdd "${exe_file}" | grep 'not found'
217 lib_basename="$(basename "${lib_file}")"
219 if [ -f "${lib_dir}/${lib_basename}" ]
224 cp --preserve=timestamps \
226 "${lib_dir}/${lib_basename}"
228 Multi::bundleGtkDepsFromFile "${lib_file}"
233 find "${bundle_dir}/lib" \
238 find "${bundle_dir}/lib" \
243 find "${bundle_dir}/lib" \
246 -exec rmdir --ignore-fail-on-non-empty {} \;
250 local exe_file="${1}"
252 local exe_dir="$(dirname "${exe_file}")"
253 local path_start="$(printf '%s' "${bundle_dir}" | wc -c)"
254 path_start="$((${path_start} + 1))"
256 local exe_subdir="$(echo "${exe_dir}" | cut -c "${path_start}-" | sed -e 's|//*|/|;s|^/||')"
258 local rpath_origin='$ORIGIN'
260 if [ "${exe_subdir}" = '' ]
262 printf '%s/lib\n' "${rpath_origin}"
264 if [ "${exe_subdir}" = 'lib' ]
266 printf '%s\n' "${rpath_origin}"
268 local num_parent_dir="$(echo "${exe_subdir}" | tr '/' '\n' | wc -l)"
271 while [ "${i}" -lt "${num_parent_dir}" ]
273 rpath_subdir="${rpath_subdir}/.."
276 printf '%s%s/lib\n' "${rpath_origin}" "${rpath_subdir}"
282 local exe_file="${1}"
284 local linux_rpath_string=$"$(Linux::getRpath "${exe_file}")"
285 patchelf --set-rpath "${linux_rpath_string}" "${exe_file}"
295 | while read exe_file
297 Linux::patchExe "${exe_file}"
301 Windows::listLibForManifest () {
308 -exec basename {} \; \
310 | xargs -0 -n1 -P1 -I{} \
311 printf ' <file name="{}"/>\n'
314 Windows::writeManifest () {
317 cat > "${manifest_file}" <<-EOF
318 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
319 <assemblyIdentity type="win32" name="lib" version="1.0.0.0"/>
320 $(Windows::listLibForManifest "${lib_dir}")
325 system_name="${1}"; shift
326 bundle_dir="${1}"; shift
330 exe_file="${1}"; shift
333 bundle_dir="$(Common::getPath "${bundle_dir}")"
334 registry_dir="${bundle_dir}/registry"
335 lib_dir="${bundle_dir}/lib"
337 manifest_file="${lib_dir}/lib.manifest"
339 exe_action='Common::noOp'
340 lib_action='Common::noOp'
342 case "${system_name}" in
344 mkdir --parents "${registry_dir}"
345 Common::getPath "${exe_file}" > "${registry_dir}/$(uuidgen)"
349 exe_action='Linux::patchExe'
350 lib_action='Linux::patchLib'
353 lib_action='Windows::writeManifest'
356 printf 'ERROR: unsupported system: %s\n' "${system_name}" >&2
361 mkdir --parents "${lib_dir}"
363 if [ -d "${registry_dir}" ]
365 for registry_entry in "${registry_dir}"/*
367 exe_file="$(cat "${registry_entry}")"
369 Multi::bundleLibFromFile "${exe_file}"
371 "${exe_action}" "${exe_file}"
373 rm "${registry_entry}"
375 "${exe_action}" "${exe_file}"
378 rmdir "${registry_dir}"
381 "${lib_action}" "${lib_dir}"