From deebb890dfa2610ba53ce0663d9e370dbbfd0207 Mon Sep 17 00:00:00 2001 From: Livia Medeiros <74449973+LiviaMedeiros@users.noreply.github.com> Date: Wed, 18 Aug 2021 08:23:11 +0800 Subject: [PATCH] Linux build multiarch (#2) * Add bash abiproxy builder * Adjust python part remove unneeded python dependencies do not rely on current working directory * Add bash apk builder and signer * Restore multiarch support --- .gitignore | 4 + abiproxy/build_release.sh | 69 +++++++++++++++++ build_release.sh | 152 ++++++++++++++++++++++++++++++++++++++ buildassets.py | 34 +++++---- requirements.txt | 2 - sign_example.sh | 22 ++++++ 6 files changed, 265 insertions(+), 18 deletions(-) create mode 100644 abiproxy/build_release.sh create mode 100644 build_release.sh create mode 100644 sign_example.sh diff --git a/.gitignore b/.gitignore index 09f883e..445cbf7 100644 --- a/.gitignore +++ b/.gitignore @@ -419,6 +419,10 @@ FodyWeavers.xsd .vscode/ abiproxy/build/ +abiproxy/.ninja_deps +abiproxy/.ninja_log +abiproxy/build.ninja lib/cocos_old/ lib/Dobby_old/ sign.bat +sign.sh diff --git a/abiproxy/build_release.sh b/abiproxy/build_release.sh new file mode 100644 index 0000000..d213f27 --- /dev/null +++ b/abiproxy/build_release.sh @@ -0,0 +1,69 @@ +#!/bin/bash +BASEDIR="$(realpath "$(dirname "${0}")")" + +# env-based +CMAKE="${MT_CMAKE:-cmake}" # /usr/bin/cmake +NINJA="${MT_NINJA:-ninja}" # /usr/bin/ninja + +# arg-based +NDK="${1:-${BASEDIR}/../ndk/android-ndk-r16b}" +TARCHS="${2:-"armeabi-v7a arm64-v8a"}" + +_start() { + [ -d "${NDK}" ] || _errorexit 6 "NDK directory does not exist! Tried path: ${NDK}" + NDK=$(realpath "${NDK}") + echo "Found ndk directory ${NDK}" + + [ -f "${NDK}/build/cmake/android.toolchain.cmake" ] || _errorexit 7 "NDK is missing! Unpack it into ${NDK}" + + mkdir -p "${BASEDIR}/build" + _build +} + +_build() { + echo "Building libraries." + + for tarch in ${TARCHS} + do + rm -rf "${BASEDIR}/build/${tarch}" + mkdir -p "${BASEDIR}/build/${tarch}" + + echo "Running cmake ${tarch}..." + cd "${BASEDIR}" + ${CMAKE} -G Ninja \ + -DANDROID_ABI="${tarch}" \ + -DCMAKE_BUILD_TYPE:STRING="Release" \ + -DCMAKE_INSTALL_PREFIX:PATH="${BASEDIR}/build/${tarch}" \ + -DCMAKE_TOOLCHAIN_FILE:FILEPATH="${NDK}/build/cmake/android.toolchain.cmake" \ + -DCMAKE_MAKE_PROGRAM:FILEPATH="${NINJA}" \ + -DANDROID_PLATFORM="android-19" \ + -DCMAKE_SYSTEM_NAME="Android" \ + -DCMAKE_ANDROID_ARCH_ABI="${tarch}" \ + -DCMAKE_ANDROID_NDK="${NDK}" \ + -DCMAKE_SYSTEM_VERSION="16" \ + -DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION="clang" \ + -DCMAKE_ANDROID_STL_TYPE="gnustl_static" \ + "${BASEDIR}/" + [ "$?" -ne "0" ] && _errorexit 1 "cmake failed for ${tarch}" + ${NINJA} + [ "$?" -ne "0" ] && _errorexit 2 "ninja failed for ${tarch}" + + [ -f "${BASEDIR}/libabiproxy.so" ] || _errorexit 3 "libabiproxy was not cmade for ${tarch}!" + mv "${BASEDIR}/libabiproxy.so" "${BASEDIR}/build/${tarch}/libabiproxy.so" + done + + _exit +} + +_errorexit() { + [ ! -z "$2" ] && echo "$2" + echo "An error has occurred, exiting." + exit ${1} +} + +_exit() { + echo "Successful." + exit 0 +} + +_start diff --git a/build_release.sh b/build_release.sh new file mode 100644 index 0000000..c4df506 --- /dev/null +++ b/build_release.sh @@ -0,0 +1,152 @@ +#!/bin/bash +BASEDIR="$(realpath "$(dirname "${0}")")" + +# env-based +BASH="${BASH:-bash}" # /bin/bash +CMAKE="${MT_CMAKE:-cmake}" # /usr/bin/cmake +NINJA="${MT_NINJA:-ninja}" # /usr/bin/ninja +CURL="${MT_CURL:-curl}" # /usr/bin/curl +JAVA="${MT_JAVA:-java}" # /usr/bin/java +PYTHON="${MT_PYTHON:-python3}" # /usr/bin/python3.8 +JARSIGNER="${MT_JARSIGNER:-jarsigner}" # /usr/bin/jarsigner +APKTOOL="${MT_APKTOOL:-apktool_2.5.0.jar}" + +# arg-based +SRCAPK="${1:-${BASEDIR}/apk/vanilla.apk}" +VERSION="${2:-v0.50}" +NDK="${3:-${BASEDIR}/ndk/android-ndk-r21e}" +FORCEOW="${4:-true}" +TARCHS="${5:-"armeabi-v7a arm64-v8a"}" + +RESULT="${BASEDIR}/build/io.kamihama.magiatranslate.${VERSION}.apk" + +_pre() { + [ -f "${SRCAPK}" ] || _errorexit 5 "Did not find MagiReco APK! Tried path: ${SRCAPK}" + echo "Found apk ${SRCAPK}" + + [ -d "${NDK}" ] || _errorexit 6 "NDK directory does not exist! Tried path: ${NDK}" + NDK=$(realpath "${NDK}") + echo "Found ndk directory ${NDK}" + + [ -f "${NDK}/build/cmake/android.toolchain.cmake" ] || _errorexit 7 "NDK is missing! Unpack it into ${NDK}" + + for executie in ${BASH} ${CMAKE} ${NINJA} ${CURL} ${JAVA} ${PYTHON} + do + [ -x "$(command -v "${executie}")" ] || echo "Warning: ${executie} is missing, please install or provide path via environment" + done + + _start +} + +_start() { + mkdir -p "${BASEDIR}/build" + + [ ! -f "${BASEDIR}/build/${APKTOOL}" ] && _get_apktool + + [[ ! -d "${BASEDIR}/build/app/" || "${FORCEOW}" = true ]] && _create + + _build +} + +_get_apktool() { + echo "Downloading apktool..." + ${CURL} -A "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64)" -o "${BASEDIR}/build/${APKTOOL}" -L "https://bitbucket.org/iBotPeaches/apktool/downloads/${APKTOOL}" +} + +_create() { + echo "Removing existing build files..." + rm -rf "${BASEDIR}/build/app" + echo "Running apktool..." + ${JAVA} -jar "${BASEDIR}/build/${APKTOOL}" d "${SRCAPK}" -o "${BASEDIR}/build/app/" + mkdir -p "${BASEDIR}/build/app/smali/com/loadLib" + for tarch in ${TARCHS} + do + mkdir -p "${BASEDIR}/build/app/lib/${tarch}" + done + + echo "Applying smali patches..." + git -C "${BASEDIR}" apply --stat "${BASEDIR}/patches/NativeBridge.patch" + git -C "${BASEDIR}" apply --stat "${BASEDIR}/patches/Hook.patch" + git -C "${BASEDIR}" apply "${BASEDIR}/patches/NativeBridge.patch" + git -C "${BASEDIR}" apply "${BASEDIR}/patches/Hook.patch" + echo "Applying misc patches..." + # cp "${BASEDIR}/patches/images/story_ui_sprites00_patch.plist" "${BASEDIR}/build/app/assets/package/story/story_ui_sprites00.plist" + # cp "${BASEDIR}/patches/images/story_ui_sprites00_patch.png" "${BASEDIR}/build/app/assets/package/story/story_ui_sprites00.png" + + cp "${BASEDIR}/patches/koruri-semibold.ttf" "${BASEDIR}/build/app/assets/fonts/koruri-semibold.ttf" + + echo "Updating sprites and AndroidManifest.xml..." + ${PYTHON} "${BASEDIR}/buildassets.py" +} + + +_build() { + echo "Copying new smali files..." + cp "${BASEDIR}"/smali/loader/*.smali "${BASEDIR}/build/app/smali/com/loadLib/" + mkdir -p "${BASEDIR}/build/app/smali_classes2/io/kamihama/magianative" + echo "Copying magianative..." + cp "${BASEDIR}"/smali/MagiaNative/app/src/main/java/io/kamihama/magianative/*.smali "${BASEDIR}/build/app/smali_classes2/io/kamihama/magianative/" + echo "Copying libraries..." + cp -r "${BASEDIR}/smali/okhttp-smali/okhttp3/" "${BASEDIR}/build/app/smali_classes2/okhttp3/" + cp -r "${BASEDIR}/smali/okhttp-smali/okio/" "${BASEDIR}/build/app/smali_classes2/okio/" + echo "Copying unknown..." + cp -r "${BASEDIR}/patches/unknown/" "${BASEDIR}/build/app/unknown/" + cp "${BASEDIR}/patches/strings.xml" "${BASEDIR}/build/app/res/values/strings.xml" + + echo "Building libraries." + + for tarch in ${TARCHS} + do + rm -rf "${BASEDIR}/build/${tarch}" + mkdir -p "${BASEDIR}/build/${tarch}" + + echo "Running cmake ${tarch}..." + cd "${BASEDIR}/build/${tarch}" + ${CMAKE} -G Ninja \ + -DANDROID_ABI="${tarch}" \ + -DCMAKE_BUILD_TYPE:STRING="Release" \ + -DCMAKE_INSTALL_PREFIX:PATH="${BASEDIR}/build/${tarch}" \ + -DCMAKE_TOOLCHAIN_FILE:FILEPATH="${NDK}/build/cmake/android.toolchain.cmake" \ + -DCMAKE_MAKE_PROGRAM:FILEPATH="${NINJA}" \ + -DANDROID_PLATFORM="21" \ + -DCMAKE_SYSTEM_NAME="Android" \ + -DCMAKE_ANDROID_ARCH_ABI="${tarch}" \ + -DCMAKE_ANDROID_NDK="${NDK}" \ + -DCMAKE_SYSTEM_VERSION="16" \ + -DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION="clang" \ + -DDOBBY_DEBUG="OFF" \ + "${BASEDIR}/" + [ "$?" -ne "0" ] && _errorexit 1 "cmake failed for ${tarch}" + ${NINJA} + [ "$?" -ne "0" ] && _errorexit 2 "ninja failed for ${tarch}" + + echo "Copying libraries for ${tarch}..." + cp "${BASEDIR}/build/${tarch}/libuwasa.so" "${BASEDIR}/build/app/lib/${tarch}/libuwasa.so" + cp "${BASEDIR}/abiproxy/build/${tarch}/libabiproxy.so" "${BASEDIR}/build/app/lib/${tarch}/libabiproxy.so" + done + + echo "Rebuilding APK..." + ${JAVA} -jar "${BASEDIR}/build/${APKTOOL}" b "${BASEDIR}/build/app/" -o "${RESULT}" + + _signandupload +} + +_signandupload() { + echo "Signing apk..." + [ -f "${BASEDIR}/sign.sh" ] || _errorexit 8 "Signer is missing! It must be there: ${BASEDIR}/sign.sh" + ${BASH} "${BASEDIR}/sign.sh" "${RESULT}" + [ "$?" -ne "0" ] && _errorexit 3 || _exit +} + +_errorexit() { + [ ! -z "$2" ] && echo "$2" + echo "An error has occurred, exiting." + exit ${1} +} + +_exit() { + echo "Finished!" + exit 0 +} + +_pre diff --git a/buildassets.py b/buildassets.py index b0af466..38c16ea 100644 --- a/buildassets.py +++ b/buildassets.py @@ -3,7 +3,7 @@ from PIL import Image import plistlib import ast from pathlib import Path -sys.path.append('lib/untp/src/untp') +sys.path.append(os.path.dirname(os.path.realpath(__file__)) + '/lib/untp/src/untp') import untp from PyTexturePacker import Packer from shutil import copyfile @@ -19,9 +19,12 @@ def rmdir(directory): else: item.unlink() directory.rmdir() - -en_path = os.path.dirname(os.path.realpath(__file__)) + "/patches/magia-en-apk-assets/" -jp_path = os.path.dirname(os.path.realpath(__file__)) + "/build/app/assets/package/" + +basePath = os.path.dirname(os.path.realpath(__file__)) +os.chdir(basePath) + +en_path = basePath + "/patches/magia-en-apk-assets/" +jp_path = basePath + "/build/app/assets/package/" print("EN Path: " + en_path) print("JP Path: " + jp_path) @@ -31,8 +34,8 @@ for path in Path(en_path).rglob('*.png'): en_assets[path.name] = path for path in Path(jp_path).rglob('*.png'): jp_assets[path.name] = path - - + + required_assets = [["quest_image0","quest_image1"], ["data_download0"], @@ -59,10 +62,9 @@ text = path.read_text() text = text.replace("com.aniplex.magireco", "io.kamihama.magiatranslate") path.write_text(text) -basePath = os.path.dirname(os.path.realpath(__file__)) rmdir("build/assets") Path("build/assets").mkdir(parents=True, exist_ok=True) - + for assets in required_assets: rmdir("build/assets/work_jp") Path("build/assets/work_jp").mkdir(parents=True, exist_ok=True) @@ -77,26 +79,26 @@ for assets in required_assets: jp_asset_plist = str(jp_assets[asset_png])[:-4] + ".plist" jp_asset_png = jp_assets[asset_png] #print("Working on JP " + jp_asset_plist) - + untp.unpacker(str(jp_asset_plist), image_file = str(jp_asset_png), output_dir = "build/assets/work_jp") untp.unpacker(str(jp_asset_plist), image_file = str(jp_asset_png), output_dir = "build/assets/work_jp_old") for asset in assets: asset_png = asset + ".png" - + if asset_png in en_assets: na_asset_plist = str(en_assets[asset_png])[:-4] + ".plist" na_asset_png = en_assets[asset_png] #print("Working on NA " + na_asset_plist) untp.unpacker(str(na_asset_plist), image_file = str(na_asset_png), output_dir = "build/assets/work_en") - #print("Skipping NA %s" % asset_png) - + #print("Skipping NA %s" % asset_png) + for toCopy in Path("build/assets/work_en").rglob("*.*"): filename = os.path.basename(str(toCopy)) #print("Copying %s" % str(toCopy)[8:]) if (filename not in ignored_images): copyfile("build/assets/work_en/" + filename, "build/assets/work_jp/" + filename) - + manualPath = basePath + "patches/images/" + assets[0] + "/" if os.path.exists(manualPath): print("Adding manual replacements for " + assets[0] + ".") @@ -104,7 +106,7 @@ for assets in required_assets: filename = os.path.basename(str(toCopy)) print("Copying " + filename + "...") copyfile(toCopy, "build/assets/work_jp/" + filename) - + if assets[0] == "toppage_bg_020": print("Manual override for toppage") packer = Packer.create(max_width=2048, max_height=1920, bg_color=0x00ffffff, enable_rotated=False) @@ -125,6 +127,6 @@ for assets in required_assets: savedir = os.path.dirname(jp_asset_png) print("Saving to %s" % savedir) file_names = os.listdir("build/assets/work_out/") - + for file_name in file_names: - shutil.move(os.path.join("build/assets/work_out/", file_name), savedir) \ No newline at end of file + shutil.move(os.path.join("build/assets/work_out/", file_name), savedir) diff --git a/requirements.txt b/requirements.txt index 7455acb..cc3c469 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,2 @@ parse==1.18.0 -Pillow==8.0.1 -pkg-resources==0.0.0 PyTexturePacker==1.1.0 diff --git a/sign_example.sh b/sign_example.sh new file mode 100644 index 0000000..5327013 --- /dev/null +++ b/sign_example.sh @@ -0,0 +1,22 @@ +#!/bin/bash +BASEDIR="$(realpath "$(dirname "${0}")")" + +# env-based +JARSIGNER="${MT_JARSIGNER:-jarsigner}" # /usr/bin/jarsigner + +# arg-based +APK="${1:-${BASEDIR}/build/io.kamihama.magiatranslate.v0.50.apk}" +KEYSTORE="${2:-${BASEDIR}/changeme.keystore}" + +if [ ! -f "${APK}" ] +then + echo "Missing apk to sign! Tried file: ${APK}" + exit 1 +fi +if [ ! -f "${KEYSTORE}" ] +then + echo "Missing keystore! Tried file: ${KEYSTORE}" + exit 2 +fi + +${JARSIGNER} -sigalg SHA512withRSA -digestalg SHA-512 -keystore "${KEYSTORE}" "${APK}" -storepass changeme name