Files
opengapps/scripts/inc.buildhelper.sh
2022-01-17 22:27:15 +01:00

393 lines
14 KiB
Bash
Executable File

#This file is part of The Open GApps script of @mfonville.
#
# The Open GApps scripts are free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# These scripts are distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
preparebuildarea() {
build="$BUILD/$ARCH/$API/$VARIANT"
echo "Cleaning build area: $build"
rm -rf "$build"
install -d "$build"
install -d "$CACHE"
logfile=""
if [ -n "$VERSIONLOG" ]; then
logfile="$(eval "echo \"$VERSIONLOG\"")"
install -d "$(dirname "$logfile")"
printf "%-6s%3s| %-61s| %-50s| %s\n-----------------------------------------------------------------------------------------------------------------------------------\n" "Arch." "API" "Application / File / Folder" "Version Name" "DPIs" > "$logfile"
fi
}
copy() {
if [ -d "$1" ]; then
for f in $1/*; do
copy "$f" "$2/$(basename "$f")"
done
fi
if [ -f "$1" ]; then
install -D -p "$1" "$2"
fi
}
buildfile() {
if [ -z "$4" ]; then usearch="$ARCH"
else usearch="$4"; fi #allows for an override
case "$usearch" in
all) targetarch="common";; # technically with our currrent APKs-set, every that is 'all' is de-facto also 'common'
*) targetarch="$usearch";;
esac
if [ -e "$SOURCES/$usearch/$1" ]; then #check if directory or file exists
if [ -d "$SOURCES/$usearch/$1" ]; then #if we are handling a directory
targetdir="$build/$2-$targetarch/$3/$1"
else
targetdir="$build/$2-$targetarch/$3/$(dirname "$1")"
fi
install -d "$targetdir"
printf "%6s %s\n" "$usearch" "$1"
if [ -n "$logfile" ]; then
printf "%6s | %-s\n" "$usearch" "$1">> "$logfile"
fi
copy "$SOURCES/$usearch/$1" "$targetdir" #if we have a file specific to this architecture
# rename etc/sysconfig/google_go.xml to etc/sysconfig/google.xml
if [ "$1" = "etc/sysconfig/google_go.xml" ]; then
mv "$targetdir/google_go.xml" "$targetdir/google.xml"
fi
else
get_fallback_arch "$usearch"
if [ "$usearch" != "$fallback_arch" ]; then
buildfile "$1" "$2" "$3" "$fallback_arch"
else
echo "ERROR: No fallback available. Failed to build file $1"
exit 1
fi
fi
}
buildframework() {
frameworkname="$1"
ziplocation="$2"
targetlocation="$3"
if [ -z "$4" ]; then usearch="$ARCH"
else usearch="$4"; fi #allows for an override
case "$usearch" in
all) targetarch="common";; # technically with our currrent APKs-set, every that is 'all' is de-facto also 'common'
*) targetarch="$usearch";;
esac
if getframeworkforapi "$frameworkname" "$usearch" "$API"; then
printf "%6s-%s %s\n" "$usearch" "$api" "$frameworkname"
if [ -n "$logfile" ]; then
printf "%6s-%s| %-s\n" "$usearch" "$api" "$frameworkname" >> "$logfile"
fi
install -D -p "$sourceframework" "$build/$ziplocation-$targetarch/$targetlocation/$targetframework"
else
get_fallback_arch "$usearch"
if [ "$usearch" != "$fallback_arch" ]; then
buildframework "$frameworkname" "$ziplocation" "$targetlocation" "$fallback_arch"
else
echo "ERROR: No fallback available. Failed to build framework $frameworkname"
exit 1
fi
fi
}
buildsystemlib() {
libname="$1"
ziplocation="$2"
targetlocation="$3"
if [ -z "$4" ]; then usearch="$ARCH"
else usearch="$4"; fi #allows for an override
fallback=""
case "$libname" in
*+fallback) libname="$(echo "$libname" | sed 's/+fallback//')"
fallback="true";;
esac
case "$usearch" in
all) targetarch="common";; # technically with our currrent APKs-set, every that is 'all' is de-facto also 'common'
*) targetarch="$usearch";;
esac
if getsystemlibforapi "$libname" "$usearch" "$API"; then
printf "%6s-%s %s\n" "$usearch" "$api" "$libname"
if [ -n "$logfile" ]; then
printf "%6s-%s| %-s\n" "$usearch" "$api" "$libname" >> "$logfile"
fi
install -D -p "$sourcelib" "$build/$ziplocation-lib-$targetarch/$targetlocation/$targetlib"
else
fallback="true"
fi
if [ -n "$fallback" ]; then
get_fallback_arch "$usearch"
if [ "$usearch" != "$fallback_arch" ]; then
buildsystemlib "$libname" "$ziplocation" "$targetlocation" "$fallback_arch"
else
echo "ERROR: No fallback available. Failed to build lib $libname"
exit 1
fi
fi
}
getpathsystemlib(){
libname="$1"
if [ -z "$2" ]; then usearch="$ARCH"
else usearch="$2"; fi #allows for an override
fallback=""
case "$libname" in
*+fallback) libname="$(echo "$libname" | sed 's/+fallback//')"
fallback="true";;
esac
if getsystemlibforapi "$libname" "$usearch" "$API"; then
systemlibpath="$targetlib $systemlibpath"
else
fallback="true"
fi
if [ -n "$fallback" ]; then
get_fallback_arch "$usearch"
if [ "$usearch" != "$fallback_arch" ]; then
getpathsystemlib "$libname" "$fallback_arch"
fi
fi
}
buildapp() {
package="$1"
usemaxapi="$2"
ziplocation="$3"
targetlocation="$4"
if [ -z "$5" ]; then usearch="$ARCH"
else usearch="$5"; fi #allows for an override
packagedirsuffix="$6"
minapihack #Some packages need a minimal api level to maintain compatibility with the OS
if getapksforapi "$package" "$usearch" "$usemaxapi" "$useminapi" "$packagedirsuffix"; then
baseversionname=""
for dpivariant in $(echo "$sourceapks" | tr ' ' ''); do #we replace the spaces with a special char to survive the for-loop
dpivariant="$(echo "$dpivariant" | tr '' ' ')" #and we place the spaces back again
getapkproperties "$dpivariant" #get versionname
versionname="$(printf "%s" "$versionname" | cut -d ' ' -f 1)" #always cut off everything in the versionname after the space since that indicates a part that is ALWAYS at minimum dpi-specific
versionnamehack #Some packages have a different versionname, when the actual version is equal
systemlibhack #Some packages want their libs installed as system libs
if [ "$API" -le "19" ] || [ "$systemlib" = "true" ]; then
liblocation="$ziplocation-$usearch/common"
else
liblocation="$ziplocation-$usearch/common/$targetlocation"
fi
if [ -z "$baseversionname" ]; then
baseversionname=$versionname
buildlib "$dpivariant" "$liblocation" "$usearch" #Use the libs from this baseversion
printf "%6s-%-2s %-61s %50s" "$usearch" "$api" "$1" "$baseversionname" # use $1 instead of $package to show the foldername packagename instead of the getapkproperties-name to get the setupwizard name right
if [ -n "$logfile" ]; then
printf "%6s-%-2s| %-61s| %-50s|" "$usearch" "$api" "$1" "$baseversionname" >> "$logfile"
fi
fi
if [ "$versionname" = "$baseversionname" ]; then
density=$(basename "$(dirname "$dpivariant")")
buildapk "$dpivariant" "$ziplocation-$usearch/$density/$targetlocation"
printf " %s" "$density"
if [ -n "$logfile" ]; then
printf " %s" "$density" >> "$logfile"
fi
echo "$ziplocation-$usearch/$density/" >> "$build/app_densities.txt"
fi
done
printf "\n"
if [ -n "$logfile" ]; then
printf "\n" >> "$logfile"
fi
else
get_fallback_arch "$usearch"
if [ "$usearch" != "$fallback_arch" ]; then
buildapp "$package" "$usemaxapi" "$ziplocation" "$targetlocation" "$fallback_arch" "$packagedirsuffix"
else
echo "ERROR: No fallback available. Failed to build package $package"
exit 1
fi
fi
}
getapksforapi() {
#this functions finds the highest available acceptable apk for a given api and architecture
#$1 package, $2 arch, $3 api, $4 minapi, $5 packagedirsuffix
if [ -z "$4" ]; then minapi="0"
else minapi="$4"; fi #specify minimal api
if ! stat --printf='' "$SOURCES/$2/"*"app$5/$1" 2>/dev/null; then
return 1 #appname is not there, error!?
fi
sourceapks=""
OLDIFS="$IFS"
IFS="
" #We set IFS to newline here so that spaces can survive the for loop
#sed copies filename to the beginning, to compare version, and later we remove it with cut
maxsdkerrorapi=""
for foundapk in $(find $SOURCES/$2/*app$5/$1 -iname '*.apk' 2>/dev/null| sed 's!.*/\(.*\)!\1/&!' | sort -r -n -t/ -k1,1 | cut -d/ -f2-); do
foundpath="$(dirname "$(dirname "$foundapk")")"
api="$(basename "$foundpath")"
if [ "$maxsdkerrorapi" = "$api" ]; then
continue #if we already know that this api hit the maxsdk error, do not try it again
fi
if [ "$api" -le "$3" ] && [ "$api" -ge "$minapi" ]; then
#We need to keep them sorted
sourceapks="$(find "$foundpath" -iname '*.apk' | sed 's!.*/\(.*\)!\1/&!' | sort -r -n -t/ -k1,1 | cut -d/ -f2-)"
for maxsdkapk in $sourceapks; do
maxsdk="$(aapt dump badging "$maxsdkapk" 2>/dev/null | grep -a "maxSdkVersion:" | sed 's/maxSdkVersion://' | sed "s/'//g")"
if [ -n "$maxsdk" ] && [ "$maxsdk" -lt "$3" ]; then
echo "WARNING: Newest APK found is incompatible with API level $3 for package $1 on $2, maxSdk: $maxsdk, falling back to higher SDK"
maxsdkerrorapi="$api"
continue 2
fi
break
done
break
fi
done
IFS="$OLDIFS"
if [ -z "$sourceapks" ]; then
echo "WARNING: No APK found compatible with API level $3 for package $1 on $2, lowest found: $api"
return 1 #error
fi
#$sourceapks and $api have the useful returnvalues
return 0 #return that it was a success
}
getframeworkforapi() {
#this functions finds the highest available acceptable framework for a given api and architecture
#$1 frameworkname, $2 arch, $3 api
sourceframework=""
OLDIFS="$IFS"
IFS="
" #We set IFS to newline here so that spaces can survive the for loop
for foundframework in $(find $SOURCES/$2/framework/ -iname "$1" 2>/dev/null| sort -r); do
api="$(basename "$(dirname "$foundframework")")"
if [ "$api" -le "$3" ]; then
sourceframework="$foundframework"
break
fi
done
IFS="$OLDIFS"
if [ -z "$sourceframework" ]; then
#echo "WARNING: No framework found compatible with API level $3 for framework $1 on $2, lowest found: $api"
return 1 #error
fi
apiframeworkpath="$(echo "$sourceframework" | awk -F'/' '{print $(NF-1)}')" # is api number
targetframework="$(echo "$sourceframework" | sed "s:^$SOURCES/$2/::" | sed "s:/$apiframeworkpath/:/:g")" # framework/frameworkname.jar
#$sourceframework, $targetframework and $api have the useful returnvalues
return 0 #return that it was a success
}
getsystemlibforapi() {
#this functions finds the highest available acceptable lib for a given api and architecture
#$1 libname, $2 arch, $3 api
sourcelib=""
OLDIFS="$IFS"
IFS="
" #We set IFS to newline here so that spaces can survive the for loop
for foundlib in $(find $SOURCES/$2/lib*/ $SOURCES/$2/vendor/lib*/ -iname "$1" 2>/dev/null| sort -r); do
api="$(basename "$(dirname "$foundlib")")"
if [ "$api" -le "$3" ]; then
sourcelib="$foundlib"
break
fi
done
IFS="$OLDIFS"
if [ -z "$sourcelib" ]; then
#echo "WARNING: No lib found compatible with API level $3 for lib $1 on $2, lowest found: $api"
return 1 #error
fi
apilibpath="$(echo "$sourcelib" | awk -F'/' '{print $(NF-1)}')" # is api number
targetlib="$(echo "$sourcelib" | sed "s:^$SOURCES/$2/::" | sed "s:/$apilibpath/:/:g")" # lib/libname.so
#$sourcelib, $targetlib and $api have the useful returnvalues
return 0 #return that it was a success
}
buildapk() {
sourceapk="$1"
targetdir="$build/$2"
targetapk="$targetdir/$(basename "$targetdir").apk"
if [ "$API" -le "19" ]; then #We will do this as long as we support KitKat
targetapk="$targetdir.apk"
targetdir="$(dirname "$targetapk")"
fi
if [ -f "$targetapk" ]; then
rm "$targetapk"
fi
install -D "$sourceapk" "$targetapk"
if (unzip -v "$targetapk" | grep "lib/" | grep -qv "Stored"); then #check if there are compressed libs present
if [ "$API" -lt "23" ]; then #only if pre-Marshmallow
unzip -Z -1 "$targetapk" | grep "lib/" | grep -v "/crazy." | xargs zip -q -d "$targetapk" #delete all libs, except crazy-linked
else #Marshmallow and above needs libs to be stored without compression within the APK
unzip -qqq -o "$targetapk" -d "$targetdir" "lib/*"
zip -q -d "$targetapk" "lib/*" #delete all libs
(
cd "$targetdir"
zip -q -r -D -Z store -b "$targetdir" "$targetapk" "lib/" #no parameter for output and mode, we are in 'add and update existing' mode which is default. Lib files have to be stored without compression.
)
rm -rf "$targetdir/lib/"
fi
fi
}
buildlib() {
sourceapk="$1"
targetdir="$build/$2"
apkarch="$3"
libsearchpath="lib/*" #default that should never happen: all libs
if [ "$apkarch" = "arm" ]; then
libsearchpath="lib/armeabi*/*" #mind the wildcard
libfallbacksearchpath=""
elif [ "$apkarch" = "arm64" ]; then
libsearchpath="lib/arm64*/*" #mind the wildcard
libfallbacksearchpath="lib/armeabi*/*" #mind the wildcard
elif [ "$apkarch" = "x86" ]; then
libsearchpath="lib/x86/*"
libfallbacksearchpath=""
elif [ "$apkarch" = "x86_64" ]; then
libsearchpath="lib/x86_64/*"
libfallbacksearchpath="lib/x86/*"
elif [ "$apkarch" = "mips" ]; then
libsearchpath="lib/mips/*"
libfallbacksearchpath=""
elif [ "$apkarch" = "mips64" ]; then
libsearchpath="lib/mips64/*"
libfallbacksearchpath="lib/mips/*"
fi
get_fallback_arch "$apkarch"
if [ "$(basename "$targetdir")" = "common" ]; then #if we are installing systemwide libs
libpath="$LIBFOLDER"
fallbacklibpath="lib"
else #Lollipop-style libs bundled in the APK's folder
libpath="lib/$apkarch"
fallbacklibpath="lib/$fallback_arch" #notice that this sometimes gives 'illegal' paths like 'lib/all', but the path is not used in those situations
fi
if [ "$API" -lt "23" ]; then #libextraction is only necessary on pre-Marshmallow
if [ -n "$(unzip -Z -1 "$sourceapk" "$libsearchpath" 2>/dev/null)" ]; then
install -d "$targetdir/$libpath"
unzip -qqq -j -o "$sourceapk" "$libsearchpath" -x "lib/*/crazy.*" -d "$targetdir/$libpath" 2>/dev/null
fi
if [ "$apkarch" != "$fallback_arch" ] && [ -n "$(unzip -Z -1 "$sourceapk" "$libfallbacksearchpath" 2>/dev/null)" ]; then
install -d "$targetdir/$fallbacklibpath"
unzip -qqq -j -o "$sourceapk" "$libfallbacksearchpath" -x "lib/*/crazy.*" -d "$targetdir/$fallbacklibpath" 2>/dev/null
fi
fi
}