]> git.xonotic.org Git - xonotic/netradiant.git/blob - library-bundler
0ef9567c3c4a91896c6b35e3ddeaad7e2a4e846a
[xonotic/netradiant.git] / library-bundler
1 #! /usr/bin/env bash
2
3 Common::noOp () {
4         printf ''
5 }
6
7 Common::getPath () {
8         local file_path="${1}"
9
10         if command -v cygpath >/dev/null
11         then
12                 if [ "${file_path}" = '-' ]
13                 then
14                         tr '\n' '\0' \
15                         | xargs -0 -n1 -P1 -I{} \
16                                 cygpath --unix '{}'
17                 else
18                         cygpath --unix "${file_path}"
19                 fi
20         else
21                 if [ "${file_path}" = '-' ]
22                 then
23                         cat
24                 else
25                         printf '%s\n' "${file_path}"
26                 fi
27         fi
28 }
29
30 Common::grepLdd () {
31         egrep ' => '
32 }
33
34 Common::stripLdd () {
35         sed -e 's/ (0x[0-9a-f]*)$//;s/^.* => //'
36 }
37
38 Multi::excludeLdd () {
39         case "${system_name}" in
40                 'windows')
41                         egrep -i '\.dll => [A-Z]:\\msys64\\' \
42                         ;;
43         esac
44 }
45
46 Multi::filterLib () {
47         Common::grepLdd \
48         | Multi::excludeLdd \
49         | Common::stripLdd \
50         | Common::getPath -
51 }
52
53 Multi::printLdd () {
54         local exe_file="${1}"
55
56         case "${system_name}" in
57                 'windows')
58                         ntldd --recursive "${exe_file}"
59                         ;;
60         esac
61 }
62
63 Multi::getGtkThemeName () {
64         case "${system_name}" in
65                 'windows')
66                         echo 'MS-Windows'
67                         ;;
68         esac
69 }
70
71 Multi::getGtkLibName () {
72         case "${system_name}" in
73                 'windows')
74                         echo 'libgtk-win32-2.0-0.dll'
75                         ;;
76         esac
77 }
78
79 Multi::getRootPrefix () {
80         local lib_file="${1}"
81
82         case "${system_name}" in
83                 'windows')
84                         basename "${lib_file}" \
85                         | xargs -n1 -P 1 which \
86                         | cut -f2 -d'/'
87                         ;;
88         esac
89 }
90
91 Multi::getLibPrefix () {
92         local lib_file="${1}"
93
94         case "${system_name}" in
95                 'windows')
96                         echo 'lib'
97                         ;;
98         esac
99 }
100
101 Multi::bundleGtkDepsFromFile () {
102         local lib_file="${1}"
103
104         lib_basename="$(basename "${lib_file}")"
105
106         gtk_lib_name="$(Multi::getGtkLibName)"
107         if [ "${lib_basename}" = "${gtk_lib_name}" ]
108         then
109                 root_prefix="$(Multi::getRootPrefix "${lib_file}")"
110                 lib_prefix="$(Multi::getLibPrefix "${lib_file}")"
111                 gtk_theme_name="$(Multi::getGtkThemeName)"
112
113                 for component_dir in \
114                         'share/themes/'"${gtk_theme_name}"'/gtk-2.0' \
115                         'share/icons/hicolor' \
116                         "${lib_prefix}"'/gdk-pixbuf-2.0' \
117                         "${lib_prefix}"'/gtk-2.0'
118                 do
119                         if ! [ -d "${bundle_dir}/${component_dir}" ]
120                         then
121                                 mkdir --parents "${bundle_dir}/$(dirname "${component_dir}")"
122
123                                 cp -r --preserve=timestamps \
124                                         "/${root_prefix}/${component_dir}" \
125                                         "${bundle_dir}/${component_dir}"
126                         fi
127                 done
128         fi
129 }
130
131 Multi::bundleLibFromFile () {
132         local exe_file="${1}"
133
134         Multi::printLdd "${exe_file}" \
135         | Multi::filterLib \
136         | while read lib_file
137         do
138                 lib_basename="$(basename "${lib_file}")"
139
140                 if [ -f "${bundle_dir}/${lib_basename}" ]
141                 then
142                         continue
143                 fi
144
145                 cp --preserve=timestamps \
146                         "${lib_file}" \
147                         "${lib_dir}/${lib_basename}"
148
149                 Multi::bundleGtkDepsFromFile "${lib_file}"
150         done
151 }
152
153 Multi::cleanUp () {
154         find "${bundle_dir}/lib" \
155                 -type f \
156                 -name '*.a' \
157                 -exec rm {} \;
158
159         find "${bundle_dir}/lib" \
160                 -type f \
161                 -name '*.h' \
162                 -exec rm {} \;
163
164         find "${bundle_dir}/lib" \
165                 -type d \
166                 -depth \
167                 -exec rmdir --ignore-fail-on-non-empty {} \;
168 }
169
170 Windows::listLibForManifest () {
171         local lib_dir="${1}"
172
173         find "${lib_dir}" \
174                 -maxdepth 1 \
175                 -type f \
176                 -name '*.dll' \
177                 -exec basename {} \; \
178         | tr '\n' '\0' \
179         | xargs -0 -n1 -P1 -I{} \
180                 printf '  <file name="{}"/>\n'
181 }
182
183 Windows::writeManifest () {
184         local lib_dir="${1}"
185
186         cat > "${manifest_file}" <<-EOF
187         <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
188           <assemblyIdentity type="win32" name="lib" version="1.0.0.0"/>
189         $(Windows::listLibForManifest "${lib_dir}")
190         </assembly>
191         EOF
192 }
193
194 system_name="${1}"; shift
195 bundle_dir="${1}"; shift
196 exe_file="${1}"; shift
197
198 bundle_dir="$(Common::getPath "${bundle_dir}")"
199 registry_dir="${bundle_dir}/registry"
200 lib_dir="${bundle_dir}/lib"
201
202 rpath_string='@executable_path:lib'
203
204 lib_action='Common::noOp'
205
206 case "${system_name}" in
207         'register')
208                 mkdir --parents "${registry_dir}"
209                 Common::getPath "${exe_file}" > "${registry_dir}/$(uuidgen)"
210                 exit
211                 ;;
212         'windows')
213                 lib_action='Windows::writeManifest'
214                 ;;
215         *)
216                 printf 'ERROR: unsupported system: %s\n' "${system_name}" >&2
217                 exit 1
218                 ;;
219 esac
220
221 mkdir --parents "${lib_dir}"
222
223 if [ -d "${registry_dir}" ]
224 then
225         for registry_entry in "${registry_dir}"/*
226         do
227                 exe_file="$(cat "${registry_entry}")"
228
229                 Multi::bundleLibFromFile "${exe_file}"
230
231                 "${exe_action}" "${exe_file}"
232
233                 rm "${registry_entry}"
234         done
235
236         rmdir "${registry_dir}"
237 fi
238
239 "${lib_action}" "${lib_dir}"
240
241 Multi::cleanUp