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