10 if command -v cygpath >/dev/null
12 if [ "${file_path}" = '-' ]
15 | xargs -0 -n1 -P1 -I{} \
18 cygpath --unix "${file_path}"
21 if [ "${file_path}" = '-' ]
25 printf '%s\n' "${file_path}"
36 sed -e 's/ (0x[0-9a-f]*)$//;s/^.* => //'
39 Multi::excludeLdd () {
40 case "${system_name}" in
42 # - always rely on up-to-date x11 and gl libraries, bundling them will break on future distros
43 # - gtk is not easily bundlable on linux because it looks for harcoded system path to optional
44 # shared libraries like image codecs, theme engines, sound notification system, etc.
45 # so expect user to install gtk first
46 # - since we ask user to instal gtk, we can also ask them to install gtkglext,
47 # which is likely to pull gtk itself, x11 and gl dependencies
48 # - old fontconfig does not work correctly if newer fontconfig configuration is installed
49 # - if gtk and fontconfig is installed, pango and freetype are
50 egrep -v '/libc\.|/libstdc\+\+\.|/libdl\.|/libm\.|/libX|/libxcb|/libGL|/libICE\.|/libSM\.|/libpthread\.' \
51 | egrep -v '/libatk|/libgdk|/libgtk|/libgio|/libglib|/libgmodule|/libgobject|/libcairo|/libpango|/libfontconfig|/libfreetype'
54 egrep -i '\.dll => [A-Z]:\\msys64\\' \
69 case "${system_name}" in
74 ntldd --recursive "${exe_file}"
79 Multi::getGtkThemeName () {
80 case "${system_name}" in
90 Multi::getGtkLibName () {
91 case "${system_name}" in
93 echo 'libgtk-x11-2.0.so.0'
96 echo 'libgtk-win32-2.0-0.dll'
101 Multi::getRootPrefix () {
102 local lib_file="${1}"
104 case "${system_name}" in
110 basename "${lib_file}" \
111 | xargs -n1 -P 1 which \
117 Multi::getLibPrefix () {
118 local lib_file="${1}"
120 case "${system_name}" in
122 dirname "${lib_file}" \
131 Multi::getGtkDeps () {
132 local lib_prefix="${1}"
133 local gtk_theme_name="${2}"
136 share/themes/${gtk_theme_name}/gtk-2.0
138 ${lib_prefix}/gdk-pixbuf-2.0
139 ${lib_prefix}/gtk-2.0
142 case "${system_name}" in
145 ${lib_prefix}/libatk-bridge-2.0.so.0
146 ${lib_prefix}/libcanberra-0.30
147 ${lib_prefix}/libcanberra.so.0
148 ${lib_prefix}/libcanberra-gtk.so.0
154 Multi::bundleGtkDepsFromFile () {
155 local lib_file="${1}"
157 lib_basename="$(basename "${lib_file}")"
159 gtk_lib_name="$(Multi::getGtkLibName)"
160 if [ "${lib_basename}" = "${gtk_lib_name}" ]
162 root_prefix="$(Multi::getRootPrefix "${lib_file}")"
163 lib_prefix="$(Multi::getLibPrefix "${lib_file}")"
164 gtk_theme_name="$(Multi::getGtkThemeName)"
166 for component_dir in $(Multi::getGtkDeps "${lib_prefix}" "${gtk_theme_name}")
168 bundle_component_dir="$(echo "${component_dir}" | sed -e 's|^'"${lib_prefix}"'|lib|')"
169 if ! [ -e "${bundle_dir}/${bundle_component_dir}" ]
171 mkdir --parents "${bundle_dir}/$(dirname "${bundle_component_dir}")"
173 cp -H -r --preserve=timestamps \
174 "/${root_prefix}/${component_dir}" \
175 "${bundle_dir}/${bundle_component_dir}"
181 Multi::bundleLibFromFile () {
182 local exe_file="${1}"
184 Multi::printLdd "${exe_file}" \
186 | while read lib_file
188 lib_basename="$(basename "${lib_file}")"
190 if [ -f "${lib_dir}/${lib_basename}" ]
195 cp --preserve=timestamps \
197 "${lib_dir}/${lib_basename}"
199 Multi::bundleGtkDepsFromFile "${lib_file}"
204 find "${bundle_dir}/lib" \
209 find "${bundle_dir}/lib" \
214 find "${bundle_dir}/lib" \
217 -exec rmdir --ignore-fail-on-non-empty {} \;
221 local exe_file="${1}"
223 local exe_dir="$(dirname "${exe_file}")"
224 local path_start="$(printf '%s' "${bundle_dir}" | wc -c)"
225 path_start="$((${path_start} + 1))"
227 local exe_subdir="$(echo "${exe_dir}" | cut -c "${path_start}-" | sed -e 's|//*|/|;s|^/||')"
229 local rpath_origin='$ORIGIN'
231 if [ "${exe_subdir}" = '' ]
233 printf '%s/lib\n' "${rpath_origin}"
235 if [ "${exe_subdir}" = 'lib' ]
237 printf '%s\n' "${rpath_origin}"
239 local num_parent_dir="$(echo "${exe_subdir}" | tr '/' '\n' | wc -l)"
242 while [ "${i}" -lt "${num_parent_dir}" ]
244 rpath_subdir="${rpath_subdir}/.."
247 printf '%s%s/lib\n' "${rpath_origin}" "${rpath_subdir}"
253 local exe_file="${1}"
255 local linux_rpath_string=$"$(Linux::getRpath "${exe_file}")"
256 patchelf --set-rpath "${linux_rpath_string}" "${exe_file}"
266 | while read exe_file
268 Linux::patchExe "${exe_file}"
272 Windows::listLibForManifest () {
279 -exec basename {} \; \
281 | xargs -0 -n1 -P1 -I{} \
282 printf ' <file name="{}"/>\n'
285 Windows::writeManifest () {
288 cat > "${manifest_file}" <<-EOF
289 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
290 <assemblyIdentity type="win32" name="lib" version="1.0.0.0"/>
291 $(Windows::listLibForManifest "${lib_dir}")
296 system_name="${1}"; shift
297 bundle_dir="${1}"; shift
298 exe_file="${1}"; shift
300 bundle_dir="$(Common::getPath "${bundle_dir}")"
301 registry_dir="${bundle_dir}/registry"
302 lib_dir="${bundle_dir}/lib"
304 manifest_file="${lib_dir}/lib.manifest"
306 exe_action='Common::noOp'
307 lib_action='Common::noOp'
309 case "${system_name}" in
311 mkdir --parents "${registry_dir}"
312 Common::getPath "${exe_file}" > "${registry_dir}/$(uuidgen)"
316 exe_action='Linux::patchExe'
317 lib_action='Linux::patchLib'
320 lib_action='Windows::writeManifest'
323 printf 'ERROR: unsupported system: %s\n' "${system_name}" >&2
328 mkdir --parents "${lib_dir}"
330 if [ -d "${registry_dir}" ]
332 for registry_entry in "${registry_dir}"/*
334 exe_file="$(cat "${registry_entry}")"
336 Multi::bundleLibFromFile "${exe_file}"
338 "${exe_action}" "${exe_file}"
340 rm "${registry_entry}"
342 "${exe_action}" "${exe_file}"
345 rmdir "${registry_dir}"
348 "${lib_action}" "${lib_dir}"