File indexing completed on 2024-12-15 04:00:58

0001 #!/usr/bin/env python3
0002 
0003 # SPDX-FileCopyrightText: 2021 Mattia Basaglia <dev@dragon.best>
0004 # SPDX-License-Identifier: GPL-3.0-or-later
0005 
0006 import os
0007 import shlex
0008 import pathlib
0009 import argparse
0010 import subprocess
0011 
0012 
0013 class Variable:
0014     def __init__(self, cmake_name, *a, **kw):
0015         self.cmake_name = cmake_name
0016         self.value = kw.pop("fixed_value", None)
0017         self.argparse_args = a
0018         self.argparse_kwargs = kw
0019         self.default_callable = self.argparse_kwargs.pop("default_callable", None)
0020 
0021         self.dest = self.argparse_kwargs.get("dest", None)
0022 
0023         if not self.dest:
0024             if cmake_name:
0025                 self.dest = cmake_name
0026             else:
0027                 self.dest = self.argparse_args[0].strip("-").replace("-", "_")
0028 
0029         self.argparse_kwargs["dest"] = self.dest
0030 
0031     def add_to_parser(self, parser: argparse.ArgumentParser):
0032         if self.argparse_args or self.argparse_args:
0033             parser.add_argument(
0034                 *self.argparse_args,
0035                 **self.argparse_kwargs
0036             )
0037 
0038     def from_parser(self, variables, ns):
0039         if self.argparse_args or self.argparse_args:
0040             self.value = getattr(ns, self.dest)
0041 
0042         if self.value is None and self.default_callable:
0043             self.value = self.default_callable(variables, ns)
0044 
0045     def add_to_cmd(self, cmd):
0046         if self.cmake_name:
0047             cmd.append("-D%s=%s" % (self.cmake_name, str(self.value)))
0048 
0049 
0050 class Variables:
0051     def __init__(self, parser: argparse.ArgumentParser()):
0052         self.variables = []
0053         self.vars = {}
0054         self.parser = parser
0055         self.args = []
0056         parser.add_argument("cmake_args", nargs="+", help="CMake arguments")
0057 
0058     def add(self, var: Variable) -> "Variables":
0059         self.variables.append(var)
0060         self.vars[var.dest] = var
0061         var.add_to_parser(self.parser)
0062         return self
0063 
0064     def var(self, *a, **kw) -> "Variables":
0065         return self.add(Variable(*a, **kw))
0066 
0067     def option(self, *a, **kw) -> "Variables":
0068         return self.add(Variable(None, *a, **kw))
0069 
0070     def fixed(self, cmake_name, value) -> "Variables":
0071         return self.add(Variable(cmake_name, fixed_value=value))
0072 
0073     def parse_args(self):
0074         ns = self.parser.parse_args()
0075         for var in self.variables:
0076             var.from_parser(self, ns)
0077 
0078         self.args = ns.cmake_args
0079         return ns
0080 
0081     def invoke(self):
0082         cmd = ["cmake"]
0083         for var in self.variables:
0084             var.add_to_cmd(cmd)
0085 
0086         print(" ".join(map(shlex.quote, cmd)))
0087         subprocess.call(cmd + self.args)
0088 
0089     def __getitem__(self, key):
0090         return self.vars[key].value
0091 
0092     def error(self, msg):
0093         self.parser.error(msg)
0094 
0095 
0096 def build_qt_path(variables: Variables, ns):
0097     if ns.qt is None:
0098         variables.error("You must specify either --qt or --qt-path")
0099 
0100     path = ns.qt_home / ".".join(map(str, ns.qt))
0101 
0102     if ns.qt < (5, 13):
0103         abi = ns.ANDROID_ABI
0104         if abi == "x86":
0105             abi_qt = abi
0106         elif abi == "armeabi-v7a":
0107             abi_qt = "armv7"
0108         elif abi == "arm64-v8a":
0109             abi_qt = "armv64_v8a"
0110         path /= "android_" + abi_qt
0111     else:
0112         path /= "android"
0113 
0114     return path
0115 
0116 
0117 def ndk_default(variables: Variables, ns):
0118     path = variables["ANDROID_SDK"] / "ndk"
0119     attempts = list(path.iterdir())
0120     if len(attempts) == 1:
0121         path /= attempts[0]
0122     else:
0123         variables.error("Could not determine --ndk automatically")
0124     return path
0125 
0126 
0127 parser = argparse.ArgumentParser()
0128 variables = Variables(parser)
0129 variables.option(
0130     "--qt",
0131     type=lambda x: tuple(map(int, x.split("."))),
0132     help="Qt Version",
0133     default=None,
0134 )
0135 variables.option(
0136     "--qt-home",
0137     default=pathlib.Path.home() / "Qt",
0138     type=pathlib.Path,
0139     help="Home path to Qt if installed with the Qt installer",
0140 )
0141 variables.var(
0142     "CMAKE_FIND_ROOT_PATH",
0143     "--qt-path",
0144     default=None,
0145     type=pathlib.Path,
0146     help="Base path for Qt for android, by default based on --qt-home and --qt-version",
0147     default_callable=build_qt_path,
0148 )
0149 variables.var(
0150     "CMAKE_PREFIX_PATH",
0151     default_callable=lambda variables, ns: variables.vars["CMAKE_FIND_ROOT_PATH"].value / "lib/cmake"
0152 )
0153 variables.fixed(
0154     "ANDROID_STL", "c++_shared"
0155 )
0156 variables.var(
0157     "ANDROID_ABI",
0158     "--abi",
0159     choices=["armeabi-v7a", "arm64-v8a", "x86", "x86_64"],
0160     required=True
0161 )
0162 variables.var(
0163     "ANDROID_SDK",
0164     "--sdk",
0165     default=pathlib.Path.home() / "Android" / "Sdk",
0166     type=pathlib.Path,
0167 )
0168 variables.var(
0169     "ANDROID_NDK",
0170     "--ndk",
0171     type=pathlib.Path,
0172     default_callable=ndk_default
0173 )
0174 variables.var(
0175     "CMAKE_TOOLCHAIN_FILE",
0176     "--toolchain",
0177     default_callable=lambda variables, ns: variables.vars["ANDROID_NDK"].value / "build/cmake/android.toolchain.cmake"
0178 )
0179 variables.var(
0180     "ANDROID_PLATFORM",
0181     "--platform",
0182     type=int,
0183     default=29,
0184 )
0185 variables.var(
0186     "JAVA_HOME",
0187     "--java-home",
0188     default="/usr/lib/jvm/default-java",
0189 )
0190 
0191 variables.parse_args()
0192 
0193 variables.invoke()