]>
Commit | Line | Data |
---|---|---|
1f369f0c UH |
1 | # This file is supposed to be sourced by each Recipe |
2 | # that wants to use the functions contained herein | |
3 | # like so: | |
ca369dfa | 4 | # wget -q https://github.com/AppImage/AppImages/raw/${PKG2AICOMMIT}/functions.sh -O ./functions.sh |
1f369f0c UH |
5 | # . ./functions.sh |
6 | ||
7 | # RECIPE=$(realpath "$0") | |
8 | ||
ca369dfa UH |
9 | # Specify a certain commit if you do not want to use master |
10 | # by using: | |
11 | # export PKG2AICOMMIT=<git sha> | |
12 | if [ -z "$PKG2AICOMMIT" ] ; then | |
13 | PKG2AICOMMIT=master | |
14 | fi | |
15 | ||
1f369f0c UH |
16 | # Options for apt-get to use local files rather than the system ones |
17 | OPTIONS="-o Debug::NoLocking=1 | |
18 | -o APT::Cache-Limit=125829120 | |
19 | -o Dir::Etc::sourcelist=./sources.list | |
20 | -o Dir::State=./tmp | |
21 | -o Dir::Cache=./tmp | |
22 | -o Dir::State::status=./status | |
23 | -o Dir::Etc::sourceparts=- | |
24 | -o APT::Get::List-Cleanup=0 | |
25 | -o APT::Get::AllowUnauthenticated=1 | |
26 | -o Debug::pkgProblemResolver=true | |
27 | -o Debug::pkgDepCache::AutoInstall=true | |
28 | -o APT::Install-Recommends=0 | |
29 | -o APT::Install-Suggests=0 | |
30 | " | |
31 | ||
af040d31 UH |
32 | # Detect if we are running inside Docker |
33 | grep docker /proc/1/cgroup >/dev/null && export DOCKER_BUILD=1 || true | |
34 | ||
8c7df980 UH |
35 | # Detect system architecture to know which binaries of AppImage tools |
36 | # should be downloaded and used. | |
37 | case "$(uname -i)" in | |
38 | x86_64|amd64) | |
39 | # echo "x86-64 system architecture" | |
40 | SYSTEM_ARCH="x86_64";; | |
41 | i?86) | |
42 | # echo "x86 system architecture" | |
43 | SYSTEM_ARCH="i686";; | |
44 | # arm*) | |
45 | # echo "ARM system architecture" | |
46 | # SYSTEM_ARCH="";; | |
ca369dfa | 47 | unknown|AuthenticAMD|GenuineIntel) |
8c7df980 UH |
48 | # uname -i not answer on debian, then: |
49 | case "$(uname -m)" in | |
50 | x86_64|amd64) | |
51 | # echo "x86-64 system architecture" | |
52 | SYSTEM_ARCH="x86_64";; | |
53 | i?86) | |
54 | # echo "x86 system architecture" | |
55 | SYSTEM_ARCH="i686";; | |
56 | esac ;; | |
57 | *) | |
58 | echo "Unsupported system architecture" | |
59 | exit 1;; | |
60 | esac | |
61 | ||
1f369f0c UH |
62 | # Either get the file from remote or from a static place. |
63 | # critical for builds without network access like in Open Build Service | |
64 | cat_file_from_url() | |
65 | { | |
66 | cat_excludelist="wget -q $1 -O -" | |
67 | [ -e "$STATIC_FILES/${1##*/}" ] && cat_excludelist="cat $STATIC_FILES/${1##*/}" | |
68 | $cat_excludelist | |
69 | } | |
70 | ||
71 | git_pull_rebase_helper() | |
72 | { | |
73 | git reset --hard HEAD | |
74 | git pull | |
75 | } | |
76 | ||
77 | # Patch /usr to ././ in ./usr | |
78 | # to make the contents of usr/ relocateable | |
79 | # (this requires us to cd ./usr before running the application; AppRun does that) | |
80 | patch_usr() | |
81 | { | |
82 | find usr/ -type f -executable -exec sed -i -e "s|/usr|././|g" {} \; | |
83 | } | |
84 | ||
85 | # Download AppRun and make it executable | |
86 | get_apprun() | |
87 | { | |
8c7df980 UH |
88 | TARGET_ARCH=${ARCH:-$SYSTEM_ARCH} |
89 | wget -c https://github.com/AppImage/AppImageKit/releases/download/continuous/AppRun-${TARGET_ARCH} -O AppRun | |
1f369f0c UH |
90 | chmod a+x AppRun |
91 | } | |
92 | ||
93 | # Copy the library dependencies of all exectuable files in the current directory | |
94 | # (it can be beneficial to run this multiple times) | |
95 | copy_deps() | |
96 | { | |
97 | PWD=$(readlink -f .) | |
98 | FILES=$(find . -type f -executable -or -name *.so.* -or -name *.so | sort | uniq ) | |
99 | for FILE in $FILES ; do | |
100 | ldd "${FILE}" | grep "=>" | awk '{print $3}' | xargs -I '{}' echo '{}' >> DEPSFILE | |
101 | done | |
102 | DEPS=$(cat DEPSFILE | sort | uniq) | |
103 | for FILE in $DEPS ; do | |
104 | if [ -e $FILE ] && [[ $(readlink -f $FILE)/ != $PWD/* ]] ; then | |
105 | cp -v --parents -rfL $FILE ./ || true | |
106 | fi | |
107 | done | |
108 | rm -f DEPSFILE | |
109 | } | |
110 | ||
111 | # Move ./lib/ tree to ./usr/lib/ | |
112 | move_lib() | |
113 | { | |
114 | mkdir -p ./usr/lib ./lib && find ./lib/ -exec cp -v --parents -rfL {} ./usr/ \; && rm -rf ./lib | |
115 | mkdir -p ./usr/lib ./lib64 && find ./lib64/ -exec cp -v --parents -rfL {} ./usr/ \; && rm -rf ./lib64 | |
116 | } | |
117 | ||
118 | # Delete blacklisted files | |
119 | delete_blacklisted() | |
120 | { | |
af040d31 | 121 | BLACKLISTED_FILES=$(cat_file_from_url https://github.com/AppImage/pkg2appimage/raw/${PKG2AICOMMIT}/excludelist | sed 's|#.*||g') |
1f369f0c UH |
122 | echo $BLACKLISTED_FILES |
123 | for FILE in $BLACKLISTED_FILES ; do | |
8c7df980 UH |
124 | FILES="$(find . -name "${FILE}" -not -path "./usr/optional/*")" |
125 | for FOUND in $FILES ; do | |
126 | rm -vf "$FOUND" "$(readlink -f "$FOUND")" | |
127 | done | |
1f369f0c | 128 | done |
8c7df980 | 129 | |
1f369f0c UH |
130 | # Do not bundle developer stuff |
131 | rm -rf usr/include || true | |
132 | rm -rf usr/lib/cmake || true | |
133 | rm -rf usr/lib/pkgconfig || true | |
134 | find . -name '*.la' | xargs -i rm {} | |
135 | } | |
136 | ||
137 | # Echo highest glibc version needed by the executable files in the current directory | |
138 | glibc_needed() | |
139 | { | |
ca369dfa UH |
140 | find . -name *.so -or -name *.so.* -or -type f -executable -exec strings {} \; | grep ^GLIBC_2 | sed s/GLIBC_//g | sort --version-sort | uniq | tail -n 1 |
141 | # find . -name *.so -or -name *.so.* -or -type f -executable -exec readelf -s '{}' 2>/dev/null \; | sed -n 's/.*@GLIBC_//p'| awk '{print $1}' | sort --version-sort | tail -n 1 | |
1f369f0c UH |
142 | } |
143 | # Add desktop integration | |
144 | # Usage: get_desktopintegration name_of_desktop_file_and_exectuable | |
145 | get_desktopintegration() | |
146 | { | |
af040d31 UH |
147 | # REALBIN=$(grep -o "^Exec=.*" *.desktop | sed -e 's|Exec=||g' | cut -d " " -f 1 | head -n 1) |
148 | # cat_file_from_url https://raw.githubusercontent.com/AppImage/AppImageKit/deprecated/AppImageAssistant/desktopintegration > ./usr/bin/$REALBIN.wrapper | |
149 | # chmod a+x ./usr/bin/$REALBIN.wrapper | |
150 | echo "The desktopintegration script is deprecated. Please advise users to use https://github.com/AppImage/appimaged instead." | |
151 | # sed -i -e "s|^Exec=$REALBIN|Exec=$REALBIN.wrapper|g" $1.desktop | |
1f369f0c UH |
152 | } |
153 | ||
154 | # Generate AppImage; this expects $ARCH, $APP and $VERSION to be set | |
155 | generate_appimage() | |
156 | { | |
8c7df980 UH |
157 | # Download AppImageAssistant |
158 | URL="https://github.com/AppImage/AppImageKit/releases/download/6/AppImageAssistant_6-${SYSTEM_ARCH}.AppImage" | |
159 | wget -c "$URL" -O AppImageAssistant | |
160 | chmod a+x ./AppImageAssistant | |
161 | ||
1f369f0c UH |
162 | # if [[ "$RECIPE" == *ecipe ]] ; then |
163 | # echo "#!/bin/bash -ex" > ./$APP.AppDir/Recipe | |
164 | # echo "# This recipe was used to generate this AppImage." >> ./$APP.AppDir/Recipe | |
165 | # echo "# See http://appimage.org for more information." >> ./$APP.AppDir/Recipe | |
166 | # echo "" >> ./$APP.AppDir/Recipe | |
167 | # cat $RECIPE >> ./$APP.AppDir/Recipe | |
168 | # fi | |
169 | # | |
170 | # Detect the architecture of what we are packaging. | |
171 | # The main binary could be a script, so let's use a .so library | |
172 | BIN=$(find . -name *.so* -type f | head -n 1) | |
173 | INFO=$(file "$BIN") | |
174 | if [ -z $ARCH ] ; then | |
175 | if [[ $INFO == *"x86-64"* ]] ; then | |
176 | ARCH=x86_64 | |
177 | elif [[ $INFO == *"i686"* ]] ; then | |
178 | ARCH=i686 | |
179 | elif [[ $INFO == *"armv6l"* ]] ; then | |
180 | ARCH=armhf | |
181 | else | |
182 | echo "Could not automatically detect the architecture." | |
183 | echo "Please set the \$ARCH environment variable." | |
184 | exit 1 | |
185 | fi | |
186 | fi | |
8c7df980 | 187 | |
1f369f0c | 188 | mkdir -p ../out || true |
8c7df980 | 189 | rm ../out/$APP"-"$VERSION".glibc"$GLIBC_NEEDED"-"$ARCH".AppImage" 2>/dev/null || true |
ca369dfa | 190 | GLIBC_NEEDED=$(glibc_needed) |
8c7df980 | 191 | ./AppImageAssistant ./$APP.AppDir/ ../out/$APP"-"$VERSION".glibc"$GLIBC_NEEDED"-"$ARCH".AppImage" |
1f369f0c UH |
192 | } |
193 | ||
194 | # Generate AppImage type 2 | |
ca369dfa UH |
195 | # Additional parameters given to this routine will be passed on to appimagetool |
196 | # | |
197 | # If the environment variable NO_GLIBC_VERSION is set, the required glibc version | |
198 | # will not be added to the AppImage filename | |
1f369f0c UH |
199 | generate_type2_appimage() |
200 | { | |
201 | # Get the ID of the last successful build on Travis CI | |
8c7df980 | 202 | # ID=$(wget -q https://api.travis-ci.org/repos/AppImage/appimagetool/builds -O - | head -n 1 | sed -e 's|}|\n|g' | grep '"result":0' | head -n 1 | sed -e 's|,|\n|g' | grep '"id"' | cut -d ":" -f 2) |
1f369f0c UH |
203 | # Get the transfer.sh URL from the logfile of the last successful build on Travis CI |
204 | # Only Travis knows why build ID and job ID don't match and why the above doesn't give both... | |
205 | # URL=$(wget -q "https://s3.amazonaws.com/archive.travis-ci.org/jobs/$((ID+1))/log.txt" -O - | grep "https://transfer.sh/.*/appimagetool" | tail -n 1 | sed -e 's|\r||g') | |
206 | # if [ -z "$URL" ] ; then | |
207 | # URL=$(wget -q "https://s3.amazonaws.com/archive.travis-ci.org/jobs/$((ID+2))/log.txt" -O - | grep "https://transfer.sh/.*/appimagetool" | tail -n 1 | sed -e 's|\r||g') | |
208 | # fi | |
af040d31 UH |
209 | if [ -z "$(which appimagetool)" ] ; then |
210 | URL="https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-${SYSTEM_ARCH}.AppImage" | |
211 | wget -c "$URL" -O appimagetool | |
212 | chmod a+x ./appimagetool | |
213 | appimagetool=$(readlink -f appimagetool) | |
214 | else | |
215 | appimagetool=$(which appimagetool) | |
216 | fi | |
ca369dfa UH |
217 | if [ "$DOCKER_BUILD" ]; then |
218 | appimagetool_tempdir=$(mktemp -d) | |
219 | mv appimagetool "$appimagetool_tempdir" | |
220 | pushd "$appimagetool_tempdir" &>/dev/null | |
221 | ls -al | |
222 | ./appimagetool --appimage-extract | |
223 | rm appimagetool | |
224 | appimagetool=$(readlink -f squashfs-root/AppRun) | |
225 | popd &>/dev/null | |
226 | _appimagetool_cleanup() { [ -d "$appimagetool_tempdir" ] && rm -r "$appimagetool_tempdir"; } | |
227 | trap _appimagetool_cleanup EXIT | |
228 | fi | |
229 | ||
230 | if [ -z ${NO_GLIBC_VERSION+true} ]; then | |
231 | GLIBC_NEEDED=$(glibc_needed) | |
232 | VERSION_EXPANDED=$VERSION.glibc$GLIBC_NEEDED | |
233 | else | |
234 | VERSION_EXPANDED=$VERSION | |
235 | fi | |
236 | ||
1f369f0c | 237 | set +x |
ca369dfa | 238 | GLIBC_NEEDED=$(glibc_needed) |
1f369f0c | 239 | if ( [ ! -z "$KEY" ] ) && ( ! -z "$TRAVIS" ) ; then |
8c7df980 | 240 | wget https://github.com/AppImage/AppImageKit/files/584665/data.zip -O data.tar.gz.gpg |
1f369f0c UH |
241 | ( set +x ; echo $KEY | gpg2 --batch --passphrase-fd 0 --no-tty --skip-verify --output data.tar.gz --decrypt data.tar.gz.gpg ) |
242 | tar xf data.tar.gz | |
243 | sudo chown -R $USER .gnu* | |
244 | mv $HOME/.gnu* $HOME/.gnu_old ; mv .gnu* $HOME/ | |
ca369dfa | 245 | VERSION=$VERSION_EXPANDED "$appimagetool" $@ -n -s --bintray-user $BINTRAY_USER --bintray-repo $BINTRAY_REPO -v ./$APP.AppDir/ |
1f369f0c | 246 | else |
ca369dfa | 247 | VERSION=$VERSION_EXPANDED "$appimagetool" $@ -n --bintray-user $BINTRAY_USER --bintray-repo $BINTRAY_REPO -v ./$APP.AppDir/ |
1f369f0c UH |
248 | fi |
249 | set -x | |
250 | mkdir -p ../out/ || true | |
251 | mv *.AppImage* ../out/ | |
252 | } | |
253 | ||
254 | # Generate status file for use by apt-get; assuming that the recipe uses no newer | |
8c7df980 | 255 | # ingredients than what would require more recent dependencies than what we assume |
1f369f0c UH |
256 | # to be part of the base system |
257 | generate_status() | |
258 | { | |
259 | mkdir -p ./tmp/archives/ | |
260 | mkdir -p ./tmp/lists/partial | |
261 | touch tmp/pkgcache.bin tmp/srcpkgcache.bin | |
af040d31 UH |
262 | if [ -e "${HERE}/usr/share/pkg2appimage/excludedeblist" ] ; then |
263 | EXCLUDEDEBLIST="${HERE}/usr/share/pkg2appimage/excludedeblist" | |
264 | else | |
265 | wget -q -c "https://github.com/AppImage/AppImages/raw/${PKG2AICOMMIT}/excludedeblist" | |
266 | EXCLUDEDEBLIST=excludedeblist | |
267 | fi | |
1f369f0c UH |
268 | rm status 2>/dev/null || true |
269 | for PACKAGE in $(cat excludedeblist | cut -d "#" -f 1) ; do | |
270 | printf "Package: $PACKAGE\nStatus: install ok installed\nArchitecture: all\nVersion: 9:999.999.999\n\n" >> status | |
271 | done | |
272 | } | |
273 | ||
274 | # Find the desktop file and copy it to the AppDir | |
275 | get_desktop() | |
276 | { | |
277 | find usr/share/applications -iname "*${LOWERAPP}.desktop" -exec cp {} . \; || true | |
278 | } | |
279 | ||
8c7df980 UH |
280 | fix_desktop() { |
281 | # fix trailing semicolons | |
282 | for key in Actions Categories Implements Keywords MimeType NotShowIn OnlyShowIn; do | |
283 | sed -i '/'"$key"'.*[^;]$/s/$/;/' $1 | |
284 | done | |
285 | } | |
286 | ||
1f369f0c UH |
287 | # Find the icon file and copy it to the AppDir |
288 | get_icon() | |
289 | { | |
290 | find ./usr/share/pixmaps/$LOWERAPP.png -exec cp {} . \; 2>/dev/null || true | |
291 | find ./usr/share/icons -path *64* -name $LOWERAPP.png -exec cp {} . \; 2>/dev/null || true | |
292 | find ./usr/share/icons -path *128* -name $LOWERAPP.png -exec cp {} . \; 2>/dev/null || true | |
293 | find ./usr/share/icons -path *512* -name $LOWERAPP.png -exec cp {} . \; 2>/dev/null || true | |
294 | find ./usr/share/icons -path *256* -name $LOWERAPP.png -exec cp {} . \; 2>/dev/null || true | |
295 | ls -lh $LOWERAPP.png || true | |
296 | } | |
297 | ||
298 | # Find out the version | |
299 | get_version() | |
300 | { | |
301 | THEDEB=$(find ../*.deb -name $LOWERAPP"_*" | head -n 1) | |
302 | if [ -z "$THEDEB" ] ; then | |
303 | echo "Version could not be determined from the .deb; you need to determine it manually" | |
304 | fi | |
ca369dfa | 305 | VERSION=$(echo $THEDEB | cut -d "~" -f 1 | cut -d "_" -f 2 | cut -d "-" -f 1 | sed -e 's|1%3a||g' | sed -e 's|.dfsg||g' ) |
1f369f0c UH |
306 | echo $VERSION |
307 | } | |
308 | ||
309 | # transfer.sh | |
8c7df980 | 310 | transfer() { if [ $# -eq 0 ]; then echo "No arguments specified. Usage:\necho transfer /tmp/test.md\ncat /tmp/test.md | transfer test.md"; return 1; fi |
1f369f0c UH |
311 | tmpfile=$( mktemp -t transferXXX ); if tty -s; then basefile=$(basename "$1" | sed -e 's/[^a-zA-Z0-9._-]/-/g'); curl --progress-bar --upload-file "$1" "https://transfer.sh/$basefile" >> $tmpfile; else curl --progress-bar --upload-file "-" "https://transfer.sh/$1" >> $tmpfile ; fi; cat $tmpfile; rm -f $tmpfile; } |
312 | ||
313 | # Patch binary files; fill with padding if replacement is shorter than original | |
314 | # http://everydaywithlinux.blogspot.de/2012/11/patch-strings-in-binary-files-with-sed.html | |
315 | # Example: patch_strings_in_file foo "/usr/local/lib/foo" "/usr/lib/foo" | |
8c7df980 | 316 | patch_strings_in_file() { |
1f369f0c UH |
317 | local FILE="$1" |
318 | local PATTERN="$2" | |
319 | local REPLACEMENT="$3" | |
8c7df980 | 320 | # Find all unique strings in FILE that contain the pattern |
1f369f0c UH |
321 | STRINGS=$(strings ${FILE} | grep ${PATTERN} | sort -u -r) |
322 | if [ "${STRINGS}" != "" ] ; then | |
323 | echo "File '${FILE}' contain strings with '${PATTERN}' in them:" | |
324 | for OLD_STRING in ${STRINGS} ; do | |
325 | # Create the new string with a simple bash-replacement | |
326 | NEW_STRING=${OLD_STRING//${PATTERN}/${REPLACEMENT}} | |
327 | # Create null terminated ASCII HEX representations of the strings | |
328 | OLD_STRING_HEX="$(echo -n ${OLD_STRING} | xxd -g 0 -u -ps -c 256)00" | |
329 | NEW_STRING_HEX="$(echo -n ${NEW_STRING} | xxd -g 0 -u -ps -c 256)00" | |
330 | if [ ${#NEW_STRING_HEX} -le ${#OLD_STRING_HEX} ] ; then | |
331 | # Pad the replacement string with null terminations so the | |
332 | # length matches the original string | |
333 | while [ ${#NEW_STRING_HEX} -lt ${#OLD_STRING_HEX} ] ; do | |
334 | NEW_STRING_HEX="${NEW_STRING_HEX}00" | |
335 | done | |
8c7df980 | 336 | # Now, replace every occurrence of OLD_STRING with NEW_STRING |
1f369f0c UH |
337 | echo -n "Replacing ${OLD_STRING} with ${NEW_STRING}... " |
338 | hexdump -ve '1/1 "%.2X"' ${FILE} | \ | |
339 | sed "s/${OLD_STRING_HEX}/${NEW_STRING_HEX}/g" | \ | |
340 | xxd -r -p > ${FILE}.tmp | |
341 | chmod --reference ${FILE} ${FILE}.tmp | |
342 | mv ${FILE}.tmp ${FILE} | |
343 | echo "Done!" | |
344 | else | |
345 | echo "New string '${NEW_STRING}' is longer than old" \ | |
346 | "string '${OLD_STRING}'. Skipping." | |
347 | fi | |
348 | done | |
349 | fi | |
350 | } |