__main__.py.in 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #!/usr/bin/env python
  2. """
  3. Create a @<@PROJECT_NAME@>@ SDK prefix from an Android archive
  4. This file is meant to be placed in a the root of an android .aar archive
  5. Example usage:
  6. ```sh
  7. python @<@PROJECT_NAME@>@-@<@PROJECT_VERSION@>@.aar -o /usr/opt/android-sdks
  8. cmake -S my-project \
  9. -DCMAKE_PREFIX_PATH=/usr/opt/android-sdks \
  10. -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \
  11. -B build-arm64 -DANDROID_ABI=arm64-v8a \
  12. -DCMAKE_BUILD_TYPE=Releaase
  13. cmake --build build-arm64
  14. ```
  15. """
  16. import argparse
  17. import io
  18. import json
  19. import os
  20. import pathlib
  21. import re
  22. import stat
  23. import zipfile
  24. AAR_PATH = pathlib.Path(__file__).resolve().parent
  25. ANDROID_ARCHS = { "armeabi-v7a", "arm64-v8a", "x86", "x86_64" }
  26. def main():
  27. parser = argparse.ArgumentParser(
  28. description="Convert a @<@PROJECT_NAME@>@ Android .aar archive into a SDK",
  29. allow_abbrev=False,
  30. )
  31. parser.add_argument("--version", action="version", version="@<@PROJECT_NAME@>@ @<@PROJECT_VERSION@>@")
  32. parser.add_argument("-o", dest="output", type=pathlib.Path, required=True, help="Folder where to store the SDK")
  33. args = parser.parse_args()
  34. print(f"Creating a @<@PROJECT_NAME@>@ SDK at {args.output}...")
  35. prefix = args.output
  36. incdir = prefix / "include"
  37. libdir = prefix / "lib"
  38. RE_LIB_MODULE_ARCH = re.compile(r"prefab/modules/(?P<module>[A-Za-z0-9_-]+)/libs/android\.(?P<arch>[a-zA-Z0-9_-]+)/(?P<filename>lib[A-Za-z0-9_]+\.(?:so|a))")
  39. RE_INC_MODULE_ARCH = re.compile(r"prefab/modules/(?P<module>[A-Za-z0-9_-]+)/include/(?P<header>[a-zA-Z0-9_./-]+)")
  40. RE_LICENSE = re.compile(r"(?:.*/)?(?P<filename>(?:license|copying)(?:\.md|\.txt)?)", flags=re.I)
  41. RE_PROGUARD = re.compile(r"(?:.*/)?(?P<filename>proguard.*\.(?:pro|txt))", flags=re.I)
  42. RE_CMAKE = re.compile(r"(?:.*/)?(?P<filename>.*\.cmake)", flags=re.I)
  43. with zipfile.ZipFile(AAR_PATH) as zf:
  44. project_description = json.loads(zf.read("description.json"))
  45. project_name = project_description["name"]
  46. project_version = project_description["version"]
  47. licensedir = prefix / "share/licenses" / project_name
  48. cmakedir = libdir / "cmake" / project_name
  49. javadir = prefix / "share/java" / project_name
  50. javadocdir = prefix / "share/javadoc" / project_name
  51. def read_zipfile_and_write(path: pathlib.Path, zippath: str):
  52. data = zf.read(zippath)
  53. path.parent.mkdir(parents=True, exist_ok=True)
  54. path.write_bytes(data)
  55. for zip_info in zf.infolist():
  56. zippath = zip_info.filename
  57. if m := RE_LIB_MODULE_ARCH.match(zippath):
  58. lib_path = libdir / m["arch"] / m["filename"]
  59. read_zipfile_and_write(lib_path, zippath)
  60. if m["filename"].endswith(".so"):
  61. os.chmod(lib_path, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
  62. elif m := RE_INC_MODULE_ARCH.match(zippath):
  63. header_path = incdir / m["header"]
  64. read_zipfile_and_write(header_path, zippath)
  65. elif m:= RE_LICENSE.match(zippath):
  66. license_path = licensedir / m["filename"]
  67. read_zipfile_and_write(license_path, zippath)
  68. elif m:= RE_PROGUARD.match(zippath):
  69. proguard_path = javadir / m["filename"]
  70. read_zipfile_and_write(proguard_path, zippath)
  71. elif m:= RE_CMAKE.match(zippath):
  72. cmake_path = cmakedir / m["filename"]
  73. read_zipfile_and_write(cmake_path, zippath)
  74. elif zippath == "classes.jar":
  75. versioned_jar_path = javadir / f"{project_name}-{project_version}.jar"
  76. unversioned_jar_path = javadir / f"{project_name}.jar"
  77. read_zipfile_and_write(versioned_jar_path, zippath)
  78. os.symlink(src=versioned_jar_path.name, dst=unversioned_jar_path)
  79. elif zippath == "classes-sources.jar":
  80. jarpath = javadir / f"{project_name}-{project_version}-sources.jar"
  81. read_zipfile_and_write(jarpath, zippath)
  82. elif zippath == "classes-doc.jar":
  83. jarpath = javadocdir / f"{project_name}-{project_version}-javadoc.jar"
  84. read_zipfile_and_write(jarpath, zippath)
  85. print("... done")
  86. return 0
  87. if __name__ == "__main__":
  88. raise SystemExit(main())