Build Android prefab in releaser.py script

[ci skip]
This commit is contained in:
Anonymous Maarten 2022-10-02 16:41:20 +02:00 committed by Anonymous Maarten
parent 1f89c407e0
commit 45081db9d4
4 changed files with 290 additions and 327 deletions

View file

@ -423,3 +423,59 @@ jobs:
-Werror=dev \ -Werror=dev \
-B build_x64 -B build_x64
cmake --build build_x64 --config Release --verbose cmake --build build_x64 --config Release --verbose
android:
needs: [src]
runs-on: ubuntu-latest
outputs:
android-aar: ${{ steps.releaser.outputs.android-aar }}
steps:
- name: 'Set up Python'
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: 'Fetch build-release.py'
uses: actions/checkout@v4
with:
sparse-checkout: 'build-scripts/build-release.py'
- name: 'Setup Android NDK'
uses: nttld/setup-ndk@v1
id: setup_ndk
with:
local-cache: true
ndk-version: r21e
- name: 'Setup Java JDK'
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '11'
- name: 'Install ninja'
run: |
sudo apt-get update -y
sudo apt-get install -y ninja-build
- name: 'Download source archives'
uses: actions/download-artifact@v4
with:
name: sources
path: '${{ github.workspace }}'
- name: 'Untar ${{ needs.src.outputs.src-tar-gz }}'
id: tar
run: |
mkdir -p /tmp/tardir
tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}"
echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT
- name: 'Build Android prefab binary archive(s)'
id: releaser
run: |
python build-scripts/build-release.py \
--create android \
--commit ${{ inputs.commit }} \
--project SDL3 \
--root "${{ steps.tar.outputs.path }}" \
--github \
--debug
- name: 'Store Android archive(s)'
uses: actions/upload-artifact@v4
with:
name: android
path: '${{ github.workspace }}/dist'

View file

@ -1,315 +0,0 @@
#!/bin/bash
set -e
if ! [ "x$ANDROID_NDK_HOME" != "x" -a -d "$ANDROID_NDK_HOME" ]; then
echo "ANDROID_NDK_HOME environment variable is not set"
exit 1
fi
if ! [ "x$ANDROID_HOME" != "x" -a -d "$ANDROID_HOME" ]; then
echo "ANDROID_HOME environment variable is not set"
exit 1
fi
if [ "x$ANDROID_API" = "x" ]; then
ANDROID_API="$(ls "$ANDROID_HOME/platforms" | grep -E "^android-[0-9]+$" | sed 's/android-//' | sort -n -r | head -1)"
if [ "x$ANDROID_API" = "x" ]; then
echo "No Android platform found in $ANDROID_HOME/platforms"
exit 1
fi
else
if ! [ -d "$ANDROID_HOME/platforms/android-$ANDROID_API" ]; then
echo "Android api version $ANDROID_API is not available ($ANDROID_HOME/platforms/android-$ANDROID_API does not exist)" >2
exit 1
fi
fi
android_platformdir="$ANDROID_HOME/platforms/android-$ANDROID_API"
echo "Building for android api version $ANDROID_API"
echo "android_platformdir=$android_platformdir"
scriptdir=$(cd -P -- "$(dirname -- "$0")" && printf '%s\n' "$(pwd -P)")
sdl_root=$(cd -P -- "$(dirname -- "$0")/.." && printf '%s\n' "$(pwd -P)")
build_root="${sdl_root}/build-android-prefab"
android_abis="armeabi-v7a arm64-v8a x86 x86_64"
android_api=19
android_ndk=21
android_stl="c++_shared"
sdl_major=$(sed -ne 's/^#define SDL_MAJOR_VERSION *//p' "${sdl_root}/include/SDL3/SDL_version.h")
sdl_minor=$(sed -ne 's/^#define SDL_MINOR_VERSION *//p' "${sdl_root}/include/SDL3/SDL_version.h")
sdl_micro=$(sed -ne 's/^#define SDL_MICRO_VERSION *//p' "${sdl_root}/include/SDL3/SDL_version.h")
sdl_version="${sdl_major}.${sdl_minor}.${sdl_micro}"
echo "Building Android prefab package for SDL version $sdl_version"
prefabhome="${build_root}/prefab-${sdl_version}"
rm -rf "$prefabhome"
mkdir -p "${prefabhome}"
build_cmake_projects() {
for android_abi in $android_abis; do
echo "Configuring CMake project for $android_abi"
cmake -S "$sdl_root" -B "${build_root}/build_${android_abi}" \
-DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" \
-DANDROID_PLATFORM=${android_platform} \
-DANDROID_ABI=${android_abi} \
-DSDL_SHARED=ON \
-DSDL_STATIC=ON \
-DSDL_STATIC_PIC=ON \
-DSDL_TEST=ON \
-DSDL_DISABLE_INSTALL=OFF \
-DCMAKE_INSTALL_PREFIX="${build_root}/build_${android_abi}/prefix" \
-DCMAKE_INSTALL_INCLUDEDIR=include \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_BUILD_TYPE=Release \
-GNinja
rm -rf "${build_root}/build_${android_abi}/prefix"
echo "Building CMake project for $android_abi"
cmake --build "${build_root}/build_${android_abi}"
echo "Installing CMake project for $android_abi"
cmake --install "${build_root}/build_${android_abi}"
done
}
classes_sources_jar_path="${prefabhome}/classes-sources.jar"
classes_jar_path="${prefabhome}/classes.jar"
compile_java() {
classes_sources_root="${prefabhome}/classes-sources"
rm -rf "${classes_sources_root}"
mkdir -p "${classes_sources_root}/META-INF"
echo "Copying LICENSE.txt to java build folder"
cp "$sdl_root/LICENSE.txt" "${classes_sources_root}/META-INF"
echo "Copy JAVA sources to java build folder"
cp -r "$sdl_root/android-project/app/src/main/java/org" "${classes_sources_root}"
java_sourceslist_path="${prefabhome}/java_sources.txt"
pushd "${classes_sources_root}"
echo "Collecting sources for classes-sources.jar"
find "." -name "*.java" >"${java_sourceslist_path}"
find "META-INF" -name "*" >>"${java_sourceslist_path}"
echo "Creating classes-sources.jar"
jar -cf "${classes_sources_jar_path}" "@${java_sourceslist_path}"
popd
classes_root="${prefabhome}/classes"
mkdir -p "${classes_root}/META-INF"
cp "$sdl_root/LICENSE.txt" "${classes_root}/META-INF"
java_sourceslist_path="${prefabhome}/java_sources.txt"
echo "Collecting sources for classes.jar"
find "$sdl_root/android-project/app/src/main/java" -name "*.java" >"${java_sourceslist_path}"
echo "Compiling classes"
javac -encoding utf-8 -classpath "$android_platformdir/android.jar" -d "${classes_root}" "@${java_sourceslist_path}"
java_classeslist_path="${prefabhome}/java_classes.txt"
pushd "${classes_root}"
find "." -name "*.class" >"${java_classeslist_path}"
find "META-INF" -name "*" >>"${java_classeslist_path}"
echo "Creating classes.jar"
jar -cf "${classes_jar_path}" "@${java_classeslist_path}"
popd
}
pom_filename="SDL${sdl_major}-${sdl_version}.pom"
pom_filepath="${prefabhome}/${pom_filename}"
create_pom_xml() {
echo "Creating ${pom_filename}"
cat >"${pom_filepath}" <<EOF
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.libsdl.android</groupId>
<artifactId>SDL${sdl_major}</artifactId>
<version>${sdl_version}</version>
<packaging>aar</packaging>
<name>SDL${sdl_major}</name>
<description>The AAR for SDL${sdl_major}</description>
<url>https://libsdl.org/</url>
<licenses>
<license>
<name>zlib License</name>
<url>https://github.com/libsdl-org/SDL/blob/main/LICENSE.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<connection>scm:git:https://github.com/libsdl-org/SDL</connection>
<url>https://github.com/libsdl-org/SDL</url>
</scm>
</project>
EOF
}
create_aar_androidmanifest() {
echo "Creating AndroidManifest.xml"
cat >"${aar_root}/AndroidManifest.xml" <<EOF
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="org.libsdl.android" android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="16"
android:targetSdkVersion="29"/>
</manifest>
EOF
}
echo "Creating AAR root directory"
aar_root="${prefabhome}/SDL${sdl_major}-${sdl_version}"
mkdir -p "${aar_root}"
aar_metainfdir_path=${aar_root}/META-INF
mkdir -p "${aar_metainfdir_path}"
cp "${sdl_root}/LICENSE.txt" "${aar_metainfdir_path}"
prefabworkdir="${aar_root}/prefab"
mkdir -p "${prefabworkdir}"
cat >"${prefabworkdir}/prefab.json" <<EOF
{
"schema_version": 2,
"name": "SDL$sdl_major",
"version": "$sdl_version",
"dependencies": []
}
EOF
modulesworkdir="${prefabworkdir}/modules"
mkdir -p "${modulesworkdir}"
create_shared_sdl_module() {
echo "Creating SDL${sdl_major} prefab module"
for android_abi in $android_abis; do
sdl_moduleworkdir="${modulesworkdir}/SDL${sdl_major}"
mkdir -p "${sdl_moduleworkdir}"
abi_build_prefix="${build_root}/build_${android_abi}/prefix"
cat >"${sdl_moduleworkdir}/module.json" <<EOF
{
"export_libraries": [],
"library_name": "libSDL${sdl_major}"
}
EOF
mkdir -p "${sdl_moduleworkdir}/include/SDL${sdl_major}"
cp -r "${abi_build_prefix}/include/SDL${sdl_major}/"* "${sdl_moduleworkdir}/include/SDL${sdl_major}"
abi_sdllibdir="${sdl_moduleworkdir}/libs/android.${android_abi}"
mkdir -p "${abi_sdllibdir}"
cat >"${abi_sdllibdir}/abi.json" <<EOF
{
"abi": "${android_abi}",
"api": ${android_api},
"ndk": ${android_ndk},
"stl": "${android_stl}",
"static": false
}
EOF
cp "${abi_build_prefix}/lib/libSDL${sdl_major}.so" "${abi_sdllibdir}"
done
}
create_static_sdl_module() {
echo "Creating SDL${sdl_major}-static prefab module"
for android_abi in $android_abis; do
sdl_moduleworkdir="${modulesworkdir}/SDL${sdl_major}-static"
mkdir -p "${sdl_moduleworkdir}"
abi_build_prefix="${build_root}/build_${android_abi}/prefix"
cat >"${sdl_moduleworkdir}/module.json" <<EOF
{
"export_libraries": ["-ldl", "-lGLESv1_CM", "-lGLESv2", "-llog", "-landroid", "-lOpenSLES"]
"library_name": "libSDL${sdl_major}"
}
EOF
mkdir -p "${sdl_moduleworkdir}/include/SDL${sdl_major}"
cp -r "${abi_build_prefix}/include/SDL${sdl_major}/"* "${sdl_moduleworkdir}/include/SDL${sdl_major}"
abi_sdllibdir="${sdl_moduleworkdir}/libs/android.${android_abi}"
mkdir -p "${abi_sdllibdir}"
cat >"${abi_sdllibdir}/abi.json" <<EOF
{
"abi": "${android_abi}",
"api": ${android_api},
"ndk": ${android_ndk},
"stl": "${android_stl}",
"static": true
}
EOF
cp "${abi_build_prefix}/lib/libSDL${sdl_major}.a" "${abi_sdllibdir}"
done
}
create_sdltest_module() {
echo "Creating SDL${sdl_major}test prefab module"
for android_abi in $android_abis; do
sdl_moduleworkdir="${modulesworkdir}/SDL${sdl_major}test"
mkdir -p "${sdl_moduleworkdir}"
abi_build_prefix="${build_root}/build_${android_abi}/prefix"
cat >"${sdl_moduleworkdir}/module.json" <<EOF
{
"export_libraries": [],
"library_name": "libSDL${sdl_major}_test"
}
EOF
abi_sdllibdir="${sdl_moduleworkdir}/libs/android.${android_abi}"
mkdir -p "${abi_sdllibdir}"
cat >"${abi_sdllibdir}/abi.json" <<EOF
{
"abi": "${android_abi}",
"api": ${android_api},
"ndk": ${android_ndk},
"stl": "${android_stl}",
"static": true
}
EOF
cp "${abi_build_prefix}/lib/libSDL${sdl_major}_test.a" "${abi_sdllibdir}"
done
}
build_cmake_projects
compile_java
create_pom_xml
create_aar_androidmanifest
create_shared_sdl_module
create_static_sdl_module
create_sdltest_module
pushd "${aar_root}"
aar_filename="SDL${sdl_major}-${sdl_version}.aar"
cp "${classes_jar_path}" ./classes.jar
cp "${classes_sources_jar_path}" ./classes-sources.jar
zip -r "${aar_filename}" AndroidManifest.xml classes.jar classes-sources.jar prefab META-INF
zip -Tv "${aar_filename}" 2>/dev/null ;
mv "${aar_filename}" "${prefabhome}"
popd
maven_filename="SDL${sdl_major}-${sdl_version}.zip"
pushd "${prefabhome}"
zip_filename="SDL${sdl_major}-${sdl_version}.zip"
zip "${maven_filename}" "${aar_filename}" "${pom_filename}" 2>/dev/null;
zip -Tv "${zip_filename}" 2>/dev/null;
popd
echo "Prefab zip is ready at ${prefabhome}/${aar_filename}"
echo "Maven archive is ready at ${prefabhome}/${zip_filename}"

View file

@ -4,6 +4,7 @@ import argparse
import collections import collections
import contextlib import contextlib
import datetime import datetime
import glob
import io import io
import json import json
import logging import logging
@ -26,6 +27,24 @@ logger = logging.getLogger(__name__)
VcArchDevel = collections.namedtuple("VcArchDevel", ("dll", "imp", "test")) VcArchDevel = collections.namedtuple("VcArchDevel", ("dll", "imp", "test"))
GIT_HASH_FILENAME = ".git-hash" GIT_HASH_FILENAME = ".git-hash"
ANDROID_AVAILABLE_ABIS = [
"armeabi-v7a",
"arm64-v8a",
"x86",
"x86_64",
]
ANDROID_MINIMUM_API = 19
ANDROID_TARGET_API = 29
ANDROID_MINIMUM_NDK = 21
ANDROID_LIBRARIES = [
"dl",
"GLESv1_CM",
"GLESv2",
"log",
"android",
"OpenSLES",
]
def itertools_batched(iterator: typing.Iterable, count: int): def itertools_batched(iterator: typing.Iterable, count: int):
iterator = iter(iterator) iterator = iter(iterator)
@ -373,6 +392,8 @@ class Releaser:
self.executer.run([ self.executer.run([
"cmake", "-S", str(self.root), "-B", str(build_path), "cmake", "-S", str(self.root), "-B", str(build_path),
"--fresh", "--fresh",
f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
"-DSDL_SHARED=ON", "-DSDL_SHARED=ON",
"-DSDL_STATIC=ON", "-DSDL_STATIC=ON",
"-DSDL_DISABLE_INSTALL_DOCS=ON", "-DSDL_DISABLE_INSTALL_DOCS=ON",
@ -507,6 +528,178 @@ class Releaser:
self._zip_add_git_hash(zip_file=zf, root=archive_prefix) self._zip_add_git_hash(zip_file=zf, root=archive_prefix)
self.artifacts["VC-devel"] = zip_path self.artifacts["VC-devel"] = zip_path
def detect_android_api(self, android_home: str) -> typing.Optional[int]:
platform_dirs = list(Path(p) for p in glob.glob(f"{android_home}/platforms/android-*"))
re_platform = re.compile("android-([0-9]+)")
platform_versions = []
for platform_dir in platform_dirs:
logger.debug("Found Android Platform SDK: %s", platform_dir)
if m:= re_platform.match(platform_dir.name):
platform_versions.append(int(m.group(1)))
platform_versions.sort()
logger.info("Available platform versions: %s", platform_versions)
platform_versions = list(filter(lambda v: v >= ANDROID_MINIMUM_API, platform_versions))
logger.info("Valid platform versions (>=%d): %s", ANDROID_MINIMUM_API, platform_versions)
if not platform_versions:
return None
android_api = platform_versions[0]
logger.info("Selected API version %d", android_api)
return android_api
def get_prefab_json_text(self):
return textwrap.dedent(f"""\
{{
"schema_version": 2,
"name": "{self.project}",
"version": "{self.version}",
"dependencies": []
}}
""")
def get_prefab_module_json_text(self, library_name: str, extra_libs: list[str]):
export_libraries_str = ", ".join(f"\"-l{lib}\"" for lib in extra_libs)
return textwrap.dedent(f"""\
{{
"export_libraries": [{export_libraries_str}],
"library_name": "lib{library_name}"
}}
""")
def get_prefab_abi_json_text(self, abi: str, cpp: bool, shared: bool):
return textwrap.dedent(f"""\
{{
"abi": "{abi}",
"api": {ANDROID_MINIMUM_API},
"ndk": {ANDROID_MINIMUM_NDK},
"stl": "{'c++_shared' if cpp else 'none'}",
"static": {'true' if not shared else 'false'}
}}
""")
def get_android_manifest_text(self):
return textwrap.dedent(f"""\
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="org.libsdl.android.{self.project}" android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="{ANDROID_MINIMUM_API}"
android:targetSdkVersion="{ANDROID_TARGET_API}" />
</manifest>
""")
def create_android_archives(self, android_api: int, android_home: Path, android_ndk_home: Path, android_abis: list[str]):
cmake_toolchain_file = Path(android_ndk_home) / "build/cmake/android.toolchain.cmake"
if not cmake_toolchain_file.exists():
logger.error("CMake toolchain file does not exist (%s)", cmake_toolchain_file)
raise SystemExit(1)
aar_path = self.dist_path / f"{self.project}-{self.version}.aar"
added_global_files = False
with zipfile.ZipFile(aar_path, "w", compression=zipfile.ZIP_DEFLATED) as zip_object:
zip_object.writestr("AndroidManifest.xml", self.get_android_manifest_text())
zip_object.write(self.root / "android-project/app/proguard-rules.pro", arcname="proguard.txt")
zip_object.write(self.root / "LICENSE.txt", arcname="META-INF/LICENSE.txt")
zip_object.writestr("prefab/prefab.json", self.get_prefab_json_text())
self._zip_add_git_hash(zip_file=zip_object)
for android_abi in android_abis:
with self.section_printer.group(f"Building for Android {android_api} {android_abi}"):
build_dir = self.root / "build-android" / f"{android_abi}-build"
install_dir = self.root / "install-android" / f"{android_abi}-install"
shutil.rmtree(install_dir, ignore_errors=True)
assert not install_dir.is_dir(), f"{install_dir} should not exist prior to build"
cmake_args = [
"cmake",
"-S", str(self.root),
"-B", str(build_dir),
"--fresh",
f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
"-DCMAKE_BUILD_TYPE=RelWithDebInfo",
f"-DCMAKE_TOOLCHAIN_FILE={cmake_toolchain_file}",
f"-DANDROID_PLATFORM={android_api}",
f"-DANDROID_ABI={android_abi}",
f"-DCMAKE_POSITION_INDEPENDENT_CODE=ON",
"-DSDL_SHARED=ON",
"-DSDL_STATIC=ON",
"-DSDL_STATIC_PIC=ON",
"-DSDL_TEST_LIBRARY=ON",
"-DSDL_DISABLE_ANDROID_JAR=OFF",
"-DSDL_TESTS=OFF",
f"-DCMAKE_INSTALL_PREFIX={install_dir}",
"-DSDL_DISABLE_INSTALL=OFF",
"-DSDL_DISABLE_INSTALL_DOCS=OFF",
"-DCMAKE_INSTALL_INCLUDEDIR=include ",
"-DCMAKE_INSTALL_LIBDIR=lib",
"-DCMAKE_INSTALL_DATAROOTDIR=share",
"-DCMAKE_BUILD_TYPE=Release",
f"-G{self.cmake_generator}",
]
build_args = [
"cmake",
"--build", str(build_dir),
"--config", "RelWithDebInfo",
]
install_args = [
"cmake",
"--install", str(build_dir),
"--config", "RelWithDebInfo",
]
self.executer.run(cmake_args)
self.executer.run(build_args)
self.executer.run(install_args)
main_so_library = install_dir / "lib" / f"lib{self.project}.so"
logger.debug("Expecting library %s", main_so_library)
assert main_so_library.is_file(), "CMake should have built a shared library (e.g. libSDL3.so)"
main_static_library = install_dir / "lib" / f"lib{self.project}.a"
logger.debug("Expecting library %s", main_static_library)
assert main_static_library.is_file(), "CMake should have built a static library (e.g. libSDL3.a)"
test_library = install_dir / "lib" / f"lib{self.project}_test.a"
logger.debug("Expecting library %s", test_library)
assert test_library.is_file(), "CMake should have built a static test library (e.g. libSDL3_test.a)"
java_jar = install_dir / f"share/java/{self.project}/{self.project}-{self.version}.jar"
logger.debug("Expecting java archive: %s", java_jar)
assert java_jar.is_file(), "CMake should have compiled the java sources and archived them into a JAR"
javasources_jar = install_dir / f"share/java/{self.project}/{self.project}-{self.version}-sources.jar"
logger.debug("Expecting java sources archive %s", javasources_jar)
assert javasources_jar.is_file(), "CMake should have archived the java sources into a JAR"
javadoc_dir = install_dir / "share/javadoc" / self.project
logger.debug("Expecting javadoc archive %s", javadoc_dir)
assert javadoc_dir.is_dir(), "CMake should have built javadoc documentation for the java sources"
if not added_global_files:
zip_object.write(java_jar, arcname="classes.jar")
zip_object.write(javasources_jar, arcname="classes-sources.jar", )
doc_jar_path = install_dir / "classes-doc.jar"
javadoc_jar_args = ["jar", "--create", "--file", str(doc_jar_path)]
for fn in javadoc_dir.iterdir():
javadoc_jar_args.extend(["-C", str(javadoc_dir), fn.name])
self.executer.run(javadoc_jar_args)
zip_object.write(doc_jar_path, arcname="classes-doc.jar")
for header in (install_dir / "include" / self.project).iterdir():
zip_object.write(header, arcname=f"prefab/modules/{self.project}-shared/include/{self.project}/{header.name}")
zip_object.write(header, arcname=f"prefab/modules/{self.project}-static/include/{self.project}/{header.name}")
zip_object.writestr(f"prefab/modules/{self.project}-shared/module.json", self.get_prefab_module_json_text(library_name=self.project, extra_libs=[]))
zip_object.writestr(f"prefab/modules/{self.project}-static/module.json", self.get_prefab_module_json_text(library_name=self.project, extra_libs=list(ANDROID_LIBRARIES)))
zip_object.writestr(f"prefab/modules/{self.project}_test/module.json", self.get_prefab_module_json_text(library_name=f"{self.project}_test", extra_libs=list()))
added_global_files = True
zip_object.write(main_so_library, arcname=f"prefab/modules/{self.project}-shared/libs/android.{android_abi}/lib{self.project}.so")
zip_object.writestr(f"prefab/modules/{self.project}-shared/libs/android.{android_abi}/abi.json", self.get_prefab_abi_json_text(abi=android_abi, cpp=False, shared=True))
zip_object.write(main_static_library, arcname=f"prefab/modules/{self.project}-static/libs/android.{android_abi}/lib{self.project}.a")
zip_object.writestr(f"prefab/modules/{self.project}-static/libs/android.{android_abi}/abi.json", self.get_prefab_abi_json_text(abi=android_abi, cpp=False, shared=False))
zip_object.write(test_library, arcname=f"prefab/modules/{self.project}_test/libs/android.{android_abi}/lib{self.project}_test.a")
zip_object.writestr(f"prefab/modules/{self.project}_test/libs/android.{android_abi}/abi.json", self.get_prefab_abi_json_text(abi=android_abi, cpp=False, shared=False))
self.artifacts[f"android-prefab-aar"] = aar_path
@classmethod @classmethod
def extract_sdl_version(cls, root: Path, project: str): def extract_sdl_version(cls, root: Path, project: str):
with open(root / f"include/{project}/SDL_version.h", "r") as f: with open(root / f"include/{project}/SDL_version.h", "r") as f:
@ -523,10 +716,14 @@ def main(argv=None):
parser.add_argument("--out", "-o", metavar="DIR", dest="dist_path", type=Path, default="dist", help="Output directory") parser.add_argument("--out", "-o", metavar="DIR", dest="dist_path", type=Path, default="dist", help="Output directory")
parser.add_argument("--github", action="store_true", help="Script is running on a GitHub runner") parser.add_argument("--github", action="store_true", help="Script is running on a GitHub runner")
parser.add_argument("--commit", default="HEAD", help="Git commit/tag of which a release should be created") parser.add_argument("--commit", default="HEAD", help="Git commit/tag of which a release should be created")
parser.add_argument("--project", required=True, help="Name of the project") parser.add_argument("--project", required=True, help="Name of the project (e.g. SDL3")
parser.add_argument("--create", choices=["source", "mingw", "win32", "xcframework"], required=True,action="append", dest="actions", help="SDL version") parser.add_argument("--create", choices=["source", "mingw", "win32", "xcframework", "android"], required=True, action="append", dest="actions", help="What to do")
parser.set_defaults(loglevel=logging.INFO) parser.set_defaults(loglevel=logging.INFO)
parser.add_argument('--vs-year', dest="vs_year", help="Visual Studio year") parser.add_argument('--vs-year', dest="vs_year", help="Visual Studio year")
parser.add_argument('--android-api', type=int, dest="android_api", help="Android API version")
parser.add_argument('--android-home', dest="android_home", default=os.environ.get("ANDROID_HOME"), help="Android Home folder")
parser.add_argument('--android-ndk-home', dest="android_ndk_home", default=os.environ.get("ANDROID_NDK_HOME"), help="Android NDK Home folder")
parser.add_argument('--android-abis', dest="android_abis", nargs="*", choices=ANDROID_AVAILABLE_ABIS, default=list(ANDROID_AVAILABLE_ABIS), help="Android NDK Home folder")
parser.add_argument('--cmake-generator', dest="cmake_generator", default="Ninja", help="CMake Generator") parser.add_argument('--cmake-generator', dest="cmake_generator", default="Ninja", help="CMake Generator")
parser.add_argument('--debug', action='store_const', const=logging.DEBUG, dest="loglevel", help="Print script debug information") parser.add_argument('--debug', action='store_const', const=logging.DEBUG, dest="loglevel", help="Print script debug information")
parser.add_argument('--dry-run', action='store_true', dest="dry", help="Don't execute anything") parser.add_argument('--dry-run', action='store_true', dest="dry", help="Don't execute anything")
@ -623,6 +820,31 @@ def main(argv=None):
if "mingw" in args.actions: if "mingw" in args.actions:
releaser.create_mingw_archives() releaser.create_mingw_archives()
if "android" in args.actions:
if args.android_home is None or not Path(args.android_home).is_dir():
parser.error("Invalid $ANDROID_HOME or --android-home: must be a directory containing the Android SDK")
if args.android_ndk_home is None or not Path(args.android_ndk_home).is_dir():
parser.error("Invalid $ANDROID_NDK_HOME or --android_ndk_home: must be a directory containing the Android NDK")
if args.android_api is None:
with section_printer.group("Detect Android APIS"):
args.android_api = releaser.detect_android_api(android_home=args.android_home)
if args.android_api is None or not (Path(args.android_home) / f"platforms/android-{args.android_api}").is_dir():
parser.error("Invalid --android-api, and/or could not be detected")
if not args.android_abis:
parser.error("Need at least one Android ABI")
with section_printer.group("Android arguments"):
print(f"android_home = {args.android_home}")
print(f"android_ndk_home = {args.android_ndk_home}")
print(f"android_api = {args.android_api}")
print(f"android_abis = {args.android_abis}")
releaser.create_android_archives(
android_api=args.android_api,
android_home=args.android_home,
android_ndk_home=args.android_ndk_home,
android_abis=args.android_abis,
)
with section_printer.group("Summary"): with section_printer.group("Summary"):
print(f"artifacts = {releaser.artifacts}") print(f"artifacts = {releaser.artifacts}")

View file

@ -377,9 +377,9 @@ Memory debugging
The best (and slowest) way to debug memory issues on Android is valgrind. The best (and slowest) way to debug memory issues on Android is valgrind.
Valgrind has support for Android out of the box, just grab code using: Valgrind has support for Android out of the box, just grab code using:
svn co svn://svn.valgrind.org/valgrind/trunk valgrind git clone https://sourceware.org/git/valgrind.git
... and follow the instructions in the file README.android to build it. ... and follow the instructions in the file `README.android` to build it.
One thing I needed to do on macOS was change the path to the toolchain, One thing I needed to do on macOS was change the path to the toolchain,
and add ranlib to the environment variables: and add ranlib to the environment variables: