diff --git a/.github/.gitignore b/.github/.gitignore
index 139ec1540..14d17eb2c 100644
--- a/.github/.gitignore
+++ b/.github/.gitignore
@@ -1 +1,2 @@
build_init.bat
+jdk.ini
diff --git a/.github/android-ghactions.ini b/.github/android-ghactions.ini
new file mode 100644
index 000000000..5542e27fd
--- /dev/null
+++ b/.github/android-ghactions.ini
@@ -0,0 +1,16 @@
+[constants]
+andriod_ndk_toolchain_bin = '/usr/local/lib/android/sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin'
+
+[properties]
+android_platform_jar = '/usr/local/lib/android/sdk/platforms/android-30/android.jar'
+
+[binaries]
+# android_ndk_toolchain_prefix comes from the correct cross-file in ./android/cross
+c = andriod_ndk_toolchain_bin / (android_ndk_toolchain_prefix + 'clang')
+cpp = andriod_ndk_toolchain_bin / (android_ndk_toolchain_prefix + 'clang++')
+strip = andriod_ndk_toolchain_bin / 'llvm-strip'
+d8 = '/usr/local/lib/android/sdk/build-tools/32.0.0/d8'
+aapt = '/usr/local/lib/android/sdk/build-tools/32.0.0/aapt'
+aapt2 = '/usr/local/lib/android/sdk/build-tools/32.0.0/aapt2'
+zipalign = '/usr/local/lib/android/sdk/build-tools/32.0.0/zipalign'
+apksigner = '/usr/local/lib/android/sdk/build-tools/32.0.0/apksigner'
diff --git a/.github/build.sh b/.github/build.sh
index 63f780389..d38733fe8 100755
--- a/.github/build.sh
+++ b/.github/build.sh
@@ -4,11 +4,11 @@ set -euo pipefail
IFS=$'\n\t'
if [ -z "${PLATFORM_SHORT-}" ]; then
- >&2 echo "PLATFORM_SHORT not set (lin, mac, win)"
+ >&2 echo "PLATFORM_SHORT not set (lin, mac, win, and)"
exit 1
fi
if [ -z "${MACHINE_SHORT-}" ]; then
- >&2 echo "MACHINE_SHORT not set (x86_64, i686)"
+ >&2 echo "MACHINE_SHORT not set (x86_64, i686, arm64, arm)"
exit 1
fi
if [ -z "${TOOLSET_SHORT-}" ]; then
@@ -54,9 +54,14 @@ BUILD_INIT_BAT
exit 0
fi
+if [ -d build ]; then
+ rm -r build
+fi
+
other_flags=$'\t-Dmod_id='
other_flags+=$MOD_ID
bin_suffix=
+bin_prefix=
static_flag=
if [ $STATIC_DYNAMIC == "static" ]; then
static_flag=-Dstatic=prebuilt
@@ -76,6 +81,9 @@ fi
if [ $TOOLSET_SHORT == "mingw" ]; then
bin_suffix=$bin_suffix.exe
fi
+if [ $PLATFORM_SHORT == "and" ]; then
+ bin_suffix=$bin_suffix.apk
+fi
stable_or_beta="n"
if [ "$RELTYPE" == "beta" ]; then
other_flags+=$'\t-Dbeta=true'
@@ -121,25 +129,78 @@ if [ $PLATFORM_SHORT == "mac" ]; then
export CXXFLAGS=-mmacosx-version-min=$macosx_version_min
export LDFLAGS=-mmacosx-version-min=$macosx_version_min
fi
+powder_bin=${bin_prefix}powder$bin_suffix
if [ "$RELTYPE" == "tptlibsdev" ]; then
+ if [ -z "${GITHUB_REPOSITORY_OWNER-}" ]; then
+ >&2 echo "GITHUB_REPOSITORY_OWNER not set (whose tpt-libs to clone?)"
+ exit 1
+ fi
tptlibsbranch=`echo $RELNAME | cut -d '-' -f 2-` # $RELNAME is tptlibsdev-BRANCH
- git clone https://github.com/$GITHUB_REPOSITORY_OWNER/tpt-libs --branch $tptlibsbranch
+ if [ ! -d tpt-libs ]; then
+ git clone https://github.com/$GITHUB_REPOSITORY_OWNER/tpt-libs --branch $tptlibsbranch
+ fi
cd tpt-libs
- if [ ! -d patches/$MACHINE_SHORT-$PLATFORM_SHORT-$TOOLSET_SHORT-$STATIC_DYNAMIC ]; then
+ quad=$MACHINE_SHORT-$PLATFORM_SHORT-$TOOLSET_SHORT-$STATIC_DYNAMIC
+ if [ ! -d patches/$quad ]; then
cd ..
- echo "no prebuilt libraries for this configuration" > powder$bin_suffix
+ echo "no prebuilt libraries for this configuration" > $powder_bin
exit 0
fi
- VTAG=v00000000000000 ./build.sh
- cd ../subprojects
- 7z x ../tpt-libs/temp/libraries.zip
- other_flags+=$'\t-Dtpt_libs_vtag=v00000000000000'
+ tpt_libs_vtag=v00000000000000
+ if [ ! -f .ok ]; then
+ VTAG=$tpt_libs_vtag ./build.sh
+ touch .ok
+ cd ../subprojects
+ if [ -d tpt-libs-prebuilt-$quad-$tpt_libs_vtag ]; then
+ rm -r tpt-libs-prebuilt-$quad-$tpt_libs_vtag
+ fi
+ 7z x ../tpt-libs/temp/libraries.zip
+ fi
cd ..
+ other_flags+=$'\t-Dtpt_libs_vtag='
+ other_flags+=$tpt_libs_vtag
+fi
+if [ $PLATFORM_SHORT == "and" ]; then
+ other_flags+=$'\t--cross-file='
+ if [ $MACHINE_SHORT == "x86_64" ]; then
+ other_flags+=android/cross/x86_64.ini
+ fi
+ if [ $MACHINE_SHORT == "i686" ]; then
+ other_flags+=android/cross/x86.ini
+ fi
+ if [ $MACHINE_SHORT == "arm64" ]; then
+ other_flags+=android/cross/arm64-v8a.ini
+ fi
+ if [ $MACHINE_SHORT == "arm" ]; then
+ other_flags+=android/cross/armeabi-v7a.ini
+ fi
+ other_flags+=$'\t--cross-file=.github/android-ghactions.ini'
+ if [ -z "${JAVA_HOME_8_X64-}" ]; then
+ >&2 echo "JAVA_HOME_8_X64 not set (where is jdk?)"
+ exit 1
+ fi
+ cat << BUILD_INIT_BAT > .github/jdk.ini
+[properties]
+java_runtime_jar = '$JAVA_HOME_8_X64/jre/lib/rt.jar'
+
+[binaries]
+javac = '$JAVA_HOME_8_X64/bin/javac'
+jar = '$JAVA_HOME_8_X64/bin/jar'
+BUILD_INIT_BAT
+ other_flags+=$'\t--cross-file=.github/jdk.ini'
+ other_flags+=$'\t-Dhttp=false'
fi
meson -Dbuildtype=release -Db_pie=false -Dworkaround_gcc_no_pie=true -Db_staticpic=false $lto_flag $static_flag -Dinstall_check=true $other_flags build
cd build
ninja
-if [ $PLATFORM_SHORT == "lin" ] || [ $PLATFORM_SHORT == "mac" ]; then
- strip powder$bin_suffix
+if [ $PLATFORM_SHORT == "and" ]; then
+ $ANDROID_SDK_ROOT/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip libpowder.so
+elif [ $PLATFORM_SHORT != "win" ]; then
+ strip $powder_bin
fi
-cp powder$bin_suffix ..
+if [ $PLATFORM_SHORT == "and" ]; then
+ $JAVA_HOME_8_X64/bin/keytool -genkeypair -keystore keystore.jks -alias androidkey -validity 10000 -keyalg RSA -keysize 2048 -keypass bagelsbagels -storepass bagelsbagels -dname "CN=nobody"
+ meson configure -Dandroid_keystore=`readlink -f keystore.jks`
+ ANDROID_KEYSTORE_PASS=bagelsbagels ninja powder.apk
+fi
+cp $powder_bin ..
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index aae6ad46b..df5f3ba61 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -46,14 +46,15 @@ jobs:
strategy:
fail-fast: false
matrix:
-# | lin-x86_64 | mac-x86_64 | win-x86_64 | lin-i686 | mac-i686 | win-i686 | lin-arm64 | mac-arm64 | win-arm64
-# --------------+------------+------------+------------+------------+------------+------------+------------+------------+------------
-# gcc-static | | | NO | NO | NO | NO | NO | | NO
-# msvc-static | NO | NO | | NO | NO | | NO | NO | NO
-# mingw-static | | NO | | NO | NO | NO | NO | NO | NO
-# gcc-dynamic | | | NO | NO | NO | NO | NO | NO [1] | NO
-# msvc-dynamic | NO | NO | | NO | NO | | NO | NO | NO
-# mingw-dynamic | | NO | | NO | NO | NO | NO | NO | NO
+# | x86_64 | i686 | arm64 | arm
+# | lin | mac | win | and | lin | mac | win | and | lin | mac | win | and | lin | mac | win | and
+# ---------------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------
+# gcc | | | NO | | NO | NO | NO | | NO | | NO | | NO | NO | NO |
+# static msvc | NO | NO | | NO | NO | NO | | NO | NO | NO | NO | NO | NO | NO | NO | NO
+# mingw | | NO | | NO | NO | NO | NO | NO | NO | NO | NO | NO | NO | NO | NO | NO
+# gcc | | | NO | NO | NO | NO | NO | NO | NO |NO [1]| NO | NO | NO | NO | NO | NO
+# dynamic msvc | NO | NO | | NO | NO | NO | | NO | NO | NO | NO | NO | NO | NO | NO | NO
+# mingw | | NO | | NO | NO | NO | NO | NO | NO | NO | NO | NO | NO | NO | NO | NO
#
# [1] This is only required for development on ARM Macs. We have no access to such devices, so someone will
# have to help us figure out how to get dynamic libraries.
@@ -63,8 +64,8 @@ jobs:
#########################################################
############# BEGIN BLOCK FOR COPYING BELOW #############
#########################################################
- machine_short: [x86_64, i686, arm64]
- platform_short: [lin, mac, win]
+ machine_short: [x86_64, i686, arm64, arm]
+ platform_short: [lin, mac, win, and]
toolset_short: [gcc, msvc, mingw]
static_dynamic: [static, dynamic]
exclude:
@@ -89,23 +90,43 @@ jobs:
- platform_short: mac # see [1]
static_dynamic: dynamic
machine_short: arm64
+ - platform_short: and
+ static_dynamic: dynamic
+ - platform_short: and
+ toolset_short: msvc
+ - platform_short: and
+ toolset_short: mingw
+ - platform_short: lin
+ machine_short: arm
+ - platform_short: win
+ machine_short: arm
+ - platform_short: mac
+ machine_short: arm
#########################################################
############## END BLOCK FOR COPYING BELOW ##############
#########################################################
include:
- platform_short: lin
os: ubuntu-18.04
+ prefix: ''
suffix: ''
- platform_short: mac
os: macos-11.0
+ prefix: ''
suffix: ''
- platform_short: win
os: windows-2019
+ prefix: ''
suffix: '.exe'
- platform_short: lin
toolset_short: mingw
os: ubuntu-20.04
+ prefix: ''
suffix: '.exe'
+ - platform_short: and
+ os: ubuntu-18.04
+ prefix: ''
+ suffix: '.apk'
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
@@ -137,14 +158,14 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.release.outputs.upload_url }}
- asset_path: powder${{ matrix.suffix }}
- asset_name: powder-${{ steps.get_type.outputs.NAME }}-${{ matrix.machine_short }}-${{ matrix.platform_short }}-${{ matrix.toolset_short }}-${{ matrix.static_dynamic }}${{ matrix.suffix }}
+ asset_path: ${{ matrix.prefix }}powder${{ matrix.suffix }}
+ asset_name: ${{ matrix.prefix }}powder-${{ steps.get_type.outputs.NAME }}-${{ matrix.machine_short }}-${{ matrix.platform_short }}-${{ matrix.toolset_short }}-${{ matrix.static_dynamic }}${{ matrix.suffix }}
asset_content_type: application/zip
- uses: actions/upload-artifact@v2
if: matrix.static_dynamic == 'static'
with:
- path: powder${{ matrix.suffix }}
- name: powder-${{ steps.get_type.outputs.NAME }}-${{ matrix.machine_short }}-${{ matrix.platform_short }}-${{ matrix.toolset_short }}-${{ matrix.static_dynamic }}${{ matrix.suffix }}
+ path: ${{ matrix.prefix }}powder${{ matrix.suffix }}
+ name: ${{ matrix.prefix }}powder-${{ steps.get_type.outputs.NAME }}-${{ matrix.machine_short }}-${{ matrix.platform_short }}-${{ matrix.toolset_short }}-${{ matrix.static_dynamic }}${{ matrix.suffix }}
starcatcher-publish:
runs-on: ubuntu-latest
needs: [build, release]
@@ -178,17 +199,35 @@ jobs:
- platform_short: mac # see [1]
static_dynamic: dynamic
machine_short: arm64
+ - platform_short: and
+ static_dynamic: dynamic
+ - platform_short: and
+ toolset_short: msvc
+ - platform_short: and
+ toolset_short: mingw
+ - platform_short: lin
+ machine_short: arm
+ - platform_short: win
+ machine_short: arm
+ - platform_short: mac
+ machine_short: arm
#########################################################
############## END BLOCK COPIED FROM ABOVE ##############
#########################################################
- static_dynamic: dynamic
include:
- platform_short: lin
+ prefix: ''
suffix: ''
- platform_short: mac
+ prefix: ''
suffix: ''
- platform_short: win
+ prefix: ''
suffix: '.exe'
+ - platform_short: and
+ prefix: ''
+ suffix: '.apk'
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
@@ -198,15 +237,15 @@ jobs:
run: python3 ./.github/get-type.py ${{ github.ref }}
- uses: actions/download-artifact@v1
with:
- name: powder-${{ steps.get_type.outputs.NAME }}-${{ matrix.machine_short }}-${{ matrix.platform_short }}-${{ matrix.toolset_short }}-${{ matrix.static_dynamic }}${{ matrix.suffix }}
+ name: ${{ matrix.prefix }}powder-${{ steps.get_type.outputs.NAME }}-${{ matrix.machine_short }}-${{ matrix.platform_short }}-${{ matrix.toolset_short }}-${{ matrix.static_dynamic }}${{ matrix.suffix }}
- run: sudo apt update && sudo apt install lftp
- if: steps.get_type.outputs.TYPE != 'dev' && matrix.static_dynamic == 'static'
- run: bash -c './.github/starcatcher-publish.sh powder${{ matrix.suffix }}'
+ run: bash -c './.github/starcatcher-publish.sh ${{ matrix.prefix }}powder${{ matrix.suffix }}'
env:
STARCATCHER_PUBLISH_HOSTPORT: ${{ secrets.STARCATCHER_PUBLISH_HOSTPORT }}
STARCATCHER_PUBLISH_USERNAME: ${{ secrets.STARCATCHER_PUBLISH_USERNAME }}
STARCATCHER_PUBLISH_PASSWORD: ${{ secrets.STARCATCHER_PUBLISH_PASSWORD }}
- STARCATCHER_PUBLISH_FILENAME: powder-${{ steps.get_type.outputs.NAME }}-${{ matrix.machine_short }}-${{ matrix.platform_short }}-${{ matrix.toolset_short }}-${{ matrix.static_dynamic }}${{ matrix.suffix }}
+ STARCATCHER_PUBLISH_FILENAME: ${{ matrix.prefix }}powder-${{ steps.get_type.outputs.NAME }}-${{ matrix.machine_short }}-${{ matrix.platform_short }}-${{ matrix.toolset_short }}-${{ matrix.static_dynamic }}${{ matrix.suffix }}
starcatcher-release:
runs-on: ubuntu-latest
needs: [starcatcher-publish, release]
diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
new file mode 100644
index 000000000..ba2fed4ab
--- /dev/null
+++ b/android/AndroidManifest.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/align-apk.py b/android/align-apk.py
new file mode 100644
index 000000000..acdfeca56
--- /dev/null
+++ b/android/align-apk.py
@@ -0,0 +1,26 @@
+import os
+import os.path
+import subprocess
+import sys
+
+(
+ script,
+ zipalign,
+ build_dir,
+ unsigned_name,
+ unaligned_name,
+) = sys.argv
+
+unaligned_path = os.path.join(build_dir, unaligned_name)
+unsigned_path = os.path.join(build_dir, unsigned_name)
+
+if os.path.exists(unsigned_path):
+ os.remove(unsigned_path)
+
+if subprocess.run([
+ zipalign,
+ '-f', '4',
+ unaligned_path,
+ unsigned_path,
+]).returncode:
+ sys.exit(1)
diff --git a/android/build-apk.py b/android/build-apk.py
new file mode 100644
index 000000000..099b84b06
--- /dev/null
+++ b/android/build-apk.py
@@ -0,0 +1,102 @@
+import os
+import os.path
+import shutil
+import subprocess
+import sys
+
+(
+ script,
+ d8,
+ aapt,
+ aapt2,
+ source_dir,
+ build_dir,
+ private_name,
+ unaligned_name,
+ sha_name,
+ android_jar,
+ sdl_jar,
+ powder_jar,
+ tpt_arch,
+ debug_release,
+ manifest_xml,
+ *resources,
+) = sys.argv
+
+if tpt_arch == 'i686':
+ android_arch = 'x86'
+if tpt_arch == 'arm':
+ android_arch = 'armeabi-v7a'
+if tpt_arch == 'arm64':
+ android_arch = 'arm64-v8a'
+if tpt_arch == 'x86_64':
+ android_arch = 'x86_64'
+
+manifest_path = os.path.join(build_dir, manifest_xml)
+sha_path = os.path.join(build_dir, sha_name)
+unaligned_path = os.path.join(build_dir, unaligned_name)
+private_dir = os.path.join(build_dir, private_name)
+arch_dir = os.path.join(private_dir, 'lib', android_arch)
+sha_lib_path = os.path.join(arch_dir, sha_name)
+flat_dir = os.path.join(private_dir, 'flat')
+
+if os.path.exists(arch_dir):
+ shutil.rmtree(arch_dir)
+os.makedirs(arch_dir)
+if os.path.exists(sha_lib_path):
+ os.remove(sha_lib_path)
+if os.path.exists(unaligned_path):
+ os.remove(unaligned_path)
+if os.path.exists(flat_dir):
+ shutil.rmtree(flat_dir)
+os.makedirs(flat_dir)
+
+if subprocess.run([
+ aapt2,
+ 'compile',
+ '-o', os.path.join(private_dir, 'flat'),
+ *resources,
+], cwd = build_dir).returncode:
+ sys.exit(1)
+
+aapt2_link_inputs = []
+for root, dirs, files in os.walk(flat_dir):
+ for name in files:
+ if name.endswith(".flat"):
+ aapt2_link_inputs.append(os.path.join(root, name))
+if subprocess.run([
+ aapt2,
+ 'link',
+ '-o', unaligned_path,
+ '-I', android_jar,
+ '--manifest', manifest_path,
+ *aapt2_link_inputs,
+]).returncode:
+ sys.exit(1)
+
+shutil.copy(sha_path, sha_lib_path)
+if subprocess.run([
+ aapt,
+ 'add',
+ unaligned_path,
+ os.path.join('lib', android_arch, sha_name),
+], cwd = private_dir).returncode:
+ sys.exit(1)
+
+if subprocess.run([
+ d8,
+ os.path.join(build_dir, sdl_jar),
+ os.path.join(build_dir, powder_jar),
+ '--' + debug_release,
+ '--lib', android_jar,
+ '--min-api', '21',
+], cwd = private_dir).returncode:
+ sys.exit(1)
+
+if subprocess.run([
+ aapt,
+ 'add',
+ unaligned_path,
+ 'classes.dex',
+], cwd = private_dir).returncode:
+ sys.exit(1)
diff --git a/android/cross/arm64-v8a.ini b/android/cross/arm64-v8a.ini
new file mode 100644
index 000000000..224edfe5c
--- /dev/null
+++ b/android/cross/arm64-v8a.ini
@@ -0,0 +1,8 @@
+[constants]
+android_ndk_toolchain_prefix = 'aarch64-linux-android21-'
+
+[host_machine]
+system = 'android'
+cpu_family = 'aarch64'
+cpu = 'armv8'
+endian = 'little'
diff --git a/android/cross/armeabi-v7a.ini b/android/cross/armeabi-v7a.ini
new file mode 100644
index 000000000..d01c86f98
--- /dev/null
+++ b/android/cross/armeabi-v7a.ini
@@ -0,0 +1,8 @@
+[constants]
+android_ndk_toolchain_prefix = 'armv7a-linux-androideabi19-'
+
+[host_machine]
+system = 'android'
+cpu_family = 'arm'
+cpu = 'armv7a'
+endian = 'little'
diff --git a/android/cross/x86.ini b/android/cross/x86.ini
new file mode 100644
index 000000000..46de8fc66
--- /dev/null
+++ b/android/cross/x86.ini
@@ -0,0 +1,8 @@
+[constants]
+android_ndk_toolchain_prefix = 'i686-linux-android19-'
+
+[host_machine]
+system = 'android'
+cpu_family = 'x86'
+cpu = 'i686'
+endian = 'little'
diff --git a/android/cross/x86_64.ini b/android/cross/x86_64.ini
new file mode 100644
index 000000000..03437572d
--- /dev/null
+++ b/android/cross/x86_64.ini
@@ -0,0 +1,8 @@
+[constants]
+android_ndk_toolchain_prefix = 'x86_64-linux-android21-'
+
+[host_machine]
+system = 'android'
+cpu_family = 'x86_64'
+cpu = 'amd64'
+endian = 'little'
diff --git a/android/install-apk.py b/android/install-apk.py
new file mode 100644
index 000000000..b216d7c49
--- /dev/null
+++ b/android/install-apk.py
@@ -0,0 +1,28 @@
+import os
+import os.path
+import subprocess
+import sys
+
+(
+ script,
+ adb,
+ build_dir,
+ phony,
+ apk_name,
+) = sys.argv
+
+apk_path = os.path.join(build_dir, apk_name)
+phony_path = os.path.join(build_dir, phony)
+
+if os.path.exists(phony_path):
+ os.remove(phony_path)
+
+if subprocess.run([
+ adb,
+ 'install',
+ apk_path,
+]).returncode:
+ sys.exit(1)
+
+with open(phony_path, 'w') as _:
+ pass
diff --git a/android/meson.build b/android/meson.build
new file mode 100644
index 000000000..b3d138084
--- /dev/null
+++ b/android/meson.build
@@ -0,0 +1,6 @@
+android_manifest_xml = files('AndroidManifest.xml')
+powder_jar_sources = files(
+ 'uk/co/powdertoy/tpt/PowderActivity.java',
+)
+
+subdir('res')
diff --git a/android/powder-jar.py b/android/powder-jar.py
new file mode 100644
index 000000000..331366e2c
--- /dev/null
+++ b/android/powder-jar.py
@@ -0,0 +1,54 @@
+import os
+import os.path
+import shutil
+import subprocess
+import sys
+
+(
+ script,
+ javac,
+ jar,
+ source_dir,
+ build_dir,
+ private_name,
+ powder_jar_name,
+ android_jar,
+ java_runtime,
+ sdl_jar,
+ debug_release,
+ *javac_sources,
+) = sys.argv
+
+powder_jar_path = os.path.join(build_dir, powder_jar_name)
+private_dir = os.path.join(build_dir, private_name)
+class_dir = os.path.join(private_dir, 'class')
+
+if os.path.exists(powder_jar_path):
+ os.remove(powder_jar_path)
+if os.path.exists(class_dir):
+ shutil.rmtree(class_dir)
+os.makedirs(class_dir)
+
+if subprocess.run([
+ javac,
+ '-d', class_dir,
+ '-source', '1.8',
+ '-target', '1.8',
+ '-bootclasspath', java_runtime,
+ '-classpath', os.pathsep.join([ android_jar, sdl_jar ]),
+ *javac_sources,
+], cwd = build_dir).returncode:
+ sys.exit(1)
+
+jar_inputs = []
+for root, dirs, files in os.walk(class_dir):
+ for name in files:
+ if name.endswith(".class"):
+ jar_inputs.append(os.path.relpath(os.path.join(root, name), start = class_dir))
+if subprocess.run([
+ jar,
+ 'cMf',
+ powder_jar_path,
+ *jar_inputs,
+], cwd = class_dir).returncode:
+ sys.exit(1)
diff --git a/android/res/meson.build b/android/res/meson.build
new file mode 100644
index 000000000..2e09789d1
--- /dev/null
+++ b/android/res/meson.build
@@ -0,0 +1,6 @@
+android_resources = files(
+ 'mipmap-mdpi/ic_launcher.png',
+ 'values/colors.xml',
+ 'values/strings.xml',
+ 'values/styles.xml',
+)
diff --git a/android/res/mipmap-mdpi/ic_launcher.png b/android/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 000000000..2f092750c
Binary files /dev/null and b/android/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/android/res/values/colors.xml b/android/res/values/colors.xml
new file mode 100644
index 000000000..986599506
--- /dev/null
+++ b/android/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+
diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml
new file mode 100644
index 000000000..7a69b0f5c
--- /dev/null
+++ b/android/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ The Powder Toy
+
diff --git a/android/res/values/styles.xml b/android/res/values/styles.xml
new file mode 100644
index 000000000..82138f24e
--- /dev/null
+++ b/android/res/values/styles.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/android/run-apk.py b/android/run-apk.py
new file mode 100644
index 000000000..7ee08b853
--- /dev/null
+++ b/android/run-apk.py
@@ -0,0 +1,24 @@
+import os
+import os.path
+import subprocess
+import sys
+
+(
+ script,
+ adb,
+ build_dir,
+ phony,
+ apk_name,
+) = sys.argv
+
+apk_path = os.path.join(build_dir, apk_name)
+
+if subprocess.run([
+ adb,
+ 'shell',
+ 'am',
+ 'start',
+ '--activity-clear-top',
+ '-n', 'uk.co.powdertoy.tpt/.PowderActivity',
+]).returncode:
+ sys.exit(1)
diff --git a/android/sign-apk.py b/android/sign-apk.py
new file mode 100644
index 000000000..744b38ce0
--- /dev/null
+++ b/android/sign-apk.py
@@ -0,0 +1,35 @@
+import os
+import os.path
+import subprocess
+import sys
+
+(
+ script,
+ apksigner,
+ build_dir,
+ apk_name,
+ unsigned_name,
+ android_keystore,
+ android_keyalias,
+) = sys.argv
+
+if 'ANDROID_KEYSTORE_PASS' not in os.environ:
+ print('ANDROID_KEYSTORE_PASS not set')
+ sys.exit(1)
+
+unsigned_path = os.path.join(build_dir, unsigned_name)
+apk_path = os.path.join(build_dir, apk_name)
+
+if os.path.exists(apk_path):
+ os.remove(apk_path)
+
+if subprocess.run([
+ apksigner,
+ 'sign',
+ '--ks', android_keystore,
+ '--ks-key-alias', android_keyalias,
+ '--ks-pass', 'env:ANDROID_KEYSTORE_PASS',
+ '--out', apk_path,
+ unsigned_path,
+]).returncode:
+ sys.exit(1)
diff --git a/android/uk/co/powdertoy/tpt/PowderActivity.java b/android/uk/co/powdertoy/tpt/PowderActivity.java
new file mode 100644
index 000000000..eb2650b29
--- /dev/null
+++ b/android/uk/co/powdertoy/tpt/PowderActivity.java
@@ -0,0 +1,7 @@
+package uk.co.powdertoy.tpt;
+
+import org.libsdl.app.SDLActivity;
+
+public class PowderActivity extends SDLActivity
+{
+}
diff --git a/cross-examples/android.ini b/cross-examples/android.ini
new file mode 100644
index 000000000..93b31e970
--- /dev/null
+++ b/cross-examples/android.ini
@@ -0,0 +1,23 @@
+[constants]
+andriod_ndk_toolchain_bin = '/opt/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin'
+
+[properties]
+# only needed if you want to run the custom target powder_apk (powder.apk)
+android_platform_jar = '/opt/android-sdk/platforms/android-30/android.jar'
+java_runtime_jar = '/usr/lib/jvm/java-8-openjdk/jre/lib/rt.jar'
+
+[binaries]
+# android_ndk_toolchain_prefix comes from the correct cross-file in ./android/cross
+c = andriod_ndk_toolchain_bin / (android_ndk_toolchain_prefix + 'clang')
+# c = [ 'ccache', andriod_ndk_toolchain_bin / (android_ndk_toolchain_prefix + 'clang') ]
+cpp = andriod_ndk_toolchain_bin / (android_ndk_toolchain_prefix + 'clang++')
+# cpp = [ 'ccache', andriod_ndk_toolchain_bin / (android_ndk_toolchain_prefix + 'clang++') ]
+strip = andriod_ndk_toolchain_bin / 'llvm-strip'
+# only needed if you want to run the custom target powder_apk (powder.apk)
+javac = '/usr/lib/jvm/java-8-openjdk/bin/javac'
+jar = '/usr/lib/jvm/java-8-openjdk/bin/jar'
+d8 = '/opt/android-sdk/build-tools/32.0.0/d8'
+aapt = '/opt/android-sdk/build-tools/32.0.0/aapt'
+aapt2 = '/opt/android-sdk/build-tools/32.0.0/aapt2'
+zipalign = '/opt/android-sdk/build-tools/32.0.0/zipalign'
+apksigner = '/opt/android-sdk/build-tools/32.0.0/apksigner'
diff --git a/meson.build b/meson.build
index 97a66f50c..2cd1da71a 100644
--- a/meson.build
+++ b/meson.build
@@ -9,17 +9,17 @@ to_array = generator(
arguments: [ '@OUTPUT0@', '@OUTPUT1@', '@INPUT@', '@EXTRA_ARGS@' ]
)
-cpp_compiler = meson.get_compiler('cpp')
+c_compiler = meson.get_compiler('c')
copt_x86 = false
copt_64bit = false
copt_msvc = false
-if cpp_compiler.get_id() in [ 'msvc' ]
+if c_compiler.get_id() in [ 'msvc' ]
copt_compiler = 'msvc'
copt_msvc = true
-elif cpp_compiler.get_id() in [ 'gcc', 'clang' ]
+elif c_compiler.get_id() in [ 'gcc', 'clang' ]
copt_compiler = 'gcc'
else
- warning('unsupported compiler: ' + cpp_compiler.get_id() + '; you are on your own')
+ warning('unsupported compiler: ' + c_compiler.get_id() + '; you are on your own')
copt_compiler = 'gcc'
endif
if host_machine.cpu_family() in [ 'x86_64' ]
@@ -32,6 +32,8 @@ elif host_machine.cpu_family() in [ 'x86' ]
elif host_machine.cpu_family() in [ 'aarch64' ]
copt_architecture = 'arm64'
copt_64bit = true
+elif host_machine.cpu_family() in [ 'arm' ]
+ copt_architecture = 'arm'
else
warning('unsupported architecture: ' + host_machine.cpu_family() + '; you are on your own')
copt_architecture = 'i686'
@@ -42,6 +44,8 @@ elif host_machine.system() in [ 'windows' ]
copt_platform = 'win'
elif host_machine.system() in [ 'darwin' ]
copt_platform = 'mac'
+elif host_machine.system() in [ 'android' ]
+ copt_platform = 'and'
else
warning('unsupported platform: ' + host_machine.system() + '; you are on your own')
copt_platform = 'lin'
@@ -54,10 +58,10 @@ if uopt_static == 'system'
endif
elif uopt_static == 'prebuilt'
use_tpt_libs = 'static'
-else
- if copt_platform == 'win'
- use_tpt_libs = 'dynamic'
- endif
+elif copt_platform == 'win'
+ use_tpt_libs = 'dynamic'
+elif copt_platform == 'and'
+ use_tpt_libs = 'static'
endif
conf_data = configuration_data()
@@ -70,7 +74,7 @@ endif
tpt_libs_vtag = get_option('tpt_libs_vtag')
if tpt_libs_vtag == ''
- tpt_libs_vtag = 'v20220410083352'
+ tpt_libs_vtag = 'v20220414193335'
endif
if use_tpt_libs != 'no'
nope = false
@@ -83,6 +87,9 @@ if use_tpt_libs != 'no'
if copt_architecture == 'arm64' and copt_platform != 'mac'
nope = true
endif
+ if copt_platform == 'and'
+ nope = false
+ endif
quad_compiler = copt_compiler
if copt_platform == 'win' and copt_compiler == 'gcc'
quad_compiler = 'mingw'
@@ -114,18 +121,22 @@ if not copt_x86 or uopt_native
endif
uopt_lua = get_option('lua')
+if copt_platform == 'and' and uopt_lua == 'luajit'
+ message('LuaJIT is not supported on Android')
+ uopt_lua = 'lua5.2'
+endif
if uopt_lua == 'luajit'
lua_opt_dep = [ use_tpt_libs != 'no' ? tpt_libs.get_variable('luajit_dep') : dependency('luajit', static: uopt_static == 'system') ]
elif uopt_lua == 'lua5.2'
- lua_opt_dep = [ use_tpt_libs != 'no' ? tpt_libs.get_variable('lua52_dep') : dependency('lua5.2-c++', static: uopt_static == 'system') ]
+ lua_opt_dep = [ use_tpt_libs != 'no' ? tpt_libs.get_variable('lua52_dep') : dependency('lua5.2', static: uopt_static == 'system') ]
elif uopt_lua == 'lua5.1'
- lua_opt_dep = [ use_tpt_libs != 'no' ? tpt_libs.get_variable('lua51_dep') : dependency('lua5.1-c++', static: uopt_static == 'system') ]
+ lua_opt_dep = [ use_tpt_libs != 'no' ? tpt_libs.get_variable('lua51_dep') : dependency('lua5.1', static: uopt_static == 'system') ]
else
lua_opt_dep = []
endif
uopt_http = get_option('http')
-if uopt_http
+if uopt_http and copt_platform != 'and'
curl_opt_dep = [ use_tpt_libs != 'no' ? tpt_libs.get_variable('libcurl_dep') : dependency('libcurl', static: uopt_static == 'system') ]
else
curl_opt_dep = []
@@ -216,7 +227,7 @@ else
'-DUNICODE',
'-D_UNICODE',
]
- if uopt_static != 'none'
+ if uopt_static != 'none' and copt_platform != 'and'
project_link_args += [ '-static', '-static-libgcc', '-static-libstdc++' ]
endif
endif
@@ -232,12 +243,19 @@ else
args_ccomp += [ '-mmacosx-version-min=10.9' ]
project_link_args += [ '-mmacosx-version-min=10.9' ]
endif
- if not get_option('b_pie') and get_option('workaround_gcc_no_pie') # nice one, meson
- if copt_architecture != 'arm64' # no position independent executable for arm64
- if cpp_compiler.get_id() in [ 'clang' ]
- project_link_args += [ '-Wl,-no_pie' ]
- else
- project_link_args += [ '-no-pie' ]
+ if copt_platform == 'and'
+ if not copt_64bit
+ args_ccomp += [ '-U_FILE_OFFSET_BITS' ]
+ endif
+ project_link_args += [ '-static-libstdc++' ]
+ else
+ if not get_option('b_pie') and get_option('workaround_gcc_no_pie') # nice one, meson
+ if copt_architecture != 'arm64' # no position independent executable for arm64
+ if c_compiler.get_id() in [ 'clang' ]
+ project_link_args += [ '-Wl,-no_pie' ]
+ else
+ project_link_args += [ '-no-pie' ]
+ endif
endif
endif
endif
@@ -287,6 +305,7 @@ else
endif
conf_data.set('LIN', copt_platform == 'lin')
+conf_data.set('AND', copt_platform == 'and')
conf_data.set('WIN', copt_platform == 'win')
conf_data.set('MACOSX', copt_platform == 'mac')
conf_data.set('X86', copt_x86)
@@ -335,16 +354,120 @@ if get_option('build_powder')
if copt_platform == 'win'
powder_deps += other_dep
endif
- executable(
- 'powder',
- sources: powder_files,
- include_directories: [ project_inc, powder_inc ],
- c_args: project_c_args,
- cpp_args: project_cpp_args,
- gui_app: not get_option('debug'),
- link_args: project_link_args,
- dependencies: powder_deps,
- )
+ if copt_platform == 'and'
+ subdir('android')
+ powder_sha = shared_library(
+ 'powder',
+ sources: powder_files,
+ include_directories: [ project_inc, powder_inc ],
+ c_args: project_c_args,
+ cpp_args: project_cpp_args,
+ link_args: project_link_args,
+ dependencies: powder_deps,
+ )
+ python3 = find_program('python3')
+ android_platform_jar = meson.get_external_property('android_platform_jar')
+ java_runtime_jar = meson.get_external_property('java_runtime_jar')
+ android_keystore = get_option('android_keystore')
+ sdl_jar = tpt_libs.get_variable('sdl_jar')
+ powder_jar = custom_target(
+ 'powder-jar',
+ output: 'powder.jar',
+ command: [
+ python3,
+ files('android/powder-jar.py'),
+ find_program('javac'),
+ find_program('jar'),
+ meson.current_source_dir(),
+ meson.current_build_dir(),
+ '@PRIVATE_DIR@',
+ '@OUTPUT@',
+ android_platform_jar,
+ java_runtime_jar,
+ sdl_jar,
+ get_option('debug') ? 'debug' : 'release',
+ powder_jar_sources,
+ ],
+ )
+ unaligned_apk = custom_target(
+ 'build-apk',
+ output: 'powder.unaligned.apk',
+ input: powder_sha,
+ command: [
+ python3,
+ files('android/build-apk.py'),
+ find_program('d8'),
+ find_program('aapt'),
+ find_program('aapt2'),
+ meson.current_source_dir(),
+ meson.current_build_dir(),
+ '@PRIVATE_DIR@',
+ '@OUTPUT@',
+ '@INPUT@',
+ android_platform_jar,
+ sdl_jar,
+ powder_jar,
+ copt_architecture,
+ get_option('debug') ? 'debug' : 'release',
+ android_manifest_xml,
+ android_resources,
+ ],
+ )
+ unsigned_apk = custom_target(
+ 'align-apk',
+ output: 'powder.unsigned.apk',
+ input: unaligned_apk,
+ command: [
+ python3,
+ files('android/align-apk.py'),
+ find_program('zipalign'),
+ meson.current_build_dir(),
+ '@OUTPUT@',
+ '@INPUT@',
+ ],
+ )
+ signed_apk = custom_target(
+ 'sign-apk',
+ output: 'powder.apk',
+ input: unsigned_apk,
+ command: [
+ python3,
+ files('android/sign-apk.py'),
+ find_program('apksigner'),
+ meson.current_build_dir(),
+ '@OUTPUT@',
+ '@INPUT@',
+ android_keystore,
+ get_option('android_keyalias'),
+ ],
+ )
+ adb = find_program('adb', required: false)
+ if adb.found()
+ install_apk = custom_target(
+ 'install-apk',
+ input: signed_apk,
+ output: 'install-apk',
+ command: [ python3, files('android/install-apk.py'), adb, meson.current_build_dir(), '@OUTPUT@', '@INPUT@' ],
+ )
+ custom_target(
+ 'run-apk',
+ input: [ signed_apk, install_apk ],
+ output: 'run-apk',
+ command: [ python3, files('android/run-apk.py'), adb, meson.current_build_dir(), '@OUTPUT@', '@INPUT0@' ],
+ )
+ endif
+ else
+ executable(
+ 'powder',
+ sources: powder_files,
+ include_directories: [ project_inc, powder_inc ],
+ c_args: project_c_args,
+ cpp_args: project_cpp_args,
+ gui_app: not get_option('debug'),
+ link_args: project_link_args,
+ dependencies: powder_deps,
+ )
+ endif
endif
if get_option('build_render')
diff --git a/meson_options.txt b/meson_options.txt
index 4b66cfd8a..db0ad617f 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -140,5 +140,17 @@ option(
'tpt_libs_vtag',
type: 'string',
value: '',
- description: 'tpt-libs vtag override, not useful outside tpt-libs development'
+ description: 'tpt-libs vtag override, only used for tpt-libs development'
+)
+option(
+ 'android_keystore',
+ type: 'string',
+ value: '',
+ description: 'Path to Java keystore for signing an APK, only used for Android development'
+)
+option(
+ 'android_keyalias',
+ type: 'string',
+ value: 'androidkey',
+ description: 'Signing key alias for signing an APK, only used for Android development'
)
diff --git a/src/Config.template.h b/src/Config.template.h
index 06f8e2ff9..1e161cccd 100644
--- a/src/Config.template.h
+++ b/src/Config.template.h
@@ -14,6 +14,7 @@
#mesondefine DEBUG
#mesondefine IGNORE_UPDATES
#mesondefine LIN
+#mesondefine AND
#mesondefine NATIVE
#mesondefine NO_INSTALL_CHECK
#mesondefine OGLI
diff --git a/src/bson/BSON.h b/src/bson/BSON.h
index f275d5054..7a913ab9f 100644
--- a/src/bson/BSON.h
+++ b/src/bson/BSON.h
@@ -30,7 +30,7 @@
#include
#include "common/tpt-inline.h"
-#if defined(LIN) || defined(USE_STDINT)
+#if defined(AND) || defined(LIN) || defined(USE_STDINT)
#include
#include
#else
diff --git a/src/client/Client.cpp b/src/client/Client.cpp
index 663aad7cb..387843693 100644
--- a/src/client/Client.cpp
+++ b/src/client/Client.cpp
@@ -411,7 +411,7 @@ bool Client::DoInstallation()
unlink("powdertoy-tpt-open.desktop");
unlink("powdertoy-tpt-ptsave.desktop");
return !success;
-#elif defined MACOSX
+#else
return false;
#endif
}
diff --git a/src/common/Platform.cpp b/src/common/Platform.cpp
index bf04e2fe1..9b8127c7e 100644
--- a/src/common/Platform.cpp
+++ b/src/common/Platform.cpp
@@ -47,7 +47,7 @@ ByteString ExecutableName()
ByteString ret;
#if defined(WIN)
using Char = wchar_t;
-#elif defined(LIN)
+#else
using Char = char;
#endif
#if defined(WIN)
@@ -115,9 +115,9 @@ void DoRestart()
}
else
{
-#if !defined(RENDERER) && !defined(FONTEDITOR)
+# if !defined(RENDERER) && !defined(FONTEDITOR)
Client::Ref().Shutdown(); // very ugly hack; will fix soon(tm)
-#endif
+# endif
exit(0);
}
#elif defined(LIN) || defined(MACOSX)
diff --git a/src/lua/LuaCompat.c b/src/lua/LuaCompat.c
index cabf38806..dd84b1881 100644
--- a/src/lua/LuaCompat.c
+++ b/src/lua/LuaCompat.c
@@ -8,6 +8,19 @@ int luaL_typerror (lua_State *L, int narg, const char *tname)
return luaL_argerror(L, narg, msg);
}
+void luaL_register (lua_State *L,
+ const char *libname,
+ const luaL_Reg *l)
+{
+ if (libname)
+ {
+ lua_newtable(L);
+ lua_pushvalue(L, -1);
+ lua_setglobal(L, libname);
+ }
+ luaL_setfuncs(L, l, 0);
+}
+
void tpt_lua_setmainthread(lua_State *L)
{
}
diff --git a/src/lua/LuaCompat.h b/src/lua/LuaCompat.h
index 1ca761ca8..fdbc3d5f5 100644
--- a/src/lua/LuaCompat.h
+++ b/src/lua/LuaCompat.h
@@ -15,6 +15,12 @@ LUALIB_API void tpt_lua_setmainthread(lua_State *L);
LUALIB_API void tpt_lua_getmainthread(lua_State *L);
#if LUA_VERSION_NUM >= 502
+void luaL_register(lua_State *L, const char *libname, const luaL_Reg *l);
+#define lua_strlen(L,i) lua_rawlen(L, (i))
+#define lua_objlen(L,i) lua_rawlen(L, (i))
+#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ)
+#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT)
+
LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
#else
# ifndef lua_pushglobaltable // * Thank you moonjit
diff --git a/subprojects/tpt-libs-prebuilt-arm-and-gcc-static-v20220414193335.wrap b/subprojects/tpt-libs-prebuilt-arm-and-gcc-static-v20220414193335.wrap
new file mode 100644
index 000000000..19af9d92e
--- /dev/null
+++ b/subprojects/tpt-libs-prebuilt-arm-and-gcc-static-v20220414193335.wrap
@@ -0,0 +1,6 @@
+[wrap-file]
+directory = tpt-libs-prebuilt-arm-and-gcc-static-v20220414193335
+
+source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220414193335/tpt-libs-prebuilt-arm-and-gcc-static-v20220414193335.zip
+source_filename = tpt-libs-prebuilt-arm-and-gcc-static-v20220414193335.zip
+source_hash = 226a1b2ece17c329649d3031f6c8b893f4ce08f91323728b11aa7bbdfb581c6e
diff --git a/subprojects/tpt-libs-prebuilt-arm64-and-gcc-static-v20220414193335.wrap b/subprojects/tpt-libs-prebuilt-arm64-and-gcc-static-v20220414193335.wrap
new file mode 100644
index 000000000..677bac9ca
--- /dev/null
+++ b/subprojects/tpt-libs-prebuilt-arm64-and-gcc-static-v20220414193335.wrap
@@ -0,0 +1,6 @@
+[wrap-file]
+directory = tpt-libs-prebuilt-arm64-and-gcc-static-v20220414193335
+
+source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220414193335/tpt-libs-prebuilt-arm64-and-gcc-static-v20220414193335.zip
+source_filename = tpt-libs-prebuilt-arm64-and-gcc-static-v20220414193335.zip
+source_hash = 31b9ee7abc07a13972ad346a86db1fb6e850046d4427b60eb312796c99f6069b
diff --git a/subprojects/tpt-libs-prebuilt-arm64-mac-gcc-static-v20220410083352.wrap b/subprojects/tpt-libs-prebuilt-arm64-mac-gcc-static-v20220410083352.wrap
deleted file mode 100644
index 74e8cdac0..000000000
--- a/subprojects/tpt-libs-prebuilt-arm64-mac-gcc-static-v20220410083352.wrap
+++ /dev/null
@@ -1,6 +0,0 @@
-[wrap-file]
-directory = tpt-libs-prebuilt-arm64-mac-gcc-static-v20220410083352
-
-source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220410083352/tpt-libs-prebuilt-arm64-mac-gcc-static-v20220410083352.zip
-source_filename = tpt-libs-prebuilt-arm64-mac-gcc-static-v20220410083352.zip
-source_hash = 14b529c24f24d3cb07d2f10152c9aeb55685613afc90760fd3aed246b0653c00
diff --git a/subprojects/tpt-libs-prebuilt-arm64-mac-gcc-static-v20220414193335.wrap b/subprojects/tpt-libs-prebuilt-arm64-mac-gcc-static-v20220414193335.wrap
new file mode 100644
index 000000000..260ec07c2
--- /dev/null
+++ b/subprojects/tpt-libs-prebuilt-arm64-mac-gcc-static-v20220414193335.wrap
@@ -0,0 +1,6 @@
+[wrap-file]
+directory = tpt-libs-prebuilt-arm64-mac-gcc-static-v20220414193335
+
+source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220414193335/tpt-libs-prebuilt-arm64-mac-gcc-static-v20220414193335.zip
+source_filename = tpt-libs-prebuilt-arm64-mac-gcc-static-v20220414193335.zip
+source_hash = f904875f5d4d5ae6182a21603b768451049d19d5a7d2081907785166aba5af89
diff --git a/subprojects/tpt-libs-prebuilt-i686-and-gcc-static-v20220414193335.wrap b/subprojects/tpt-libs-prebuilt-i686-and-gcc-static-v20220414193335.wrap
new file mode 100644
index 000000000..2ec3e5f69
--- /dev/null
+++ b/subprojects/tpt-libs-prebuilt-i686-and-gcc-static-v20220414193335.wrap
@@ -0,0 +1,6 @@
+[wrap-file]
+directory = tpt-libs-prebuilt-i686-and-gcc-static-v20220414193335
+
+source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220414193335/tpt-libs-prebuilt-i686-and-gcc-static-v20220414193335.zip
+source_filename = tpt-libs-prebuilt-i686-and-gcc-static-v20220414193335.zip
+source_hash = 469c8d4d3b4be42fc51232c89c8729286c98008fc84e6cd29417d3799a77b339
diff --git a/subprojects/tpt-libs-prebuilt-i686-win-msvc-dynamic-v20220410083352.wrap b/subprojects/tpt-libs-prebuilt-i686-win-msvc-dynamic-v20220410083352.wrap
deleted file mode 100644
index 0150bdfdf..000000000
--- a/subprojects/tpt-libs-prebuilt-i686-win-msvc-dynamic-v20220410083352.wrap
+++ /dev/null
@@ -1,6 +0,0 @@
-[wrap-file]
-directory = tpt-libs-prebuilt-i686-win-msvc-dynamic-v20220410083352
-
-source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220410083352/tpt-libs-prebuilt-i686-win-msvc-dynamic-v20220410083352.zip
-source_filename = tpt-libs-prebuilt-i686-win-msvc-dynamic-v20220410083352.zip
-source_hash = 4b4db479e87898e9f5f9d7805396ef1ed8b46a34eaeff077e3b720c54306ee19
diff --git a/subprojects/tpt-libs-prebuilt-i686-win-msvc-dynamic-v20220414193335.wrap b/subprojects/tpt-libs-prebuilt-i686-win-msvc-dynamic-v20220414193335.wrap
new file mode 100644
index 000000000..9a296a688
--- /dev/null
+++ b/subprojects/tpt-libs-prebuilt-i686-win-msvc-dynamic-v20220414193335.wrap
@@ -0,0 +1,6 @@
+[wrap-file]
+directory = tpt-libs-prebuilt-i686-win-msvc-dynamic-v20220414193335
+
+source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220414193335/tpt-libs-prebuilt-i686-win-msvc-dynamic-v20220414193335.zip
+source_filename = tpt-libs-prebuilt-i686-win-msvc-dynamic-v20220414193335.zip
+source_hash = 16c7818b6e2d95eb22c0a72a57c3f35ba26268615d5b7d9c9cac072fcacc156b
diff --git a/subprojects/tpt-libs-prebuilt-i686-win-msvc-static-v20220410083352.wrap b/subprojects/tpt-libs-prebuilt-i686-win-msvc-static-v20220410083352.wrap
deleted file mode 100644
index ae0212c74..000000000
--- a/subprojects/tpt-libs-prebuilt-i686-win-msvc-static-v20220410083352.wrap
+++ /dev/null
@@ -1,6 +0,0 @@
-[wrap-file]
-directory = tpt-libs-prebuilt-i686-win-msvc-static-v20220410083352
-
-source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220410083352/tpt-libs-prebuilt-i686-win-msvc-static-v20220410083352.zip
-source_filename = tpt-libs-prebuilt-i686-win-msvc-static-v20220410083352.zip
-source_hash = d1ebd911231da6f266eea128a27d8d85d474a1ed1c4f53a7760cbbb4ed5f35e8
diff --git a/subprojects/tpt-libs-prebuilt-i686-win-msvc-static-v20220414193335.wrap b/subprojects/tpt-libs-prebuilt-i686-win-msvc-static-v20220414193335.wrap
new file mode 100644
index 000000000..9e729ad47
--- /dev/null
+++ b/subprojects/tpt-libs-prebuilt-i686-win-msvc-static-v20220414193335.wrap
@@ -0,0 +1,6 @@
+[wrap-file]
+directory = tpt-libs-prebuilt-i686-win-msvc-static-v20220414193335
+
+source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220414193335/tpt-libs-prebuilt-i686-win-msvc-static-v20220414193335.zip
+source_filename = tpt-libs-prebuilt-i686-win-msvc-static-v20220414193335.zip
+source_hash = 49d93a611fee0dc2fde4e55ccd08b4ea8599a1ee295053bab790b42616d9fed5
diff --git a/subprojects/tpt-libs-prebuilt-x86_64-and-gcc-static-v20220414193335.wrap b/subprojects/tpt-libs-prebuilt-x86_64-and-gcc-static-v20220414193335.wrap
new file mode 100644
index 000000000..ff4adc487
--- /dev/null
+++ b/subprojects/tpt-libs-prebuilt-x86_64-and-gcc-static-v20220414193335.wrap
@@ -0,0 +1,6 @@
+[wrap-file]
+directory = tpt-libs-prebuilt-x86_64-and-gcc-static-v20220414193335
+
+source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220414193335/tpt-libs-prebuilt-x86_64-and-gcc-static-v20220414193335.zip
+source_filename = tpt-libs-prebuilt-x86_64-and-gcc-static-v20220414193335.zip
+source_hash = 81c216cd0e12b0bfa1a29ec31553a431e53aee2c2f94e6dd69337dc949bf4957
diff --git a/subprojects/tpt-libs-prebuilt-x86_64-lin-gcc-static-v20220410083352.wrap b/subprojects/tpt-libs-prebuilt-x86_64-lin-gcc-static-v20220410083352.wrap
deleted file mode 100644
index 33844221e..000000000
--- a/subprojects/tpt-libs-prebuilt-x86_64-lin-gcc-static-v20220410083352.wrap
+++ /dev/null
@@ -1,6 +0,0 @@
-[wrap-file]
-directory = tpt-libs-prebuilt-x86_64-lin-gcc-static-v20220410083352
-
-source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220410083352/tpt-libs-prebuilt-x86_64-lin-gcc-static-v20220410083352.zip
-source_filename = tpt-libs-prebuilt-x86_64-lin-gcc-static-v20220410083352.zip
-source_hash = 076881617230f80faf4b868c7090eb53d9f76078691568051a9cfb97ab8f1787
diff --git a/subprojects/tpt-libs-prebuilt-x86_64-lin-gcc-static-v20220414193335.wrap b/subprojects/tpt-libs-prebuilt-x86_64-lin-gcc-static-v20220414193335.wrap
new file mode 100644
index 000000000..f621110c6
--- /dev/null
+++ b/subprojects/tpt-libs-prebuilt-x86_64-lin-gcc-static-v20220414193335.wrap
@@ -0,0 +1,6 @@
+[wrap-file]
+directory = tpt-libs-prebuilt-x86_64-lin-gcc-static-v20220414193335
+
+source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220414193335/tpt-libs-prebuilt-x86_64-lin-gcc-static-v20220414193335.zip
+source_filename = tpt-libs-prebuilt-x86_64-lin-gcc-static-v20220414193335.zip
+source_hash = db4736e6633cedf3b920d311f137b877b3d9f4fae868076425c826217722a693
diff --git a/subprojects/tpt-libs-prebuilt-x86_64-mac-gcc-static-v20220410083352.wrap b/subprojects/tpt-libs-prebuilt-x86_64-mac-gcc-static-v20220410083352.wrap
deleted file mode 100644
index 4bcaa2d5c..000000000
--- a/subprojects/tpt-libs-prebuilt-x86_64-mac-gcc-static-v20220410083352.wrap
+++ /dev/null
@@ -1,6 +0,0 @@
-[wrap-file]
-directory = tpt-libs-prebuilt-x86_64-mac-gcc-static-v20220410083352
-
-source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220410083352/tpt-libs-prebuilt-x86_64-mac-gcc-static-v20220410083352.zip
-source_filename = tpt-libs-prebuilt-x86_64-mac-gcc-static-v20220410083352.zip
-source_hash = cd21543d8ec2c1c697af574902c588a7afaf91e0b64f24981c3d4ea210dd8df3
diff --git a/subprojects/tpt-libs-prebuilt-x86_64-mac-gcc-static-v20220414193335.wrap b/subprojects/tpt-libs-prebuilt-x86_64-mac-gcc-static-v20220414193335.wrap
new file mode 100644
index 000000000..54d198f3e
--- /dev/null
+++ b/subprojects/tpt-libs-prebuilt-x86_64-mac-gcc-static-v20220414193335.wrap
@@ -0,0 +1,6 @@
+[wrap-file]
+directory = tpt-libs-prebuilt-x86_64-mac-gcc-static-v20220414193335
+
+source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220414193335/tpt-libs-prebuilt-x86_64-mac-gcc-static-v20220414193335.zip
+source_filename = tpt-libs-prebuilt-x86_64-mac-gcc-static-v20220414193335.zip
+source_hash = 92cf4a7e9260a7706af6de681bcb422e7cdf002d8fd699f6bf41248c5a0e8561
diff --git a/subprojects/tpt-libs-prebuilt-x86_64-win-mingw-dynamic-v20220410083352.wrap b/subprojects/tpt-libs-prebuilt-x86_64-win-mingw-dynamic-v20220410083352.wrap
deleted file mode 100644
index 2aeda9378..000000000
--- a/subprojects/tpt-libs-prebuilt-x86_64-win-mingw-dynamic-v20220410083352.wrap
+++ /dev/null
@@ -1,6 +0,0 @@
-[wrap-file]
-directory = tpt-libs-prebuilt-x86_64-win-mingw-dynamic-v20220410083352
-
-source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220410083352/tpt-libs-prebuilt-x86_64-win-mingw-dynamic-v20220410083352.zip
-source_filename = tpt-libs-prebuilt-x86_64-win-mingw-dynamic-v20220410083352.zip
-source_hash = dde61bacaa5e4ca37ec0696d69dadc2aeb553fe1e62f35c5968d6a9575424614
diff --git a/subprojects/tpt-libs-prebuilt-x86_64-win-mingw-dynamic-v20220414193335.wrap b/subprojects/tpt-libs-prebuilt-x86_64-win-mingw-dynamic-v20220414193335.wrap
new file mode 100644
index 000000000..b5d2e7fe6
--- /dev/null
+++ b/subprojects/tpt-libs-prebuilt-x86_64-win-mingw-dynamic-v20220414193335.wrap
@@ -0,0 +1,6 @@
+[wrap-file]
+directory = tpt-libs-prebuilt-x86_64-win-mingw-dynamic-v20220414193335
+
+source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220414193335/tpt-libs-prebuilt-x86_64-win-mingw-dynamic-v20220414193335.zip
+source_filename = tpt-libs-prebuilt-x86_64-win-mingw-dynamic-v20220414193335.zip
+source_hash = c72b41274254728e1513ec07ecec574efb8138645aaa691bf7b3df7fe8e13ed7
diff --git a/subprojects/tpt-libs-prebuilt-x86_64-win-mingw-static-v20220410083352.wrap b/subprojects/tpt-libs-prebuilt-x86_64-win-mingw-static-v20220410083352.wrap
deleted file mode 100644
index 5649e26a5..000000000
--- a/subprojects/tpt-libs-prebuilt-x86_64-win-mingw-static-v20220410083352.wrap
+++ /dev/null
@@ -1,6 +0,0 @@
-[wrap-file]
-directory = tpt-libs-prebuilt-x86_64-win-mingw-static-v20220410083352
-
-source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220410083352/tpt-libs-prebuilt-x86_64-win-mingw-static-v20220410083352.zip
-source_filename = tpt-libs-prebuilt-x86_64-win-mingw-static-v20220410083352.zip
-source_hash = a5f3cba05b449198d2bb17546ea459acfb243b0927c01969505b72c7152f7edb
diff --git a/subprojects/tpt-libs-prebuilt-x86_64-win-mingw-static-v20220414193335.wrap b/subprojects/tpt-libs-prebuilt-x86_64-win-mingw-static-v20220414193335.wrap
new file mode 100644
index 000000000..6c71df378
--- /dev/null
+++ b/subprojects/tpt-libs-prebuilt-x86_64-win-mingw-static-v20220414193335.wrap
@@ -0,0 +1,6 @@
+[wrap-file]
+directory = tpt-libs-prebuilt-x86_64-win-mingw-static-v20220414193335
+
+source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220414193335/tpt-libs-prebuilt-x86_64-win-mingw-static-v20220414193335.zip
+source_filename = tpt-libs-prebuilt-x86_64-win-mingw-static-v20220414193335.zip
+source_hash = 6fac58359250d7e7c8625be12f2ff05c2d8d530d37527b1171ffef9316db0c59
diff --git a/subprojects/tpt-libs-prebuilt-x86_64-win-msvc-dynamic-v20220410083352.wrap b/subprojects/tpt-libs-prebuilt-x86_64-win-msvc-dynamic-v20220410083352.wrap
deleted file mode 100644
index aeb6299e7..000000000
--- a/subprojects/tpt-libs-prebuilt-x86_64-win-msvc-dynamic-v20220410083352.wrap
+++ /dev/null
@@ -1,6 +0,0 @@
-[wrap-file]
-directory = tpt-libs-prebuilt-x86_64-win-msvc-dynamic-v20220410083352
-
-source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220410083352/tpt-libs-prebuilt-x86_64-win-msvc-dynamic-v20220410083352.zip
-source_filename = tpt-libs-prebuilt-x86_64-win-msvc-dynamic-v20220410083352.zip
-source_hash = 2f4136e82f80f9ea36e752e46fa26f95d007730cfeb67a73d1125aafb8fdf109
diff --git a/subprojects/tpt-libs-prebuilt-x86_64-win-msvc-dynamic-v20220414193335.wrap b/subprojects/tpt-libs-prebuilt-x86_64-win-msvc-dynamic-v20220414193335.wrap
new file mode 100644
index 000000000..6aa635e54
--- /dev/null
+++ b/subprojects/tpt-libs-prebuilt-x86_64-win-msvc-dynamic-v20220414193335.wrap
@@ -0,0 +1,6 @@
+[wrap-file]
+directory = tpt-libs-prebuilt-x86_64-win-msvc-dynamic-v20220414193335
+
+source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220414193335/tpt-libs-prebuilt-x86_64-win-msvc-dynamic-v20220414193335.zip
+source_filename = tpt-libs-prebuilt-x86_64-win-msvc-dynamic-v20220414193335.zip
+source_hash = 5eb84fa27e5b7eaa153143096c72878ee26aa1e00c43ce283882f7dcc47b73a2
diff --git a/subprojects/tpt-libs-prebuilt-x86_64-win-msvc-static-v20220410083352.wrap b/subprojects/tpt-libs-prebuilt-x86_64-win-msvc-static-v20220410083352.wrap
deleted file mode 100644
index 047d57558..000000000
--- a/subprojects/tpt-libs-prebuilt-x86_64-win-msvc-static-v20220410083352.wrap
+++ /dev/null
@@ -1,6 +0,0 @@
-[wrap-file]
-directory = tpt-libs-prebuilt-x86_64-win-msvc-static-v20220410083352
-
-source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220410083352/tpt-libs-prebuilt-x86_64-win-msvc-static-v20220410083352.zip
-source_filename = tpt-libs-prebuilt-x86_64-win-msvc-static-v20220410083352.zip
-source_hash = b476b5c991d352b993bc3784690ed00b1f66e7dd87e221c8fb0de9ffb398b2a0
diff --git a/subprojects/tpt-libs-prebuilt-x86_64-win-msvc-static-v20220414193335.wrap b/subprojects/tpt-libs-prebuilt-x86_64-win-msvc-static-v20220414193335.wrap
new file mode 100644
index 000000000..42ff413ee
--- /dev/null
+++ b/subprojects/tpt-libs-prebuilt-x86_64-win-msvc-static-v20220414193335.wrap
@@ -0,0 +1,6 @@
+[wrap-file]
+directory = tpt-libs-prebuilt-x86_64-win-msvc-static-v20220414193335
+
+source_url = https://github.com/The-Powder-Toy/tpt-libs/releases/download/v20220414193335/tpt-libs-prebuilt-x86_64-win-msvc-static-v20220414193335.zip
+source_filename = tpt-libs-prebuilt-x86_64-win-msvc-static-v20220414193335.zip
+source_hash = 32f71cf6c750e0c312777538ca094a8577b4d9d27dc68e8d406aa991d1440db1