1 # This file is supposed to be sourced by each Recipe
2 # that wants to use the functions contained herein
4 # wget -q https://github.com/probonopd/AppImages/raw/master/functions.sh -O ./functions.sh
7 # RECIPE=$(realpath "$0")
9 # Options for apt-get to use local files rather than the system ones
10 OPTIONS
="-o Debug::NoLocking=1
11 -o APT::Cache-Limit=125829120
12 -o Dir::Etc::sourcelist=./sources.list
15 -o Dir::State::status=./status
16 -o Dir::Etc::sourceparts=-
17 -o APT::Get::List-Cleanup=0
18 -o APT::Get::AllowUnauthenticated=1
19 -o Debug::pkgProblemResolver=true
20 -o Debug::pkgDepCache::AutoInstall=true
21 -o APT::Install-Recommends=0
22 -o APT::Install-Suggests=0
25 # Either get the file from remote or from a static place.
26 # critical for builds without network access like in Open Build Service
29 cat_excludelist
="wget -q $1 -O -"
30 [ -e "$STATIC_FILES/${1##*/}" ] && cat_excludelist
="cat $STATIC_FILES/${1##*/}"
34 git_pull_rebase_helper
()
40 # Patch /usr to ././ in ./usr
41 # to make the contents of usr/ relocateable
42 # (this requires us to cd ./usr before running the application; AppRun does that)
45 find usr
/ -type f
-executable -exec sed -i -e "s|/usr|././|g" {} \
;
48 # Download AppRun and make it executable
51 # wget -c https://github.com/probonopd/AppImageKit/releases/download/5/AppRun -O ./AppRun # 64-bit
52 wget
-c https
://github.com
/probonopd
/AppImageKit
/releases
/download
/6/AppRun_6-x86_64
-O AppRun
# 64-bit
56 # Copy the library dependencies of all exectuable files in the current directory
57 # (it can be beneficial to run this multiple times)
61 FILES
=$
(find .
-type f
-executable -or -name *.so.
* -or -name *.so |
sort |
uniq )
62 for FILE
in $FILES ; do
63 ldd
"${FILE}" |
grep "=>" |
awk '{print $3}' |
xargs -I '{}' echo '{}' >> DEPSFILE
65 DEPS
=$
(cat DEPSFILE |
sort |
uniq)
66 for FILE
in $DEPS ; do
67 if [ -e $FILE ] && [[ $
(readlink
-f $FILE)/ != $PWD/* ]] ; then
68 cp -v --parents -rfL $FILE .
/ || true
74 # Move ./lib/ tree to ./usr/lib/
77 mkdir
-p .
/usr
/lib .
/lib
&& find .
/lib
/ -exec cp -v --parents -rfL {} .
/usr
/ \
; && rm -rf .
/lib
78 mkdir
-p .
/usr
/lib .
/lib64
&& find .
/lib64
/ -exec cp -v --parents -rfL {} .
/usr
/ \
; && rm -rf .
/lib64
81 # Delete blacklisted files
84 BLACKLISTED_FILES
=$
( cat_file_from_url https
://github.com
/probonopd
/AppImages
/raw
/master
/excludelist |
sed '/^\s*$/d' |
sed '/^#.*$/d')
85 echo $BLACKLISTED_FILES
86 for FILE
in $BLACKLISTED_FILES ; do
87 FOUND
=$
(find .
-xtype f
-name "${FILE}" 2>/dev
/null
)
88 if [ ! -z "$FOUND" ] ; then
89 echo "Deleting blacklisted ${FOUND}"
94 # Do not bundle developer stuff
95 rm -rf usr
/include || true
96 rm -rf usr
/lib
/cmake || true
97 rm -rf usr
/lib
/pkgconfig || true
98 find .
-name '*.la' |
xargs -i rm {}
101 # Echo highest glibc version needed by the executable files in the current directory
104 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
106 # Add desktop integration
107 # Usage: get_desktopintegration name_of_desktop_file_and_exectuable
108 get_desktopintegration
()
110 REALBIN
=$
(grep -o "^Exec=.*" *.desktop |
sed -e 's|Exec=||g' | cut
-d " " -f 1 |
head -n 1)
111 cat_file_from_url https
://raw.githubusercontent.com
/probonopd
/AppImageKit
/master
/desktopintegration
> .
/usr
/bin
/$REALBIN.wrapper
112 chmod a
+x .
/usr
/bin
/$REALBIN.wrapper
114 sed -i -e "s|^Exec=$REALBIN|Exec=$REALBIN.wrapper|g" $1.desktop
117 # Generate AppImage; this expects $ARCH, $APP and $VERSION to be set
120 # if [[ "$RECIPE" == *ecipe ]] ; then
121 # echo "#!/bin/bash -ex" > ./$APP.AppDir/Recipe
122 # echo "# This recipe was used to generate this AppImage." >> ./$APP.AppDir/Recipe
123 # echo "# See http://appimage.org for more information." >> ./$APP.AppDir/Recipe
124 # echo "" >> ./$APP.AppDir/Recipe
125 # cat $RECIPE >> ./$APP.AppDir/Recipe
128 # Detect the architecture of what we are packaging.
129 # The main binary could be a script, so let's use a .so library
130 BIN
=$
(find .
-name *.so
* -type f |
head -n 1)
132 if [ -z $ARCH ] ; then
133 if [[ $INFO == *"x86-64"* ]] ; then
135 elif [[ $INFO == *"i686"* ]] ; then
137 elif [[ $INFO == *"armv6l"* ]] ; then
140 echo "Could not automatically detect the architecture."
141 echo "Please set the \$ARCH environment variable."
145 wget
-c "https://github.com/probonopd/AppImageKit/releases/download/6/AppImageAssistant_6-x86_64.AppImage" -O AppImageAssistant
# (64-bit)
146 chmod a
+x .
/AppImageAssistant
147 mkdir
-p ..
/out || true
148 rm ..
/out
/$APP"-"$VERSION"-x86_64.AppImage" 2>/dev
/null || true
149 .
/AppImageAssistant .
/$APP.AppDir
/ ..
/out
/$APP"-"$VERSION"-"$ARCH".AppImage"
152 # Generate AppImage type 2
153 generate_type2_appimage
()
155 # Get the ID of the last successful build on Travis CI
156 # ID=$(wget -q https://api.travis-ci.org/repos/probonopd/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)
157 # Get the transfer.sh URL from the logfile of the last successful build on Travis CI
158 # Only Travis knows why build ID and job ID don't match and why the above doesn't give both...
159 # 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')
160 # if [ -z "$URL" ] ; then
161 # 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')
163 URL
="https://github.com/probonopd/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
164 wget
-c "$URL" -O appimagetool
165 chmod a
+x .
/appimagetool
167 if ( [ ! -z "$KEY" ] ) && ( ! -z "$TRAVIS" ) ; then
168 wget https
://github.com
/probonopd
/AppImageKit
/files
/584665/data.
zip -O data.
tar.gz.gpg
169 ( set +x
; echo $KEY | gpg2
--batch --passphrase-fd 0 --no-tty --skip-verify --output data.
tar.gz
--decrypt data.
tar.gz.gpg
)
171 sudo chown
-R $USER .gnu
*
172 mv $HOME/.gnu
* $HOME/.gnu_old
; mv .gnu
* $HOME/
173 VERSION
=$VERSION .
/appimagetool
-n -s --bintray-user $BINTRAY_USER --bintray-repo $BINTRAY_REPO -v .
/$APP.AppDir
/
175 VERSION
=$VERSION .
/appimagetool
-n --bintray-user $BINTRAY_USER --bintray-repo $BINTRAY_REPO -v .
/$APP.AppDir
/
178 mkdir
-p ..
/out
/ || true
179 mv *.AppImage
* ..
/out
/
182 # Generate status file for use by apt-get; assuming that the recipe uses no newer
183 # ingredients than what would require more recent dependencies than what we assume
184 # to be part of the base system
187 mkdir
-p .
/tmp
/archives
/
188 mkdir
-p .
/tmp
/lists
/partial
189 touch tmp
/pkgcache.bin tmp
/srcpkgcache.bin
190 wget
-q -c "https://github.com/probonopd/AppImages/raw/master/excludedeblist"
191 rm status
2>/dev
/null || true
192 for PACKAGE
in $
(cat excludedeblist | cut
-d "#" -f 1) ; do
193 printf "Package: $PACKAGE\nStatus: install ok installed\nArchitecture: all\nVersion: 9:999.999.999\n\n" >> status
197 # Find the desktop file and copy it to the AppDir
200 find usr
/share
/applications
-iname "*${LOWERAPP}.desktop" -exec cp {} . \
; || true
203 # Find the icon file and copy it to the AppDir
206 find .
/usr
/share
/pixmaps
/$LOWERAPP.png
-exec cp {} . \
; 2>/dev
/null || true
207 find .
/usr
/share
/icons
-path *64* -name $LOWERAPP.png
-exec cp {} . \
; 2>/dev
/null || true
208 find .
/usr
/share
/icons
-path *128* -name $LOWERAPP.png
-exec cp {} . \
; 2>/dev
/null || true
209 find .
/usr
/share
/icons
-path *512* -name $LOWERAPP.png
-exec cp {} . \
; 2>/dev
/null || true
210 find .
/usr
/share
/icons
-path *256* -name $LOWERAPP.png
-exec cp {} . \
; 2>/dev
/null || true
211 ls -lh $LOWERAPP.png || true
214 # Find out the version
217 THEDEB
=$
(find ..
/*.deb
-name $LOWERAPP"_*" |
head -n 1)
218 if [ -z "$THEDEB" ] ; then
219 echo "Version could not be determined from the .deb; you need to determine it manually"
221 VER1
=$
(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' )
222 GLIBC_NEEDED
=$
(glibc_needed
)
223 VERSION
=$VER1.glibc
$GLIBC_NEEDED
228 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
229 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; }
231 # Patch binary files; fill with padding if replacement is shorter than original
232 # http://everydaywithlinux.blogspot.de/2012/11/patch-strings-in-binary-files-with-sed.html
233 # Example: patch_strings_in_file foo "/usr/local/lib/foo" "/usr/lib/foo"
234 function patch_strings_in_file
() {
237 local REPLACEMENT
="$3"
238 # Find all unique strings in FILE that contain the pattern
239 STRINGS
=$
(strings ${FILE} |
grep ${PATTERN} |
sort -u -r)
240 if [ "${STRINGS}" != "" ] ; then
241 echo "File '${FILE}' contain strings with '${PATTERN}' in them:"
242 for OLD_STRING
in ${STRINGS} ; do
243 # Create the new string with a simple bash-replacement
244 NEW_STRING
=${OLD_STRING//${PATTERN}/${REPLACEMENT}}
245 # Create null terminated ASCII HEX representations of the strings
246 OLD_STRING_HEX
="$(echo -n ${OLD_STRING} | xxd -g 0 -u -ps -c 256)00"
247 NEW_STRING_HEX
="$(echo -n ${NEW_STRING} | xxd -g 0 -u -ps -c 256)00"
248 if [ ${#NEW_STRING_HEX} -le ${#OLD_STRING_HEX} ] ; then
249 # Pad the replacement string with null terminations so the
250 # length matches the original string
251 while [ ${#NEW_STRING_HEX} -lt ${#OLD_STRING_HEX} ] ; do
252 NEW_STRING_HEX
="${NEW_STRING_HEX}00"
254 # Now, replace every occurrence of OLD_STRING with NEW_STRING
255 echo -n "Replacing ${OLD_STRING} with ${NEW_STRING}... "
256 hexdump -ve '1/1 "%.2X"' ${FILE} | \
257 sed "s/${OLD_STRING_HEX}/${NEW_STRING_HEX}/g" | \
258 xxd
-r -p > ${FILE}.tmp
259 chmod --reference ${FILE} ${FILE}.tmp
260 mv ${FILE}.tmp
${FILE}
263 echo "New string '${NEW_STRING}' is longer than old" \
264 "string '${OLD_STRING}'. Skipping."