jw.pkg.App: Add more distro_xxx properties

In addition to the existing propert distro_id, add the properties
distro_codename, distro_name, distro_cascade and distro_gnu_triplet.

Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2026-03-01 17:01:50 +01:00
commit f58e9fe298

View file

@ -3,6 +3,8 @@
# This source code file is a merge of various build tools and a horrible mess. # This source code file is a merge of various build tools and a horrible mess.
# #
from __future__ import annotations
from typing import TypeAlias from typing import TypeAlias
import os, sys, argparse, pwd, re import os, sys, argparse, pwd, re
@ -210,7 +212,10 @@ class App(Base):
# -- Members without default values # -- Members without default values
self.__opt_os: str|None = None self.__opt_os: str|None = None
self.__top_name: str|None = None self.__top_name: str|None = None
self.__os_release: str|None = None
self.__distro_id: str|None = None self.__distro_id: str|None = None
self.__distro_name: str|None = None
self.__distro_codename: str|None = None
self.__os_cascade: list[str]|None = None self.__os_cascade: list[str]|None = None
self.__res_cache = ResultCache() self.__res_cache = ResultCache()
self.__topdir: str|None = None self.__topdir: str|None = None
@ -253,16 +258,95 @@ class App(Base):
return self.__projs_root return self.__projs_root
@property @property
def distro_id(self): def os_release(self) -> str:
if self.__distro_id is None: if self.__os_release is None:
os_release = '/etc/os-release' os_release = '/etc/os-release'
with open(os_release, 'r') as file: with open(os_release, 'r') as file:
m = re.search(r'^\s*ID\s*=\s*("?)([^"\n]+)\1\s*$', file.read(), re.MULTILINE) self.__os_release = file.read()
if m is None: return self.__os_release
raise Exception(f'Could not read "ID=" from "{os_release}"')
self.__distro_id = m.group(2) def os_release_field(self, key: str, throw: bool=False) -> str:
m = re.search(r'^\s*' + key + r'\s*=\s*("?)([^"\n]+)\1\s*$', self.os_release, re.MULTILINE)
if m is None:
if throw:
raise Exception(f'Could not read "{key}=" from /etc/os-release')
return None
return m.group(2)
@property
def distro_name(self) -> str:
if self.__distro_name is None:
self.__distro_name = self.os_release_field('NAME', throw=True)
return self.__distro_name
@property
def distro_id(self) -> str:
if self.__distro_id is None:
val = self.os_release_field('ID', throw=True)
match val:
case 'opensuse-tumbleweed':
self.__distro_id = 'opensuse'
case 'kali':
self.__distro_id = 'kali'
case _:
self.__distro_id = val
return self.__distro_id return self.__distro_id
@property
def distro_codename(self) -> str:
match self.distro_id:
case 'opensuse':
self.__distro_codename = \
self.os_release_field('ID', throw=True).split('-')[1]
case 'kali':
self.__distro_codename = \
self.os_release_field('VERSION_CODENAME', throw=True).split('-')[1]
case _:
self.__distro_codename = \
self.os_release_field('VERSION_CODENAME', throw=True)
return self.__distro_codename
@property
def distro_cascade(self) -> str:
return ' '.join(self.os_cascade())
@property
def distro_gnu_triplet(self) -> str:
import sysconfig
import shutil
import subprocess
# Best: GNU host triplet Python was built for
for key in ("HOST_GNU_TYPE", "BUILD_GNU_TYPE"): # BUILD_GNU_TYPE can exist too
ret = sysconfig.get_config_var(key)
if isinstance(ret, str) and ret:
return ret
# Common on Debian/Ubuntu: multiarch component (often looks like a triplet)
ret = sysconfig.get_config_var("MULTIARCH")
if isinstance(ret, str) and ret:
return ret
# Sometimes exposed (privately) by CPython
ret = getattr(sys.implementation, "_multiarch", None)
if isinstance(ret, str) and ret:
return ret
# Last resort: ask the system compiler
for cc in ("gcc", "cc", "clang"):
path = shutil.which(cc)
if not path:
continue
try:
ret = subprocess.check_output([path, "-dumpmachine"], text=True, stderr=subprocess.DEVNULL).strip()
if ret:
return ret
except Exception:
pass
raise RuntimeError('Failed to get GNU triplet from running machine')
def find_dir(self, name: str, search_subdirs: list[str]=[], search_absdirs: list[str]=[], pretty: bool=True): def find_dir(self, name: str, search_subdirs: list[str]=[], search_absdirs: list[str]=[], pretty: bool=True):
return self.__find_dir(name, search_subdirs, search_absdirs, pretty) return self.__find_dir(name, search_subdirs, search_absdirs, pretty)