10 local file_path="${1}"
12 if command -v cygpath >/dev/null
14 if [ "${file_path}" = '-' ]
17 | xargs -0 -n1 -P1 -I{} \
20 cygpath --unix "${file_path}"
23 if [ "${file_path}" = '-' ]
27 printf '%s\n' "${file_path}"
38 sed -e 's/ (0x[0-9a-f]*)$//;s/^.* => //'
41 Multi::excludeLdd () {
42 case "${system_name}" in
44 # - always rely on up-to-date x11 and gl libraries, bundling them will break on future distros
45 # - gtk is not easily bundlable on linux because it looks for harcoded system path to optional
46 # shared libraries like image codecs, theme engines, sound notification system, etc.
47 # so expect user to install gtk first
48 # - since we ask user to instal gtk, we can also ask them to install gtkglext,
49 # which is likely to pull gtk itself, x11 and gl dependencies
50 # - old fontconfig does not work correctly if newer fontconfig configuration is installed
51 # - if gtk and fontconfig is installed, pango and freetype are
52 egrep -v '/libc\.|/libstdc\+\+\.|/libdl\.|/libm\.|/libX|/libxcb|/libGL|/libICE\.|/libSM\.|/libpthread\.' \
53 | egrep -v '/libatk|/libgdk|/libgtk|/libgio|/libglib|/libgmodule|/libgobject|/libcairo|/libpango|/libfontconfig|/libfreetype'
56 egrep -i '\.dll => [A-Z]:\\msys64\\' \
71 case "${system_name}" in
76 ntldd --recursive "${exe_file}"
81 Multi::getGtkThemeName () {
82 case "${system_name}" in
92 Multi::getGtkLibName () {
93 case "${system_name}" in
95 echo 'libgtk-x11-2.0.so.0'
98 echo 'libgtk-win32-2.0-0.dll'
103 Multi::getRootPrefix () {
104 local lib_file="${1}"
106 case "${system_name}" in
112 basename "${lib_file}" \
113 | xargs -n1 -P1 which \
119 Multi::getLibPrefix () {
120 local lib_file="${1}"
122 case "${system_name}" in
124 dirname "${lib_file}" \
133 Multi::getGtkDeps () {
134 local lib_prefix="${1}"
135 local gtk_theme_name="${2}"
138 share/themes/${gtk_theme_name}/gtk-2.0
140 ${lib_prefix}/gdk-pixbuf-2.0
141 ${lib_prefix}/gtk-2.0
144 case "${system_name}" in
147 ${lib_prefix}/libatk-bridge-2.0.so.0
148 ${lib_prefix}/libcanberra-0.30
149 ${lib_prefix}/libcanberra.so.0
150 ${lib_prefix}/libcanberra-gtk.so.0
156 Multi::bundleGtkDepsFromFile () {
157 local lib_file="${1}"
159 lib_basename="$(basename "${lib_file}")"
161 gtk_lib_name="$(Multi::getGtkLibName)"
162 if [ "${lib_basename}" = "${gtk_lib_name}" ]
164 root_prefix="$(Multi::getRootPrefix "${lib_file}")"
165 lib_prefix="$(Multi::getLibPrefix "${lib_file}")"
166 gtk_theme_name="$(Multi::getGtkThemeName)"
168 for component_dir in $(Multi::getGtkDeps "${lib_prefix}" "${gtk_theme_name}")
170 bundle_component_dir="$(echo "${component_dir}" | sed -e 's|^'"${lib_prefix}"'|lib|')"
171 if ! [ -e "${bundle_dir}/${bundle_component_dir}" ]
173 mkdir --parents "${bundle_dir}/$(dirname "${bundle_component_dir}")"
175 cp -H -r --preserve=timestamps \
176 "/${root_prefix}/${component_dir}" \
177 "${bundle_dir}/${bundle_component_dir}"
183 Multi::bundleLibFromFile () {
184 local exe_file="${1}"
186 Multi::printLdd "${exe_file}" \
188 | while read lib_file
190 lib_basename="$(basename "${lib_file}")"
192 if [ -f "${lib_dir}/${lib_basename}" ]
197 cp --preserve=timestamps \
199 "${lib_dir}/${lib_basename}"
201 Multi::bundleGtkDepsFromFile "${lib_file}"
206 find "${bundle_dir}/lib" \
211 find "${bundle_dir}/lib" \
216 find "${bundle_dir}/lib" \
219 -exec rmdir --ignore-fail-on-non-empty {} \;
223 local exe_file="${1}"
225 local exe_dir="$(dirname "${exe_file}")"
226 local path_start="$(printf '%s' "${bundle_dir}" | wc -c)"
227 path_start="$((${path_start} + 1))"
229 local exe_subdir="$(echo "${exe_dir}" | cut -c "${path_start}-" | sed -e 's|//*|/|;s|^/||')"
231 local rpath_origin='$ORIGIN'
233 if [ "${exe_subdir}" = '' ]
235 printf '%s/lib\n' "${rpath_origin}"
237 if [ "${exe_subdir}" = 'lib' ]
239 printf '%s\n' "${rpath_origin}"
241 local num_parent_dir="$(echo "${exe_subdir}" | tr '/' '\n' | wc -l)"
244 while [ "${i}" -lt "${num_parent_dir}" ]
246 rpath_subdir="${rpath_subdir}/.."
249 printf '%s%s/lib\n' "${rpath_origin}" "${rpath_subdir}"
255 local exe_file="${1}"
257 local linux_rpath_string=$"$(Linux::getRpath "${exe_file}")"
258 patchelf --set-rpath "${linux_rpath_string}" "${exe_file}"
268 | while read exe_file
270 Linux::patchExe "${exe_file}"
274 Windows::listLibForManifest () {
281 -exec basename {} \; \
283 | xargs -0 -n1 -P1 -I{} \
284 printf ' <file name="{}"/>\n'
287 Windows::writeManifest () {
290 cat > "${manifest_file}" <<-EOF
291 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
292 <assemblyIdentity type="win32" name="lib" version="1.0.0.0"/>
293 $(Windows::listLibForManifest "${lib_dir}")
298 system_name="${1}"; shift
299 bundle_dir="${1}"; shift
303 exe_file="${1}"; shift
306 bundle_dir="$(Common::getPath "${bundle_dir}")"
307 registry_dir="${bundle_dir}/registry"
308 lib_dir="${bundle_dir}/lib"
310 manifest_file="${lib_dir}/lib.manifest"
312 exe_action='Common::noOp'
313 lib_action='Common::noOp'
315 case "${system_name}" in
317 mkdir --parents "${registry_dir}"
318 Common::getPath "${exe_file}" > "${registry_dir}/$(uuidgen)"
322 exe_action='Linux::patchExe'
323 lib_action='Linux::patchLib'
326 lib_action='Windows::writeManifest'
329 printf 'ERROR: unsupported system: %s\n' "${system_name}" >&2
334 mkdir --parents "${lib_dir}"
336 if [ -d "${registry_dir}" ]
338 for registry_entry in "${registry_dir}"/*
340 exe_file="$(cat "${registry_entry}")"
342 Multi::bundleLibFromFile "${exe_file}"
344 "${exe_action}" "${exe_file}"
346 rm "${registry_entry}"
348 "${exe_action}" "${exe_file}"
351 rmdir "${registry_dir}"
354 "${lib_action}" "${lib_dir}"