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}"
35 sed -e 's/ (0x[0-9a-f]*)$//;s/^.* => //'
38 Multi::excludeLdd () {
39 case "${system_name}" in
41 # - always rely on up-to-date x11 and gl libraries, bundling them will break on future distros
42 # - gtk is not easily bundlable on linux because it looks for harcoded system path to optional
43 # shared libraries like image codecs, theme engines, sound notification system, etc.
44 # so expect user to install gtk first
45 # - since we ask user to instal gtk, we can also ask them to install gtkglext,
46 # which is likely to pull gtk itself, x11 and gl dependencies
47 # - old fontconfig does not work correctly if newer fontconfig configuration is installed
48 # - if gtk and fontconfig is installed, freetype is
49 egrep -v '/libc\.|/libdl\.|/libm\.|/libX|/libxcb|/libGL' \
50 | egrep -v '/libatk|/libgdk|/libgtk|/libgio|/libglib|/libgmodule|/libgobject|/libfontconfig|/libfreetype'
53 egrep -i '\.dll => [A-Z]:\\msys64\\' \
68 case "${system_name}" in
73 ntldd --recursive "${exe_file}"
78 Multi::getGtkThemeName () {
79 case "${system_name}" in
89 Multi::getGtkLibName () {
90 case "${system_name}" in
92 echo 'libgtk-x11-2.0.so.0'
95 echo 'libgtk-win32-2.0-0.dll'
100 Multi::getRootPrefix () {
101 local lib_file="${1}"
103 case "${system_name}" in
109 basename "${lib_file}" \
110 | xargs -n1 -P 1 which \
116 Multi::getLibPrefix () {
117 local lib_file="${1}"
119 case "${system_name}" in
121 dirname "${lib_file}" \
130 Multi::getGtkDeps () {
131 local lib_prefix="${1}"
132 local gtk_theme_name="${2}"
135 share/themes/${gtk_theme_name}/gtk-2.0
137 ${lib_prefix}/gdk-pixbuf-2.0
138 ${lib_prefix}/gtk-2.0
141 case "${system_name}" in
144 ${lib_prefix}/libatk-bridge-2.0.so.0
145 ${lib_prefix}/libcanberra-0.30
146 ${lib_prefix}/libcanberra.so.0
147 ${lib_prefix}/libcanberra-gtk.so.0
153 Multi::bundleGtkDepsFromFile () {
154 local lib_file="${1}"
156 lib_basename="$(basename "${lib_file}")"
158 gtk_lib_name="$(Multi::getGtkLibName)"
159 if [ "${lib_basename}" = "${gtk_lib_name}" ]
161 root_prefix="$(Multi::getRootPrefix "${lib_file}")"
162 lib_prefix="$(Multi::getLibPrefix "${lib_file}")"
163 gtk_theme_name="$(Multi::getGtkThemeName)"
165 for component_dir in $(Multi::getGtkDeps "${lib_prefix}" "${gtk_theme_name}")
167 bundle_component_dir="$(echo "${component_dir}" | sed -e 's|^'"${lib_prefix}"'|lib|')"
168 if ! [ -e "${bundle_dir}/${bundle_component_dir}" ]
170 mkdir --parents "${bundle_dir}/$(dirname "${bundle_component_dir}")"
172 cp -H -r --preserve=timestamps \
173 "/${root_prefix}/${component_dir}" \
174 "${bundle_dir}/${bundle_component_dir}"
180 Multi::bundleLibFromFile () {
181 local exe_file="${1}"
183 Multi::printLdd "${exe_file}" \
185 | while read lib_file
187 lib_basename="$(basename "${lib_file}")"
189 if [ -f "${bundle_dir}/${lib_basename}" ]
194 cp --preserve=timestamps \
196 "${lib_dir}/${lib_basename}"
198 Multi::bundleGtkDepsFromFile "${lib_file}"
203 find "${bundle_dir}/lib" \
208 find "${bundle_dir}/lib" \
213 find "${bundle_dir}/lib" \
216 -exec rmdir --ignore-fail-on-non-empty {} \;
220 local exe_file="${1}"
222 patchelf --set-rpath "${rpath_string}" "${exe_file}"
231 -exec patchelf --set-rpath "${rpath_string}" {} \;
234 Windows::listLibForManifest () {
241 -exec basename {} \; \
243 | xargs -0 -n1 -P1 -I{} \
244 printf ' <file name="{}"/>\n'
247 Windows::writeManifest () {
250 cat > "${manifest_file}" <<-EOF
251 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
252 <assemblyIdentity type="win32" name="lib" version="1.0.0.0"/>
253 $(Windows::listLibForManifest "${lib_dir}")
258 system_name="${1}"; shift
259 bundle_dir="${1}"; shift
260 exe_file="${1}"; shift
262 bundle_dir="$(Common::getPath "${bundle_dir}")"
263 registry_dir="${bundle_dir}/registry"
264 lib_dir="${bundle_dir}/lib"
266 manifest_file="${lib_dir}/lib.manifest"
268 rpath_string='@executable_path:lib'
270 exe_action='Common::noOp'
271 lib_action='Common::noOp'
273 case "${system_name}" in
275 mkdir --parents "${registry_dir}"
276 Common::getPath "${exe_file}" > "${registry_dir}/$(uuidgen)"
280 exe_action='Linux::patchExe'
281 lib_action='Linux::patchLib'
284 lib_action='Windows::writeManifest'
287 printf 'ERROR: unsupported system: %s\n' "${system_name}" >&2
292 mkdir --parents "${lib_dir}"
294 if [ -d "${registry_dir}" ]
296 for registry_entry in "${registry_dir}"/*
298 exe_file="$(cat "${registry_entry}")"
300 Multi::bundleLibFromFile "${exe_file}"
302 "${exe_action}" "${exe_file}"
304 rm "${registry_entry}"
306 "${exe_action}" "${exe_file}"
309 rmdir "${registry_dir}"
312 "${lib_action}" "${lib_dir}"