python/build/toolchain.py: add AnyToolchain for type hints

This commit is contained in:
Max Kellermann 2023-09-26 12:47:44 +02:00
parent 4669f7e2b9
commit 5f253e66f6
9 changed files with 39 additions and 27 deletions

View File

@ -2,6 +2,7 @@ import os.path, subprocess, sys
from typing import Collection, Iterable, Optional from typing import Collection, Iterable, Optional
from build.makeproject import MakeProject from build.makeproject import MakeProject
from .toolchain import AnyToolchain
class AutotoolsProject(MakeProject): class AutotoolsProject(MakeProject):
def __init__(self, url: str, md5: str, installed: str, def __init__(self, url: str, md5: str, installed: str,
@ -22,7 +23,7 @@ class AutotoolsProject(MakeProject):
self.libs = libs self.libs = libs
self.subdirs = subdirs self.subdirs = subdirs
def configure(self, toolchain) -> str: def configure(self, toolchain: AnyToolchain) -> str:
src = self.unpack(toolchain) src = self.unpack(toolchain)
if self.autogen: if self.autogen:
if sys.platform == 'darwin': if sys.platform == 'darwin':
@ -70,7 +71,7 @@ class AutotoolsProject(MakeProject):
return build return build
def _build(self, toolchain) -> None: def _build(self, toolchain: AnyToolchain) -> None:
build = self.configure(toolchain) build = self.configure(toolchain)
if self.subdirs is not None: if self.subdirs is not None:
for subdir in self.subdirs: for subdir in self.subdirs:

View File

@ -5,6 +5,7 @@ from typing import Optional, TextIO
from collections.abc import Mapping from collections.abc import Mapping
from build.project import Project from build.project import Project
from .toolchain import AnyToolchain
def __write_cmake_compiler(f: TextIO, language: str, compiler: str) -> None: def __write_cmake_compiler(f: TextIO, language: str, compiler: str) -> None:
s = compiler.split(' ', 1) s = compiler.split(' ', 1)
@ -13,7 +14,7 @@ def __write_cmake_compiler(f: TextIO, language: str, compiler: str) -> None:
compiler = s[1] compiler = s[1]
print(f'set(CMAKE_{language}_COMPILER {compiler})', file=f) print(f'set(CMAKE_{language}_COMPILER {compiler})', file=f)
def __write_cmake_toolchain_file(f: TextIO, toolchain) -> None: def __write_cmake_toolchain_file(f: TextIO, toolchain: AnyToolchain) -> None:
if '-darwin' in toolchain.actual_arch: if '-darwin' in toolchain.actual_arch:
cmake_system_name = 'Darwin' cmake_system_name = 'Darwin'
elif toolchain.is_windows: elif toolchain.is_windows:
@ -54,7 +55,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
""") """)
def configure(toolchain, src: str, build: str, args: list[str]=[], env: Optional[Mapping[str, str]]=None) -> None: def configure(toolchain: AnyToolchain, src: str, build: str, args: list[str]=[], env: Optional[Mapping[str, str]]=None) -> None:
cross_args = [] cross_args = []
if toolchain.is_windows: if toolchain.is_windows:
@ -103,7 +104,7 @@ class CmakeProject(Project):
self.windows_configure_args = windows_configure_args self.windows_configure_args = windows_configure_args
self.env = env self.env = env
def configure(self, toolchain) -> str: def configure(self, toolchain: AnyToolchain) -> str:
src = self.unpack(toolchain) src = self.unpack(toolchain)
build = self.make_build_path(toolchain) build = self.make_build_path(toolchain)
configure_args = self.configure_args configure_args = self.configure_args
@ -112,7 +113,7 @@ class CmakeProject(Project):
configure(toolchain, src, build, configure_args, self.env) configure(toolchain, src, build, configure_args, self.env)
return build return build
def _build(self, toolchain) -> None: def _build(self, toolchain: AnyToolchain) -> None:
build = self.configure(toolchain) build = self.configure(toolchain)
subprocess.check_call(['ninja', '-v', 'install'], subprocess.check_call(['ninja', '-v', 'install'],
cwd=build, env=toolchain.env) cwd=build, env=toolchain.env)

View File

@ -2,6 +2,7 @@ import subprocess, multiprocessing
from typing import Optional from typing import Optional
from build.project import Project from build.project import Project
from .toolchain import AnyToolchain
class MakeProject(Project): class MakeProject(Project):
def __init__(self, url: str, md5: str, installed: str, def __init__(self, url: str, md5: str, installed: str,
@ -18,17 +19,17 @@ class MakeProject(Project):
# default to 12, if multiprocessing.cpu_count() is not implemented # default to 12, if multiprocessing.cpu_count() is not implemented
return 12 return 12
def get_make_args(self, toolchain) -> list[str]: def get_make_args(self, toolchain: AnyToolchain) -> list[str]:
return ['--quiet', '-j' + str(self.get_simultaneous_jobs())] return ['--quiet', '-j' + str(self.get_simultaneous_jobs())]
def get_make_install_args(self, toolchain) -> list[str]: def get_make_install_args(self, toolchain: AnyToolchain) -> list[str]:
return ['--quiet', self.install_target] return ['--quiet', self.install_target]
def make(self, toolchain, wd: str, args: list[str]) -> None: def make(self, toolchain: AnyToolchain, wd: str, args: list[str]) -> None:
subprocess.check_call(['make'] + args, subprocess.check_call(['make'] + args,
cwd=wd, env=toolchain.env) cwd=wd, env=toolchain.env)
def build_make(self, toolchain, wd: str, install: bool=True) -> None: def build_make(self, toolchain: AnyToolchain, wd: str, install: bool=True) -> None:
self.make(toolchain, wd, self.get_make_args(toolchain)) self.make(toolchain, wd, self.get_make_args(toolchain))
if install: if install:
self.make(toolchain, wd, self.get_make_install_args(toolchain)) self.make(toolchain, wd, self.get_make_install_args(toolchain))

View File

@ -4,8 +4,9 @@ import platform
from typing import Optional from typing import Optional
from build.project import Project from build.project import Project
from .toolchain import AnyToolchain
def make_cross_file(toolchain) -> str: def make_cross_file(toolchain: AnyToolchain) -> str:
if toolchain.is_windows: if toolchain.is_windows:
system = 'windows' system = 'windows'
windres = "windres = '%s'" % toolchain.windres windres = "windres = '%s'" % toolchain.windres
@ -81,7 +82,7 @@ endian = '{endian}'
""") """)
return path return path
def configure(toolchain, src: str, build: str, args: list[str]=[]) -> None: def configure(toolchain: AnyToolchain, src: str, build: str, args: list[str]=[]) -> None:
cross_file = make_cross_file(toolchain) cross_file = make_cross_file(toolchain)
configure = [ configure = [
'meson', 'setup', 'meson', 'setup',
@ -110,13 +111,13 @@ class MesonProject(Project):
Project.__init__(self, url, md5, installed, **kwargs) Project.__init__(self, url, md5, installed, **kwargs)
self.configure_args = configure_args self.configure_args = configure_args
def configure(self, toolchain) -> str: def configure(self, toolchain: AnyToolchain) -> str:
src = self.unpack(toolchain) src = self.unpack(toolchain)
build = self.make_build_path(toolchain) build = self.make_build_path(toolchain)
configure(toolchain, src, build, self.configure_args) configure(toolchain, src, build, self.configure_args)
return build return build
def _build(self, toolchain) -> None: def _build(self, toolchain: AnyToolchain) -> None:
build = self.configure(toolchain) build = self.configure(toolchain)
subprocess.check_call(['ninja', '-v', 'install'], subprocess.check_call(['ninja', '-v', 'install'],
cwd=build, env=toolchain.env) cwd=build, env=toolchain.env)

View File

@ -2,13 +2,14 @@ import subprocess
from typing import Optional from typing import Optional
from build.makeproject import MakeProject from build.makeproject import MakeProject
from .toolchain import AnyToolchain
class OpenSSLProject(MakeProject): class OpenSSLProject(MakeProject):
def __init__(self, url: str, md5: str, installed: str, def __init__(self, url: str, md5: str, installed: str,
**kwargs): **kwargs):
MakeProject.__init__(self, url, md5, installed, install_target='install_dev', **kwargs) MakeProject.__init__(self, url, md5, installed, install_target='install_dev', **kwargs)
def get_make_args(self, toolchain) -> list[str]: def get_make_args(self, toolchain: AnyToolchain) -> list[str]:
return MakeProject.get_make_args(self, toolchain) + [ return MakeProject.get_make_args(self, toolchain) + [
'CC=' + toolchain.cc, 'CC=' + toolchain.cc,
'CFLAGS=' + toolchain.cflags, 'CFLAGS=' + toolchain.cflags,
@ -18,13 +19,13 @@ class OpenSSLProject(MakeProject):
'build_libs', 'build_libs',
] ]
def get_make_install_args(self, toolchain) -> list[str]: def get_make_install_args(self, toolchain: AnyToolchain) -> list[str]:
# OpenSSL's Makefile runs "ranlib" during installation # OpenSSL's Makefile runs "ranlib" during installation
return MakeProject.get_make_install_args(self, toolchain) + [ return MakeProject.get_make_install_args(self, toolchain) + [
'RANLIB=' + toolchain.ranlib, 'RANLIB=' + toolchain.ranlib,
] ]
def _build(self, toolchain) -> None: def _build(self, toolchain: AnyToolchain) -> None:
src = self.unpack(toolchain, out_of_tree=False) src = self.unpack(toolchain, out_of_tree=False)
# OpenSSL has a weird target architecture scheme with lots of # OpenSSL has a weird target architecture scheme with lots of

View File

@ -5,6 +5,7 @@ from typing import cast, BinaryIO, Optional
from build.download import download_and_verify from build.download import download_and_verify
from build.tar import untar from build.tar import untar
from build.quilt import push_all from build.quilt import push_all
from .toolchain import AnyToolchain
class Project: class Project:
def __init__(self, url: str, md5: str, installed: str, def __init__(self, url: str, md5: str, installed: str,
@ -41,10 +42,10 @@ class Project:
self.edits = edits self.edits = edits
self.use_cxx = use_cxx self.use_cxx = use_cxx
def download(self, toolchain) -> str: def download(self, toolchain: AnyToolchain) -> str:
return download_and_verify(self.url, self.md5, toolchain.tarball_path) return download_and_verify(self.url, self.md5, toolchain.tarball_path)
def is_installed(self, toolchain) -> bool: def is_installed(self, toolchain: AnyToolchain) -> bool:
tarball = self.download(toolchain) tarball = self.download(toolchain)
installed = os.path.join(toolchain.install_prefix, self.installed) installed = os.path.join(toolchain.install_prefix, self.installed)
tarball_mtime = os.path.getmtime(tarball) tarball_mtime = os.path.getmtime(tarball)
@ -53,7 +54,7 @@ class Project:
except FileNotFoundError: except FileNotFoundError:
return False return False
def unpack(self, toolchain, out_of_tree: bool=True) -> str: def unpack(self, toolchain: AnyToolchain, out_of_tree: bool=True) -> str:
if out_of_tree: if out_of_tree:
parent_path = toolchain.src_path parent_path = toolchain.src_path
else: else:
@ -74,7 +75,7 @@ class Project:
return path return path
def make_build_path(self, toolchain, lazy: bool=False) -> str: def make_build_path(self, toolchain: AnyToolchain, lazy: bool=False) -> str:
path = os.path.join(toolchain.build_path, self.base) path = os.path.join(toolchain.build_path, self.base)
if lazy and os.path.isdir(path): if lazy and os.path.isdir(path):
return path return path
@ -85,5 +86,5 @@ class Project:
os.makedirs(path, exist_ok=True) os.makedirs(path, exist_ok=True)
return path return path
def build(self, toolchain) -> None: def build(self, toolchain: AnyToolchain) -> None:
self._build(toolchain) self._build(toolchain)

View File

@ -1,10 +1,12 @@
import subprocess import subprocess
from typing import Union from typing import Union
def run_quilt(toolchain, cwd: str, patches_path: str, *args: str) -> None: from .toolchain import AnyToolchain
def run_quilt(toolchain: AnyToolchain, cwd: str, patches_path: str, *args: str) -> None:
env = dict(toolchain.env) env = dict(toolchain.env)
env['QUILT_PATCHES'] = patches_path env['QUILT_PATCHES'] = patches_path
subprocess.check_call(['quilt'] + list(args), cwd=cwd, env=env) subprocess.check_call(['quilt'] + list(args), cwd=cwd, env=env)
def push_all(toolchain, src_path: str, patches_path: str) -> None: def push_all(toolchain: AnyToolchain, src_path: str, patches_path: str) -> None:
run_quilt(toolchain, src_path, patches_path, 'push', '-a') run_quilt(toolchain, src_path, patches_path, 'push', '-a')

View File

@ -1,5 +1,6 @@
import os.path import os.path
import shutil import shutil
from typing import Union
android_abis = { android_abis = {
'armeabi-v7a': { 'armeabi-v7a': {
@ -172,3 +173,5 @@ class MingwToolchain:
self.pkg_config = shutil.copy(os.path.join(top_path, 'build', 'pkg-config.sh'), self.pkg_config = shutil.copy(os.path.join(top_path, 'build', 'pkg-config.sh'),
os.path.join(bin_dir, 'pkg-config')) os.path.join(bin_dir, 'pkg-config'))
self.env['PKG_CONFIG'] = self.pkg_config self.env['PKG_CONFIG'] = self.pkg_config
AnyToolchain = Union[AndroidNdkToolchain, MingwToolchain]

View File

@ -2,13 +2,14 @@ import subprocess
from typing import Optional from typing import Optional
from build.makeproject import MakeProject from build.makeproject import MakeProject
from .toolchain import AnyToolchain
class ZlibProject(MakeProject): class ZlibProject(MakeProject):
def __init__(self, url: str, md5: str, installed: str, def __init__(self, url: str, md5: str, installed: str,
**kwargs): **kwargs):
MakeProject.__init__(self, url, md5, installed, **kwargs) MakeProject.__init__(self, url, md5, installed, **kwargs)
def get_make_args(self, toolchain) -> list[str]: def get_make_args(self, toolchain: AnyToolchain) -> list[str]:
return MakeProject.get_make_args(self, toolchain) + [ return MakeProject.get_make_args(self, toolchain) + [
'CC=' + toolchain.cc + ' ' + toolchain.cppflags + ' ' + toolchain.cflags, 'CC=' + toolchain.cc + ' ' + toolchain.cppflags + ' ' + toolchain.cflags,
'CPP=' + toolchain.cc + ' -E ' + toolchain.cppflags, 'CPP=' + toolchain.cc + ' -E ' + toolchain.cppflags,
@ -19,13 +20,13 @@ class ZlibProject(MakeProject):
'libz.a' 'libz.a'
] ]
def get_make_install_args(self, toolchain) -> list[str]: def get_make_install_args(self, toolchain: AnyToolchain) -> list[str]:
return [ return [
'RANLIB=' + toolchain.ranlib, 'RANLIB=' + toolchain.ranlib,
self.install_target self.install_target
] ]
def _build(self, toolchain) -> None: def _build(self, toolchain: AnyToolchain) -> None:
src = self.unpack(toolchain, out_of_tree=False) src = self.unpack(toolchain, out_of_tree=False)
subprocess.check_call(['./configure', '--prefix=' + toolchain.install_prefix, '--static'], subprocess.check_call(['./configure', '--prefix=' + toolchain.install_prefix, '--static'],