mirror of
https://gitlab.com/kupfer/kupferbootstrap.git
synced 2025-06-27 10:45:37 -04:00
Move mounting code to utils.py, move a lot of chroot-logic from packages to chroot.py, cmd_chroot
also moar crossdirect Signed-off-by: InsanePrawn <insane.prawny@gmail.com>
This commit is contained in:
parent
a4c06446e3
commit
d85c00fa12
8 changed files with 207 additions and 110 deletions
125
chroot.py
125
chroot.py
|
@ -1,9 +1,16 @@
|
|||
import click
|
||||
import logging
|
||||
import subprocess
|
||||
import os
|
||||
from config import config
|
||||
from distro import get_base_distros, RepoInfo
|
||||
from shlex import quote as shell_quote
|
||||
from utils import mount
|
||||
from distro import get_kupfer_local
|
||||
from wrapper import enforce_wrap
|
||||
from constants import GCC_HOSTSPECS
|
||||
|
||||
BIND_BUILD_DIRS = 'BINDBUILDDIRS'
|
||||
|
||||
|
||||
def get_chroot_path(chroot_name, override_basepath: str = None) -> str:
|
||||
|
@ -11,13 +18,12 @@ def get_chroot_path(chroot_name, override_basepath: str = None) -> str:
|
|||
return os.path.join(base_path, chroot_name)
|
||||
|
||||
|
||||
def create_chroot(
|
||||
chroot_name: str,
|
||||
arch: str,
|
||||
packages: list[str] = ['base'],
|
||||
extra_repos: dict[str, RepoInfo] = {},
|
||||
chroot_base_path: str = None,
|
||||
):
|
||||
def create_chroot(chroot_name: str,
|
||||
arch: str,
|
||||
packages: list[str] = ['base'],
|
||||
extra_repos: dict[str, RepoInfo] = {},
|
||||
chroot_base_path: str = None,
|
||||
bind_mounts: dict[str, str] = BIND_BUILD_DIRS):
|
||||
base_chroot = f'base_{arch}'
|
||||
chroot_path = get_chroot_path(chroot_name, override_basepath=chroot_base_path)
|
||||
base_distro = get_base_distros()[arch]
|
||||
|
@ -39,11 +45,34 @@ def create_chroot(
|
|||
f'{chroot_path}/',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal('Failed to sync chroot copy')
|
||||
exit(1)
|
||||
raise Exception(f'Failed to copy {base_chroot} to {chroot_name}')
|
||||
|
||||
# patch makepkg
|
||||
with open(f'{chroot_path}/usr/bin/makepkg', 'r') as file:
|
||||
data = file.read()
|
||||
data = data.replace('EUID == 0', 'EUID == -1')
|
||||
with open(f'{chroot_path}/usr/bin/makepkg', 'w') as file:
|
||||
file.write(data)
|
||||
|
||||
# configure makepkg
|
||||
with open(f'{chroot_path}/etc/makepkg.conf', 'r') as file:
|
||||
data = file.read()
|
||||
data = data.replace('xz -c', 'xz -T0 -c')
|
||||
data = data.replace(' check ', ' !check ')
|
||||
with open(f'{chroot_path}/etc/makepkg.conf', 'w') as file:
|
||||
file.write(data)
|
||||
|
||||
os.makedirs(chroot_path + '/etc', exist_ok=True)
|
||||
|
||||
if bind_mounts == BIND_BUILD_DIRS:
|
||||
bind_mounts = {p: p for p in [config.get_path(path) for path in ['packages', 'pkgbuilds']]}
|
||||
for src, _dest in bind_mounts.items():
|
||||
dest = os.path.join(chroot_path, _dest.lstrip('/'))
|
||||
os.makedirs(dest, exist_ok=True)
|
||||
result = mount(src, dest)
|
||||
if result.returncode != 0:
|
||||
raise Exception(f"Couldn't bind-mount {src} to {dest}")
|
||||
|
||||
conf_text = base_distro.get_pacman_conf(extra_repos)
|
||||
with open(pacman_conf_target, 'w') as file:
|
||||
file.write(conf_text)
|
||||
|
@ -67,7 +96,7 @@ def create_chroot(
|
|||
return chroot_path
|
||||
|
||||
|
||||
def run_chroot_cmd(script: str, chroot_path: str, env: dict[str, str] = {}):
|
||||
def run_chroot_cmd(script: str, chroot_path: str, env: dict[str, str] = {}) -> subprocess.CompletedProcess:
|
||||
|
||||
env_cmd = ['/usr/bin/env'] + [f'{shell_quote(key)}={shell_quote(value)}' for key, value in env.items()]
|
||||
result = subprocess.run(['arch-chroot', chroot_path] + env_cmd + [
|
||||
|
@ -99,3 +128,79 @@ def create_chroot_user(
|
|||
result = run_chroot_cmd([install_script], chroot_path=chroot_path)
|
||||
if result.returncode != 0:
|
||||
raise Exception('Failed to setup user')
|
||||
|
||||
|
||||
def try_install_packages(packages: list[str], chroot: str) -> dict[str, subprocess.CompletedProcess]:
|
||||
"""Try installing packages one by one"""
|
||||
results = {}
|
||||
for pkg in set(packages):
|
||||
# Don't check for errors here because there might be packages that are listed as dependencies but are not available on x86_64
|
||||
results[pkg] = run_chroot_cmd(f'pacman -Syy --noconfirm --needed {pkg}', chroot)
|
||||
return results
|
||||
|
||||
|
||||
def mount_crossdirect(native_chroot: str, target_chroot: str, target_arch: str, host_arch: str = None):
|
||||
if host_arch is None:
|
||||
host_arch = config.runtime['arch']
|
||||
gcc = f'{GCC_HOSTSPECS[host_arch][target_arch]}-gcc'
|
||||
|
||||
native_mount = os.path.join(target_chroot, 'native')
|
||||
logging.debug(f'Activating crossdirect in {native_mount}')
|
||||
results = try_install_packages(['crossdirect', gcc], native_chroot)
|
||||
if results[gcc].returncode != 0:
|
||||
logging.debug('Failed to install cross-compiler package {gcc}')
|
||||
if results['crossdirect'].returncode != 0:
|
||||
raise Exception('Failed to install crossdirect')
|
||||
|
||||
os.makedirs(native_mount, exist_ok=True)
|
||||
|
||||
logging.debug(f'Mounting {native_chroot} to {native_mount}')
|
||||
result = mount(native_chroot, native_mount)
|
||||
if result.returncode != 0:
|
||||
raise Exception(f'Failed to mount native chroot {native_chroot} to {native_mount}')
|
||||
|
||||
|
||||
@click.command('chroot')
|
||||
@click.argument('type', required=False, default='build')
|
||||
@click.argument('arch', required=False, default=None)
|
||||
def cmd_chroot(type: str = 'build', arch: str = None):
|
||||
chroot_path = ''
|
||||
if type not in ['base', 'build', 'rootfs']:
|
||||
raise Exception('Unknown chroot type: ' + type)
|
||||
|
||||
enforce_wrap()
|
||||
if type == 'rootfs':
|
||||
if arch:
|
||||
name = 'rootfs_' + arch
|
||||
else:
|
||||
raise Exception('"rootfs" not yet implemented, sorry!')
|
||||
# TODO: name = config.get_profile()[...]
|
||||
chroot_path = os.path.join(config.get_path('chroots'), name)
|
||||
if not os.path.exists(chroot_path):
|
||||
raise Exception(f"rootfs {name} doesn't exist")
|
||||
else:
|
||||
if not arch:
|
||||
#TODO: arch = config.get_profile()[...]
|
||||
arch = 'aarch64'
|
||||
chroot_name = type + '_' + arch
|
||||
chroot_path = get_chroot_path(chroot_name)
|
||||
if not os.path.exists(os.path.join(chroot_path, 'bin')):
|
||||
create_chroot(
|
||||
chroot_name,
|
||||
arch=arch,
|
||||
packages=['base-devel', 'git'],
|
||||
extra_repos=get_kupfer_local(arch).repos,
|
||||
)
|
||||
if type == 'build' and config.file['build']['crossdirect']:
|
||||
native_arch = config.runtime['arch']
|
||||
native_chroot = create_chroot(
|
||||
'build_' + native_arch,
|
||||
native_arch,
|
||||
packages=['base-devel', 'crossdirect'],
|
||||
extra_repos=get_kupfer_local(native_arch).repos,
|
||||
)
|
||||
mount_crossdirect(native_chroot=native_chroot, target_chroot=chroot_path, target_arch=arch)
|
||||
|
||||
cmd = ['arch-chroot', chroot_path, '/bin/bash']
|
||||
logging.debug('Starting chroot: ' + repr(cmd))
|
||||
subprocess.call(cmd)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue