mirror of
https://github.com/truenas/scale-build.git
synced 2025-12-20 02:49:28 +00:00
* Trixie related changes for scale-build
* Point to HM mirrors
* Update apt preferences for trixie
* Update debootstrap changes for trixie
* Minor fix
* Remove python3 package
* Remove mandatory explicit dep
* Use openjdk-21-jdk for kernel
* Update passwd
* There is no need for custom openssl now
* Move from libssl3 to libssl3t64
* Remove util-linux from build manifest
* Set env variable for spdk
* Don't buidl spdk for now
* ipmctl is not available in stable
* Remove legacy sysv unit stuff
* Comment out netdata for now
* Small umount fix
* Also umount efivars
* Update build manifest to reflect updated branches
* Remove nfs entry from mtree
* Make sure to umount efivars
* Properly have apt sources fixed in update image
* Pull in grub2-common
* Add netdata mirror
* Fix url
* Make sure corepack is non-interactive
* Update netdata groups
* Fix efivars mounting
* Properly use clean_mounts
* Add fixme for netdata
* Properly comment out spdk explicit deps
* Remove grub-efi-amd64-signed from iso
* Make sure efivarfs is definitely mounted
* Bring in isc-dhcp-client for now
* Revert "Bring in isc-dhcp-client for now"
This reverts commit 259ffebba5.
* Only try to umount efivarfs if host is actually efi based
* Update repo's branches
199 lines
7.5 KiB
Python
199 lines
7.5 KiB
Python
import contextlib
|
|
import json
|
|
import logging
|
|
import os
|
|
|
|
from scale_build.exceptions import CallError
|
|
from scale_build.utils.run import run
|
|
from scale_build.utils.paths import HASH_DIR, PKG_LOG_DIR, SOURCES_DIR
|
|
|
|
from .binary_package import BinaryPackage
|
|
from .bootstrap import BootstrapMixin
|
|
from .build import BuildPackageMixin
|
|
from .ccache import CCacheMixin
|
|
from .clean import BuildCleanMixin
|
|
from .git import GitPackageMixin
|
|
from .overlay import OverlayMixin
|
|
from .utils import (
|
|
DEPENDS_SCRIPT_PATH, gather_build_time_dependencies, get_normalized_build_constraint_value,
|
|
get_normalized_specified_build_constraint_value, normalize_build_depends, normalize_bin_packages_depends,
|
|
)
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class Package(BootstrapMixin, BuildPackageMixin, BuildCleanMixin, CCacheMixin, GitPackageMixin, OverlayMixin):
|
|
def __init__(
|
|
self, name, branch, repo, prebuildcmd=None, explicit_deps=None,
|
|
generate_version=True, predepscmd=None, deps_path=None, subdir=None, deoptions=None, jobs=None,
|
|
buildcmd=None, tmpfs=True, tmpfs_size=12, batch_priority=100, env=None, identity_file_path=None,
|
|
build_constraints=None, debian_fork=False, source_name=None, depscmd=None, supports_ccache=False,
|
|
secret_env=None,
|
|
):
|
|
self.name = name
|
|
self.source_name = source_name or name
|
|
self.branch = branch
|
|
self.origin = repo
|
|
self.supports_ccache = supports_ccache
|
|
self.prebuildcmd = prebuildcmd or []
|
|
self.buildcmd = buildcmd or []
|
|
self.build_constraints = build_constraints or []
|
|
self.depscmd = depscmd or []
|
|
self.explicit_deps = set(explicit_deps or set())
|
|
self.generate_version = generate_version
|
|
self.predepscmd = predepscmd or []
|
|
self.deps_path = deps_path
|
|
self.subdir = subdir
|
|
self.identity_file_path = identity_file_path
|
|
self.deoptions = deoptions
|
|
self.jobs = jobs
|
|
self.tmpfs = tmpfs
|
|
self.tmpfs_size = tmpfs_size
|
|
self.initialized_deps = False
|
|
self._binary_packages = []
|
|
self.build_depends = set()
|
|
self.source_package = None
|
|
self.parent_changed = False
|
|
self.force_build = False
|
|
self._build_time_dependencies = None
|
|
self.build_stage = None
|
|
self.logger = logger
|
|
self.children = set()
|
|
self.batch_priority = batch_priority
|
|
self.env = env or {}
|
|
self.secret_env = secret_env or []
|
|
self.debian_fork = debian_fork
|
|
|
|
if name in self.explicit_deps:
|
|
self.explicit_deps.remove(name)
|
|
|
|
def __eq__(self, other):
|
|
return other == self.name if isinstance(other, str) else self.name == other.name
|
|
|
|
@property
|
|
def log_file_path(self):
|
|
return os.path.join(PKG_LOG_DIR, f'{self.name}.log')
|
|
|
|
@property
|
|
def package_path(self):
|
|
pkg_path = self.source_path
|
|
if self.subdir:
|
|
pkg_path = os.path.join(pkg_path, self.subdir)
|
|
return pkg_path
|
|
|
|
@property
|
|
def debian_control_file_path(self):
|
|
if self.deps_path:
|
|
return os.path.join(self.package_path, self.deps_path, 'control')
|
|
else:
|
|
return os.path.join(self.package_path, 'debian/control')
|
|
|
|
@property
|
|
def source_path(self):
|
|
return os.path.join(SOURCES_DIR, self.source_name)
|
|
|
|
@property
|
|
def binary_packages(self):
|
|
if self._binary_packages:
|
|
return self._binary_packages
|
|
|
|
if self.name in ('kernel', 'kernel-dbg') or (self.predepscmd and not self.deps_path):
|
|
# We cannot determine dependency of this package because it does not probably have a control file
|
|
# in it's current state - the only example we have is grub right now. Let's improve this if there are
|
|
# more examples
|
|
self._binary_packages.append(BinaryPackage(self.name, self.build_depends, self.name, self.name, set()))
|
|
return self._binary_packages
|
|
|
|
with (self.build_dir() if self.depscmd else contextlib.nullcontext()):
|
|
if self.depscmd:
|
|
self.setup_control_file_for_dependency_ordering()
|
|
control_file_path = os.path.join(self.package_source_with_chroot, 'debian/control')
|
|
else:
|
|
control_file_path = self.debian_control_file_path
|
|
|
|
cp = run([DEPENDS_SCRIPT_PATH, control_file_path], log=False)
|
|
info = json.loads(cp.stdout)
|
|
self.build_depends = set(
|
|
normalize_build_depends(info['source_package']['build_depends'])
|
|
) | self.explicit_deps
|
|
self.source_package = info['source_package']['name']
|
|
for bin_package in info['binary_packages']:
|
|
self._binary_packages.append(BinaryPackage(
|
|
bin_package['name'], self.build_depends, self.source_package, self.name,
|
|
set(normalize_bin_packages_depends(bin_package['depends'] or ''))
|
|
))
|
|
if self.name == 'truenas':
|
|
self._binary_packages[-1].build_dependencies |= self._binary_packages[-1].install_dependencies
|
|
|
|
return self._binary_packages
|
|
|
|
def setup_control_file_for_dependency_ordering(self):
|
|
self.execute_pre_depends_commands()
|
|
for dependency_command in self.depscmd:
|
|
self.logger.debug('Running depscmd: %r', dependency_command)
|
|
self.run_in_chroot(
|
|
f'cd {self.package_source} && {dependency_command}', 'Failed to execute depscmd command'
|
|
)
|
|
|
|
def build_time_dependencies(self, all_binary_packages=None):
|
|
if self._build_time_dependencies is not None:
|
|
return self._build_time_dependencies
|
|
elif not all_binary_packages:
|
|
raise CallError('Binary packages must be specified when computing build time dependencies')
|
|
|
|
self._build_time_dependencies = gather_build_time_dependencies(
|
|
all_binary_packages, set(), self.build_depends
|
|
) | self.explicit_deps
|
|
return self._build_time_dependencies
|
|
|
|
@property
|
|
def hash_changed(self):
|
|
return self._hash_changed()
|
|
|
|
def _hash_changed(self):
|
|
if self.name == 'truenas':
|
|
# truenas is special and we want to rebuild it always
|
|
# TODO: Do see why that is so
|
|
return True
|
|
|
|
source_hash = self.source_hash
|
|
existing_hash = None
|
|
if os.path.exists(self.hash_path):
|
|
with open(self.hash_path, 'r') as f:
|
|
existing_hash = f.read().strip()
|
|
if source_hash == existing_hash:
|
|
return run(
|
|
['git', '-C', self.source_path, 'diff-files', '--quiet', '--ignore-submodules'], check=False, log=False
|
|
).returncode != 0
|
|
else:
|
|
return True
|
|
|
|
@property
|
|
def source_hash(self):
|
|
return run(['git', '-C', self.source_path, 'rev-parse', '--verify', 'HEAD'], log=False).stdout.strip()
|
|
|
|
@property
|
|
def rebuild(self):
|
|
return self.hash_changed or self.parent_changed
|
|
|
|
@property
|
|
def hash_path(self):
|
|
return os.path.join(HASH_DIR, f'{self.name}.hash')
|
|
|
|
@property
|
|
def exists(self):
|
|
return os.path.exists(self.source_path)
|
|
|
|
@property
|
|
def pkglist_hash_file_path(self):
|
|
return os.path.join(HASH_DIR, f'{self.name}.pkglist')
|
|
|
|
@property
|
|
def to_build(self):
|
|
return all(
|
|
get_normalized_build_constraint_value(constraint) == get_normalized_specified_build_constraint_value(
|
|
constraint
|
|
) for constraint in self.build_constraints
|
|
) if self.build_constraints else True
|