This commit is contained in:
VXTLS 2026-04-15 12:33:39 +00:00 committed by GitHub
commit 99069b8e99
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
184 changed files with 14484 additions and 217 deletions

108
Payload_img_design.md Normal file
View file

@ -0,0 +1,108 @@
# live-bootstrap
This repository uses [`README.rst`](./README.rst) as the canonical main documentation.
## Kernel-bootstrap raw `external.img`
`external.img` is a raw container disk used in kernel-bootstrap mode when
`--external-sources` is set and `--repo` is unset.
### Why not put everything in the initial image?
In kernel-bootstrap mode, the first boot image is consumed by very early
runtime code before the system reaches the normal bash-based build stage.
That early stage has tight assumptions about memory layout and file table usage.
When too many distfiles are packed into the initial image, those assumptions can
be exceeded, which leads to unstable handoff behavior (for example, failures
around the Fiwix transition in QEMU or on bare metal).
So the design is intentionally split:
- Initial image: only what is required to reach `improve: import_payload`
- `external.img`: the rest of distfiles
This is not a patch-style workaround. It is a two-phase transport design that
keeps early boot deterministic and moves bulk data import to a stage where the
runtime is robust enough to process it safely.
### Why import from an external image and copy into main filesystem?
Because the bootstrap still expects distfiles to end up under the normal local
path (`/external/distfiles`) for later steps. `external.img` is used as a
transport medium only.
The flow is:
1. Boot minimal initial image.
2. Reach `improve: import_payload`.
3. Detect the external container disk by magic (`LBPAYLD1`) across detected block devices.
4. Copy payload files into `/external/distfiles`.
5. Continue the build exactly as if files had been present locally all along.
### Format
- Magic: `LBPAYLD1` (8 bytes)
- Then: little-endian `u64` file count
- Repeated entries:
- little-endian `u64` name length
- little-endian `u64` file size
- file name string, encoded as UTF-8 bytes (no terminator)
- file bytes
`name length` is the number of bytes in the UTF-8 encoded file name (not the number of Unicode code points).
The importer probes detected block devices and selects the one with magic `LBPAYLD1`.
### Manual creation without Python
Prepare `external.list` as:
```text
<archive-name> <absolute-path-to-archive>
```
Then:
```sh
cat > make-payload.sh <<'SH'
#!/bin/sh
set -e
out="${1:-external.img}"
list="${2:-external.list}"
write_u64le() {
v="$1"
printf '%016x' "$v" | sed -E 's/(..)(..)(..)(..)(..)(..)(..)(..)/\8\7\6\5\4\3\2\1/' | xxd -r -p
}
count="$(wc -l < "${list}" | tr -d ' ')"
: > "${out}"
printf 'LBPAYLD1' >> "${out}"
write_u64le "${count}" >> "${out}"
while read -r name path; do
[ -n "${name}" ] || continue
size="$(wc -c < "${path}" | tr -d ' ')"
name_len="$(printf '%s' "${name}" | wc -c | tr -d ' ')"
write_u64le "${name_len}" >> "${out}"
write_u64le "${size}" >> "${out}"
printf '%s' "${name}" >> "${out}"
cat "${path}" >> "${out}"
done < "${list}"
SH
chmod +x make-payload.sh
./make-payload.sh external.img external.list
```
Attach `external.img` as an extra raw disk in QEMU, or as the second disk on bare metal.
### When it is used
- Used in kernel-bootstrap with `--external-sources` and without `--repo`.
- Not used with `--repo` (that path still uses an ext filesystem disk).
- Without `--external-sources` and without `--repo`, there is no second disk:
the initial image only includes distfiles needed before `improve: get_network`,
and later distfiles are downloaded from mirrors.
- `--extra-builds=guix` increases container contents (includes post-early `steps-guix`
sources), but does not change the mechanism.

View file

@ -63,17 +63,86 @@ Without using Python:
* *Only* copy distfiles listed in ``sources`` files for ``build:`` steps
manifested before ``improve: get_network`` into this disk.
* Optionally (if you don't do this, distfiles will be network downloaded):
* In kernel-bootstrap mode with ``--external-sources`` (and no ``--repo``),
use the second image as ``external.img``.
``external.img`` is a raw container (not a filesystem) used to carry the
distfiles that are not needed before ``improve: import_payload``.
In other words, the first image only carries the minimal set needed to
reach the importer; the rest of the distfiles live in ``external.img``.
* On the second image, create an MSDOS partition table and one ext3
partition.
* Copy ``distfiles/`` into this disk.
* Run QEMU, with 4+G RAM, optionally SMP (multicore), both drives (in the
order introduced above), a NIC with model E1000
* Header magic: ``LBPAYLD1`` (8 bytes).
* Then: little-endian ``u64`` file count.
* Repeated for each file: little-endian ``u64`` name length,
little-endian ``u64`` file size, UTF-8 encoded file name bytes
(no terminator), raw file bytes.
* ``name length`` is the number of UTF-8 bytes (not Unicode code points).
* With ``--repo``, the second disk remains an ext3 distfiles/repo disk.
* Without ``--external-sources`` and without ``--repo``, no second disk is
used: the initial image includes only pre-network distfiles, and later
distfiles are downloaded from configured mirrors after networking starts.
* Run QEMU, with 4+G RAM, optionally SMP (multicore), both drives (main
builder image plus external image, when a second image is used), a NIC with model E1000
(``-nic user,model=e1000``), and ``-machine kernel-irqchip=split``.
c. **Bare metal:** Follow the same steps as QEMU, but the disks need to be
two different *physical* disks, and boot from the first disk.
Manual raw ``external.img`` preparation
---------------------------------------
The following script creates a raw ``external.img`` from a manually prepared
file list. This is equivalent to what ``rootfs.py`` does for kernel-bootstrap
with ``--external-sources`` (and no ``--repo``).
1. Prepare an ``external.list`` with one file per line, formatted as:
``<archive-name> <absolute-path-to-archive>``.
2. Run:
::
cat > make-payload.sh <<'EOF'
#!/bin/sh
set -e
out="${1:-external.img}"
list="${2:-external.list}"
write_u64le() {
v="$1"
printf '%016x' "$v" | sed -E 's/(..)(..)(..)(..)(..)(..)(..)(..)/\8\7\6\5\4\3\2\1/' | xxd -r -p
}
count="$(wc -l < "${list}" | tr -d ' ')"
: > "${out}"
printf 'LBPAYLD1' >> "${out}"
write_u64le "${count}" >> "${out}"
while read -r name path; do
[ -n "${name}" ] || continue
size="$(wc -c < "${path}" | tr -d ' ')"
name_len="$(printf '%s' "${name}" | wc -c | tr -d ' ')"
write_u64le "${name_len}" >> "${out}"
write_u64le "${size}" >> "${out}"
printf '%s' "${name}" >> "${out}"
cat "${path}" >> "${out}"
done < "${list}"
EOF
chmod +x make-payload.sh
./make-payload.sh external.img external.list
3. Attach ``external.img`` as an additional raw disk when booting in QEMU, or
as the second physical disk on bare metal.
Notes:
* ``external.img`` raw container mode is used with ``--external-sources`` (and
no ``--repo``). With ``--extra-builds=guix``, the container content is larger
because it also includes post-early sources from ``steps-guix``.
* Without ``--external-sources`` and without ``--repo``, there is no second
image. The initial image only includes distfiles needed before
``improve: get_network``; later distfiles are downloaded from mirrors.
* The runtime importer identifies the correct disk by checking the magic
``LBPAYLD1`` on each detected block device, not by assuming a device name.
Mirrors
-------

View file

@ -12,6 +12,7 @@ import hashlib
import os
import random
import shutil
import struct
import tarfile
import traceback
@ -25,16 +26,34 @@ class Generator():
git_dir = os.path.join(os.path.dirname(os.path.join(__file__)), '..')
distfiles_dir = os.path.join(git_dir, 'distfiles')
raw_container_magic = b'LBPAYLD1'
# pylint: disable=too-many-arguments,too-many-positional-arguments
def __init__(self, arch, external_sources, early_preseed, repo_path, mirrors):
def __init__(self, arch, external_sources, early_preseed, repo_path, mirrors,
extra_builds=None):
self.arch = arch
self.early_preseed = early_preseed
self.external_sources = external_sources
self.repo_path = repo_path
self.mirrors = mirrors
self.source_manifest = self.get_source_manifest(not self.external_sources)
self.early_source_manifest = self.get_source_manifest(True)
self.extra_builds = list(extra_builds or [])
self.pre_network_source_manifest = self.get_source_manifest(
stop_before_improve="get_network",
extra_builds=[],
)
self.pre_import_source_manifest = self.get_source_manifest(
stop_before_improve="import_payload",
extra_builds=[],
)
# Only raw-external mode needs full upfront availability for container generation.
if self.external_sources and not self.repo_path:
self.source_manifest = self.get_source_manifest(extra_builds=self.extra_builds)
else:
self.source_manifest = self.pre_network_source_manifest
self.bootstrap_source_manifest = self.source_manifest
self.external_source_manifest = []
self.external_image = None
self.kernel_bootstrap_mode = None
self.target_dir = None
self.external_dir = None
@ -46,6 +65,115 @@ class Generator():
self.external_dir = os.path.join(self.target_dir, 'external')
self.distfiles()
def _select_kernel_bootstrap_mode(self):
"""
Select how kernel-bootstrap should transport distfiles.
"""
if self.repo_path:
# Keep second-disk staging outside init image for ext3 repo mode.
self.external_dir = os.path.join(os.path.dirname(self.target_dir), 'external')
self.kernel_bootstrap_mode = "repo"
self.external_source_manifest = []
return
if self.external_sources:
# Raw external container mode keeps early distfiles inside init image.
self.external_dir = os.path.join(self.target_dir, 'external')
self.kernel_bootstrap_mode = "raw_external"
self._prepare_kernel_bootstrap_external_manifests()
return
# Network-only mode keeps pre-network distfiles inside init image.
self.external_dir = os.path.join(self.target_dir, 'external')
self.kernel_bootstrap_mode = "network_only"
self.bootstrap_source_manifest = self.pre_network_source_manifest
self.external_source_manifest = []
def _prepare_kernel_bootstrap_external_manifests(self):
"""
Split distfiles between init image and external raw container.
"""
# Keep the early builder image small: include only sources needed
# before improve: import_payload runs, so external.img is the primary
# carrier for the remaining distfiles.
self.bootstrap_source_manifest = self.pre_import_source_manifest
full_manifest = self.get_source_manifest(extra_builds=self.extra_builds)
if self.bootstrap_source_manifest == full_manifest:
raise ValueError("steps/manifest must include `improve: import_payload` in kernel-bootstrap mode.")
bootstrap_set = set(self.bootstrap_source_manifest)
self.external_source_manifest = [entry for entry in full_manifest if entry not in bootstrap_set]
def _kernel_bootstrap_init_manifest(self):
"""
Return the exact manifest that is allowed inside init image.
"""
mode_to_manifest = {
"network_only": self.pre_network_source_manifest, # up to get_network
"raw_external": self.bootstrap_source_manifest, # up to import_payload
"repo": self.pre_network_source_manifest, # up to get_network
}
manifest = mode_to_manifest.get(self.kernel_bootstrap_mode)
if manifest is None:
raise ValueError(f"Unexpected kernel bootstrap mode: {self.kernel_bootstrap_mode}")
return manifest
def _copy_manifest_distfiles(self, out_dir, manifest):
os.makedirs(out_dir, exist_ok=True)
for entry in manifest:
file_name = entry[3].strip()
shutil.copy2(os.path.join(self.distfiles_dir, file_name),
os.path.join(out_dir, file_name))
def _ensure_manifest_distfiles(self, manifest):
for entry in manifest:
checksum, directory, url, file_name = entry
distfile_path = os.path.join(directory, file_name)
if not os.path.isfile(distfile_path):
self.download_file(url, directory, file_name)
self.check_file(distfile_path, checksum)
def _create_raw_container_image(self, target_path, manifest, image_name="external.img"):
if manifest is None:
manifest = []
if manifest:
# Guarantee all payload distfiles exist and match checksums.
self._ensure_manifest_distfiles(manifest)
files_by_name = {}
for checksum, _, _, file_name in manifest:
if file_name in files_by_name and files_by_name[file_name] != checksum:
raise ValueError(
f"Conflicting container file with same name but different hash: {file_name}"
)
files_by_name[file_name] = checksum
container_path = os.path.join(target_path, image_name)
ordered_names = sorted(files_by_name.keys())
with open(container_path, "wb") as container:
container.write(self.raw_container_magic)
if len(ordered_names) > 0xFFFFFFFFFFFFFFFF:
raise ValueError("Too many files for raw container format.")
container.write(struct.pack("<Q", len(ordered_names)))
for file_name in ordered_names:
file_name_bytes = file_name.encode("utf_8")
if len(file_name_bytes) > 0xFFFFFFFFFFFFFFFF:
raise ValueError(f"Container file name too long: {file_name}")
src_path = os.path.join(self.distfiles_dir, file_name)
file_size = os.path.getsize(src_path)
if file_size > 0xFFFFFFFFFFFFFFFF:
raise ValueError(f"Container file too large for raw container format: {file_name}")
container.write(struct.pack("<QQ", len(file_name_bytes), file_size))
container.write(file_name_bytes)
with open(src_path, "rb") as src_file:
shutil.copyfileobj(src_file, container, 1024 * 1024)
return container_path
def prepare(self, target, using_kernel=False, kernel_bootstrap=False, target_size=0):
"""
Prepare basic media of live-bootstrap.
@ -55,6 +183,10 @@ class Generator():
"""
self.target_dir = target.path
self.external_dir = os.path.join(self.target_dir, 'external')
self.external_image = None
self.external_source_manifest = []
self.bootstrap_source_manifest = self.source_manifest
self.kernel_bootstrap_mode = None
# We use ext3 here; ext4 actually has a variety of extensions that
# have been added with varying levels of recency
@ -67,9 +199,7 @@ class Generator():
if kernel_bootstrap:
self.target_dir = os.path.join(self.target_dir, 'init')
os.mkdir(self.target_dir)
if not self.repo_path and not self.external_sources:
self.external_dir = os.path.join(self.target_dir, 'external')
self._select_kernel_bootstrap_mode()
elif using_kernel:
self.target_dir = os.path.join(self.target_dir, 'disk')
self.external_dir = os.path.join(self.target_dir, 'external')
@ -101,9 +231,17 @@ class Generator():
if kernel_bootstrap:
self.create_builder_hex0_disk_image(self.target_dir + '.img', target_size)
if self.repo_path or self.external_sources:
if self.kernel_bootstrap_mode == "repo":
mkfs_args = ['-d', os.path.join(target.path, 'external')]
target.add_disk("external", filesystem="ext3", mkfs_args=mkfs_args)
elif self.kernel_bootstrap_mode == "raw_external":
# external.img is a raw container, imported at improve: import_payload.
self.external_image = self._create_raw_container_image(
target.path,
self.external_source_manifest,
image_name="external.img",
)
target.add_existing_disk("external", self.external_image)
elif using_kernel:
mkfs_args = ['-F', '-d', os.path.join(target.path, 'disk')]
target.add_disk("disk",
@ -117,6 +255,18 @@ class Generator():
self.get_packages()
shutil.copytree(os.path.join(self.git_dir, 'steps'), os.path.join(self.target_dir, 'steps'))
for extra_build in self.extra_builds:
steps_extra = f"steps-{extra_build}"
steps_extra_dir = os.path.join(self.git_dir, steps_extra)
if not os.path.isdir(steps_extra_dir):
raise ValueError(
f"{steps_extra} directory does not exist while --extra-builds includes {extra_build}."
)
if not os.path.isfile(os.path.join(steps_extra_dir, 'manifest')):
raise ValueError(
f"{steps_extra}/manifest does not exist while --extra-builds includes {extra_build}."
)
shutil.copytree(steps_extra_dir, os.path.join(self.target_dir, steps_extra))
def stage0_posix(self, kernel_bootstrap=False):
"""Copy in all of the stage0-posix"""
@ -147,26 +297,25 @@ class Generator():
def distfiles(self):
"""Copy in distfiles"""
def copy_no_network_distfiles(out, early):
# Note that "no disk" implies "no network" for kernel bootstrap mode
manifest = self.early_source_manifest if early else self.source_manifest
for file in manifest:
file = file[3].strip()
shutil.copy2(os.path.join(self.distfiles_dir, file),
os.path.join(out, file))
distfile_dir = os.path.join(self.external_dir, 'distfiles')
early_distfile_dir = os.path.join(self.target_dir, 'external', 'distfiles')
main_distfile_dir = os.path.join(self.external_dir, 'distfiles')
if self.kernel_bootstrap_mode is not None:
# Kernel bootstrap always copies a bounded manifest, never full distfiles tree.
init_manifest = self._kernel_bootstrap_init_manifest()
init_distfile_dir = os.path.join(self.target_dir, 'external', 'distfiles')
self._copy_manifest_distfiles(init_distfile_dir, init_manifest)
if early_distfile_dir != main_distfile_dir:
os.makedirs(early_distfile_dir, exist_ok=True)
copy_no_network_distfiles(early_distfile_dir, True)
if self.kernel_bootstrap_mode == "repo":
# Repo mode also stages the same bounded set for the second ext3 disk.
staged_distfile_dir = distfile_dir
if staged_distfile_dir != init_distfile_dir:
self._copy_manifest_distfiles(staged_distfile_dir, init_manifest)
return
if self.external_sources:
shutil.copytree(self.distfiles_dir, main_distfile_dir, dirs_exist_ok=True)
shutil.copytree(self.distfiles_dir, distfile_dir, dirs_exist_ok=True)
else:
os.mkdir(main_distfile_dir)
copy_no_network_distfiles(main_distfile_dir, False)
self._copy_manifest_distfiles(distfile_dir, self.bootstrap_source_manifest)
@staticmethod
def output_dir(srcfs_file, dirpath):
@ -344,21 +493,38 @@ this script the next time")
self.check_file(path, line[0])
@classmethod
def get_source_manifest(cls, pre_network=False):
def get_source_manifest(cls, stop_before_improve=None, extra_builds=None):
"""
Generate a source manifest for the system.
"""
entries = []
directory = os.path.relpath(cls.distfiles_dir, cls.git_dir)
extra_builds = list(extra_builds or [])
# Find all source files
steps_dir = os.path.join(cls.git_dir, 'steps')
with open(os.path.join(steps_dir, 'manifest'), 'r', encoding="utf_8") as file:
manifests = [os.path.join(cls.git_dir, 'steps')]
for extra_build in extra_builds:
steps_extra = f"steps-{extra_build}"
steps_extra_dir = os.path.join(cls.git_dir, steps_extra)
if not os.path.isdir(steps_extra_dir):
raise ValueError(
f"{steps_extra} directory does not exist while --extra-builds includes {extra_build}."
)
manifests.append(steps_extra_dir)
for steps_dir in manifests:
manifest_path = os.path.join(steps_dir, 'manifest')
if not os.path.isfile(manifest_path):
raise ValueError(f"Missing manifest: {manifest_path}")
with open(manifest_path, 'r', encoding="utf_8") as file:
for line in file:
if pre_network and line.strip().startswith("improve: ") and "network" in line:
stripped = line.strip()
if stop_before_improve and stripped.startswith("improve: "):
improve_step = stripped.split(" ")[1].split("#")[0].strip()
if improve_step == stop_before_improve:
break
if not line.strip().startswith("build: "):
if not stripped.startswith("build: "):
continue
step = line.split(" ")[1].split("#")[0].strip()

View file

@ -12,7 +12,7 @@ class SimpleMirror(socketserver.TCPServer):
"""Simple HTTP mirror from a directory"""
def __init__(self, directory: str):
self.directory = directory
super().__init__(("localhost", 0), self._handler)
super().__init__(("0.0.0.0", 0), self._handler)
@property
def port(self):

View file

@ -59,3 +59,7 @@ class Target:
def get_disk(self, name):
"""Get the path to a device of a disk"""
return self._disks.get(name)
def add_existing_disk(self, name, path):
"""Register an existing disk image path."""
self._disks[name] = os.path.abspath(path)

View file

@ -186,7 +186,8 @@ do_file() {
esac
}
for src in steps/*/sources; do
for src in steps/*/sources steps-*/*/sources; do
[ -f "${src}" ] || continue
while read -r line; do
# shellcheck disable=SC2086
do_file ${line}

662
rootfs.py
View file

@ -17,6 +17,8 @@ you can run bootstap inside chroot.
import argparse
import os
import signal
import shutil
import tempfile
import threading
from lib.generator import Generator, stage0_arch_map
@ -24,6 +26,503 @@ from lib.simple_mirror import SimpleMirror
from lib.target import Target
from lib.utils import run, run_as_root
def parse_internal_ci_break_after(value):
"""
Parse INTERNAL_CI break directive in the form '<scope>:<step>'.
"""
if not value:
return None, None
scope, separator, step_name = value.partition(":")
scope = scope.strip()
step_name = step_name.strip()
if (
separator != ":"
or not _is_valid_manifest_scope(scope)
or not step_name
):
raise ValueError(
"--internal-ci-break-after must be in the form "
"'steps:<name>' or 'steps-<extra>:<name>'."
)
return scope, step_name
def _is_valid_extra_build_name(name):
if not name:
return False
return all(ch.isalnum() or ch in ("-", "_") for ch in name)
def parse_extra_builds(value):
"""
Parse comma-separated extra build namespaces (e.g. 'guix,gentoo').
"""
if not value:
return []
builds = []
for raw_name in value.split(","):
name = raw_name.strip()
if not name:
continue
if not _is_valid_extra_build_name(name):
raise ValueError(
"--extra-builds must be a comma-separated list of names using "
"letters, digits, '-' or '_'."
)
if name not in builds:
builds.append(name)
return builds
def _scope_for_extra_build(extra_build):
return f"steps-{extra_build}"
def _is_valid_manifest_scope(scope):
if scope == "steps":
return True
if not scope.startswith("steps-"):
return False
return _is_valid_extra_build_name(scope[len("steps-"):])
def _parse_build_step_name(line):
"""
Extract the package name from a manifest build directive.
"""
stripped = line.strip()
if not stripped.startswith("build: "):
return None
payload = stripped[len("build: "):].split("#", 1)[0].strip()
if not payload:
return None
return payload.split()[0]
_INIT_MOUNT_MARKER = "# LB_STAGE0_EARLY_MOUNTS"
_INIT_REGEN_MARKER = "# LB_STAGE0_REGENERATE_SCRIPTS"
_RESUME_NEXT_PATH = "/steps/.lb-resume-next"
_RESUME_NEXT_SCOPE_VAR = "LB_RESUME_NEXT_SCOPE"
_RESUME_NEXT_PACKAGE_VAR = "LB_RESUME_NEXT_PACKAGE"
_INIT_LEGACY_NETWORK_BLOCK = (
'if [ "${CHROOT}" = False ] && command -v dhcpcd >/dev/null 2>&1; then\n'
'dhcpcd --waitip=4 || true\n'
'fi\n'
)
_INIT_GATED_NETWORK_BLOCK = (
'if [ -f /steps/env ]; then\n'
'. /steps/env\n'
'fi\n'
'if [ "${CHROOT}" = False ] && [ "${NETWORK_READY}" = True ] && command -v dhcpcd >/dev/null 2>&1; then\n'
'dhcpcd --waitip=4 || true\n'
'fi\n'
)
_INIT_MOUNT_BLOCK = (
_INIT_MOUNT_MARKER + "\n"
+ "mount | grep ' on /dev ' >/dev/null 2>&1 || (mkdir -p /dev; mount -t devtmpfs devtmpfs /dev)\n"
+ "mount | grep ' on /proc ' >/dev/null 2>&1 || (mkdir -p /proc; mount -t proc proc /proc)\n"
)
_INIT_REGEN_BLOCK = (
_INIT_REGEN_MARKER + "\n"
+ "# Regenerate scripts from current manifests so resume runs stay deterministic.\n"
+ 'resume_entry=""\n'
+ 'resume_root=""\n'
+ 'resume_pkg=""\n'
+ 'resume_next_scope=""\n'
+ 'resume_next_pkg=""\n'
+ 'if [ -f "$0" ]; then\n'
+ 'resume_entry="$(sed -n "s/.*bash \\(\\/steps[^ ]*\\/[0-9][0-9]*\\.sh\\).*/\\1/p" "$0" | head -n1)"\n'
+ 'fi\n'
+ 'if [ -n "${resume_entry}" ]; then\n'
+ 'resume_root="$(dirname "${resume_entry}")"\n'
+ 'if [ -f "${resume_entry}" ]; then\n'
+ 'resume_pkg="$(sed -n "s/^build \\([^ ]*\\) .*/\\1/p" "${resume_entry}" | head -n1)"\n'
+ 'fi\n'
+ 'fi\n'
+ f'if [ -f "{_RESUME_NEXT_PATH}" ]; then\n'
+ f'resume_next_scope="$(sed -n "s/^scope=//p" "{_RESUME_NEXT_PATH}" | head -n1)"\n'
+ f'resume_next_pkg="$(sed -n "s/^package=//p" "{_RESUME_NEXT_PATH}" | head -n1)"\n'
+ 'if [ "${resume_next_scope}" = "steps" ]; then\n'
+ 'resume_root="/steps"\n'
+ 'elif echo "${resume_next_scope}" | grep -Eq "^steps-[A-Za-z0-9_-]+$"; then\n'
+ 'resume_root="/${resume_next_scope}"\n'
+ 'fi\n'
+ 'if [ -n "${resume_next_pkg}" ]; then\n'
+ 'resume_pkg="${resume_next_pkg}"\n'
+ 'fi\n'
+ f'rm -f "{_RESUME_NEXT_PATH}"\n'
+ 'fi\n'
+ 'if [ -x /script-generator ] && [ -f /steps/manifest ]; then\n'
+ '/script-generator /steps/manifest\n'
+ 'fi\n'
+ 'for extra_manifest in /steps-*/manifest; do\n'
+ 'if [ ! -f "${extra_manifest}" ]; then\n'
+ 'continue\n'
+ 'fi\n'
+ 'if [ -x /script-generator ]; then\n'
+ '/script-generator "${extra_manifest}" /steps\n'
+ 'fi\n'
+ 'done\n'
+ 'if [ -n "${resume_pkg}" ] && [ -d "${resume_root}" ]; then\n'
+ 'mapped_entry="$(grep -F -l "build ${resume_pkg} " "${resume_root}"/[0-9]*.sh 2>/dev/null | head -n1 || true)"\n'
+ 'if [ -n "${mapped_entry}" ]; then\n'
+ 'resume_entry="${mapped_entry}"\n'
+ 'fi\n'
+ 'fi\n'
+ 'if [ -n "${resume_entry}" ] && [ -f "${resume_entry}" ] && [ "${resume_entry}" != "$0" ]; then\n'
+ 'bash "${resume_entry}"\n'
+ 'exit "$?"\n'
+ 'fi\n'
)
def _find_next_build_after(manifest_lines, break_step, context_label):
"""
Return the next build step after break_step within the same manifest.
"""
found_break = False
for line in manifest_lines:
step_name = _parse_build_step_name(line)
if step_name is None:
continue
if found_break:
return step_name
if step_name == break_step:
found_break = True
if not found_break:
raise ValueError(
"INTERNAL_CI_BREAK_AFTER target not found in "
+ context_label
+ ": "
+ break_step
)
return None
def _insert_internal_ci_break(manifest_lines, break_step, internal_ci, context_label):
inserted = False
break_line = f"jump: break ( INTERNAL_CI == {internal_ci} )\n"
output_lines = []
for line in manifest_lines:
output_lines.append(line)
if inserted:
continue
step_name = _parse_build_step_name(line)
if step_name is None:
continue
if step_name == break_step:
output_lines.append(break_line)
inserted = True
if not inserted:
raise ValueError(
"INTERNAL_CI_BREAK_AFTER target not found in "
+ context_label
+ ": "
+ break_step
)
return output_lines
def _copytree_replace(src, dst):
if os.path.isdir(dst):
shutil.copytree(src, dst, dirs_exist_ok=True)
else:
shutil.copytree(src, dst)
def _inject_block_after_shebang(content, marker, block):
if marker in content:
return content
first_newline = content.find("\n")
if first_newline == -1:
return content
return content[: first_newline + 1] + block + content[first_newline + 1 :]
def _patch_resume_init_scripts(mountpoint):
for init_name in os.listdir(mountpoint):
if init_name != "init" and not init_name.startswith("init."):
continue
init_path = os.path.join(mountpoint, init_name)
if not os.path.isfile(init_path):
continue
with open(init_path, "r", encoding="utf-8", errors="ignore") as init_file:
init_content = init_file.read()
init_content = _inject_block_after_shebang(
init_content,
_INIT_MOUNT_MARKER,
_INIT_MOUNT_BLOCK,
)
if (
_INIT_LEGACY_NETWORK_BLOCK in init_content
and _INIT_GATED_NETWORK_BLOCK not in init_content
):
init_content = init_content.replace(
_INIT_LEGACY_NETWORK_BLOCK,
_INIT_GATED_NETWORK_BLOCK,
)
init_content = _inject_block_after_shebang(
init_content,
_INIT_REGEN_MARKER,
_INIT_REGEN_BLOCK,
)
with open(init_path, "w", encoding="utf-8") as init_file:
init_file.write(init_content)
def _update_stage0_tree(mountpoint,
steps_dir,
extra_builds,
mirrors,
internal_ci,
break_scope,
break_step):
"""
Apply all resume updates directly to a mounted stage0 filesystem tree.
"""
old_config_path = os.path.join(mountpoint, "steps", "bootstrap.cfg")
if not os.path.isfile(old_config_path):
raise SystemExit(f"Missing config in stage0 image: {old_config_path}")
old_env_path = os.path.join(mountpoint, "steps", "env")
old_env_content = None
break_output_lines = None
break_manifest_relpath = None
next_step = None
if os.path.isfile(old_env_path):
with open(old_env_path, "rb") as env_file:
old_env_content = env_file.read()
with open(old_config_path, "r", encoding="utf-8") as cfg:
lines = [
line for line in cfg
if not line.startswith("EXTRA_BUILDS=")
and not line.startswith("INTERNAL_CI=")
and not line.startswith(_RESUME_NEXT_SCOPE_VAR + "=")
and not line.startswith(_RESUME_NEXT_PACKAGE_VAR + "=")
and not line.startswith("MIRRORS=")
and not line.startswith("MIRRORS_LEN=")
and not line.startswith("PAYLOAD_REQUIRED=")
]
dest_steps = os.path.join(mountpoint, "steps")
_copytree_replace(steps_dir, dest_steps)
env_path = os.path.join(dest_steps, "env")
if old_env_content is not None:
with open(env_path, "wb") as env_file:
env_file.write(old_env_content)
if os.path.isfile(env_path):
with open(env_path, "r", encoding="utf-8", errors="ignore") as env_file:
env_content = env_file.read()
else:
env_content = ""
if "NETWORK_READY=" not in env_content:
with open(env_path, "a", encoding="utf-8") as env_file:
if env_content and not env_content.endswith("\n"):
env_file.write("\n")
env_file.write("NETWORK_READY=False\n")
if break_scope and break_step:
if internal_ci in ("", "False", None):
raise SystemExit("INTERNAL_CI must be set when INTERNAL_CI_BREAK_AFTER is used.")
if break_scope == "steps":
source_manifest_path = os.path.join(steps_dir, "manifest")
else:
allowed_scopes = {_scope_for_extra_build(extra) for extra in extra_builds}
if break_scope not in allowed_scopes:
raise SystemExit(
f"INTERNAL_CI_BREAK_AFTER scope '{break_scope}' is not enabled by EXTRA_BUILDS."
)
source_manifest_path = os.path.join(
os.path.dirname(steps_dir),
break_scope,
"manifest",
)
if not os.path.isfile(source_manifest_path):
raise SystemExit(f"Missing manifest for INTERNAL_CI_BREAK_AFTER: {source_manifest_path}")
with open(source_manifest_path, "r", encoding="utf-8") as manifest_file:
manifest_lines = manifest_file.readlines()
next_step = _find_next_build_after(
manifest_lines,
break_step,
f"{break_scope}/manifest",
)
break_output_lines = _insert_internal_ci_break(
manifest_lines,
break_step,
internal_ci,
f"{break_scope}/manifest",
)
break_manifest_relpath = os.path.join(break_scope, "manifest")
if next_step:
lines.append(f"{_RESUME_NEXT_SCOPE_VAR}={break_scope}\n")
lines.append(f"{_RESUME_NEXT_PACKAGE_VAR}={next_step}\n")
config_path = os.path.join(dest_steps, "bootstrap.cfg")
if extra_builds:
lines.append("EXTRA_BUILDS=" + ",".join(extra_builds) + "\n")
if mirrors:
lines.append(f'MIRRORS="{" ".join(mirrors)}"\n')
lines.append(f"MIRRORS_LEN={len(mirrors)}\n")
lines.append(f"INTERNAL_CI={internal_ci}\n")
lines.append("PAYLOAD_REQUIRED=False\n")
with open(config_path, "w", encoding="utf-8") as cfg:
cfg.writelines(lines)
_patch_resume_init_scripts(mountpoint)
for extra_build in extra_builds:
extra_scope = _scope_for_extra_build(extra_build)
source_steps_extra = os.path.join(os.path.dirname(steps_dir), extra_scope)
dest_steps_extra = os.path.join(mountpoint, extra_scope)
_copytree_replace(source_steps_extra, dest_steps_extra)
if break_output_lines is not None and break_manifest_relpath is not None:
manifest_path = os.path.join(mountpoint, break_manifest_relpath)
if not os.path.isfile(manifest_path):
raise SystemExit(f"Missing manifest for INTERNAL_CI_BREAK_AFTER: {manifest_path}")
with open(manifest_path, "w", encoding="utf-8") as manifest_file:
manifest_file.writelines(break_output_lines)
def _stage0_update_cli(argv):
"""
Internal entrypoint executed as root for mutating mounted stage0 trees.
"""
if len(argv) < 6:
raise SystemExit("stage0 update cli expects at least 6 arguments")
mountpoint = argv[0]
steps_dir = argv[1]
extra_builds = parse_extra_builds(argv[2])
internal_ci = argv[3]
break_scope = argv[4]
break_step = argv[5]
mirrors = argv[6:]
_update_stage0_tree(
mountpoint,
steps_dir,
extra_builds,
mirrors,
internal_ci,
break_scope,
break_step,
)
def apply_internal_ci_break_to_tree(tree_root, break_scope, break_step, internal_ci):
"""
Inject INTERNAL_CI break jump after a build step in a prepared steps tree.
"""
if not break_scope or not break_step:
return
if internal_ci in ("", "False", None):
raise ValueError("INTERNAL_CI must be set when INTERNAL_CI_BREAK_AFTER is used.")
manifest_path = os.path.join(tree_root, break_scope, "manifest")
if not os.path.isfile(manifest_path):
raise ValueError(f"Missing manifest for INTERNAL_CI_BREAK_AFTER: {manifest_path}")
with open(manifest_path, "r", encoding="utf-8") as manifest_file:
manifest_lines = manifest_file.readlines()
output_lines = _insert_internal_ci_break(
manifest_lines,
break_step,
internal_ci,
f"{break_scope}/manifest",
)
with open(manifest_path, "w", encoding="utf-8") as manifest_file:
manifest_file.writelines(output_lines)
def update_stage0_image(image_path,
extra_builds=None,
mirrors=None,
internal_ci=False,
internal_ci_break_after=None):
"""
Update an existing stage0 image by refreshing step sources from the working
tree and patching bootstrap config / optional extra build handoff bits.
"""
if extra_builds is None:
extra_builds = []
if mirrors is None:
mirrors = []
steps_dir = os.path.abspath("steps")
steps_manifest = os.path.join(steps_dir, "manifest")
if not os.path.isdir(steps_dir) or not os.path.isfile(steps_manifest):
raise ValueError("steps/manifest does not exist.")
for extra_build in extra_builds:
extra_scope = _scope_for_extra_build(extra_build)
extra_steps_dir = os.path.abspath(extra_scope)
manifest = os.path.join(extra_steps_dir, "manifest")
if not os.path.isdir(extra_steps_dir) or not os.path.isfile(manifest):
raise ValueError(
f"{extra_scope}/manifest does not exist while --extra-builds includes {extra_build}."
)
break_scope, break_step = parse_internal_ci_break_after(internal_ci_break_after)
mountpoint = tempfile.mkdtemp(prefix="lb-stage0-", dir="/tmp")
mounted = False
try:
run_as_root(
"mount",
"-t", "ext4",
"-o", "loop,offset=1073741824",
image_path,
mountpoint,
)
mounted = True
loader = (
"import importlib.util, sys;"
"spec=importlib.util.spec_from_file_location('lb_rootfs', sys.argv[1]);"
"mod=importlib.util.module_from_spec(spec);"
"spec.loader.exec_module(mod);"
"mod._stage0_update_cli(sys.argv[2:])"
)
run_as_root(
"python3",
"-c",
loader,
os.path.abspath(__file__),
mountpoint,
steps_dir,
",".join(extra_builds),
str(internal_ci) if internal_ci else "False",
break_scope or "",
break_step or "",
*mirrors,
)
finally:
if mounted:
run_as_root("umount", mountpoint)
os.rmdir(mountpoint)
def prepare_stage0_work_image(base_image,
output_dir,
extra_builds,
mirrors=None,
internal_ci=False,
internal_ci_break_after=None):
"""
Copy stage0 base image to a disposable work image and refresh steps/config.
"""
work_image = os.path.join(output_dir, "stage0-work.img")
shutil.copy2(base_image, work_image)
update_stage0_image(work_image,
extra_builds=extra_builds,
mirrors=mirrors,
internal_ci=internal_ci,
internal_ci_break_after=internal_ci_break_after)
return work_image
def create_configuration_file(args):
"""
Creates bootstrap.cfg file which would contain options used to
@ -31,6 +530,8 @@ def create_configuration_file(args):
"""
config_path = os.path.join('steps', 'bootstrap.cfg')
with open(config_path, "w", encoding="utf_8") as config:
kernel_bootstrap = ((args.bare_metal or args.qemu) and not args.kernel)
payload_required = kernel_bootstrap and args.external_sources and not args.repo
config.write(f"ARCH={args.arch}\n")
config.write(f"ARCH_DIR={stage0_arch_map.get(args.arch, args.arch)}\n")
config.write(f"FORCE_TIMESTAMPS={args.force_timestamps}\n")
@ -41,13 +542,13 @@ def create_configuration_file(args):
config.write(f"FINAL_JOBS={args.cores}\n")
config.write(f"INTERNAL_CI={args.internal_ci or False}\n")
config.write(f"INTERACTIVE={args.interactive}\n")
config.write(f"PAYLOAD_REQUIRED={payload_required}\n")
config.write(f"QEMU={args.qemu}\n")
config.write(f"BARE_METAL={args.bare_metal or (args.qemu and args.interactive)}\n")
if (args.bare_metal or args.qemu) and not args.kernel:
if args.repo or args.external_sources:
config.write("DISK=sdb1\n")
else:
config.write("DISK=sda\n")
if args.extra_builds:
config.write("EXTRA_BUILDS=" + ",".join(args.extra_builds) + "\n")
if kernel_bootstrap:
config.write("DISK=sdb1\n" if args.repo else "DISK=sda\n")
config.write("KERNEL_BOOTSTRAP=True\n")
else:
config.write("DISK=sda1\n")
@ -95,6 +596,9 @@ def main():
parser.add_argument("--build-kernels",
help="Also build kernels in chroot and bwrap builds",
action="store_true")
parser.add_argument("--extra-builds",
help="Comma-separated extra build namespaces to run after main steps "
"(e.g. guix or guix,gentoo,azl3).")
parser.add_argument("--no-create-config",
help="Do not automatically create config file",
action="store_true")
@ -112,6 +616,10 @@ def main():
parser.add_argument("--early-preseed",
help="Skip early stages of live-bootstrap", nargs=None)
parser.add_argument("--internal-ci", help="INTERNAL for github CI")
parser.add_argument("--internal-ci-break-after",
help="Insert a temporary jump: break after a build step using "
"'steps:<name>' or 'steps-<extra>:<name>' "
"for --stage0-image resume runs and fresh --qemu kernel-bootstrap runs.")
parser.add_argument("-s", "--swap", help="Swap space to allocate in Linux",
default=0)
@ -125,11 +633,14 @@ def main():
parser.add_argument("-qs", "--target-size", help="Size of the target image (for QEMU only)",
default="16G")
parser.add_argument("-qk", "--kernel", help="Custom early kernel to use")
parser.add_argument("--stage0-image",
help="Boot an existing stage0 image (target/init.img) directly in QEMU")
parser.add_argument("-b", "--bare-metal", help="Build images for bare metal",
action="store_true")
args = parser.parse_args()
args.extra_builds = parse_extra_builds(args.extra_builds)
# Mode validation
def check_types():
@ -179,9 +690,34 @@ def main():
args.swap = 0
# Validate mirrors
if not args.mirrors:
if not args.mirrors and not args.stage0_image:
raise ValueError("At least one mirror must be provided.")
if args.internal_ci_break_after:
if not args.internal_ci:
raise ValueError("--internal-ci-break-after requires --internal-ci (e.g. pass2).")
break_scope, _ = parse_internal_ci_break_after(args.internal_ci_break_after)
if break_scope != "steps":
extra_build = break_scope[len("steps-"):]
if extra_build not in args.extra_builds:
raise ValueError(
f"--internal-ci-break-after {break_scope}:* requires --extra-builds include "
f"{extra_build}."
)
if not args.qemu:
raise ValueError("--internal-ci-break-after currently requires --qemu.")
if args.kernel:
raise ValueError("--internal-ci-break-after cannot be used with --kernel.")
if args.stage0_image:
if not args.qemu:
raise ValueError("--stage0-image can only be used with --qemu.")
if args.kernel:
raise ValueError("--stage0-image cannot be combined with --kernel.")
if not os.path.isfile(args.stage0_image):
raise ValueError(f"Stage0 image does not exist: {args.stage0_image}")
args.stage0_image = os.path.abspath(args.stage0_image)
# Set constant umask
os.umask(0o022)
@ -199,6 +735,7 @@ def main():
mirror_servers.append(server)
# bootstrap.cfg
if not args.stage0_image:
try:
os.remove(os.path.join('steps', 'bootstrap.cfg'))
except FileNotFoundError:
@ -223,38 +760,40 @@ def main():
server.shutdown()
signal.signal(signal.SIGINT, cleanup)
generator = None
if not args.stage0_image:
generator = Generator(arch=args.arch,
external_sources=args.external_sources,
repo_path=args.repo,
early_preseed=args.early_preseed,
mirrors=args.mirrors)
mirrors=args.mirrors,
extra_builds=args.extra_builds)
bootstrap(args, generator, target, args.target_size, cleanup)
cleanup()
def bootstrap(args, generator, target, size, cleanup):
"""Kick off bootstrap process."""
print(f"Bootstrapping {args.arch}", flush=True)
if args.chroot:
def _bootstrap_chroot(args, generator, target, cleanup):
find_chroot = """
import shutil
print(shutil.which('chroot'))
"""
chroot_binary = run_as_root('python3', '-c', find_chroot,
capture_output=True).stdout.decode().strip()
chroot_binary = run_as_root(
'python3',
'-c',
find_chroot,
capture_output=True,
).stdout.decode().strip()
generator.prepare(target, using_kernel=False)
arch = stage0_arch_map.get(args.arch, args.arch)
init = os.path.join(os.sep, 'bootstrap-seeds', 'POSIX', arch, 'kaem-optional-seed')
run_as_root('env', '-i', 'PATH=/bin', chroot_binary, generator.target_dir, init,
cleanup=cleanup)
run_as_root('env', '-i', 'PATH=/bin', chroot_binary, generator.target_dir, init, cleanup=cleanup)
elif args.bwrap:
def _bootstrap_bwrap(args, generator, target, cleanup):
init = '/init'
if not args.internal_ci or args.internal_ci == "pass1":
generator.prepare(target, using_kernel=False)
arch = stage0_arch_map.get(args.arch, args.arch)
init = os.path.join(os.sep, 'bootstrap-seeds', 'POSIX', arch, 'kaem-optional-seed')
else:
@ -280,28 +819,57 @@ print(shutil.which('chroot'))
init,
cleanup=cleanup)
elif args.bare_metal:
def _bootstrap_bare_metal(args, generator, target, size):
if args.kernel:
generator.prepare(target, using_kernel=True, target_size=size)
path = os.path.join(args.target, os.path.relpath(generator.target_dir, args.target))
print("Please:")
print(f" 1. Take {path}/initramfs and your kernel, boot using this.")
print(f" 2. Take {path}/disk.img and put this on a writable storage medium.")
else:
return
generator.prepare(target, kernel_bootstrap=True, target_size=size)
path = os.path.join(args.target, os.path.relpath(generator.target_dir, args.target))
print("Please:")
print(f" 1. Take {path}.img and write it to a boot drive and then boot it.")
external_disk = target.get_disk("external")
if external_disk is None:
return
external_path = os.path.join(args.target, os.path.relpath(external_disk, args.target))
if args.repo:
print(" 2. Take " + f"{external_path} and attach it as a second disk (/dev/sdb preferred).")
else:
if args.kernel:
print(" 2. Take " + f"{external_path} and attach it as a second raw container disk (/dev/sdb preferred).")
def _qemu_arg_list_for_stage0_image(args, target):
work_image = prepare_stage0_work_image(
args.stage0_image,
target.path,
args.extra_builds,
mirrors=args.mirrors,
internal_ci=args.internal_ci,
internal_ci_break_after=args.internal_ci_break_after,
)
return [
'-enable-kvm',
'-m', str(args.qemu_ram) + 'M',
'-smp', str(args.cores),
'-drive', 'file=' + work_image + ',format=raw',
'-machine', 'kernel-irqchip=split',
'-nic', 'user,ipv6=off,model=e1000',
]
def _qemu_arg_list_for_kernel(args, generator, target, size):
generator.prepare(target, using_kernel=True, target_size=size)
arg_list = [
'-enable-kvm',
'-m', str(args.qemu_ram) + 'M',
'-smp', str(args.cores),
'-drive', 'file=' + target.get_disk("disk") + ',format=raw'
'-drive', 'file=' + target.get_disk("disk") + ',format=raw',
]
if target.get_disk("external") is not None:
arg_list += [
@ -313,18 +881,30 @@ print(shutil.which('chroot'))
'-append',
]
if args.interactive:
arg_list += ['consoleblank=0 earlyprintk=vga root=/dev/sda1 '
'rootfstype=ext3 init=/init rw']
else:
arg_list += ['console=ttyS0 earlycon=uart8250,io,0x3f8,115200n8 '
'root=/dev/sda1 rootfstype=ext3 init=/init rw']
arg_list += ['consoleblank=0 earlyprintk=vga root=/dev/sda1 init=/init rw']
else:
arg_list += ['console=ttyS0 earlycon=uart8250,io,0x3f8,115200n8 root=/dev/sda1 init=/init rw']
return arg_list
def _qemu_arg_list_for_kernel_bootstrap(args, generator, target, size):
generator.prepare(target, kernel_bootstrap=True, target_size=size)
if args.internal_ci_break_after:
break_scope, break_step = parse_internal_ci_break_after(args.internal_ci_break_after)
apply_internal_ci_break_to_tree(
generator.target_dir,
break_scope,
break_step,
args.internal_ci,
)
os.remove(generator.target_dir + '.img')
generator.create_builder_hex0_disk_image(generator.target_dir + '.img', size)
arg_list = [
'-enable-kvm',
'-m', str(args.qemu_ram) + 'M',
'-smp', str(args.cores),
'-drive', 'file=' + generator.target_dir + '.img' + ',format=raw'
'-drive', 'file=' + generator.target_dir + '.img' + ',format=raw',
]
if target.get_disk("external") is not None:
arg_list += [
@ -332,8 +912,30 @@ print(shutil.which('chroot'))
]
arg_list += [
'-machine', 'kernel-irqchip=split',
'-nic', 'user,ipv6=off,model=e1000'
'-nic', 'user,ipv6=off,model=e1000',
]
return arg_list
def bootstrap(args, generator, target, size, cleanup):
"""Kick off bootstrap process."""
print(f"Bootstrapping {args.arch}", flush=True)
if args.chroot:
_bootstrap_chroot(args, generator, target, cleanup)
return
if args.bwrap:
_bootstrap_bwrap(args, generator, target, cleanup)
return
if args.bare_metal:
_bootstrap_bare_metal(args, generator, target, size)
return
if args.stage0_image:
arg_list = _qemu_arg_list_for_stage0_image(args, target)
elif args.kernel:
arg_list = _qemu_arg_list_for_kernel(args, generator, target, size)
else:
arg_list = _qemu_arg_list_for_kernel_bootstrap(args, generator, target, size)
if not args.interactive:
arg_list += ['-no-reboot', '-nographic']
run(args.qemu_cmd, *arg_list, cleanup=cleanup)

View file

@ -32,6 +32,48 @@ struct Directive {
};
typedef struct Directive Directive;
char *steps_root = "/steps";
char *config_root = "/steps";
char *join_path(const char *base, const char *suffix) {
char *out = calloc(MAX_STRING, sizeof(char));
strcpy(out, base);
if (strlen(out) > 0 && out[strlen(out) - 1] != '/') {
strcat(out, "/");
}
while (*suffix == '/') {
suffix += 1;
}
strcat(out, suffix);
return out;
}
char *config_path(const char *suffix) {
return join_path(config_root, suffix);
}
char *dirname_from_path(const char *path) {
char *slash = strrchr(path, '/');
char *out = calloc(MAX_STRING, sizeof(char));
if (slash == NULL) {
strcpy(out, ".");
return out;
}
if (slash == path) {
strcpy(out, "/");
return out;
}
strncpy(out, path, slash - path);
return out;
}
void write_steps_prefix(FILE *out) {
fputs(steps_root, out);
if (steps_root[strlen(steps_root) - 1] != '/') {
fputs("/", out);
}
}
/* Tokenizer. */
/* Skip over a comment. */
@ -120,10 +162,11 @@ typedef struct Variable Variable;
Variable *variables;
Variable *load_config() {
FILE *config = fopen("/steps/bootstrap.cfg", "r");
/* File does not exist check. */
char *config_file = config_path("bootstrap.cfg");
FILE *config = fopen(config_file, "r");
if (config == NULL) {
return NULL;
fputs("Unable to open bootstrap.cfg\n", stderr);
exit(1);
}
char *line = calloc(MAX_STRING, sizeof(char));
@ -392,9 +435,12 @@ Directive *interpreter(Directive *directives) {
/* Script generator. */
FILE *start_script(int id, int bash_build) {
/* Create the file /steps/$id.sh */
/* Create the file ${steps_root}/$id.sh */
char *filename = calloc(MAX_STRING, sizeof(char));
strcpy(filename, "/steps/");
strcpy(filename, steps_root);
if (filename[strlen(filename) - 1] != '/') {
strcat(filename, "/");
}
strcat(filename, int2str(id, 10, 0));
strcat(filename, ".sh");
@ -407,28 +453,47 @@ FILE *start_script(int id, int bash_build) {
}
if (bash_build) {
char *bootstrap_file = config_path("bootstrap.cfg");
char *env_file = config_path("env");
char *helpers_file = join_path(steps_root, "helpers.sh");
fputs("#!/bin/bash\n", out);
if (strcmp(get_var("INTERACTIVE"), "True") == 0) {
if (bash_build != 1) {
fputs("set -eEo pipefail\ntrap 'env PS1=\"[TRAP] \\w # \" bash -i' ERR\n", out);
} else {
/* FIXME early bash has buggy ERR trap handling */
fputs("set -e\ntrap 'bash -c '\"'\"'while true; do printf \""
"[TRAP - use Ctrl+D] $(pwd) # \"; eval \"$(cat)\"; done'\"'\"'' EXIT\n",
out);
fputs("set -e\ntrap 'status=$?; if [ \"${status}\" -ne 0 ]; then env PS1=\"[TRAP] \\w # \" bash -i; fi' EXIT\n", out);
}
} else {
fputs("set -e\n", out);
}
fputs("cd /steps\n", out);
fputs(". ./bootstrap.cfg\n", out);
fputs(". ./env\n", out);
fputs(". ./helpers.sh\n", out);
fputs("cd ", out);
fputs(steps_root, out);
fputs("\n", out);
fputs(". ", out);
fputs(bootstrap_file, out);
fputs("\n", out);
fputs(". ", out);
fputs(env_file, out);
fputs("\n", out);
fputs("SRCDIR=", out);
fputs(steps_root, out);
fputs("\n", out);
fputs(". ", out);
fputs(helpers_file, out);
fputs("\n", out);
} else {
char *env_file = config_path("env");
fputs("set -ex\n", out);
fputs("cd /steps\n", out);
fputs("cd ", out);
fputs(steps_root, out);
fputs("\n", out);
output_config(out);
FILE *env = fopen("/steps/env", "r");
FILE *env = fopen(env_file, "r");
if (env == NULL) {
fputs("Unable to open env\n", stderr);
exit(1);
}
char *line = calloc(MAX_STRING, sizeof(char));
while (fgets(line, MAX_STRING, env) != 0) {
/* Weird M2-Planet behaviour. */
@ -454,7 +519,7 @@ void output_call_script(FILE *out, char *type, char *name, int bash_build, int s
} else {
fputs("kaem --file ", out);
}
fputs("/steps/", out);
write_steps_prefix(out);
if (strlen(type) != 0) {
fputs(type, out);
fputs("/", out);
@ -463,6 +528,23 @@ void output_call_script(FILE *out, char *type, char *name, int bash_build, int s
fputs(".sh\n", out);
}
void output_resume_network_init(FILE *out) {
fputs("if [ -f ", out);
write_steps_prefix(out);
fputs("helpers.sh ]; then\n", out);
fputs(". ", out);
write_steps_prefix(out);
fputs("helpers.sh\n", out);
fputs("resume_network_init \"", out);
fputs(config_root, out);
fputs("\"\n", out);
fputs("fi\n", out);
}
void output_init_call_script(FILE *out, char *name, int bash_build) {
output_call_script(out, "", name, bash_build, 0);
}
void output_build(FILE *out, Directive *directive, int pass_no, int bash_build) {
if (bash_build) {
fputs("build ", out);
@ -486,7 +568,8 @@ void generate_preseed_jump(int id) {
FILE *out = fopen("/preseed-jump.kaem", "w");
fputs("set -ex\n", out);
fputs("PATH=/usr/bin\n", out);
fputs("bash /steps/", out);
fputs("bash ", out);
write_steps_prefix(out);
fputs(int2str(id, 10, 0), out);
fputs(".sh\n", out);
fclose(out);
@ -503,8 +586,14 @@ void generate(Directive *directives) {
int counter = 0;
/* Initially, we use kaem, not bash. */
/*
* Default /steps manifests start in kaem.
* Alternative step roots (for example /steps-guix) start in bash.
*/
int bash_build = 0;
if (strcmp(steps_root, "/steps") != 0) {
bash_build = 2;
}
FILE *out = start_script(counter, bash_build);
counter += 1;
@ -576,6 +665,7 @@ void generate(Directive *directives) {
exit(1);
}
fputs("#!/bin/bash\n", out);
output_resume_network_init(out);
} else {
out = fopen(filename, "w");
if (out == NULL) {
@ -584,7 +674,7 @@ void generate(Directive *directives) {
}
fputs("set -ex\n", out);
}
output_call_script(out, "", int2str(counter, 10, 0), bash_build, 0);
output_init_call_script(out, int2str(counter, 10, 0), bash_build);
fclose(out);
out = start_script(counter, bash_build);
counter += 1;
@ -598,8 +688,8 @@ void generate(Directive *directives) {
}
void main(int argc, char **argv) {
if (argc != 2) {
fputs("Usage: script-generator <script>\n", stderr);
if (argc != 2 && argc != 3) {
fputs("Usage: script-generator <script> [config-root]\n", stderr);
exit(1);
}
@ -608,12 +698,18 @@ void main(int argc, char **argv) {
fputs("Error opening input file\n", stderr);
exit(1);
}
steps_root = dirname_from_path(argv[1]);
config_root = steps_root;
if (argc == 3) {
config_root = argv[2];
}
Directive *directives = tokenizer(in);
fclose(in);
load_config();
directives = interpreter(directives);
generate(directives);
FILE *config = fopen("/steps/bootstrap.cfg", "w");
char *config_file = config_path("bootstrap.cfg");
FILE *config = fopen(config_file, "w");
output_config(config);
fclose(config);
}

View file

@ -1 +1 @@
fbec25d987c89e66fd7dd89d780be0629bab84f78ebf1878fd2528fca9e46c45 script-generator
3c136337e679e39407701dee9d65402c8b538ae786af850b8430370cb07df25d script-generator

View file

@ -0,0 +1,38 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# Build argp-standalone for the kernel toolchain sysroot. This is used by
# later kernel-side dependencies (for example elfutils).
: "${KERNEL_SYSROOT:=/kernel-toolchain}"
src_prepare() {
default
autoreconf -fi
}
src_configure() {
mkdir build
cd build
# argp-standalone's testsuite expects argp.h from source root even when
# building out-of-tree.
CPPFLAGS="-I${PWD}/.." \
CC=gcc \
AR=ar \
RANLIB=ranlib \
../configure \
--prefix="${KERNEL_SYSROOT}" \
--libdir="${KERNEL_SYSROOT}/lib"
}
src_compile() {
default_src_compile
}
src_install() {
mkdir -p "${DESTDIR}${KERNEL_SYSROOT}/include"
mkdir -p "${DESTDIR}${KERNEL_SYSROOT}/lib"
# noinst_HEADERS/noinst_LIBRARIES: install artifacts explicitly.
install -m644 ../argp.h "${DESTDIR}${KERNEL_SYSROOT}/include/argp.h"
install -m644 libargp.a "${DESTDIR}${KERNEL_SYSROOT}/lib/libargp.a"
}

View file

@ -0,0 +1 @@
g https://github.com/ericonr/argp-standalone.git~743004c68e7358fb9cd4737450f2d9a34076aadf https://github.com/ericonr/argp-standalone/archive/743004c68e7358fb9cd4737450f2d9a34076aadf.tar.gz a79f2a6fd6c68a423063ee53bc4afb6a5633a296a25764e5cc368c1e323a0997 argp-standalone-743004c6.tar.gz

View file

@ -0,0 +1,54 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
}
src_configure() {
local host_triplet pkg_config_path
host_triplet="$(gcc -dumpmachine)"
pkg_config_path="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig:${PREFIX}/share/pkgconfig"
PATH="${PREFIX}/bin:/usr/bin:/bin" \
PKG_CONFIG_PATH="${pkg_config_path}" \
PKG_CONFIG_LIBDIR="${pkg_config_path}" \
DBUS_CFLAGS="$(pkg-config --cflags dbus-1)" \
DBUS_LIBS="$(pkg-config --libs dbus-1)" \
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--includedir="${PREFIX}/include" \
--host="${host_triplet}" \
--build="${host_triplet}" \
--with-distro=lfs \
--disable-stack-protector \
--enable-gdbm \
--disable-dbm \
--enable-static \
--enable-shared \
--disable-glib \
--disable-gobject \
--disable-gtk \
--disable-gtk3 \
--disable-qt3 \
--disable-qt4 \
--disable-qt5 \
--disable-python \
--disable-python-dbus \
--disable-pygobject \
--disable-mono \
--disable-monodoc \
--disable-autoipd \
--disable-doxygen-doc \
--disable-manpages \
--disable-xmltoman \
--disable-tests
}
src_compile() {
default_src_compile
}
src_install() {
default_src_install
}

View file

@ -0,0 +1 @@
f https://github.com/avahi/avahi/releases/download/v0.8/avahi-0.8.tar.gz 060309d7a333d38d951bc27598c677af1796934dbd98e1024e7ad8de798fedda avahi-0.8.tar.gz

View file

@ -0,0 +1,29 @@
# SPDX-License-Identifier: GPL-3.0-or-later
SEED_PREFIX="/bootstrap-seeds/bash-5.3-1"
src_prepare() {
default
}
src_configure() {
./configure \
--prefix="${SEED_PREFIX}" \
--without-bash-malloc \
--disable-nls \
--enable-static-link \
--build="${TARGET}" \
bash_cv_dev_stdin=absent \
bash_cv_dev_fd=whacky
}
src_compile() {
make -j1
}
src_install() {
# Keep seed output for bootstrap artifact generation.
install -D -m 0755 bash "${DESTDIR}${SEED_PREFIX}/bin/bash"
# same as steps/bash
install -D -m 0755 bash "${DESTDIR}/usr/bin/bash"
}

View file

@ -0,0 +1 @@
f https://ftp.gnu.org/gnu/bash/bash-5.3.tar.gz 0d5cd86965f869a26cf64f4b71be7b96f90a3ba8b3d74e27e8e9d9d5550f31ba

View file

@ -0,0 +1,178 @@
# SPDX-FileCopyrightText: 2022 Dor Askayo <dor.askayo@gmail.com>
# SPDX-FileCopyrightText: 2021 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-FileCopyrightText: 2021 Paul Dersey <pdersey@gmail.com>
# SPDX-FileCopyrightText: 2023,2025 Samuel Tyler <samuel@samuelt.me>
#
# SPDX-License-Identifier: GPL-3.0-or-later
# This binutils build targets the 64-bit kernel toolchain.
: "${KERNEL_TARGET:=x86_64-unknown-linux-musl}"
: "${KERNEL_SYSROOT:=/kernel-toolchain}"
src_prepare() {
default
# Remove unused generated files
rm etc/Makefile.in etc/configure
# Remove unused parts
rm -r zlib
# intl/ Makefile is a bit broken because of new gettext
sed -i 's/@USE_INCLUDED_LIBINTL@/no/' intl/Makefile.in
# There is no way to add -all-static to libtool LDFLAGS (such a thing doesn't exist)
# -all-static is required for static binaries with libtool
sed -i 's:\(--mode=link $(CCLD)\):\1 -all-static:' {bfd,binutils,opcodes,ld,libctf,gas,gprof}/Makefile.in
# Rebuild bison files
touch -- */*.y
rm binutils/arparse.c binutils/arparse.h binutils/defparse.c \
binutils/defparse.h binutils/mcparse.c binutils/mcparse.h \
binutils/rcparse.c binutils/rcparse.h binutils/sysinfo.c \
binutils/sysinfo.h gas/config/bfin-parse.c gas/config/bfin-parse.h \
gas/config/loongarch-parse.c gas/config/loongarch-parse.h \
gas/config/m68k-parse.c gas/config/rl78-parse.c \
gas/config/rl78-parse.h gas/config/rx-parse.c gas/config/rx-parse.h \
gas/itbl-parse.c gas/itbl-parse.h gold/yyscript.c gold/yyscript.h \
intl/plural.c ld/deffilep.c ld/deffilep.h ld/ldgram.c ld/ldgram.h
# Rebuild flex generated files
touch -- */*.l */*/*.l
rm binutils/arlex.c binutils/deflex.c binutils/syslex.c \
gas/config/bfin-lex.c gas/config/loongarch-lex.c gas/itbl-lex.c \
ld/ldlex.c
# Remove prebuilt docs
find . -type f -name '*.info*' \
-not -wholename './binutils/sysroff.info' \
-delete
find . -type f \( -name '*.1' -or -name '*.man' \) -delete
rm libiberty/functions.texi
# Remove gettext translation files
find . -type f -name '*.gmo' -delete
# Remove pregenerated opcodes files
rm opcodes/i386-init.h opcodes/i386-tbl.h opcodes/i386-mnem.h \
opcodes/ia64-asmtab.c opcodes/z8k-opc.h opcodes/aarch64-asm-2.c \
opcodes/aarch64-opc-2.c opcodes/aarch64-dis-2.c \
opcodes/msp430-decode.c opcodes/rl78-decode.c opcodes/rx-decode.c
rm $(grep -l 'MACHINE GENERATED' opcodes/*.c opcodes/*.h)
# Various other blobs/generated headers
rm ld/emultempl/*.o_c
rm gprof/bsd_callg_bl.c gprof/flat_bl.c gprof/fsf_callg_bl.c
rm bfd/libcoff.h bfd/libbfd.h bfd/go32stub.h bfd/bfd-in2.h
# Generated testsuite stuff (xz-style attack)
rm libsframe/testsuite/libsframe.decode/DATA* \
ld/testsuite/ld-x86-64/*.obj.bz2 ld/testsuite/ld-sh/arch/*.s \
ld/testsuite/ld-sh/arch/arch_expected.txt \
ld/testsuite/ld-i386/pr27193a.o.bz2 \
gas/testsuite/gas/xstormy16/allinsn.sh \
gas/testsuite/gas/tic4x/opcodes.s gas/testsuite/gas/sh/arch/*.s \
gas/testsuite/gas/sh/arch/arch_expected.txt \
binutils/testsuite/binutils-all/x86-64/pr22451.o.bz2 \
binutils/testsuite/binutils-all/x86-64/pr26808.dwp.bz2 \
binutils/testsuite/binutils-all/x86-64/pr27708.exe.bz2 \
binutils/testsuite/binutils-all/nfp/*.nffw \
binutils/testsuite/binutils-all/pr26112.o.bz2 \
binutils/testsuite/binutils-all/pr26160.dwp.bz2
# Regenerate crc table in libiberty/crc32.c
cd libiberty
sed -n '/^ #include <stdio.h>/,/^ \}$/p' crc32.c > crcgen.c
gcc -o crcgen crcgen.c
sed '/crc_v3\.txt/{n; q}' crc32.c > crc32.c.new
./crcgen >> crc32.c.new
sed '1,/^};$/d' crc32.c >> crc32.c.new
mv crc32.c.new crc32.c
cd ..
# bfd-in2.h is required to run autoreconf, but we don't have it yet
cd bfd
cp configure.ac configure.ac.bak
sed -i "s/bfd-in3.h:bfd-in2.h //" configure.ac
AUTOPOINT=true ACLOCAL=aclocal-1.15 AUTOMAKE=automake-1.15 autoreconf-2.69 -fi
./configure
make headers
mv configure.ac.bak configure.ac
make distclean
cd ..
# Regenerate top-level (autogen + autotools)
autogen Makefile.def
ACLOCAL=aclocal-1.15 autoreconf-2.69 -fi
# Regenerate autoconf
for dir in bfd binutils gas gold gprof intl ld libctf libiberty libsframe opcodes; do
cd $dir
ACLOCAL=aclocal-1.15 AUTOMAKE=automake-1.15 autoreconf-2.69 -fi
cd ..
done
cd gprofng
# there is no libtool in gprofng, and libtoolize fails
LIBTOOLIZE=true ACLOCAL=aclocal-1.15 AUTOMAKE=automake-1.15 autoreconf-2.69 -fi
cd ..
# Rebuild dependencies in libiberty/Makefile.in
cd libiberty
./configure --enable-maintainer-mode
make maint-deps
make distclean
cd ..
# Regenerate MeP sections
./bfd/mep-relocs.pl
}
src_configure() {
mkdir build
cd build
LDFLAGS="-static" \
../configure \
--prefix="${KERNEL_SYSROOT}" \
--libdir="${KERNEL_SYSROOT}/lib" \
--build="${TARGET}" \
--host="${TARGET}" \
--target="${KERNEL_TARGET}" \
--enable-static \
--disable-nls \
--disable-multilib \
--disable-plugins \
--disable-gprofng \
--enable-threads \
--enable-64-bit-bfd \
--enable-gold \
--enable-ld=default \
--enable-install-libiberty \
--enable-deterministic-archives \
--enable-targets=x86_64-elf,i386-elf \
--with-system-zlib \
--program-prefix="" \
--with-sysroot="${KERNEL_SYSROOT}" \
--srcdir=..
}
src_compile() {
default_src_compile
}
src_install() {
make "${MAKEJOBS}" install \
DESTDIR="${DESTDIR}" \
prefix="${KERNEL_SYSROOT}" \
libdir="${KERNEL_SYSROOT}/lib"
# Create triplet symlinks
pushd "${DESTDIR}${KERNEL_SYSROOT}/bin"
for f in *; do
ln -sf "${KERNEL_SYSROOT}/bin/${f}" "${KERNEL_TARGET}-${f}"
done
popd
# FIXME: Binutils' manpages dates are not reproducible
rm -rf "${DESTDIR}${KERNEL_SYSROOT}/share/man"
}

View file

@ -0,0 +1,17 @@
SPDX-FileCopyrightText: 2023 Samuel Tyler <samuel@samuelt.me>
SPDX-License-Identifier: GPL-3.0-or-later
In new gettext external is required for AM_GNU_GETTEXT.
--- binutils-2.41/intl/configure.ac 2023-02-07 18:57:56.350832016 +1100
+++ binutils-2.41/intl/configure.ac 2023-02-07 18:58:07.310054484 +1100
@@ -4,7 +4,7 @@
AC_CONFIG_HEADER(config.h)
AC_CONFIG_MACRO_DIR(../config)
AM_GNU_GETTEXT_VERSION(0.12.1)
-AM_GNU_GETTEXT([], [need-ngettext])
+AM_GNU_GETTEXT([external], [need-ngettext])
# This replaces the extensive use of DEFS in the original Makefile.in.
AC_DEFINE(IN_LIBINTL, 1, [Define because this is libintl.])

View file

@ -0,0 +1,26 @@
SPDX-FileCopyrightText: 2023 Samuel Tyler <samuel@samuelt.me>
SPDX-License-Identifier: GPL-3.0-or-later
Ensure functions.texi dependencies are satisfied.
--- binutils-2.41/libiberty/Makefile.in 2023-12-08 15:18:57.985791235 +1100
+++ binutils-2.41/libiberty/Makefile.in 2023-12-08 15:19:15.391252344 +1100
@@ -368,12 +368,12 @@
libiberty.html : $(srcdir)/libiberty.texi $(TEXISRC)
$(MAKEINFO) --no-split --html -I$(srcdir) -o $@ $<
-@MAINT@$(srcdir)/functions.texi : stamp-functions
-@MAINT@ @true
+$(srcdir)/functions.texi : stamp-functions
+ @true
-@MAINT@stamp-functions : $(CFILES:%=$(srcdir)/%) $(TEXIFILES:%=$(srcdir)/%) $(srcdir)/gather-docs Makefile
-@MAINT@@HAVE_PERL@ $(PERL) $(srcdir)/gather-docs $(srcdir) $(srcdir)/functions.texi $(CFILES) $(TEXIFILES)
-@MAINT@ echo stamp > stamp-functions
+stamp-functions : $(CFILES:%=$(srcdir)/%) $(TEXIFILES:%=$(srcdir)/%) $(srcdir)/gather-docs Makefile
+@HAVE_PERL@ $(PERL) $(srcdir)/gather-docs $(srcdir) $(srcdir)/functions.texi $(CFILES) $(TEXIFILES)
+ echo stamp > stamp-functions
INSTALL_DEST = @INSTALL_DEST@
install: install_to_$(INSTALL_DEST) install-subdir

View file

@ -0,0 +1,18 @@
SPDX-FileCopyrightText: 2022 Dor Askayo <dor.askayo@gmail.com>
SPDX-FileCopyrightText: 2023 Samuel Tyler <samuel@samuelt.me>
SPDX-License-Identifier: GPL-3.0-or-later
Ensure i386-tbl.h dependencies are satisfied.
--- binutils-2.41/opcodes/Makefile.am 2023-12-08 17:13:05.669136957 +1100
+++ binutils-2.41/opcodes/Makefile.am 2023-12-08 17:13:18.410480026 +1100
@@ -540,7 +540,7 @@
# i386-gen will generate all headers in one go. Use a pattern rule to properly
# express this, with the inner dash ('-') arbitrarily chosen to be the stem.
$(srcdir)/i386%tbl.h $(srcdir)/i386%init.h $(srcdir)/i386%mnem.h: \
- @MAINT@ i386-gen$(EXEEXT_FOR_BUILD) i386-opc.tbl i386-reg.tbl i386-opc.h
+ i386-gen$(EXEEXT_FOR_BUILD) i386-opc.tbl i386-reg.tbl i386-opc.h
$(AM_V_GEN)$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) - \
< $(srcdir)/i386-opc.tbl \
| ./i386-gen$(EXEEXT_FOR_BUILD) --srcdir $(srcdir)

View file

@ -0,0 +1 @@
f https://mirrors.kernel.org/gnu/binutils/binutils-2.41.tar.xz ae9a5789e23459e59606e6714723f2d3ffc31c03174191ef0d015bdf06007450

View file

@ -0,0 +1,17 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_unpack() {
mkdir -p boost-unordered-patch
}
src_configure() {
:
}
src_compile() {
:
}
src_install() {
install -D -m 0644 /dev/null "${DESTDIR}/usr/share/boost-unordered-patch.done"
}

View file

@ -0,0 +1 @@
f https://cdn.jsdelivr.net/npm/@openziti/ziti-sdk-nodejs@0.14.2/vcpkg/ports/boost-unordered/0001-unordered-fix-copy-assign.patch c6e04429fbf1629f10f456d47d9cfda1a89c4b1f242665cb4c091cd84b0d4626

View file

@ -0,0 +1,22 @@
# SPDX-License-Identifier: GPL-3.0-or-later
SEED_PREFIX="/bootstrap-seeds/bzip2-1.0.6"
SYSTEM_PREFIX="/usr"
src_configure() {
:
}
src_compile() {
make "${MAKEJOBS}" CFLAGS="-O2" LDFLAGS="-static"
}
src_install() {
# Upstream bzip2 Makefile does not support DESTDIR, so PREFIX must include it.
make CFLAGS="-O2" LDFLAGS="-static" PREFIX="${DESTDIR}${SYSTEM_PREFIX}" install
make CFLAGS="-O2" LDFLAGS="-static" PREFIX="${DESTDIR}${SEED_PREFIX}" install
# Fail early if either installed binary is not executable in this environment.
"${DESTDIR}${SYSTEM_PREFIX}/bin/bzip2" --help >/dev/null
"${DESTDIR}${SEED_PREFIX}/bin/bzip2" --help >/dev/null
}

View file

@ -0,0 +1 @@
f https://sourceware.org/pub/bzip2/bzip2-1.0.6.tar.gz a2848f34fcd5d6cf47def00461fcb528a0484d8edef8208d6d2e2909dc61d9cd

View file

@ -0,0 +1,24 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
}
src_configure() {
./bootstrap \
--prefix="${PREFIX}" \
--parallel="${JOBS}" \
--no-qt-gui \
-- \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_USE_OPENSSL=ON \
-DCMAKE_INSTALL_LIBDIR="${LIBDIR}"
}
src_compile() {
make "${MAKEJOBS}"
}
src_install() {
make install DESTDIR="${DESTDIR}"
}

View file

@ -0,0 +1 @@
f https://github.com/Kitware/CMake/releases/download/v4.2.3/cmake-4.2.3.tar.gz 7efaccde8c5a6b2968bad6ce0fe60e19b6e10701a12fce948c2bf79bac8a11e9

View file

@ -0,0 +1,23 @@
# SPDX-License-Identifier: GPL-3.0-or-later
SEED_PREFIX="/bootstrap-seeds/coreutils-8.30"
src_configure() {
FORCE_UNSAFE_CONFIGURE=1 ./configure \
--prefix="${SEED_PREFIX}" \
--disable-nls \
--disable-silent-rules \
--enable-no-install-program=stdbuf,libstdbuf.so \
CFLAGS="-Os -g0" \
LDFLAGS="-static -pthread" \
gl_cv_func_getcwd_path_max="no, but it is partly working" \
gl_cv_prog_perl="no"
}
src_compile() {
make "${MAKEJOBS}" MAKEINFO=true GPERF=true
}
src_install() {
make DESTDIR="${DESTDIR}" MAKEINFO=true install
}

View file

@ -0,0 +1 @@
f https://mirrors.kernel.org/gnu/coreutils/coreutils-8.30.tar.xz e831b3a86091496cdba720411f9748de81507798f6130adeaef872d206e1b057

View file

@ -0,0 +1,41 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
}
src_configure() {
local cmake_libdir
cmake_libdir="${LIBDIR#${PREFIX}/}"
if [ "${cmake_libdir}" = "${LIBDIR}" ]; then
cmake_libdir="${LIBDIR#/}"
fi
mkdir -p build
cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="${PREFIX}" \
-DCMAKE_INSTALL_LIBDIR="${cmake_libdir}" \
-DCMAKE_INSTALL_INCLUDEDIR="include" \
-DCMAKE_PREFIX_PATH="${PREFIX}" \
-DCMAKE_INCLUDE_PATH="${PREFIX}/include" \
-DCMAKE_LIBRARY_PATH="${LIBDIR}:${PREFIX}/lib" \
-DBUILD_SHARED_LIBS=ON \
-DDBUS_BUILD_TESTS=OFF \
-DDBUS_ENABLE_XML_DOCS=OFF \
-DDBUS_ENABLE_DOXYGEN_DOCS=OFF \
-DDBUS_BUILD_X11=OFF \
-DDBUS_WITH_GLIB=OFF \
-DENABLE_SYSTEMD=OFF \
-DENABLE_USER_SESSION=OFF
}
src_compile() {
make "${MAKEJOBS}"
}
src_install() {
make install DESTDIR="${DESTDIR}"
}

View file

@ -0,0 +1 @@
f https://dbus.freedesktop.org/releases/dbus/dbus-1.16.2.tar.xz 0ba2a1a4b16afe7bceb2c07e9ce99a8c2c3508e5dec290dbb643384bd6beb7e2 dbus-1.16.2.tar.xz

View file

@ -0,0 +1,53 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# Build elfutils against kernel-toolchain dependencies.
: "${KERNEL_SYSROOT:=/kernel-toolchain}"
src_prepare() {
default
# Regenerate autotools outputs from source metadata.
AUTOMAKE=automake-1.15 \
ACLOCAL=aclocal-1.15 \
AUTOCONF=autoconf-2.69 \
AUTOHEADER=autoheader-2.69 \
autoreconf-2.69 -fi
}
src_configure() {
mkdir build
cd build
PKG_CONFIG_PATH="${KERNEL_SYSROOT}/lib/pkgconfig:${KERNEL_SYSROOT}/share/pkgconfig" \
PKG_CONFIG_LIBDIR="${KERNEL_SYSROOT}/lib/pkgconfig:${KERNEL_SYSROOT}/share/pkgconfig" \
CPPFLAGS="-I${KERNEL_SYSROOT}/include" \
CFLAGS="-Wno-error=unused-but-set-variable" \
LDFLAGS="-L${KERNEL_SYSROOT}/lib" \
CC=gcc \
AR=ar \
RANLIB=ranlib \
../configure \
--prefix="${KERNEL_SYSROOT}" \
--libdir="${KERNEL_SYSROOT}/lib" \
--includedir="${KERNEL_SYSROOT}/include" \
--build="${TARGET}" \
--host="${TARGET}" \
--disable-textrelcheck \
--disable-debuginfod \
--disable-libdebuginfod
}
src_compile() {
LD_LIBRARY_PATH="${KERNEL_SYSROOT}/lib:${LD_LIBRARY_PATH}" \
make "${MAKEJOBS}" \
LDFLAGS="-L${KERNEL_SYSROOT}/lib -Wl,-rpath-link,${KERNEL_SYSROOT}/lib" \
LIBS="-lfts -lobstack -largp"
}
src_install() {
make "${MAKEJOBS}" install \
DESTDIR="${DESTDIR}" \
prefix="${KERNEL_SYSROOT}" \
libdir="${KERNEL_SYSROOT}/lib" \
includedir="${KERNEL_SYSROOT}/include"
}

View file

@ -0,0 +1,39 @@
--- elfutils-0.194/src/strip.c
+++ elfutils-0.194/src/strip.c
@@ -26,6 +26,10 @@
#include <endian.h>
#include <fcntl.h>
#include <fnmatch.h>
+#ifndef FNM_EXTMATCH
+#define FNM_EXTMATCH 0
+#endif
+
#include <gelf.h>
#include <libelf.h>
#include <locale.h>
--- elfutils-0.194/src/elfcompress.c
+++ elfutils-0.194/src/elfcompress.c
@@ -26,6 +26,10 @@
#include <locale.h>
#include <fcntl.h>
#include <fnmatch.h>
+#ifndef FNM_EXTMATCH
+#define FNM_EXTMATCH 0
+#endif
+
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
--- elfutils-0.194/debuginfod/debuginfod-client.c
+++ elfutils-0.194/debuginfod/debuginfod-client.c
@@ -106,6 +106,10 @@
#include <stdio.h>
#include <dwarf.h>
#include <fnmatch.h>
+#ifndef FNM_EXTMATCH
+#define FNM_EXTMATCH 0
+#endif
+
#include <json-c/json.h>
#include <stdlib.h>
#include <unistd.h>

View file

@ -0,0 +1 @@
f https://sourceware.org/elfutils/ftp/0.194/elfutils-0.194.tar.bz2 09e2ff033d39baa8b388a2d7fbc5390bfde99ae3b7c67c7daaf7433fbcf0f01e

View file

@ -0,0 +1,29 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
}
src_configure() {
local host_triplet
host_triplet="$(gcc -dumpmachine)"
PATH="${PREFIX}/bin:/usr/bin:/bin" \
PKG_CONFIG_PATH="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig" \
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--includedir="${PREFIX}/include" \
--host="${host_triplet}" \
--build="${host_triplet}" \
--enable-static \
--enable-shared
}
src_compile() {
default_src_compile
}
src_install() {
default_src_install
}

View file

@ -0,0 +1 @@
f https://github.com/libexpat/libexpat/releases/download/R_2_7_4/expat-2.7.4.tar.gz 461ecc8aa98ab1a68c2db788175665d1a4db640dc05bf0e289b6ea17122144ec expat-2.7.4.tar.gz

View file

@ -0,0 +1,22 @@
# SPDX-License-Identifier: GPL-3.0-or-later
SEED_PREFIX="/bootstrap-seeds/gawk-4.2.1"
src_prepare() {
default
}
src_configure() {
CFLAGS="-O2" LDFLAGS="-static" ./configure \
--prefix="${SEED_PREFIX}" \
--disable-nls \
--disable-shared
}
src_compile() {
default_src_compile
}
src_install() {
make DESTDIR="${DESTDIR}" install
}

View file

@ -0,0 +1,26 @@
SPDX-License-Identifier: GPL-3.0-or-later
Fix legacy getopt declarations that conflict with modern libc headers.
--- gawk-4.2.1/support/getopt.c
+++ gawk-4.2.1/support/getopt.c
@@ -152,7 +152,7 @@
whose names are inconsistent. */
#ifndef getenv
-extern char *getenv ();
+extern char *getenv (const char *);
#endif
#endif /* not __GNU_LIBRARY__ */
--- gawk-4.2.1/support/getopt.h
+++ gawk-4.2.1/support/getopt.h
@@ -181,7 +181,7 @@
# endif
# endif
#else /* not __GNU_LIBRARY__ */
-extern int getopt ();
+extern int getopt (int, char *const *, const char *);
#endif /* __GNU_LIBRARY__ */
#ifndef __need_getopt

View file

@ -0,0 +1,15 @@
SPDX-License-Identifier: GPL-3.0-or-later
Fix MPFR callback pointer prototype for modern compilers.
--- gawk-4.2.1/mpfr.c
+++ gawk-4.2.1/mpfr.c
@@ -689,7 +689,7 @@
static inline NODE *
do_mpfr_func(const char *name,
- int (*mpfr_func)(), /* putting argument types just gets the compiler confused */
+ int (*mpfr_func)(mpfr_ptr, mpfr_srcptr, mpfr_rnd_t),
int nargs)
{
NODE *t1, *res;

View file

@ -0,0 +1,53 @@
SPDX-License-Identifier: GPL-3.0-or-later
Fix read_func prototype to use a modern typed function pointer.
--- gawk-4.2.1/gawkapi.h
+++ gawk-4.2.1/gawkapi.h
@@ -190,7 +190,7 @@
* No argument prototype on read_func to allow for older systems
* whose headers are not up to date.
*/
- ssize_t (*read_func)();
+ ssize_t (*read_func)(int, void *, size_t);
/*
* The close_func is called to allow the parser to free private data.
--- gawk-4.2.1/io.c
+++ gawk-4.2.1/io.c
@@ -310,7 +310,7 @@
static NODE *in_PROCINFO(const char *pidx1, const char *pidx2, NODE **full_idx);
static long get_read_timeout(IOBUF *iop);
-static ssize_t read_with_timeout(int fd, char *buf, size_t size);
+static ssize_t read_with_timeout(int fd, void *buf, size_t size);
static bool read_can_timeout = false;
static long read_timeout;
@@ -3340,7 +3340,7 @@
iop->public.fd = fd;
iop->public.name = name;
- iop->public.read_func = ( ssize_t(*)() ) read;
+ iop->public.read_func = (ssize_t (*)(int, void *, size_t)) read;
iop->valid = false;
iop->errcode = errno_val;
@@ -4318,7 +4318,7 @@
tmout = read_default_timeout; /* initialized from env. variable in init_io() */
/* overwrite read routine only if an extension has not done so */
- if ((iop->public.read_func == ( ssize_t(*)() ) read) && tmout > 0)
+ if ((iop->public.read_func == (ssize_t (*)(int, void *, size_t)) read) && tmout > 0)
iop->public.read_func = read_with_timeout;
return tmout;
@@ -4330,7 +4330,7 @@
*/
static ssize_t
-read_with_timeout(int fd, char *buf, size_t size)
+read_with_timeout(int fd, void *buf, size_t size)
{
#if ! defined(VMS)
fd_set readfds;

View file

@ -0,0 +1,64 @@
SPDX-License-Identifier: GPL-3.0-or-later
Use an explicit function pointer prototype for readfunc so gawk 4.2.1
builds with modern C compilers where an empty parameter list is treated
as a no-argument function.
--- gawk-4.2.1/awkgram.y
+++ gawk-4.2.1/awkgram.y
@@ -2870,22 +2870,17 @@
struct stat sbuf;
/*
- * No argument prototype on readfunc on purpose,
- * avoids problems with some ancient systems where
- * the types of arguments to read() aren't up to date.
+ * Use an explicit prototype so modern C compilers (C23 and newer)
+ * do not treat an empty parameter list as a no-argument function.
*/
- static ssize_t (*readfunc)() = 0;
+ static ssize_t (*readfunc)(int, void *, size_t) = NULL;
if (readfunc == NULL) {
char *cp = getenv("AWKREADFUNC");
/* If necessary, one day, test value for different functions. */
if (cp == NULL)
- /*
- * cast is to remove warnings on systems with
- * different return types for read.
- */
- readfunc = ( ssize_t(*)() ) read;
+ readfunc = read;
else
readfunc = read_one_line;
}
--- gawk-4.2.1/awkgram.c
+++ gawk-4.2.1/awkgram.c
@@ -5290,22 +5290,17 @@
struct stat sbuf;
/*
- * No argument prototype on readfunc on purpose,
- * avoids problems with some ancient systems where
- * the types of arguments to read() aren't up to date.
+ * Use an explicit prototype so modern C compilers (C23 and newer)
+ * do not treat an empty parameter list as a no-argument function.
*/
- static ssize_t (*readfunc)() = 0;
+ static ssize_t (*readfunc)(int, void *, size_t) = NULL;
if (readfunc == NULL) {
char *cp = getenv("AWKREADFUNC");
/* If necessary, one day, test value for different functions. */
if (cp == NULL)
- /*
- * cast is to remove warnings on systems with
- * different return types for read.
- */
- readfunc = ( ssize_t(*)() ) read;
+ readfunc = read;
else
readfunc = read_one_line;
}

View file

@ -0,0 +1,14 @@
SPDX-License-Identifier: GPL-3.0-or-later
Drop obsolete K&R-style strtod declaration in node.c.
--- gawk-4.2.1/node.c
+++ gawk-4.2.1/node.c
@@ -62,7 +62,6 @@ r_force_number(NODE *n)
char *cpend;
char save;
char *ptr;
- extern double strtod();
if ((n->flags & NUMCUR) != 0)
return n;

View file

@ -0,0 +1 @@
f https://mirrors.kernel.org/gnu/gawk/gawk-4.2.1.tar.xz d1119785e746d46a8209d28b2de404a57f983aa48670f4e225531d3bdc175551

View file

@ -0,0 +1,16 @@
# SPDX-FileCopyrightText: 2021 Andrius Štikonas <andrius@stikonas.eu>
#
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
autoreconf-2.71 -fi
}
src_configure() {
# CFLAGS needed on musl
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--disable-shared \
CFLAGS='-D_GNU_SOURCE -DNO_GETCONTEXT -DSEARCH_FOR_DATA_START -DUSE_MMAP -DHAVE_DL_ITERATE_PHDR'
}

View file

@ -0,0 +1 @@
f https://github.com/bdwgc/bdwgc/releases/download/v8.2.12/gc-8.2.12.tar.gz 42e5194ad06ab6ffb806c83eb99c03462b495d979cda782f3c72c08af833cd4e

View file

@ -0,0 +1,59 @@
// SPDX-FileCopyrightText: 2007, 2009 Free Software Foundation, Inc.
// SPDX-License-Identifier: GPL-3.0-or-later
/* Conversion lookup tables for the decNumber C Library.
Copyright (C) 2007, 2009 Free Software Foundation, Inc.
Contributed by IBM Corporation. Author Mike Cowlishaw.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* ------------------------------------------------------------------------ */
/* Binary Coded Decimal and Densely Packed Decimal conversion lookup tables */
/* [Automatically generated -- do not edit. 2008.06.21] */
/* ------------------------------------------------------------------------ */
/* For details, see DPDecimal.html on the General Decimal Arithmetic page. */
#include "decDPDSymbols.h"
/* This include file defines several DPD and BCD conversion tables: */
/* */
/* uint16_t BCD2DPD[2458]; -- BCD -> DPD (0x999 => 2457) */
/* uint16_t BIN2DPD[1000]; -- Bin -> DPD (999 => 2457) */
/* uint8_t BIN2CHAR[4001]; -- Bin -> CHAR (999 => '\3' '9' '9' '9') */
/* uint8_t BIN2BCD8[4000]; -- Bin -> bytes (999 => 9 9 9 3) */
/* uint16_t DPD2BCD[1024]; -- DPD -> BCD (0x3FF => 0x999) */
/* uint16_t DPD2BIN[1024]; -- DPD -> BIN (0x3FF => 999) */
/* uint32_t DPD2BINK[1024]; -- DPD -> BIN * 1000 (0x3FF => 999000) */
/* uint32_t DPD2BINM[1024]; -- DPD -> BIN * 1E+6 (0x3FF => 999000000) */
/* uint8_t DPD2BCD8[4096]; -- DPD -> bytes (x3FF => 9 9 9 3) */
/* */
/* In all cases the result (10 bits or 12 bits, or binary) is right-aligned */
/* in the table entry. BIN2CHAR entries are a single byte length (0 for */
/* value 0) followed by three digit characters; a trailing terminator is */
/* included to allow 4-char moves always. BIN2BCD8 and DPD2BCD8 entries */
/* are similar with the three BCD8 digits followed by a one-byte length */
/* (again, length=0 for value 0). */
/* */
/* To use a table, its name, prefixed with DEC_, must be defined with a */
/* value of 1 before this header file is included. For example: */
/* #define DEC_BCD2DPD 1 */
/* This mechanism allows software to only include tables that are needed. */
/* ------------------------------------------------------------------------ */

View file

@ -0,0 +1,228 @@
// SPDX-FileCopyrightText: 2025 Samuel Tyler <samuel@samuelt.me>
// SPDX-License-Identifier: GPL-3.0-or-later
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
/*
* Creates decDPD.h.
* Based upon the algorithm given on;
* https://web.archive.org/web/20080308073422/http://www2.hursley.ibm.com/decimal/DPDecimal.html
* originally written in the (obsolete) language Rexx.
*
* Is not bit-for-bit identical to the original decDPD.h, as we don't bother
* to follow the same formatting.
*
* The original Rexx code follows;
*/
// /* dpdGenerate.rex -- display Densely Packed Decimal table */
// /* mfc 2000.10.03; Rexx version with new equations 2007.02.01 */
//
// do i=0 to 999
// bcd=right(i, 3, 0) -- make three-digit hexadecimal string
// bit10=bcd2dpd(x2b(bcd)) -- compress
// bit12=dpd2bcd(bit10) -- expand
// say bcd bit10 bit12 -- display
// end i
// exit
//
// /* bcd2dpd -- Compress BCD to Densely Packed Decimal
// argument is a string of 12 characters, each 0 or 1, being 3 digits
// of 4 bits, each being a valid BCD digit (0000-1001)
// (for example, 923 is 100100100011)
// result is a string of 10 characters, each 0 or 1
// (for the example, this would be 1001010011)
// */
// bcd2dpd: procedure
// -- assign each bit to a variable, named as in the description
// parse arg a +1 b +1 c +1 d +1 e +1 f +1 g +1 h +1 i +1 j +1 k +1 m +1
//
// -- derive the result bits, using boolean expressions only
// -- [the operators are: '&'=AND, '|'=OR, '\'=NOT.]
// p=b | (a & j) | (a & f & i)
// q=c | (a & k) | (a & g & i)
// r=d
// s=(f & (\a | \i)) | (\a & e & j) | (e & i)
// t=g | (\a & e &k;) | (a & i)
// u=h
// v=a | e | i
// w=a | (e & i) | (\e & j)
// x=e | (a & i) | (\a & k)
// y=m
// -- concatenate the bits and return
// return p||q||r||s||t||u||v||w||x||y
//
// /* dpd2bcd -- Expand Densely Packed Decimal to BCD
// argument is a string of 10 characters, each 0 or 1; all 1024
// possibilities are accepted (non-canonicals -> 999)
// (for example, 1001010011)
// result is a string of 12 characters, each 0 or 1
// (for the example, 100100100011 -- 923)
// */
// dpd2bcd: procedure
// -- assign each bit to a variable, named as in the description
// parse arg p +1 q +1 r +1 s +1 t +1 u +1 v +1 w +1 x +1 y +1
//
// -- derive the result bits, using boolean expressions only
// a= (v & w) & (\s | t | \x)
// b=p & (\v | \w | (s & \t & x))
// c=q & (\v | \w | (s & \t & x))
// d=r
// e=v & ((\w & x) | (\t & x) | (s & x))
// f=(s & (\v | \x)) | (p & \s & t & v & w & x)
// g=(t & (\v | \x)) | (q & \s & t & w)
// h=u
// i=v & ((\w & \x) | (w & x & (s | t)))
// j=(\v & w) | (s & v & \w & x) | (p & w & (\x | (\s & \t)))
// k=(\v & x) | (t & \w & x) | (q & v & w & (\x | (\s & \t)))
// m=y
// -- concatenate the bits and return
// return a||b||c||d||e||f||g||h||i||j||k||m
void int2boolarr(uint32_t num, bool *arr, int bits) {
int j = 0;
for (int i = bits - 1; i >= 0; i--) {
arr[j++] = (num >> i) & 0x1;
}
}
uint32_t boolarr2int(bool *dpd, int bits) {
uint32_t num = 0;
int j = 0;
for (int i = bits - 1; i >= 0; i--) {
num |= dpd[j++] << i;
}
return num;
}
uint32_t bcd2dpd(uint16_t ibcd) {
bool bcd[12];
int2boolarr(ibcd, bcd, 12);
bool dpd[10];
dpd[0] = bcd[1] | (bcd[0] & bcd[9]) | (bcd[0] & bcd[5] & bcd[8]);
dpd[1] = bcd[2] | (bcd[0] & bcd[10]) | (bcd[0] & bcd[6] & bcd[8]);
dpd[2] = bcd[3];
dpd[3] = (bcd[5] & (~bcd[0] | ~bcd[8])) | (~bcd[0] & bcd[4] & bcd[9]) | (bcd[4] & bcd[8]);
dpd[4] = bcd[6] | (~bcd[0] & bcd[4] & bcd[10]) | (bcd[0] & bcd[8]);
dpd[5] = bcd[7];
dpd[6] = bcd[0] | bcd[4] | bcd[8];
dpd[7] = bcd[0] | (bcd[4] & bcd[8]) | (~bcd[4] & bcd[9]);
dpd[8] = bcd[4] | (bcd[0] & bcd[8]) | (~bcd[0] & bcd[10]);
dpd[9] = bcd[11];
return boolarr2int(dpd, 10);
}
uint32_t dpd2bcd(uint32_t idpd) {
bool dpd[10];
int2boolarr(idpd, dpd, 10);
bool bcd[12];
bcd[0] = (dpd[6] & dpd[7]) & (~dpd[3] | dpd[4] | ~dpd[8]);
bcd[1] = dpd[0] & (~dpd[6] | ~dpd[7] | (dpd[3] & ~dpd[4] & dpd[8]));
bcd[2] = dpd[1] & (~dpd[6] | ~dpd[7] | (dpd[3] & ~dpd[4] & dpd[8]));
bcd[3] = dpd[2];
bcd[4] = dpd[6] & ((~dpd[7] & dpd[8]) | (~dpd[4] & dpd[8]) | (dpd[3] & dpd[8]));
bcd[5] = (dpd[3] & (~dpd[6] | ~dpd[8])) | (dpd[0] & ~dpd[3] & dpd[4] & dpd[6] & dpd[7] & dpd[8]);
bcd[6] = (dpd[4] & (~dpd[6] | ~dpd[8])) | (dpd[1] & ~dpd[3] & dpd[4] & dpd[7]);
bcd[7] = dpd[5];
bcd[8] = dpd[6] & ((~dpd[7] & ~dpd[8]) | (dpd[7] & dpd[8] & (dpd[3] | dpd[4])));
bcd[9] = (~dpd[6] & dpd[7]) | (dpd[3] & dpd[6] & ~dpd[7] & dpd[8]) | (dpd[0] & dpd[7] & (~dpd[8] | (~dpd[3] & ~dpd[4])));
bcd[10] = (~dpd[6] & dpd[8]) | (dpd[4] & ~dpd[7] & dpd[8]) | (dpd[1] & dpd[6] & dpd[7] & (~dpd[8] | (~dpd[3] & ~dpd[4])));
bcd[11] = dpd[9];
return boolarr2int(bcd, 12);
}
uint8_t get_cntrl_char(uint8_t num) {
if (num == 0) {
return 0;
} else if (num < 10) {
return 1;
} else if (num < 100) {
return 2;
} else {
return 3;
}
}
void bin2char(uint8_t num, uint32_t str[4]) {
str[0] = get_cntrl_char(num);
str[1] = num / 100 + '0';
str[2] = (num % 100) / 10 + '0';
str[3] = num % 10 + '0';
}
void bin2bcd8(uint8_t num, char digit[4], uint32_t arr[4]) {
for (int i = 0; i < 3; i++) {
arr[i] = digit[i] - '0';
}
arr[3] = get_cntrl_char(num);
}
#define TABLES_COUNT 9
int main(void) {
uint32_t BCD2DPD[2458] = {0};
uint32_t BIN2DPD[1000] = {0};
uint32_t BIN2BCD8[4000];
uint32_t BIN2CHAR[4001];
uint32_t DPD2BCD[1024] = {0};
uint32_t DPD2BIN[1024] = {0};
uint32_t DPD2BINK[1024] = {0};
uint32_t DPD2BINM[1024] = {0};
uint32_t DPD2BCD8[4096];
for (int i = 0; i < 1000; i++) {
char digit[4];
snprintf(digit, 4, "%03d", i);
uint32_t bcd = 0;
for (int j = 0; j < 3; j++) {
bcd |= (digit[j] - '0') << (4 * (2 - j));
}
uint32_t dpd = bcd2dpd(bcd);
BCD2DPD[bcd] = dpd;
DPD2BCD[dpd] = bcd;
BIN2DPD[i] = dpd;
DPD2BIN[dpd] = i;
DPD2BINK[dpd] = i * 1000;
DPD2BINM[dpd] = i * 1E+6;
bin2char(i, BIN2CHAR + (4 * i));
bin2bcd8(i, digit, BIN2BCD8 + (4 * i));
bin2bcd8(i, digit, DPD2BCD8 + (4 * dpd));
}
BIN2CHAR[4000] = '\0';
char *names[] = {
"BCD2DPD", "BIN2DPD", "BIN2CHAR", "BIN2BCD8", "DPD2BCD", "DPD2BIN",
"DPD2BINK", "DPD2BINM", "DPD2BCD8",
};
char *types[] = {
"uint16_t", "uint16_t", "uint8_t", "uint8_t", "uint16_t", "uint16_t",
"uint32_t", "uint32_t", "uint8_t",
};
uint32_t *data[] = {
BCD2DPD, BIN2DPD, BIN2CHAR, BIN2BCD8, DPD2BCD, DPD2BIN,
DPD2BINK, DPD2BINM, DPD2BCD8,
};
int lengths[] = {2458, 1000, 4001, 4000, 1024, 1024, 1024, 1024, 4096};
for (int i = 0; i < TABLES_COUNT; i++) {
printf("#if defined(DEC_%s) && DEC_%s==1 && !defined(DEC%s)\n", names[i], names[i], names[i]);
printf("#define DEC%s\n", names[i]);
printf("const %s %s[%d] = {\n", types[i], names[i], lengths[i]);
for (int j = 0; j < lengths[i] / 16; j++) {
for (int k = j * 16; k < (j + 1) * 16 && k < lengths[i]; k++) {
printf("%s%d,", k == j * 16 ? "" : " ", data[i][k]);
}
printf("\n");
}
printf("};\n");
printf("#endif\n\n");
}
}

View file

@ -0,0 +1,286 @@
# SPDX-FileCopyrightText: 2023 Samuel Tyler <samuel@samuelt.me>
#
# SPDX-License-Identifier: GPL-3.0-or-later
# This gcc build targets the 64-bit kernel toolchain and keeps multilib enabled
# so the compiler can emit both 64-bit and 32-bit code.
: "${KERNEL_TARGET:=x86_64-unknown-linux-musl}"
: "${KERNEL_SYSROOT:=/kernel-toolchain}"
src_prepare() {
default
# Remove unused pregenerated files
rm libsanitizer/include/sanitizer/netbsd_syscall_hooks.h \
libsanitizer/sanitizer_common/sanitizer_syscalls_netbsd.inc
rm -r libgfortran/generated
rm gcc/testsuite/go.test/test/bench/go1/jsondata_test.go \
gcc/testsuite/go.test/test/bench/go1/parserdata_test.go \
gcc/testsuite/go.test/test/cmplxdivide1.go \
gcc/testsuite/go.test/test/fixedbugs/issue6866.go
rm gcc/testsuite/gcc.target/x86_64/abi/test_3_element_struct_and_unions.c \
gcc/testsuite/gcc.target/x86_64/abi/test_basic_returning.c \
gcc/testsuite/gcc.target/x86_64/abi/test_passing_floats.c \
gcc/testsuite/gcc.target/x86_64/abi/test_passing_integers.c \
gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_floats.c \
gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_returning.c \
gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_3_element_struct_and_unions.c \
gcc/testsuite/gcc.target/x86_64/abi/bf16/test_passing_floats.c \
gcc/testsuite/gcc.target/x86_64/abi/bf16/test_3_element_struct_and_unions.c
rm gcc/testsuite/c-c++-common/analyzer/flex-with-call-summaries.c \
gcc/testsuite/c-c++-common/analyzer/flex-without-call-summaries.c
rm gcc/testsuite/gdc.test/compilable/dtoh_windows.d
rm gcc/testsuite/sarif-replay.dg/2.1.0-valid/malloc-vs-local-4.c.sarif \
gcc/testsuite/sarif-replay.dg/2.1.0-valid/signal-1.c.sarif
rm gcc/testsuite/gm2/projects/pim/run/pass/tower/advflex.c \
gcc/testsuite/gm2/projects/pim/run/pass/tower/AdvParse.mod
rm -r gcc/testsuite/gdc.test/compilable
rm gcc/config/rs6000/rs6000-tables.opt \
gcc/config/rs6000/fusion.md \
gcc/config/h8300/mova.md \
gcc/config/aarch64/aarch64-tune.md \
gcc/config/riscv/t-elf-multilib \
gcc/config/riscv/t-linux-multilib \
gcc/config/arm/arm-tune.md \
gcc/config/arm/arm-tables.opt \
gcc/config/arm/ldmstm.md \
gcc/config/arc/t-multilib \
gcc/config/m68k/m68k-tables.opt \
gcc/config/c6x/c6x-mult.md \
gcc/config/c6x/c6x-tables.opt \
gcc/config/c6x/c6x-sched.md \
gcc/config/csky/csky_tables.opt \
gcc/config/mips/mips-tables.opt \
gcc/config/nvptx/nvptx-gen.opt \
gcc/config/nvptx/nvptx-gen.h
rm libphobos/src/std/internal/unicode_tables.d \
libphobos/src/std/internal/unicode_decomp.d \
libphobos/src/std/internal/unicode_grapheme.d \
libphobos/src/std/internal/unicode_norm.d
rm libgo/go/math/bits/example_test.go \
libgo/go/math/bits/bits_tables.go \
libgo/go/math/big/accuracy_string.go \
libgo/go/math/big/roundingmode_string.go \
libgo/go/strconv/isprint.go \
libgo/go/strconv/eisel_lemire.go \
libgo/go/sort/zfuncversion.go \
libgo/go/golang.org/x/net/route/zsys_*.go \
libgo/go/golang.org/x/net/idna/*.go \
libgo/go/golang.org/x/text/unicode/bidi/t*.go \
libgo/go/golang.org/x/text/unicode/norm/tables*.go \
libgo/go/golang.org/x/tools/internal/typeparams/typeterm.go \
libgo/go/golang.org/x/tools/internal/typeparams/termlist.go \
libgo/go/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go \
libgo/go/internal/syscall/windows/registry/zsyscall_windows.go \
libgo/go/internal/syscall/windows/zsyscall_windows.go \
libgo/go/encoding/gob/*_helpers.go \
libgo/go/index/suffixarray/sais2.go \
libgo/go/net/http/*_bundle.go \
libgo/go/runtime/sizeclasses.go \
libgo/go/runtime/fastlog2table.go \
libgo/go/html/template/*_string.go \
libgo/go/crypto/md5/md5block.go \
libgo/go/crypto/tls/common_string.go \
libgo/go/crypto/elliptic/internal/fiat/p*.go \
libgo/go/crypto/ed25519/internal/edwards25519/field/fe_amd64.go \
libgo/go/time/zoneinfo_abbrs_windows.go \
libgo/go/unicode/tables.go \
libgo/go/regexp/syntax/doc.go \
libgo/go/regexp/syntax/op_string.go \
libgo/go/regexp/syntax/perl_groups.go \
libgo/go/image/internal/imageutil/impl.go \
libgo/go/image/color/palette/palette.go \
libgo/go/cmd/internal/objabi/*_string.go \
libgo/go/cmd/go/internal/test/flagdefs.go \
libgo/go/debug/dwarf/*_string.go \
libgo/go/debug/macho/reloctype_string.go \
libgo/go/internal/goexperiment/exp_*.go \
libgo/go/time/tzdata/zipdata.go \
libgo/go/go/constant/kind_string.go
rm libgo/go/compress/bzip2/testdata/*.bin \
libgo/go/go/internal/gccgoimporter/testdata/v1reflect.gox \
libgo/go/go/internal/gccgoimporter/testdata/time.gox \
libgo/go/go/internal/gccgoimporter/testdata/unicode.gox \
libgo/go/go/internal/gccgoimporter/testdata/escapeinfo.gox \
libgo/go/go/internal/gccgoimporter/testdata/libimportsar.a \
libgo/go/go/internal/gcimporter/testdata/versions/*.a
rm -r libgo/go/compress/*/testdata \
libgo/go/runtime/pprof/testdata \
libgo/go/debug/*/testdata \
libgo/go/internal/trace/testdata \
libgo/go/time/testdata \
libgo/go/internal/xcoff/testdata \
libgo/go/archive/*/testdata
rm gcc/d/dmd/common/identifiertables.d
rm -r gcc/rust/checks/errors/borrowck/ffi-polonius/vendor \
libgrust/libformat_parser/vendor
find fixincludes/tests -name "*.h" -delete
rm gcc/m2/mc/mcp*.bnf
rm -r gcc/m2/pge-boot \
gcc/m2/mc-boot
# Partially generated unused files
rm libgcc/config/sh/lib1funcs.S \
libgcc/config/sh/lib1funcs-4-300.S \
libgcc/config/arc/lib1funcs.S
# Remove vendored zlib
rm -r zlib/
# gperf files
rm gcc/cp/cfns.h gcc/cp/std-name-hint.h
# Generate it now, because gcc doesn't regenerate it for some reason
# (taken directly from gcc/cp/Make-lang.in)
gperf -o -C -E -k '1-6,$' -j1 -D -N 'libc_name_p' -L C++ \
gcc/cp/cfns.gperf --output-file gcc/cp/cfns.h
# Regenerate autogen stuff
rm Makefile.in fixincludes/fixincl.x
autogen Makefile.def
pushd fixincludes
./genfixes
popd
# Regenerate autotools
# configure
find . -name configure | sed 's:/configure::' | while read d; do
pushd "${d}"
AUTOMAKE=automake-1.15 ACLOCAL=aclocal-1.15 autoreconf-2.69 -fiv
popd
done
# Because GCC is stupid, copy depcomp back in
cp "${PREFIX}/share/automake-1.15/depcomp" .
# A odd script
pushd gcc/m2/gm2-libs
autoconf-2.69 -f config-host.in > config-host
popd
# Makefile.in only
local BACK="${PWD}"
find . -type d \
-exec test -e "{}/Makefile.am" -a ! -e "{}/configure" \; \
-print | while read d; do
d="$(readlink -f "${d}")"
cd "${d}"
# Find the appropriate configure script for automake
while [ ! -e configure ]; do
cd ..
done
automake-1.15 -fai "${d}/Makefile"
cd "${BACK}"
done
# Remove bison generated files
rm gcc/cobol/parse.{cc,h}
rm gcc/cobol/cdf.{cc,h}
# Remove flex generated files
rm gcc/gengtype-lex.cc
rm gcc/cobol/scan.cc
# Regenerate crc table in libiberty/crc32.c
pushd libiberty
sed -n '/^ #include <stdio.h>/,/^ \}$/p' crc32.c > crcgen.c
gcc -o crcgen crcgen.c
sed '/crc_v3\.txt/{n; q}' crc32.c > crc32.c.new
./crcgen >> crc32.c.new
sed '1,/^};$/d' crc32.c >> crc32.c.new
mv crc32.c.new crc32.c
popd
# Regenerate decDPD.h
rm libdecnumber/decDPD.h
gcc -std=c99 -o decDPD_generate decDPD_generate.c
cp decDPD.h.preamble libdecnumber/decDPD.h
./decDPD_generate >> libdecnumber/decDPD.h
# Regenerate sarif-spec-urls.def
rm gcc/sarif-spec-urls.def
cp -t contrib ../sarif-v2.1.0-errata01-os-complete.html
pushd contrib
# windows-1252 is not supported by our Python build
sed -i "s/'windows-1252'/'latin-1'/g" regenerate-sarif-spec-index.py
python3 regenerate-sarif-spec-index.py
popd
# Regenerate box-drawing-chars.inc
rm gcc/text-art/box-drawing-chars.inc
python3 contrib/unicode/gen-box-drawing-chars.py > gcc/text-art/box-drawing-chars.inc
# Regenerate combining-chars.inc
rm libcpp/combining-chars.inc
python3 contrib/unicode/gen-combining-chars.py > libcpp/combining-chars.inc
# Regenerate printable-chars.inc
rm libcpp/printable-chars.inc
python3 contrib/unicode/gen-printable-chars.py > libcpp/printable-chars.inc
# Regenerate unicode-data.h
rm libstdc++-v3/include/bits/unicode-data.h
pushd contrib/unicode
python3 gen_libstdcxx_unicode_data.py > ../../libstdc++-v3/include/bits/unicode-data.h
popd
# Regenerate loongarch files
pushd gcc/config/loongarch
rm loongarch-evolution.{cc,h} loongarch-str.h loongarch.opt
./genopts/genstr.sh evolution_c > loongarch-evolution.cc
./genopts/genstr.sh evolution_h > loongarch-evolution.h
./genopts/genstr.sh header > loongarch-str.h
./genopts/genstr.sh opt > loongarch.opt
popd
# Regenerate gcn files
pushd gcc/config/gcn
rm gcn-tables.opt
awk -f gen-opt-tables.awk gcn-devices.def > gcn-tables.opt
popd
# Remove docs/translation
find . -name "*.gmo" -delete
find . -name "*.info" -delete
find . -type f -name '*.[1-9]' -delete
rm libiberty/functions.texi
# Sphinx-generated
rm gcc/jit/docs/conf.py
rm gcc/jit/docs/_build/texinfo/libgccjit.texi \
gcc/ada/gnat_rm.texi \
gcc/ada/gnat_ugn.texi
rm gcc/doc/avr-mmcu.texi
gcc -o gen-avr-mmcu-texi gcc/config/avr/gen-avr-mmcu-texi.cc
./gen-avr-mmcu-texi > gcc/doc/avr-mmcu.texi
}
src_configure() {
export PATH="${KERNEL_SYSROOT}/bin:${PATH}"
mkdir build
cd build
LDFLAGS="-static" \
../configure \
--target="${KERNEL_TARGET}" \
--prefix="${KERNEL_SYSROOT}" \
--disable-nls \
--enable-languages=c \
--without-headers \
--disable-threads \
--disable-shared \
--disable-libssp \
--disable-libsanitizer \
--disable-libquadmath \
--disable-libatomic \
--disable-libgomp \
--enable-multilib
}
src_compile() {
make "${MAKEJOBS}" all-gcc
make "${MAKEJOBS}" all-target-libgcc
}
src_install() {
make install-gcc DESTDIR="${DESTDIR}"
make install-target-libgcc DESTDIR="${DESTDIR}"
}

View file

@ -0,0 +1,2 @@
f https://mirrors.kernel.org/gnu/gcc/gcc-15.2.0/gcc-15.2.0.tar.xz 438fd996826b0c82485a29da03a72d71d6e3541a83ec702df4271f6fe025d24e
f https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html 835a4d043e4415a76668c8f38d5605f4e6f8ac2279dfab7e61c3f06e9228dd1c

View file

@ -0,0 +1,24 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
}
src_configure() {
PATH="${PREFIX}/bin:/usr/bin:/bin" \
CFLAGS="${CFLAGS:-} -std=gnu89" \
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--includedir="${PREFIX}/include" \
--enable-static \
--enable-shared
}
src_compile() {
default_src_compile
}
src_install() {
default_src_install
}

View file

@ -0,0 +1 @@
f https://ftp.gnu.org/gnu/gdbm/gdbm-1.8.3.tar.gz cc340338a2e28b40058ab9eb5354a21d53f88a1582ea21ba0bb185c37a281dc9 gdbm-1.8.3.tar.gz

View file

@ -0,0 +1,46 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
}
src_configure() {
local host_triplet curl_static_libs
host_triplet="$(gcc -dumpmachine)"
curl_static_libs="-lcurl -lssl -lcrypto -lz -pthread"
PATH="${PREFIX}/bin:/usr/bin:/bin" \
LIBS="${curl_static_libs}" \
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--build="${host_triplet}" \
--host="${host_triplet}"
}
src_compile() {
local curl_static_libs
curl_static_libs="-lcurl -lssl -lcrypto -lz -pthread"
make "${MAKEJOBS}" \
NO_GETTEXT=YesPlease \
NO_TCLTK=YesPlease \
NO_PERL=YesPlease \
NO_PYTHON=YesPlease \
CURL_LDFLAGS="${curl_static_libs}"
}
src_install() {
local curl_static_libs
curl_static_libs="-lcurl -lssl -lcrypto -lz -pthread"
make install \
NO_GETTEXT=YesPlease \
NO_TCLTK=YesPlease \
NO_PERL=YesPlease \
NO_PYTHON=YesPlease \
CURL_LDFLAGS="${curl_static_libs}" \
DESTDIR="${DESTDIR}" \
prefix="${PREFIX}" \
libdir="${LIBDIR}"
}

View file

@ -0,0 +1,19 @@
--- git-2.53.0/configure
+++ git-2.53.0/configure
@@ -5582,7 +5582,7 @@
printf %s "(cached) " >&6
else case e in #(
e) ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcurl $LIBS"
+LIBS="-lcurl -lssl -lcrypto -lz -pthread $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -5695,6 +5695,7 @@
fi
CURL_LDFLAGS=$($CURL_CONFIG $CURL_CONFIG_OPTS)
+ CURL_LDFLAGS="$CURL_LDFLAGS -lssl -lcrypto -lz -pthread"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: Setting CURL_LDFLAGS to '$CURL_LDFLAGS'" >&5
printf "%s\n" "$as_me: Setting CURL_LDFLAGS to '$CURL_LDFLAGS'" >&6;}

View file

@ -0,0 +1 @@
f https://www.kernel.org/pub/software/scm/git/git-2.53.0.tar.xz 5818bd7d80b061bbbdfec8a433d609dc8818a05991f731ffc4a561e2ca18c653

View file

@ -0,0 +1,39 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
}
src_configure() {
local host_triplet
host_triplet="$(gcc -dumpmachine)"
PATH="${PREFIX}/bin:/usr/bin:/bin" \
PKG_CONFIG_PATH="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig" \
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--includedir="${PREFIX}/include" \
--host="${host_triplet}" \
--build="${host_triplet}" \
--enable-shared \
--disable-static \
--disable-doc \
--disable-tests \
--disable-tools \
--disable-libdane \
--without-p11-kit \
--without-idn \
--without-zlib \
--without-brotli \
--without-tpm \
--without-tpm2
}
src_compile() {
default_src_compile
}
src_install() {
default_src_install
}

View file

@ -0,0 +1 @@
f https://www.gnupg.org/ftp/gcrypt/gnutls/v3.8/gnutls-3.8.12.tar.xz a7b341421bfd459acf7a374ca4af3b9e06608dcd7bd792b2bf470bea012b8e51 gnutls-3.8.0.tar.xz

View file

@ -0,0 +1,18 @@
# SPDX-License-Identifier: GPL-3.0-or-later
SEED_PREFIX="/bootstrap-seeds/grep-3.1"
src_configure() {
CFLAGS="-O2" LDFLAGS="-static" ./configure \
--prefix="${SEED_PREFIX}" \
--disable-perl-regexp \
--disable-shared
}
src_compile() {
default_src_compile
}
src_install() {
make DESTDIR="${DESTDIR}" install
}

View file

@ -0,0 +1 @@
f https://mirrors.kernel.org/gnu/grep/grep-3.1.tar.xz db625c7ab3bb3ee757b3926a5cfa8d9e1c3991ad24707a83dde8a5ef2bf7a07e

View file

@ -0,0 +1,51 @@
# SPDX-License-Identifier: GPL-3.0-or-later
SEED_PREFIX="/bootstrap-seeds/guile-2.0.9"
src_prepare() {
default
AUTOPOINT=true \
ACLOCAL_PATH="${PREFIX}/share/aclocal:${PREFIX}/share/gettext/m4${ACLOCAL_PATH:+:${ACLOCAL_PATH}}" \
autoreconf -fi
# Match Guix's static bootstrap Guile approach: force the final `guile`
# executable to be linked through libtool with -all-static.
sed -i \
-e 's|^guile_LDADD =.*$|guile_LDADD = libguile-@GUILE_EFFECTIVE_VERSION@.la -ldl|' \
-e 's|^guile_LDFLAGS =.*$|guile_LDFLAGS = -all-static|' \
libguile/Makefile.in
}
src_configure() {
local pkg_config_path libffi_cflags libffi_libs
pkg_config_path="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig"
libffi_cflags="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
pkg-config --cflags libffi)"
libffi_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
pkg-config --static --libs libffi)"
PKG_CONFIG_LIBDIR="${pkg_config_path}" \
PKG_CONFIG_PATH="${pkg_config_path}" \
CFLAGS="${CFLAGS:-} -std=gnu89" \
LIBFFI_CFLAGS="${libffi_cflags}" \
LIBFFI_LIBS="${libffi_libs}" \
LDFLAGS="-ldl" \
./configure \
--prefix="${SEED_PREFIX}" \
--disable-shared \
--enable-static
}
src_compile() {
default_src_compile
}
src_install() {
local stage
stage="${DESTDIR}${SEED_PREFIX}"
make DESTDIR="${DESTDIR}" install
seed_make_repro_tar_xz "${stage}" "${DISTFILES}/guile-static-stripped-2.0.9-i686-linux.tar.xz"
}

View file

@ -0,0 +1,45 @@
--- guile-2.0.9/libguile/posix.c
+++ guile-2.0.9/libguile/posix.c
@@ -2254,6 +2254,8 @@
#endif
#ifdef WAIT_ANY
scm_c_define ("WAIT_ANY", scm_from_int (WAIT_ANY));
+#else
+ scm_c_define ("WAIT_ANY", scm_from_int (-1));
#endif
#ifdef WAIT_MYPGRP
scm_c_define ("WAIT_MYPGRP", scm_from_int (WAIT_MYPGRP));
@@ -2288,21 +2290,33 @@
#endif
#ifdef LC_PAPER
scm_c_define ("LC_PAPER", scm_from_int (LC_PAPER));
+#else
+ scm_c_define ("LC_PAPER", scm_from_int (7));
#endif
#ifdef LC_NAME
scm_c_define ("LC_NAME", scm_from_int (LC_NAME));
+#else
+ scm_c_define ("LC_NAME", scm_from_int (8));
#endif
#ifdef LC_ADDRESS
scm_c_define ("LC_ADDRESS", scm_from_int (LC_ADDRESS));
+#else
+ scm_c_define ("LC_ADDRESS", scm_from_int (9));
#endif
#ifdef LC_TELEPHONE
scm_c_define ("LC_TELEPHONE", scm_from_int (LC_TELEPHONE));
+#else
+ scm_c_define ("LC_TELEPHONE", scm_from_int (10));
#endif
#ifdef LC_MEASUREMENT
scm_c_define ("LC_MEASUREMENT", scm_from_int (LC_MEASUREMENT));
+#else
+ scm_c_define ("LC_MEASUREMENT", scm_from_int (11));
#endif
#ifdef LC_IDENTIFICATION
scm_c_define ("LC_IDENTIFICATION", scm_from_int (LC_IDENTIFICATION));
+#else
+ scm_c_define ("LC_IDENTIFICATION", scm_from_int (12));
#endif
#ifdef PIPE_BUF
scm_c_define ("PIPE_BUF", scm_from_long (PIPE_BUF));

View file

@ -0,0 +1,41 @@
diff --git a/configure.ac b/configure.ac
index 27f1463..9b16da7 100644
--- guile-2.0.9/configure.ac
+++ guile-2.0.9/configure.ac
@@ -741,7 +741,9 @@ AC_CHECK_HEADERS([assert.h crt_externs.h])
# truncate - not in mingw
# isblank - available as a GNU extension or in C99
# _NSGetEnviron - Darwin specific
-# strcoll_l, newlocale - GNU extensions (glibc), also available on Darwin
+# strcoll_l, strtol_l, strtod_l, nl_langinfo_l, toupper_l, tolower_l,
+# newlocale - GNU/POSIX locale APIs used together by libguile/i18n.c;
+# if some are missing, Guile must fall back to the compatibility path
# fork - unavailable on Windows
# utimensat - posix.1-2008
# sched_getaffinity, sched_setaffinity - GNU extensions (glibc)
@@ -756,7 +758,8 @@ AC_CHECK_FUNCS([DINFINITY DQNAN cexp chsize clog clog10 ctermid \
strptime symlink sync sysconf tcgetpgrp tcsetpgrp uname waitpid \
strdup system usleep atexit on_exit chown link fcntl ttyname getpwent \
getgrent kill getppid getpgrp fork setitimer getitimer strchr strcmp \
- index bcopy memcpy rindex truncate unsetenv isblank _NSGetEnviron \
+ index bcopy memcpy rindex truncate unsetenv isblank _NSGetEnviron \
+ nl_langinfo_l strtod_l strtol_l tolower_l toupper_l \
strcoll strcoll_l newlocale utimensat sched_getaffinity \
sched_setaffinity sendfile])
diff --git a/libguile/i18n.c b/libguile/i18n.c
index 09524e6..8b9534a 100644
--- guile-2.0.9/libguile/i18n.c
+++ guile-2.0.9/libguile/i18n.c
@@ -40,7 +40,10 @@
#include <unicase.h>
#include <unistr.h>
-#if (defined HAVE_NEWLOCALE) && (defined HAVE_STRCOLL_L)
+#if defined HAVE_NEWLOCALE && defined HAVE_NL_LANGINFO_L \
+ && defined HAVE_STRCOLL_L && defined HAVE_STRTOD_L \
+ && defined HAVE_STRTOL_L && defined HAVE_TOLOWER_L \
+ && defined HAVE_TOUPPER_L
/* The GNU thread-aware locale API is documented in ``Thread-Aware Locale
Model, a Proposal'', by Ulrich Drepper:

View file

@ -0,0 +1,12 @@
diff -ru guile-2.0.9/libguile/filesys.c guile-2.0.9/libguile/filesys.c
--- guile-2.0.9/libguile/filesys.c
+++ guile-2.0.9/libguile/filesys.c
@@ -1130,7 +1130,7 @@
ssize_t result SCM_UNUSED;
size_t c_count, total = 0;
- scm_t_off c_offset;
+ off_t c_offset;
int in_fd, out_fd;
VALIDATE_FD_OR_PORT (out_fd, out, 1);

View file

@ -0,0 +1,122 @@
This hack makes Guile default to UTF-8. This avoids calls to
`iconv_open'; `iconv_open' tries to open shared objects that aren't
available during bootstrap, so using UTF-8 avoids that (and UTF-8 has
built-in conversions in glibc, too.)
diff --git a/libguile/bytevectors.c b/libguile/bytevectors.c
index cf41f2f..facfb91 100644
--- guile-2.0.9/libguile/bytevectors.c
+++ guile-2.0.9/libguile/bytevectors.c
@@ -1887,7 +1887,7 @@ utf_encoding_name (char *name, size_t utf_width, SCM endianness)
if (scm_i_is_narrow_string (str)) \
{ \
err = mem_iconveh (scm_i_string_chars (str), c_strlen, \
- "ISO-8859-1", c_utf_name, \
+ "UTF-8", c_utf_name, \
iconveh_question_mark, NULL, \
&c_utf, &c_utf_len); \
if (SCM_UNLIKELY (err)) \
diff --git a/libguile/ports.c b/libguile/ports.c
index 301bc44..b0ea2e6 100644
--- guile-2.0.9/libguile/ports.c
+++ guile-2.0.9/libguile/ports.c
@@ -1750,7 +1750,7 @@ scm_ungetc (scm_t_wchar c, SCM port)
if (pt->encoding != NULL)
encoding = pt->encoding;
else
- encoding = "ISO-8859-1";
+ encoding = "UTF-8";
len = sizeof (result_buf);
result = u32_conv_to_encoding (encoding,
@@ -2212,7 +2212,7 @@ scm_i_set_port_encoding_x (SCM port, const char *encoding)
pt = SCM_PTAB_ENTRY (port);
if (encoding == NULL)
- encoding = "ISO-8859-1";
+ encoding = "UTF-8";
if (pt->encoding != encoding)
pt->encoding = scm_gc_strdup (encoding, "port");
diff --git a/libguile/posix.c b/libguile/posix.c
index 4f8b8ac..fea7f74 100644
--- guile-2.0.9/libguile/posix.c
+++ guile-2.0.9/libguile/posix.c
@@ -1740,7 +1740,7 @@ SCM_DEFINE (scm_setlocale, "setlocale", 1, 1, 0,
SCM_SYSERROR;
}
- enc = locale_charset ();
+ enc = "UTF-8";
/* Set the default encoding for new ports. */
scm_i_set_default_port_encoding (enc);
diff --git a/libguile/script.c b/libguile/script.c
index 83daf8a..083891e 100644
--- guile-2.0.9/libguile/script.c
+++ guile-2.0.9/libguile/script.c
@@ -387,7 +387,7 @@ locale_arguments_to_string_list (int argc, char **const argv)
SCM lst;
const char *encoding;
- encoding = environ_locale_charset ();
+ encoding = "UTF-8";
for (i = argc - 1, lst = SCM_EOL;
i >= 0;
i--)
diff --git a/libguile/strings.c b/libguile/strings.c
index 5d0db23..8266247 100644
--- guile-2.0.9/libguile/strings.c
+++ guile-2.0.9/libguile/strings.c
@@ -1576,7 +1576,7 @@ scm_from_locale_string (const char *str)
SCM
scm_from_locale_stringn (const char *str, size_t len)
{
- return scm_from_stringn (str, len, locale_charset (),
+ return scm_from_stringn (str, len, "UTF-8",
scm_i_default_port_conversion_handler ());
}
@@ -1803,7 +1803,7 @@ char *
scm_to_locale_stringn (SCM str, size_t *lenp)
{
return scm_to_stringn (str, lenp,
- locale_charset (),
+ "UTF-8",
scm_i_default_port_conversion_handler ());
}
@@ -2054,7 +2054,7 @@ scm_to_stringn (SCM str, size_t *lenp, const char *encoding,
"string contains #\\nul character: ~S",
scm_list_1 (str));
- if (scm_i_is_narrow_string (str) && (encoding == NULL))
+ if (scm_i_is_narrow_string (str))
{
/* If using native Latin-1 encoding, just copy the string
contents. */
@@ -2079,11 +2079,11 @@ scm_to_stringn (SCM str, size_t *lenp, const char *encoding,
len = 0;
enc = encoding;
if (enc == NULL)
- enc = "ISO-8859-1";
+ enc = "UTF-8";
if (scm_i_is_narrow_string (str))
{
ret = mem_iconveh (scm_i_string_chars (str), ilen,
- "ISO-8859-1", enc,
+ "UTF-8", enc,
(enum iconv_ilseq_handler) handler, NULL,
&buf, &len);
--- guile-2.0.9/libguile/ports.c 2013-08-21 11:08:50.000000000 +0200
+++ guile-2.0.9/libguile/ports.c 2013-08-21 11:09:47.000000000 +0200
@@ -2512,7 +2512,7 @@ scm_i_port_iconv_descriptors (SCM port,
const char *precise_encoding;
if (!pt->encoding)
- pt->encoding = "ISO-8859-1";
+ pt->encoding = "UTF-8";
/* If the specified encoding is UTF-16 or UTF-32, then make
that more precise by deciding what byte order to use. */

View file

@ -0,0 +1,377 @@
This patch adds bindings to Linux syscalls for which glibc has symbols.
Using the FFI would have been nice, but that's not an option when using
a statically-linked Guile in an initrd that doesn't have libc.so around.
diff --git a/libguile/posix.c b/libguile/posix.c
index b0fcad5fd..1343186e3 100644
--- guile-2.0.9/libguile/posix.c
+++ guile-2.0.9/libguile/posix.c
@@ -2341,6 +2341,367 @@ scm_init_popen (void)
}
#endif /* HAVE_START_CHILD */
+
+/* Linux! */
+#ifdef __linux__
+
+#include <sys/mount.h>
+#include <sys/syscall.h>
+
+#include "libguile/foreign.h"
+#include "libguile/bytevectors.h"
+
+SCM_DEFINE (scm_mount, "mount", 3, 2, 0,
+ (SCM source, SCM target, SCM type, SCM flags, SCM data),
+ "Mount file system of @var{type} specified by @var{source} "
+ "on @var{target}.")
+#define FUNC_NAME s_scm_mount
+{
+ int err;
+ char *c_source, *c_target, *c_type, *c_data;
+ unsigned long c_flags;
+
+ c_source = scm_to_locale_string (source);
+ c_target = scm_to_locale_string (target);
+ c_type = scm_to_locale_string (type);
+ c_flags = SCM_UNBNDP (flags) ? 0 : scm_to_ulong (flags);
+
+ if (SCM_UNBNDP (data) || scm_is_false (data))
+ c_data = NULL;
+ else
+ c_data = scm_to_locale_string (data);
+
+ err = mount (c_source, c_target, c_type, c_flags, c_data);
+ if (err != 0)
+ err = errno;
+
+ free (c_source);
+ free (c_target);
+ free (c_type);
+
+ if (c_data != NULL)
+ free (c_data);
+
+ if (err != 0)
+ {
+ errno = err;
+ SCM_SYSERROR;
+ }
+
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_umount, "umount", 1, 0, 0,
+ (SCM target),
+ "Unmount the file system on @var{target}.")
+#define FUNC_NAME s_scm_umount
+{
+ int err;
+ char *c_target;
+
+ c_target = scm_to_locale_string (target);
+
+ err = umount (c_target);
+ if (err != 0)
+ err = errno;
+
+ free (c_target);
+
+ if (err != 0)
+ {
+ errno = err;
+ SCM_SYSERROR;
+ }
+
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+/* Linux's module installation syscall. See `kernel/module.c' in Linux;
+ the function itself is part of the GNU libc.
+
+ Load the LEN bytes at MODULE as a kernel module, with arguments from
+ ARGS, a space-separated list of options. */
+extern long init_module (void *module, unsigned long len, const char *args);
+
+/* Load a kernel module from FD. FLAGS must be a bitwise or of
+ MODULE_INIT_* constants. The GNU libc doesn't provide a wrapper for
+ this one so we use 'syscall'. */
+static int
+finit_module (int fd, const char *args, int flags)
+{
+ return syscall (SYS_finit_module, fd, args, flags);
+}
+
+
+SCM_DEFINE (scm_load_linux_module, "load-linux-module", 1, 1, 0,
+ (SCM data, SCM options),
+ "Load the Linux kernel module whose contents are in bytevector "
+ "DATA (the contents of a @code{.ko} file), with the arguments "
+ "from the OPTIONS string.")
+#define FUNC_NAME s_scm_load_linux_module
+{
+ long err;
+ void *c_data;
+ unsigned long c_len;
+ char *c_options;
+
+ SCM_VALIDATE_BYTEVECTOR (SCM_ARG1, data);
+
+ c_data = SCM_BYTEVECTOR_CONTENTS (data);
+ c_len = SCM_BYTEVECTOR_LENGTH (data);
+ c_options =
+ scm_to_locale_string (SCM_UNBNDP (options) ? scm_nullstr : options);
+
+ err = init_module (c_data, c_len, c_options);
+
+ free (c_options);
+
+ if (err != 0)
+ SCM_SYSERROR;
+
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_load_linux_module_fd, "load-linux-module/fd", 1, 2, 0,
+ (SCM fd, SCM options, SCM flags),
+ "Load the Linux kernel module from the file at FD, "
+ "with the arguments from the OPTIONS string, and "
+ "optionally the given FLAGS.")
+#define FUNC_NAME s_scm_load_linux_module_fd
+{
+ long err;
+ int c_fd, c_flags;
+ char *c_options;
+
+ c_fd = scm_to_int (fd);
+ c_options =
+ scm_to_locale_string (SCM_UNBNDP (options) ? scm_nullstr : options);
+ c_flags = SCM_UNBNDP (flags) ? 0 : scm_to_int (flags);
+
+ err = finit_module (c_fd, c_options, c_flags);
+
+ free (c_options);
+
+ if (err != 0)
+ SCM_SYSERROR;
+
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+
+/* Rebooting, halting, and all that. */
+
+#include <sys/reboot.h>
+
+SCM_VARIABLE_INIT (flag_RB_AUTOBOOT, "RB_AUTOBOOT",
+ scm_from_int (RB_AUTOBOOT));
+SCM_VARIABLE_INIT (flag_RB_HALT_SYSTEM, "RB_HALT_SYSTEM",
+ scm_from_int (RB_HALT_SYSTEM));
+SCM_VARIABLE_INIT (flag_RB_ENABLE_CAD, "RB_ENABLE_CAD",
+ scm_from_int (RB_ENABLE_CAD));
+SCM_VARIABLE_INIT (flag_RB_DISABLE_CAD, "RB_DISABLE_CAD",
+ scm_from_int (RB_DISABLE_CAD));
+SCM_VARIABLE_INIT (flag_RB_POWER_OFF, "RB_POWER_OFF",
+ scm_from_int (RB_POWER_OFF));
+SCM_VARIABLE_INIT (flag_RB_SW_SUSPEND, "RB_SW_SUSPEND",
+ scm_from_int (RB_SW_SUSPEND));
+SCM_VARIABLE_INIT (flag_RB_KEXEC, "RB_KEXEC",
+ scm_from_int (RB_KEXEC));
+
+SCM_DEFINE (scm_reboot, "reboot", 0, 1, 0,
+ (SCM command),
+ "Reboot the system. @var{command} must be one of the @code{RB_} "
+ "constants; if omitted, @var{RB_AUTOBOOT} is used, thus "
+ "performing a hard reset.")
+#define FUNC_NAME s_scm_reboot
+{
+ int c_command;
+
+ if (SCM_UNBNDP (command))
+ c_command = RB_AUTOBOOT;
+ else
+ c_command = scm_to_int (command);
+
+ reboot (c_command);
+
+ return SCM_UNSPECIFIED; /* likely unreached */
+}
+#undef FUNC_NAME
+
+/* Linux network interfaces. See <linux/if.h>. */
+
+#include <linux/if.h>
+#include <linux/sockios.h>
+#include "libguile/socket.h"
+
+SCM_VARIABLE_INIT (flag_IFF_UP, "IFF_UP",
+ scm_from_int (IFF_UP));
+SCM_VARIABLE_INIT (flag_IFF_BROADCAST, "IFF_BROADCAST",
+ scm_from_int (IFF_BROADCAST));
+SCM_VARIABLE_INIT (flag_IFF_DEBUG, "IFF_DEBUG",
+ scm_from_int (IFF_DEBUG));
+SCM_VARIABLE_INIT (flag_IFF_LOOPBACK, "IFF_LOOPBACK",
+ scm_from_int (IFF_LOOPBACK));
+SCM_VARIABLE_INIT (flag_IFF_POINTOPOINT, "IFF_POINTOPOINT",
+ scm_from_int (IFF_POINTOPOINT));
+SCM_VARIABLE_INIT (flag_IFF_NOTRAILERS, "IFF_NOTRAILERS",
+ scm_from_int (IFF_NOTRAILERS));
+SCM_VARIABLE_INIT (flag_IFF_RUNNING, "IFF_RUNNING",
+ scm_from_int (IFF_RUNNING));
+SCM_VARIABLE_INIT (flag_IFF_NOARP, "IFF_NOARP",
+ scm_from_int (IFF_NOARP));
+SCM_VARIABLE_INIT (flag_IFF_PROMISC, "IFF_PROMISC",
+ scm_from_int (IFF_PROMISC));
+SCM_VARIABLE_INIT (flag_IFF_ALLMULTI, "IFF_ALLMULTI",
+ scm_from_int (IFF_ALLMULTI));
+
+SCM_DEFINE (scm_set_network_interface_address, "set-network-interface-address",
+ 3, 0, 0,
+ (SCM socket, SCM name, SCM address),
+ "Configure network interface @var{name}.")
+#define FUNC_NAME s_scm_set_network_interface_address
+{
+ char *c_name;
+ struct ifreq ifr;
+ struct sockaddr *c_address;
+ size_t sa_len;
+ int fd, err;
+
+ socket = SCM_COERCE_OUTPORT (socket);
+ SCM_VALIDATE_OPFPORT (1, socket);
+ fd = SCM_FPORT_FDES (socket);
+
+ memset (&ifr, 0, sizeof ifr);
+ c_name = scm_to_locale_string (name);
+ c_address = scm_to_sockaddr (address, &sa_len);
+
+ strncpy (ifr.ifr_name, c_name, sizeof ifr.ifr_name - 1);
+ memcpy (&ifr.ifr_addr, c_address, sa_len);
+
+ err = ioctl (fd, SIOCSIFADDR, &ifr);
+ if (err != 0)
+ err = errno;
+
+ free (c_name);
+ free (c_address);
+
+ if (err != 0)
+ {
+ errno = err;
+ SCM_SYSERROR;
+ }
+
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_set_network_interface_flags, "set-network-interface-flags",
+ 3, 0, 0,
+ (SCM socket, SCM name, SCM flags),
+ "Change the flags of network interface @var{name} to "
+ "@var{flags}.")
+#define FUNC_NAME s_scm_set_network_interface_flags
+{
+ struct ifreq ifr;
+ char *c_name;
+ int fd, err;
+
+ socket = SCM_COERCE_OUTPORT (socket);
+ SCM_VALIDATE_OPFPORT (1, socket);
+ fd = SCM_FPORT_FDES (socket);
+
+ memset (&ifr, 0, sizeof ifr);
+ c_name = scm_to_locale_string (name);
+ strncpy (ifr.ifr_name, c_name, sizeof ifr.ifr_name - 1);
+ ifr.ifr_flags = scm_to_short (flags);
+
+ err = ioctl (fd, SIOCSIFFLAGS, &ifr);
+ if (err != 0)
+ err = errno;
+
+ free (c_name);
+
+ if (err != 0)
+ {
+ errno = err;
+ SCM_SYSERROR;
+ }
+
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_network_interface_flags, "network-interface-flags",
+ 2, 0, 0,
+ (SCM socket, SCM name),
+ "Return the flags of network interface @var{name}.")
+#define FUNC_NAME s_scm_network_interface_flags
+{
+ struct ifreq ifr;
+ char *c_name;
+ int fd, err;
+
+ socket = SCM_COERCE_OUTPORT (socket);
+ SCM_VALIDATE_OPFPORT (1, socket);
+ fd = SCM_FPORT_FDES (socket);
+
+ memset (&ifr, 0, sizeof ifr);
+ c_name = scm_to_locale_string (name);
+ strncpy (ifr.ifr_name, c_name, sizeof ifr.ifr_name - 1);
+
+ err = ioctl (fd, SIOCGIFFLAGS, &ifr);
+ if (err != 0)
+ err = errno;
+
+ free (c_name);
+
+ if (err != 0)
+ {
+ errno = err;
+ SCM_SYSERROR;
+ }
+
+ return scm_from_short (ifr.ifr_flags);
+}
+#undef FUNC_NAME
+#endif
+
+#include <sys/statfs.h>
+
+SCM_DEFINE (scm_statfs_raw, "statfs-raw", 1, 0, 0,
+ (SCM filesystem),
+ "Return a bytevector describing @var{filesystem}")
+#define FUNC_NAME s_scm_statfs_raw
+{
+ int err;
+ char *c_filesystem;
+ SCM bv;
+
+ c_filesystem = scm_to_locale_string (filesystem);
+
+ bv = scm_c_make_bytevector (sizeof (struct statfs));
+ struct statfs *bv_pointer = scm_to_pointer (scm_bytevector_to_pointer (bv, scm_from_int (0)));
+
+ err = statfs (c_filesystem, bv_pointer);
+ if (err != 0)
+ err = errno;
+
+ free (c_filesystem);
+
+ if (err != 0)
+ {
+ errno = err;
+ SCM_SYSERROR;
+ }
+
+ return bv;
+}
+#undef FUNC_NAME
+
void
scm_init_posix ()
{

View file

@ -0,0 +1,67 @@
--- guile-2.0.9/libguile/load.c
+++ guile-2.0.9/libguile/load.c
@@ -26,6 +26,7 @@
#include <string.h>
#include <stdio.h>
+#include <libgen.h>
#include "libguile/_scm.h"
#include "libguile/private-gc.h" /* scm_getenv_int */
@@ -297,6 +298,32 @@
SCM cpath = SCM_EOL;
#ifdef SCM_LIBRARY_DIR
+ char *program, *bin_dir, *prefix, *module_dir, *ccache_dir;
+
+ /* Determine the source and compiled module directories at run-time,
+ relative to the executable's location.
+
+ Note: Use /proc/self/exe instead of argv[0] because the latter is
+ not necessarily an absolute, nor a valid file name. */
+
+ program = scm_gc_malloc_pointerless (256, "string");
+ readlink ("/proc/self/exe", program, 256);
+
+ bin_dir = dirname (strdupa (program));
+
+ prefix = scm_gc_malloc_pointerless (strlen (bin_dir) + 4, "string");
+ strcpy (prefix, bin_dir);
+ strcat (prefix, "/..");
+ prefix = canonicalize_file_name (prefix);
+
+ module_dir = scm_gc_malloc_pointerless (strlen (prefix) + 50, "string");
+ strcpy (module_dir, prefix);
+ strcat (module_dir, "/share/guile/" SCM_EFFECTIVE_VERSION);
+
+ ccache_dir = scm_gc_malloc_pointerless (strlen (prefix) + 50, "string");
+ strcpy (ccache_dir, prefix);
+ strcat (ccache_dir, "/lib/guile/" SCM_EFFECTIVE_VERSION "/ccache");
+
env = getenv ("GUILE_SYSTEM_PATH");
if (env && strcmp (env, "") == 0)
/* special-case interpret system-path=="" as meaning no system path instead
@@ -305,10 +332,7 @@
else if (env)
path = scm_parse_path (scm_from_locale_string (env), path);
else
- path = scm_list_4 (scm_from_locale_string (SCM_LIBRARY_DIR),
- scm_from_locale_string (SCM_SITE_DIR),
- scm_from_locale_string (SCM_GLOBAL_SITE_DIR),
- scm_from_locale_string (SCM_PKGDATA_DIR));
+ path = scm_list_1 (scm_from_locale_string (module_dir));
env = getenv ("GUILE_SYSTEM_COMPILED_PATH");
if (env && strcmp (env, "") == 0)
@@ -317,10 +341,7 @@
else if (env)
cpath = scm_parse_path (scm_from_locale_string (env), cpath);
else
- {
- cpath = scm_list_2 (scm_from_locale_string (SCM_CCACHE_DIR),
- scm_from_locale_string (SCM_SITE_CCACHE_DIR));
- }
+ cpath = scm_list_1 (scm_from_locale_string (ccache_dir));
#endif /* SCM_LIBRARY_DIR */

View file

@ -0,0 +1,112 @@
--- guile-2.0.9/libguile/simpos.c
+++ guile-2.0.9/libguile/simpos.c
@@ -24,9 +24,11 @@
#endif
#include <errno.h>
+#include <fcntl.h>
#include <signal.h> /* for SIG constants */
#include <stdlib.h> /* for getenv */
#include <stdio.h>
+#include <sys/types.h>
#include "libguile/_scm.h"
@@ -66,7 +68,11 @@
"indicating whether the command processor is available.")
#define FUNC_NAME s_scm_system
{
- int rv, eno;
+ int rv, eno, child_errno = 0;
+ int status;
+ int errpipe[2];
+ ssize_t nread;
+ pid_t pid;
char *c_cmd;
if (SCM_UNBNDP (cmd))
@@ -77,11 +83,79 @@
SCM_VALIDATE_STRING (1, cmd);
errno = 0;
c_cmd = scm_to_locale_string (cmd);
- rv = system (c_cmd);
- eno = errno; free (c_cmd); errno = eno;
- if (rv == -1 || (rv == 127 && errno != 0))
- SCM_SYSERROR;
- return scm_from_int (rv);
+ if (pipe (errpipe) < 0)
+ {
+ eno = errno;
+ free (c_cmd);
+ errno = eno;
+ SCM_SYSERROR;
+ }
+
+ if (fcntl (errpipe[1], F_SETFD, FD_CLOEXEC) == -1)
+ {
+ eno = errno;
+ close (errpipe[0]);
+ close (errpipe[1]);
+ free (c_cmd);
+ errno = eno;
+ SCM_SYSERROR;
+ }
+
+ pid = fork ();
+ if (pid == 0)
+ {
+ char *argv[] = { (char *) "sh", (char *) "-c", c_cmd, NULL };
+ close (errpipe[0]);
+ execvp ("sh", argv);
+ child_errno = errno;
+ if (write (errpipe[1], &child_errno, sizeof (child_errno)) < 0)
+ ;
+ _exit (127);
+ }
+ else if (pid < 0)
+ {
+ eno = errno;
+ close (errpipe[0]);
+ close (errpipe[1]);
+ free (c_cmd);
+ errno = eno;
+ SCM_SYSERROR;
+ }
+
+ close (errpipe[1]);
+ while ((nread = read (errpipe[0], &child_errno, sizeof (child_errno))) == -1
+ && errno == EINTR)
+ ;
+ close (errpipe[0]);
+ if (nread == -1)
+ {
+ eno = errno;
+ free (c_cmd);
+ errno = eno;
+ SCM_SYSERROR;
+ }
+ if (nread != sizeof (child_errno))
+ child_errno = 0;
+
+ while ((rv = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
+ ;
+ if (rv == -1)
+ {
+ eno = errno;
+ free (c_cmd);
+ errno = eno;
+ SCM_SYSERROR;
+ }
+
+ free (c_cmd);
+
+ if (child_errno != 0)
+ {
+ errno = child_errno;
+ SCM_SYSERROR;
+ }
+
+ return scm_from_int (status);
}
#undef FUNC_NAME
#endif /* HAVE_SYSTEM */

View file

@ -0,0 +1 @@
f http://ftp.gnu.org/pub/gnu/guile/guile-2.0.9.tar.xz f70a38c8d9751f442679bfe61852bba8545af4d4355d037630997c2f37f2895b

View file

@ -0,0 +1,89 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
autoreconf -fi
}
src_configure() {
local host_triplet pkg_config_path guile_cflags guile_libs
local avahi_cflags avahi_libs
host_triplet="$(gcc -dumpmachine)"
pkg_config_path="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig:${PREFIX}/share/pkgconfig"
guile_cflags="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --cflags guile-3.0)"
guile_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs guile-3.0)"
avahi_cflags="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --cflags avahi-client)"
avahi_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs avahi-client)"
PATH="${PREFIX}/bin:/usr/bin:/bin" \
PKG_CONFIG="/usr/bin/pkg-config" \
PKG_CONFIG_LIBDIR="${pkg_config_path}" \
PKG_CONFIG_PATH="${pkg_config_path}" \
LD_LIBRARY_PATH="${LIBDIR}:${PREFIX}/lib:${LD_LIBRARY_PATH}" \
GUILE_CFLAGS="${guile_cflags}" \
GUILE_LDFLAGS="${guile_libs}" \
AVAHI_CFLAGS="${avahi_cflags}" \
AVAHI_LIBS="${avahi_libs}" \
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--host="${host_triplet}" \
--build="${host_triplet}" \
--enable-shared \
--disable-static \
'--with-guilemoduledir=$(datarootdir)/guile/site/$(GUILE_EFFECTIVE_VERSION)'
}
src_compile() {
local pkg_config_path guile_cflags guile_libs avahi_cflags avahi_libs gnutls_libs
pkg_config_path="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig:${PREFIX}/share/pkgconfig"
guile_cflags="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --cflags guile-3.0)"
guile_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs guile-3.0)"
avahi_cflags="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --cflags avahi-client)"
avahi_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs avahi-client)"
gnutls_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs gnutls)"
CPPFLAGS="${guile_cflags} ${avahi_cflags} ${CPPFLAGS:-}" \
GUILE_CFLAGS="${guile_cflags}" \
GUILE_LDFLAGS="${guile_libs}" \
AVAHI_CFLAGS="${avahi_cflags}" \
AVAHI_LIBS="${avahi_libs}" \
GNUTLS_LIBS="${gnutls_libs}" \
default_src_compile
}
src_install() {
local pkg_config_path guile_cflags guile_libs avahi_cflags avahi_libs gnutls_libs
pkg_config_path="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig:${PREFIX}/share/pkgconfig"
guile_cflags="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --cflags guile-3.0)"
guile_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs guile-3.0)"
avahi_cflags="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --cflags avahi-client)"
avahi_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs avahi-client)"
gnutls_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs gnutls)"
CPPFLAGS="${guile_cflags} ${avahi_cflags} ${CPPFLAGS:-}" \
GUILE_CFLAGS="${guile_cflags}" \
GUILE_LDFLAGS="${guile_libs}" \
AVAHI_CFLAGS="${avahi_cflags}" \
AVAHI_LIBS="${avahi_libs}" \
GNUTLS_LIBS="${gnutls_libs}" \
default_src_install
}
src_postprocess() {
default_src_postprocess
}

View file

@ -0,0 +1,171 @@
diff -urN guile-avahi-0.4.1/Makefile.am guile-avahi-0.4.1/Makefile.am
--- guile-avahi-0.4.1/Makefile.am 2023-01-15 17:29:00
+++ guile-avahi-0.4.1/Makefile.am 2026-03-08 10:22:35
@@ -37,6 +37,7 @@
EXTRA_DIST += \
src/make-enum-map.scm src/make-smob-types.scm \
src/make-enum-header.scm src/make-smob-header.scm \
+ src/guile-static-main.c \
src/make-callback-header.scm src/make-callback-trampolines.scm
# Files generated by (avahi build ...).
@@ -61,6 +62,11 @@
src/common.c.x src/watch.c.x src/client.c.x \
src/errors.c.x src/publish.c.x src/lookup.c.x
+guile_avahi_common_cflags = \
+ $(AVAHI_CFLAGS) $(GUILE_CFLAGS) $(AM_CFLAGS)
+
+if ENABLE_SHARED
+
nobase_guileextension_LTLIBRARIES = guile-avahi-v-0.la
# Use '-module' to build a "dlopenable module", in Libtool terms.
@@ -72,11 +78,29 @@
src/utils.c src/errors.c src/watch.c \
src/common.c src/client.c \
src/publish.c src/lookup.c
-guile_avahi_v_0_la_CFLAGS = \
- $(AVAHI_CFLAGS) $(GUILE_CFLAGS) $(AM_CFLAGS)
+guile_avahi_v_0_la_CFLAGS = $(guile_avahi_common_cflags)
+guile_avahi_v_0_la_DEPENDENCIES = $(BUILT_SOURCES)
guile_avahi_v_0_la_LIBADD = \
$(AVAHI_LIBS) $(GUILE_LDFLAGS)
+else
+lib_LIBRARIES = libguile-avahi-static.a
+libguile_avahi_static_a_SOURCES = \
+ src/utils.c src/errors.c src/watch.c \
+ src/common.c src/client.c \
+ src/publish.c src/lookup.c
+libguile_avahi_static_a_CPPFLAGS = $(AM_CPPFLAGS)
+libguile_avahi_static_a_CFLAGS = $(guile_avahi_common_cflags)
+libguile_avahi_static_a_DEPENDENCIES = $(BUILT_SOURCES)
+bin_PROGRAMS = guile
+guile_SOURCES = src/guile-static-main.c
+guile_CPPFLAGS = $(AM_CPPFLAGS)
+guile_CFLAGS = $(guile_avahi_common_cflags)
+guile_LDFLAGS = -static
+guile_LDADD = libguile-avahi-static.a $(GUILE_GNUTLS_STATIC_LIB) \
+ $(GUILE_LDFLAGS) $(AVAHI_LIBS) $(GNUTLS_LIBS) $(LIBS)
+endif
+
AM_CFLAGS = $(GCC_CFLAGS)
AM_CPPFLAGS = -I$(builddir)/src -I$(srcdir)/src \
-I$(top_srcdir)/lib -I$(top_builddir)/lib
@@ -173,6 +196,8 @@
gosubdir = $(godir)/avahi
goclientdir = $(gosubdir)/client
+if ENABLE_SHARED
+
nodist_go_DATA = \
modules/avahi.go
nodist_gosub_DATA = \
@@ -213,6 +238,7 @@
SUFFIXES += .go
CLEANFILES += $(GOBJECTS)
+endif ENABLE_SHARED
#
diff -urN guile-avahi-0.4.1/configure.ac guile-avahi-0.4.1/configure.ac
--- guile-avahi-0.4.1/configure.ac 2023-01-15 17:30:33
+++ guile-avahi-0.4.1/configure.ac 2026-03-08 10:22:35
@@ -27,7 +27,8 @@
# Libtool.
LT_PREREQ([2.2.6])
-LT_INIT([disable-static dlopen])
+LT_INIT([dlopen])
+AM_CONDITIONAL([ENABLE_SHARED], [test "x$enable_shared" != "xno"])
# Checks for programs.
AC_PROG_CC
diff -urN guile-avahi-0.4.1/modules/avahi.in guile-avahi-0.4.1/modules/avahi.in
--- guile-avahi-0.4.1/modules/avahi.in 2023-01-15 16:21:01
+++ guile-avahi-0.4.1/modules/avahi.in 2026-03-08 10:22:35
@@ -110,7 +110,8 @@
(string-append %libdir "/guile-avahi-v-0")
"guile-avahi-v-0"))
- (unless (getenv "AVAHI_GUILE_CROSS_COMPILING")
+ (unless (or (getenv "AVAHI_GUILE_CROSS_COMPILING")
+ (module-variable (current-module) 'watch?))
(load-extension %avahi-extension "scm_avahi_common_init")))
;; Optional bindings, depending on the configuration.
diff -urN guile-avahi-0.4.1/modules/avahi/client/lookup.scm guile-avahi-0.4.1/modules/avahi/client/lookup.scm
--- guile-avahi-0.4.1/modules/avahi/client/lookup.scm 2023-01-15 16:21:14
+++ guile-avahi-0.4.1/modules/avahi/client/lookup.scm 2026-03-08 10:22:35
@@ -63,7 +63,8 @@
resolver-event->string
resolver-event/found resolver-event/failure))
-(unless (getenv "AVAHI_GUILE_CROSS_COMPILING")
- (load-extension %avahi-extension "scm_avahi_lookup_init"))
+(unless (or (getenv "AVAHI_GUILE_CROSS_COMPILING")
+ (module-variable (current-module) 'domain-browser?))
+ (load-extension %avahi-extension "scm_avahi_lookup_init"))
;;; arch-tag: 9ab68bd4-4705-42e5-89c3-e02551be4d09
diff -urN guile-avahi-0.4.1/modules/avahi/client/publish.scm guile-avahi-0.4.1/modules/avahi/client/publish.scm
--- guile-avahi-0.4.1/modules/avahi/client/publish.scm 2023-01-15 16:21:20
+++ guile-avahi-0.4.1/modules/avahi/client/publish.scm 2026-03-08 10:22:35
@@ -39,7 +39,8 @@
publish-flag/no-cookie publish-flag/update
publish-flag/use-wide-area publish-flag/use-multicast))
-(unless (getenv "AVAHI_GUILE_CROSS_COMPILING")
- (load-extension %avahi-extension "scm_avahi_publish_init"))
+(unless (or (getenv "AVAHI_GUILE_CROSS_COMPILING")
+ (module-variable (current-module) 'entry-group?))
+ (load-extension %avahi-extension "scm_avahi_publish_init"))
;;; arch-tag: 36180c98-3262-40a6-a90c-eb8f283e628e
diff -urN guile-avahi-0.4.1/modules/avahi/client.scm guile-avahi-0.4.1/modules/avahi/client.scm
--- guile-avahi-0.4.1/modules/avahi/client.scm 2023-01-15 16:21:09
+++ guile-avahi-0.4.1/modules/avahi/client.scm 2026-03-08 10:22:35
@@ -29,8 +29,9 @@
client-flag->string
client-flag/ignore-user-config client-flag/no-fail))
-(unless (getenv "AVAHI_GUILE_CROSS_COMPILING")
- (load-extension %avahi-extension "scm_avahi_client_init"))
+(unless (or (getenv "AVAHI_GUILE_CROSS_COMPILING")
+ (module-variable (current-module) 'client?))
+ (load-extension %avahi-extension "scm_avahi_client_init"))
;; Optional bindings, depending on the configuration.
(if (defined? 'set-client-host-name!) (export set-client-host-name!))
diff -urN guile-avahi-0.4.1/src/guile-static-main.c guile-avahi-0.4.1/src/guile-static-main.c
--- guile-avahi-0.4.1/src/guile-static-main.c 1969-12-31 19:00:00
+++ guile-avahi-0.4.1/src/guile-static-main.c 2026-03-08 10:22:35
@@ -0,0 +1,26 @@
+#include <libguile.h>
+
+void scm_init_gnutls(void);
+void scm_avahi_common_init(void);
+void scm_avahi_client_init(void);
+void scm_avahi_lookup_init(void);
+void scm_avahi_publish_init(void);
+
+static void
+inner_main(void *closure, int argc, char **argv)
+{
+ (void) closure;
+ scm_init_gnutls();
+ scm_avahi_common_init();
+ scm_avahi_client_init();
+ scm_avahi_lookup_init();
+ scm_avahi_publish_init();
+ scm_shell(argc, argv);
+}
+
+int
+main(int argc, char **argv)
+{
+ scm_boot_guile(argc, argv, inner_main, NULL);
+ return 0;
+}

View file

@ -0,0 +1 @@
f https://download-mirror.savannah.gnu.org/releases/guile-avahi/guile-avahi-0.4.1.tar.gz db9de9e19df728b40d23c0381caa9f8eda2b175fa7f69f153be8f3f078044ca5 guile-avahi-0.4.1.tar.gz

View file

@ -0,0 +1,36 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
autoreconf -fi
}
src_configure() {
local host_triplet pkg_config_path
host_triplet="$(gcc -dumpmachine)"
pkg_config_path="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig:${PREFIX}/share/pkgconfig"
mkdir -p build
cd build
PATH="${PREFIX}/bin:/usr/bin:/bin" \
PKG_CONFIG="/usr/bin/pkg-config" \
PKG_CONFIG_LIBDIR="${pkg_config_path}" \
PKG_CONFIG_PATH="${pkg_config_path}" \
LD_LIBRARY_PATH="${LIBDIR}:${PREFIX}/lib:${LD_LIBRARY_PATH}" \
../configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--host="${host_triplet}" \
--build="${host_triplet}" \
--with-libgcrypt-prefix="${PREFIX}" \
--with-libgcrypt-libdir="${LIBDIR}"
}
src_compile() {
default_src_compile
}
src_install() {
default_src_install
}

View file

@ -0,0 +1 @@
f https://deb.debian.org/debian/pool/main/g/guile-gcrypt/guile-gcrypt_0.5.0.orig.tar.gz 59fafedf6bc23dce32d26400c957a4d7cd32be1fbb26d0c6992aa71777284fe3

View file

@ -0,0 +1,57 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
autoreconf -fi
}
src_configure() {
local host_triplet pkg_config_path libgit2_cflags libgit2_libs
host_triplet="$(gcc -dumpmachine)"
pkg_config_path="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig:${PREFIX}/share/pkgconfig"
libgit2_cflags="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --cflags libgit2)"
libgit2_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs libgit2)"
PATH="${PREFIX}/bin:/usr/bin:/bin" \
PKG_CONFIG="/usr/bin/pkg-config" \
PKG_CONFIG_LIBDIR="${pkg_config_path}" \
PKG_CONFIG_PATH="${pkg_config_path}" \
CPPFLAGS="${libgit2_cflags} ${CPPFLAGS:-}" \
LIBS="${libgit2_libs}" \
LIBGIT2_CFLAGS="${libgit2_cflags}" \
LIBGIT2_LIBS="${libgit2_libs}" \
libgit2_CFLAGS="${libgit2_cflags}" \
libgit2_LIBS="${libgit2_libs}" \
LD_LIBRARY_PATH="${LIBDIR}:${PREFIX}/lib:${LD_LIBRARY_PATH}" \
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
'--with-guile-site-dir=$(datarootdir)/guile/site/$(GUILE_EFFECTIVE_VERSION)' \
'--with-guile-extension-dir=$(libdir)/guile/$(GUILE_EFFECTIVE_VERSION)/extensions' \
--host="${host_triplet}" \
--build="${host_triplet}"
}
src_compile() {
local pkg_config_path libgit2_cflags libgit2_libs
pkg_config_path="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig:${PREFIX}/share/pkgconfig"
libgit2_cflags="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --cflags libgit2)"
libgit2_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs libgit2)"
CPPFLAGS="${libgit2_cflags} ${CPPFLAGS:-}" \
LIBS="${libgit2_libs}" \
LIBGIT2_CFLAGS="${libgit2_cflags}" \
LIBGIT2_LIBS="${libgit2_libs}" \
libgit2_CFLAGS="${libgit2_cflags}" \
libgit2_LIBS="${libgit2_libs}" \
default_src_compile
}
src_install() {
default_src_install
}

View file

@ -0,0 +1 @@
g https://gitlab.com/guile-git/guile-git.git~v0.10.0 https://gitlab.com/guile-git/guile-git/-/archive/v0.10.0/guile-git-v0.10.0.tar.gz 97966a8fb862bf50eb200c92a75039fc655e169a76dcb929e7e6ca3d81b493fc guile-git-v0.10.0.tar.gz

View file

@ -0,0 +1,68 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
autoreconf -fi
}
src_configure() {
local host_triplet pkg_config_path guile_cflags guile_libs gnutls_libs
host_triplet="$(gcc -dumpmachine)"
pkg_config_path="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig:${PREFIX}/share/pkgconfig"
guile_cflags="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --cflags guile-3.0)"
guile_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs guile-3.0)"
gnutls_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs gnutls)"
PATH="${PREFIX}/bin:/usr/bin:/bin" \
PKG_CONFIG="/usr/bin/pkg-config" \
PKG_CONFIG_LIBDIR="${pkg_config_path}" \
PKG_CONFIG_PATH="${pkg_config_path}" \
CFLAGS="-fPIC" \
CXXFLAGS="-fPIC" \
LD_LIBRARY_PATH="${LIBDIR}:${PREFIX}/lib:${LD_LIBRARY_PATH}" \
GUILE_CFLAGS="${guile_cflags}" \
GUILE_LIBS="${guile_libs}" \
GNUTLS_LIBS="${gnutls_libs}" \
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--host="${host_triplet}" \
--build="${host_triplet}" \
--enable-shared \
--disable-static \
'--with-guile-site-dir=$(datarootdir)/guile/site/$(GUILE_EFFECTIVE_VERSION)' \
'--with-guile-site-ccache-dir=$(libdir)/guile/$(GUILE_EFFECTIVE_VERSION)/site-ccache' \
'--with-guile-extension-dir=$(libdir)/guile/$(GUILE_EFFECTIVE_VERSION)/extensions'
}
src_compile() {
local pkg_config_path guile_cflags guile_libs gnutls_cflags gnutls_libs
pkg_config_path="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig:${PREFIX}/share/pkgconfig"
guile_cflags="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --cflags guile-3.0)"
guile_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs guile-3.0)"
gnutls_cflags="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --cflags gnutls)"
gnutls_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs gnutls)"
CPPFLAGS="${guile_cflags} ${gnutls_cflags} ${CPPFLAGS:-}" \
GUILE_CFLAGS="${guile_cflags}" \
GUILE_LDFLAGS="${guile_libs}" \
GNUTLS_CFLAGS="${gnutls_cflags}" \
GNUTLS_LIBS="${gnutls_libs}" \
default_src_compile
}
src_install() {
default_src_install
}
src_postprocess() {
default_src_postprocess
}

View file

@ -0,0 +1 @@
f https://ftp.gnu.org/gnu/gnutls/guile-gnutls-v5.0.1-src.tar.gz b190047cee068f6b22a5e8d49ca49a2425ad4593901b9ac8940f8842ba7f164f guile-gnutls-v5.0.1-src.tar.gz

View file

@ -0,0 +1,30 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
autoreconf -fi
}
src_configure() {
local host_triplet pkg_config_path
host_triplet="$(gcc -dumpmachine)"
pkg_config_path="${LIBDIR}/pkgconfig"
PATH="${PREFIX}/bin:/usr/bin:/bin" \
PKG_CONFIG_LIBDIR="${pkg_config_path}:${PREFIX}/lib/pkgconfig" \
PKG_CONFIG_PATH="${pkg_config_path}:${PREFIX}/lib/pkgconfig" \
LD_LIBRARY_PATH="${LIBDIR}:${LD_LIBRARY_PATH}" \
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--host="${host_triplet}" \
--build="${host_triplet}"
}
src_compile() {
default_src_compile
}
src_install() {
default_src_install
}

View file

@ -0,0 +1 @@
g https://github.com/aconchillo/guile-json.git~4.7.3 https://github.com/aconchillo/guile-json/archive/refs/tags/4.7.3.tar.gz 91485b2ac9453326e72d38ab4c0ffbe850597a4e3723993979d8aeb57d1ebb32 guile-json-v4.7.3.tar.gz

View file

@ -0,0 +1,34 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
autoreconf -fi
}
src_configure() {
local host_triplet pkg_config_path
host_triplet="$(gcc -dumpmachine)"
pkg_config_path="${LIBDIR}/pkgconfig"
PATH="${PREFIX}/bin:/usr/bin:/bin" \
PKG_CONFIG_LIBDIR="${pkg_config_path}" \
PKG_CONFIG_PATH="${pkg_config_path}:${PREFIX}/lib/pkgconfig" \
LD_LIBRARY_PATH="${LIBDIR}:${LD_LIBRARY_PATH}" \
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--host="${host_triplet}" \
--build="${host_triplet}"
}
src_compile() {
default_src_compile
}
src_install() {
default_src_install
}
src_postprocess() {
default_src_postprocess
}

View file

@ -0,0 +1,32 @@
SPDX-License-Identifier: GPL-3.0-or-later
Avoid requiring scm_gc_register_allocation to be exported from the
main Guile executable. Static Guile builds in this bootstrap do not
provide that symbol to dynamic-func, so fall back to a no-op.
--- guile-lzlib/lzlib.scm
+++ guile-lzlib/lzlib.scm
@@ -56,10 +56,15 @@
(define %liblz-handle
(delay (dynamic-link %liblz)))
-(define register-allocation
- ;; Let the GC know that an unmanaged heap allocation took place.
- (pointer->procedure void
- (dynamic-func "scm_gc_register_allocation"
- (dynamic-link))
- (list size_t)))
+(define register-allocation
+ ;; Let the GC know that an unmanaged heap allocation took place.
+ ;; Static Guile builds may not export this symbol from the main program.
+ (match (false-if-exception
+ (dynamic-func "scm_gc_register_allocation"
+ (dynamic-link)))
+ ((? pointer? proc)
+ (pointer->procedure void proc (list size_t)))
+ (#f
+ (lambda (_size)
+ #t))))
(define (lzlib-procedure ret name parameters)
"Return a procedure corresponding to C function NAME in liblz, or #f if

View file

@ -0,0 +1 @@
f https://deb.debian.org/debian/pool/main/g/guile-lzlib/guile-lzlib_0.3.0.orig.tar.gz a7f99c8d2a143e05ea22db2dc8b9ce6c27cae942162b45ee3015ed9027af0ff2 guile-lzlib_0.3.0.orig.tar.gz

View file

@ -0,0 +1,50 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
autoreconf -fi
}
src_configure() {
local host_triplet pkg_config_path
host_triplet="$(gcc -dumpmachine)"
pkg_config_path="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig:${PREFIX}/share/pkgconfig"
PATH="${PREFIX}/bin:/usr/bin:/bin" \
PKG_CONFIG="/usr/bin/pkg-config" \
PKG_CONFIG_LIBDIR="${pkg_config_path}:${PREFIX}/lib/pkgconfig" \
PKG_CONFIG_PATH="${pkg_config_path}:${PREFIX}/lib/pkgconfig" \
LD_LIBRARY_PATH="${LIBDIR}:${PREFIX}/lib:${LD_LIBRARY_PATH}" \
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--host="${host_triplet}" \
--build="${host_triplet}" \
'--with-guile-site-dir=$(datarootdir)/guile/site/$(GUILE_EFFECTIVE_VERSION)' \
'--with-guile-site-ccache-dir=$(libdir)/guile/$(GUILE_EFFECTIVE_VERSION)/site-ccache'
}
src_compile() {
default_src_compile
}
src_install() {
default_src_install
}
src_postprocess() {
local guile_site_path guile_site_ccache guile_core_ccache
default_src_postprocess
guile_site_path="${DESTDIR}${PREFIX}/share/guile/site/3.0:${PREFIX}/share/guile/site/3.0:${PREFIX}/share/guile/3.0"
guile_site_ccache="${DESTDIR}${LIBDIR}/guile/3.0/site-ccache:${LIBDIR}/guile/3.0/site-ccache"
guile_core_ccache="${LIBDIR}/guile/3.0/ccache"
PATH="${PREFIX}/bin:/usr/bin:/bin" \
GUILE_LOAD_PATH="${guile_site_path}" \
GUILE_LOAD_COMPILED_PATH="${guile_site_ccache}:${guile_core_ccache}" \
GUILE_SYSTEM_PATH="${guile_site_path}" \
GUILE_SYSTEM_COMPILED_PATH="${guile_site_ccache}:${guile_core_ccache}" \
"${PREFIX}/bin/guile" -c '(use-modules (semver)) (display "semver-module-ok\n")'
}

View file

@ -0,0 +1 @@
g https://codeberg.org/daym/guile-semver.git~607ca84c24b8950fdb5aca73e9d53d924e49fc24 _ 914b5aaf3064dedcea8bb55de31e48ba564971ebac3f2e33968c030ecc40c51f guile-semver-607ca84c24b8950fdb5aca73e9d53d924e49fc24.tar.gz

View file

@ -0,0 +1,30 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
autoreconf -fi
}
src_configure() {
local host_triplet pkg_config_path
host_triplet="$(gcc -dumpmachine)"
pkg_config_path="${LIBDIR}/pkgconfig"
PATH="${PREFIX}/bin:/usr/bin:/bin" \
PKG_CONFIG_LIBDIR="${pkg_config_path}" \
PKG_CONFIG_PATH="${pkg_config_path}" \
LD_LIBRARY_PATH="${LIBDIR}:${LD_LIBRARY_PATH}" \
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--host="${host_triplet}" \
--build="${host_triplet}"
}
src_compile() {
default_src_compile
}
src_install() {
default_src_install
}

View file

@ -0,0 +1 @@
f https://deb.debian.org/debian/pool/main/g/guile-sqlite3/guile-sqlite3_0.1.3.orig.tar.gz 158cb82958c6329319f911412999ea125980f327f54185bf0dad271d6f8f45c2

View file

@ -0,0 +1,30 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
autoreconf -fi
}
src_configure() {
local host_triplet pkg_config_path
host_triplet="$(gcc -dumpmachine)"
pkg_config_path="${LIBDIR}/pkgconfig"
PATH="${PREFIX}/bin:/usr/bin:/bin" \
PKG_CONFIG_LIBDIR="${pkg_config_path}" \
PKG_CONFIG_PATH="${pkg_config_path}:${PREFIX}/lib/pkgconfig" \
LD_LIBRARY_PATH="${LIBDIR}:${LD_LIBRARY_PATH}" \
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--host="${host_triplet}" \
--build="${host_triplet}"
}
src_compile() {
default_src_compile
}
src_install() {
default_src_install
}

View file

@ -0,0 +1 @@
f https://deb.debian.org/debian/pool/main/g/guile-zlib/guile-zlib_0.2.2.orig.tar.gz 6f6cca4b32ca79f3f4627cdb7ea68569a3cc38be60468991e2b5c085783e38c1 guile-zlib_0.2.2.orig.tar.gz

177
steps-guix/guix-1.5.0/pass2.sh Executable file
View file

@ -0,0 +1,177 @@
# SPDX-License-Identifier: GPL-3.0-or-later
: "${KERNEL_SYSROOT:=/kernel-toolchain}"
src_prepare() {
local patch_template rendered_patch
local mes_patch_template rendered_mes_patch
default
if [ ! -f /tmp/guix-bootstrap-seeds.env ]; then
echo "Missing /tmp/guix-bootstrap-seeds.env" >&2
false
fi
. /tmp/guix-bootstrap-seeds.env
patch_template="${base_dir}/patches/bootstrap-local-seeds.patch.in"
rendered_patch="/tmp/guix-bootstrap-local-seeds.patch"
mes_patch_template="${base_dir}/patches/bootstrap-local-mes-extra.patch.in"
rendered_mes_patch="/tmp/guix-bootstrap-local-mes-extra.patch"
sed \
-e "s|@EXEC_BASH_HASH@|${EXEC_BASH_HASH}|g" \
-e "s|@EXEC_MKDIR_HASH@|${EXEC_MKDIR_HASH}|g" \
-e "s|@EXEC_TAR_HASH@|${EXEC_TAR_HASH}|g" \
-e "s|@EXEC_XZ_HASH@|${EXEC_XZ_HASH}|g" \
-e "s|@STATIC_BINARIES_SEED_HASH@|${STATIC_BINARIES_SEED_HASH}|g" \
-e "s|@GUILE_I686_SEED_HASH@|${GUILE_I686_SEED_HASH}|g" \
-e "s|@GUILE_X86_64_SEED_HASH@|${GUILE_X86_64_SEED_HASH}|g" \
-e "s|@MES_MINIMAL_SEED_HASH@|${MES_MINIMAL_SEED_HASH}|g" \
-e "s|@MESCC_TOOLS_SEED_HASH@|${MESCC_TOOLS_SEED_HASH}|g" \
"${patch_template}" > "${rendered_patch}"
sed \
-e "s|@MES_MINIMAL_SEED_HASH@|${MES_MINIMAL_SEED_HASH}|g" \
-e "s|@MESCC_TOOLS_SEED_HASH@|${MESCC_TOOLS_SEED_HASH}|g" \
"${mes_patch_template}" > "${rendered_mes_patch}"
patch -p1 < "${rendered_patch}"
patch -p1 < "${rendered_mes_patch}"
autoreconf -fi
}
probe_guile_module() {
local module_name debug_log
local guile_site_path guile_site_ccache guile_core_ccache guile_ext_path
local pkg_config_path probe_label probe_pkg_config probe_expression
local find_name find_module
module_name="$1"
debug_log="/tmp/${module_name}-guile-probe.log"
pkg_config_path="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig:${PREFIX}/share/pkgconfig"
guile_site_path="${PREFIX}/share/guile/site/3.0:${PREFIX}/share/guile/3.0"
guile_site_ccache="${LIBDIR}/guile/3.0/site-ccache"
guile_core_ccache="${LIBDIR}/guile/3.0/ccache"
guile_ext_path="${LIBDIR}/guile/3.0/extensions"
case "${module_name}" in
git)
probe_label="git-related"
probe_pkg_config="libgit2"
find_name='libguile-git*'
find_module='git'
probe_expression="(use-modules (git)) (display \"git-module-ok\\n\")"
;;
gnutls)
probe_label="gnutls-related"
probe_pkg_config="gnutls"
find_name='libguile-gnutls*'
find_module='gnutls'
probe_expression="(use-modules (gnutls)) (if (module-variable (resolve-module '(gnutls)) 'make-session) (display \"gnutls-module-ok\\n\") (begin (display \"gnutls-make-session-missing\\n\") (exit 1)))"
;;
*)
probe_label="${module_name}-related"
probe_pkg_config=""
find_name="*${module_name}*"
find_module="${module_name}"
probe_expression="(use-modules (${module_name})) (display \"${module_name}-module-ok\\n\")"
;;
esac
rm -f "${debug_log}"
echo "guix: probing (${module_name}) before configure" >&2
echo "guix: GUILE_LOAD_PATH=${guile_site_path}" >&2
echo "guix: GUILE_LOAD_COMPILED_PATH=${guile_site_ccache}:${guile_core_ccache}" >&2
echo "guix: GUILE_EXTENSIONS_PATH=${guile_ext_path}" >&2
if [ -n "${probe_pkg_config}" ]; then
echo "guix: ${probe_pkg_config} pkg-config libs=$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" /usr/bin/pkg-config --libs "${probe_pkg_config}")" >&2
echo "guix: ${probe_pkg_config} pkg-config static-libs=$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" /usr/bin/pkg-config --static --libs "${probe_pkg_config}")" >&2
fi
if command -v find >/dev/null 2>&1; then
echo "guix: installed Guile ${probe_label} files:" >&2
find "${PREFIX}/share/guile" "${LIBDIR}/guile" -type f \
\( -path "*/${find_module}/*.scm" -o -path "*/${find_module}.scm" -o -path "*/${find_module}/*.go" -o -path "*/${find_module}.go" -o -name "${find_name}" \) \
2>/dev/null | LC_ALL=C sort >&2 || true
fi
if ! PATH="${PREFIX}/bin:/usr/bin:/bin" \
PKG_CONFIG="/usr/bin/pkg-config" \
PKG_CONFIG_LIBDIR="${pkg_config_path}" \
PKG_CONFIG_PATH="${pkg_config_path}" \
LD_LIBRARY_PATH="${LIBDIR}:${PREFIX}/lib:${LD_LIBRARY_PATH}" \
GUILE_LOAD_PATH="${guile_site_path}" \
GUILE_LOAD_COMPILED_PATH="${guile_site_ccache}:${guile_core_ccache}" \
GUILE_SYSTEM_PATH="${guile_site_path}" \
GUILE_SYSTEM_COMPILED_PATH="${guile_site_ccache}:${guile_core_ccache}" \
GUILE_EXTENSIONS_PATH="${guile_ext_path}" \
GNUTLS_GUILE_EXTENSION_DIR="${guile_ext_path}" \
"${PREFIX}/bin/guile" -c "${probe_expression}" \
>"${debug_log}" 2>&1; then
echo "guix: explicit (${module_name}) probe failed; raw Guile output follows:" >&2
cat "${debug_log}" >&2 || true
false
fi
}
src_configure() {
local host_triplet pkg_config_path guile_cflags guile_libs
local argp_cppflags argp_ldflags
local guile_site_path guile_site_ccache guile_core_ccache guile_ext_path
host_triplet="$(gcc -dumpmachine)"
pkg_config_path="${LIBDIR}/pkgconfig:${PREFIX}/lib/pkgconfig:${PREFIX}/share/pkgconfig"
guile_site_path="${PREFIX}/share/guile/site/3.0:${PREFIX}/share/guile/3.0"
guile_site_ccache="${LIBDIR}/guile/3.0/site-ccache"
guile_core_ccache="${LIBDIR}/guile/3.0/ccache"
guile_ext_path="${LIBDIR}/guile/3.0/extensions"
argp_cppflags="-I${KERNEL_SYSROOT}/include"
argp_ldflags="-L${KERNEL_SYSROOT}/lib"
guile_cflags="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --cflags guile-3.0)"
# Guix runtime loads Guile extensions such as guile-gnutls dynamically.
# Link against the shared libguile so those extensions reuse one runtime.
guile_libs="$(PKG_CONFIG_LIBDIR="${pkg_config_path}" PKG_CONFIG_PATH="${pkg_config_path}" \
/usr/bin/pkg-config --libs guile-3.0)"
probe_guile_module gnutls
probe_guile_module git
probe_guile_module zlib
probe_guile_module lzlib
probe_guile_module semver
export GC_RETRY_SIGNALS=0
PATH="${PREFIX}/bin:/usr/bin:/bin" \
PKG_CONFIG="/usr/bin/pkg-config" \
PKG_CONFIG_LIBDIR="${pkg_config_path}" \
PKG_CONFIG_PATH="${pkg_config_path}" \
LD_LIBRARY_PATH="${LIBDIR}:${PREFIX}/lib:${LD_LIBRARY_PATH}" \
GUILE_LOAD_PATH="${guile_site_path}" \
GUILE_LOAD_COMPILED_PATH="${guile_site_ccache}:${guile_core_ccache}" \
GUILE_SYSTEM_PATH="${guile_site_path}" \
GUILE_SYSTEM_COMPILED_PATH="${guile_site_ccache}:${guile_core_ccache}" \
GUILE_EXTENSIONS_PATH="${guile_ext_path}" \
GNUTLS_GUILE_EXTENSION_DIR="${guile_ext_path}" \
GUILE_CFLAGS="${guile_cflags}" \
GUILE_LIBS="${guile_libs}" \
CPPFLAGS="${argp_cppflags} ${CPPFLAGS:-}" \
LDFLAGS="${argp_ldflags} ${LDFLAGS:-}" \
LIBS="${LIBS:-} -largp" \
./configure \
--prefix="${PREFIX}" \
--libdir="${LIBDIR}" \
--sysconfdir=/etc \
--localstatedir=/var \
--host="${host_triplet}" \
--build="${host_triplet}"
}
src_compile() {
default_src_compile
}
src_install() {
default_src_install
}

View file

@ -0,0 +1,57 @@
--- a/gnu/packages/bootstrap.scm
+++ b/gnu/packages/bootstrap.scm
@@ -676,7 +676,45 @@
(substitute* '("bin/egrep" "bin/fgrep")
(("^exec grep") (string-append (getcwd) "/bin/grep"))))
(chmod "bin" #o555))))
+
+
+(define (bootstrap-mes-minimal-origin system)
+ (origin
+ (method url-fetch)
+ (uri (map (cut string-append <>
+ "/mes-minimal-stripped-0.19-i686-linux.tar.xz")
+ %bootstrap-base-urls))
+ (sha256
+ (match system
+ ((or "i686-linux" "x86_64-linux")
+ (base32 "@MES_MINIMAL_SEED_HASH@"))
+ (_
+ (base32 "@MES_MINIMAL_SEED_HASH@"))))))
+
+(define %bootstrap-mes-minimal
+ (package-from-tarball "mes-minimal-bootstrap"
+ bootstrap-mes-minimal-origin
+ "mes"
+ "Bootstrap Mes minimal binary seed"))
+
+(define (bootstrap-mescc-tools-origin system)
+ (origin
+ (method url-fetch)
+ (uri (map (cut string-append <>
+ "/mescc-tools-static-stripped-0.5.2-i686-linux.tar.xz")
+ %bootstrap-base-urls))
+ (sha256
+ (match system
+ ((or "i686-linux" "x86_64-linux")
+ (base32 "@MESCC_TOOLS_SEED_HASH@"))
+ (_
+ (base32 "@MESCC_TOOLS_SEED_HASH@"))))))
+(define %bootstrap-mescc-tools
+ (package-from-tarball "mescc-tools-bootstrap"
+ bootstrap-mescc-tools-origin
+ "M2-Planet"
+ "Bootstrap MesCC tools binary seed"))
(define-public %bootstrap-linux-libre-headers
(package-from-tarball
"linux-libre-headers-bootstrap"
@@ -1012,6 +1050,8 @@
("gcc" ,%bootstrap-gcc)
("binutils" ,%bootstrap-binutils)
("coreutils&co" ,%bootstrap-coreutils&co)
+ ("mes-minimal" ,%bootstrap-mes-minimal)
+ ("mescc-tools" ,%bootstrap-mescc-tools)
("bash" ,%bootstrap-coreutils&co)))
;;; bootstrap.scm ends here

View file

@ -0,0 +1,101 @@
--- a/gnu/packages/bootstrap.scm
+++ b/gnu/packages/bootstrap.scm
@@ -109,13 +109,13 @@
,(base32 "1cqqavghjfr0iwxqf61lrssv27wfigysgq2rs4rm1gkmn04yn1k3")))
("i686-linux"
("bash"
- ,(base32 "0rjaxyzjdllfkf1abczvgaf3cdcc7mmahyvdbkjmjzhgz92pv23g"))
+ ,(base32 "@EXEC_BASH_HASH@"))
("mkdir"
- ,(base32 "133ybmfpkmsnysrzbngwvbysqnsmfi8is8zifs7i7n6n600h4s1w"))
+ ,(base32 "@EXEC_MKDIR_HASH@"))
("tar"
- ,(base32 "07830bx29ad5i0l1ykj0g0b1jayjdblf01sr3ww9wbnwdbzinqms"))
+ ,(base32 "@EXEC_TAR_HASH@"))
("xz"
- ,(base32 "0i9kxdi17bm5gxfi2xzm0y73p3ii0cqxli1sbljm6rh2fjgyn90k")))
+ ,(base32 "@EXEC_XZ_HASH@")))
("i586-gnu"
("bash"
,(base32 "1as8649aqaibahhhrvkj10ci8shpi4hq5n7gnik8rhhy0dc1jarg"))
@@ -164,15 +164,12 @@
(define %bootstrap-executable-base-urls
;; This is where the bootstrap executables come from.
- '("https://ftpmirror.gnu.org/guix/bootstrap/"
- "https://git.savannah.gnu.org/cgit/guix.git/plain/gnu/packages/bootstrap/"
- "https://alpha.gnu.org/gnu/guix/bootstrap/"
- "http://flashner.co.il/guix/bootstrap/"
- "http://lilypond.org/janneke/guix/"))
+ '("http://127.0.0.1:38445/"))
(define (bootstrap-executable-file-name system program)
"Return the FILE-NAME part of url where PROGRAM can be found for SYSTEM."
(match system
+ ("i686-linux" (string-append "i686-linux/bootstrap-exec-" program "-i686-linux"))
("powerpc64le-linux" (string-append system "/20210106/" program))
("i586-gnu" (string-append system "/20200326/" program))
("x86_64-gnu" (string-append system "/20241122/" program))
@@ -403,9 +400,9 @@
"Return the SHA256 hash of the Guile bootstrap tarball for SYSTEM."
(match system
("x86_64-linux"
- (base32 "1w2p5zyrglzzniqgvyn1b55vprfzhgk8vzbzkkbdgl5248si0yq3"))
+ (base32 "@GUILE_X86_64_SEED_HASH@"))
("i686-linux"
- (base32 "0im800m30abgh7msh331pcbjvb4n02smz5cfzf1srv0kpx3csmxp"))
+ (base32 "@GUILE_I686_SEED_HASH@"))
("mips64el-linux"
(base32 "0fzp93lvi0hn54acc0fpvhc7bvl0yc853k62l958cihk03q80ilr"))
("armhf-linux"
@@ -634,16 +631,16 @@
("riscv64-linux"
"/20210725/static-binaries.tar.xz")
(_
- "/20131110/static-binaries.tar.xz")))
+ "/static-binaries-0-i686-linux.tar.xz")))
%bootstrap-base-urls))
(sha256
(match system
("x86_64-linux"
(base32
- "0c533p9dhczzcsa1117gmfq3pc8w362g4mx84ik36srpr7cx2bg4"))
+ "@STATIC_BINARIES_SEED_HASH@"))
("i686-linux"
(base32
- "0s5b3jb315n13m1k8095l0a5hfrsz8g0fv1b6riyc5hnxqyphlak"))
+ "@STATIC_BINARIES_SEED_HASH@"))
("armhf-linux"
(base32
"0gf0fn2kbpxkjixkmx5f4z6hv6qpmgixl69zgg74dbsfdfj8jdv5"))
@@ -998,12 +995,16 @@
;; own packages.
(match (%current-system)
((or "i686-linux" "x86_64-linux")
- `(("linux-libre-headers" ,%bootstrap-linux-libre-headers)))
+ `(("linux-libre-headers" ,%bootstrap-linux-libre-headers)
+ ("mes-minimal" ,%bootstrap-mes-minimal)
+ ("mescc-tools" ,%bootstrap-mescc-tools)))
(_
`(("libc" ,%bootstrap-glibc)
("gcc" ,%bootstrap-gcc)
("binutils" ,%bootstrap-binutils)
("coreutils&co" ,%bootstrap-coreutils&co)
+ ("mes-minimal" ,%bootstrap-mes-minimal)
+ ("mescc-tools" ,%bootstrap-mescc-tools)
;; In gnu-build-system.scm, we rely on the availability of Bash.
("bash" ,%bootstrap-coreutils&co)))))
--- a/guix/channels.scm
+++ b/guix/channels.scm
@@ -194,8 +194,8 @@
(introduction %guix-channel-introduction)))
(define %default-channels
- ;; Default list of channels.
- (list %default-guix-channel))
+ ;; Offline bootstrap environment: require explicit channels.
+ '())
(define (guix-channel? channel)
"Return true if CHANNEL is the 'guix' channel."

View file

@ -0,0 +1,270 @@
diff --git guix-1.5.0/gnu/packages/commencement.scm guix-1.5.0/gnu/packages/commencement.scm
index 852fa2d..2dfb6a3 100644
--- guix-1.5.0/gnu/packages/commencement.scm
+++ guix-1.5.0/gnu/packages/commencement.scm
@@ -1225,21 +1225,43 @@ ac_cv_c_float_format='IEEE (little-endian)'
("libc" ,glibc-mesboot0)
,@(alist-delete "gcc" (%boot-mesboot-core-inputs))))
-(define binutils-mesboot1
+(define (mesboot0-package name inputs pkg)
(package
- (inherit binutils-mesboot0)
- (name "binutils-mesboot1")
- (native-inputs (%boot-mesboot0-inputs))
+ (inherit pkg)
+ (name name)
+ (source (bootstrap-origin (package-source pkg)))
+ (native-inputs (inputs))
+ (supported-systems '("i686-linux" "x86_64-linux"))
+ (inputs '())
+ (propagated-inputs '())
(arguments
- (substitute-keyword-arguments (package-arguments binutils-mesboot0)
- ((#:configure-flags configure-flags)
- #~(let ((out (assoc-ref %outputs "out")))
- `("--disable-nls" "--disable-shared"
- "--disable-werror"
- "--build=i686-unknown-linux-gnu"
- "--host=i686-unknown-linux-gnu"
- "--with-sysroot=/"
- ,(string-append "--prefix=" out))))))))
+ (ensure-keyword-arguments (package-arguments pkg)
+ `(#:implicit-inputs? #f
+ #:guile ,%bootstrap-guile
+ #:tests? #f)))))
+
+;; Build native versions of critical utilities earlier, for performance reasons
+;; It would be great to build xz here, but it requres a newer gcc...
+
+;; Bash provides built-in "test", avoiding guile startup overhead
+(define bash-mesboot0
+ (let ((pkg (mesboot0-package
+ "bash-mesboot0"
+ %boot-mesboot0-inputs
+ static-bash)))
+ (package
+ (inherit pkg)
+ (arguments (substitute-keyword-arguments (package-arguments pkg)
+ ((#:configure-flags flags)
+ #~(cons* "CFLAGS=-g -O2" "LIBS=-lc -lnss_files -lnss_dns -lresolv"
+ (delete
+ "CFLAGS=-g -O2 -Wno-error=implicit-function-declaration"
+ #$flags))))))))
+
+(define (%boot-mesboot0-native0-inputs)
+ `(("bash" ,bash-mesboot0)
+ ,@(fold alist-delete (%boot-mesboot0-inputs)
+ '("bash"))))
(define gnu-make-mesboot
(package
@@ -1253,7 +1275,7 @@ ac_cv_c_float_format='IEEE (little-endian)'
(sha256
(base32
"1rs2f9hmvy3q6zkl15jnlmnpgffm0bhw5ax0h5c7q604wqrip69x"))))
- (native-inputs (%boot-mesboot0-inputs))
+ (native-inputs (%boot-mesboot0-native0-inputs))
(supported-systems '("i686-linux" "x86_64-linux"))
(inputs '())
(propagated-inputs '())
@@ -1273,11 +1295,31 @@ ac_cv_c_float_format='IEEE (little-endian)'
(bin (string-append out "/bin")))
(install-file "make" bin)))))))))
+(define (%boot-mesboot0-native-inputs)
+ `(("make" ,gnu-make-mesboot)
+ ,@(fold alist-delete (%boot-mesboot0-native0-inputs)
+ '("make"))))
+
+(define binutils-mesboot1
+ (package
+ (inherit binutils-mesboot0)
+ (name "binutils-mesboot1")
+ (native-inputs (%boot-mesboot0-native-inputs))
+ (arguments
+ (substitute-keyword-arguments (package-arguments binutils-mesboot0)
+ ((#:configure-flags configure-flags)
+ #~(let ((out (assoc-ref %outputs "out")))
+ `("--disable-nls" "--disable-shared"
+ "--disable-werror"
+ "--build=i686-unknown-linux-gnu"
+ "--host=i686-unknown-linux-gnu"
+ "--with-sysroot=/"
+ ,(string-append "--prefix=" out))))))))
+
(define (%boot-mesboot1-inputs)
`(("binutils" ,binutils-mesboot1)
- ("make" ,gnu-make-mesboot)
- ,@(fold alist-delete (%boot-mesboot0-inputs)
- '("binutils" "make"))))
+ ,@(fold alist-delete (%boot-mesboot0-native-inputs)
+ '("binutils"))))
(define gmp-boot
(let ((version "4.3.2"))
@@ -1467,7 +1509,7 @@ ac_cv_c_float_format='IEEE (little-endian)'
;; libstdc++ is being compiled.
(setenv "CPLUS_INCLUDE_PATH" (getenv "C_INCLUDE_PATH"))))))))))
-(define (%boot-mesboot2-inputs)
+(define (%boot-mesboot2-bootar-inputs)
`(("gcc" ,gcc-mesboot1)
,@(alist-delete "gcc" (%boot-mesboot1-inputs))))
@@ -1490,7 +1532,7 @@ ac_cv_c_float_format='IEEE (little-endian)'
(supported-systems '("i686-linux" "x86_64-linux"))
(inputs '())
(propagated-inputs '())
- (native-inputs (%boot-mesboot2-inputs))
+ (native-inputs (%boot-mesboot2-bootar-inputs))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
@@ -1504,6 +1546,119 @@ ac_cv_c_float_format='IEEE (little-endian)'
(lambda _
(invoke "./hello"))))))))
+;; Now, that we have GCC 4.6, we can finally build xz.
+(define xz-mesboot0
+ (let ((pkg (mesboot0-package "xz-mesboot0" %boot-mesboot2-bootar-inputs xz)))
+ (package
+ (inherit pkg)
+ (arguments
+ (ensure-keyword-arguments (package-arguments pkg)
+ ;; XXX: This fails even though the
+ ;; actual runpaths seem fine.
+ `(#:validate-runpath? #f
+ ;; XXX: The build gets stuck
+ ;; when parallel build is enabled.
+ #:parallel-build? #f
+ #:configure-flags (list
+ ;; static build
+ "--enable-static"
+ "--disable-shared"
+ ;; missing pthread.h
+ "--enable-threads=no"
+ ;; extern inlines broken
+ "CFLAGS=-g -O2 -fgnu89-inline")))))))
+
+;; Tar doesn't build at this stage, so teach gash-utils tar to use xz using a wrapper
+(define gash-utils-tar-wrapper
+ ;; Wrapper around gash-utils tar that extracts xz files using xz-mesboot0
+ ;; before passing them on to tar.
+ (package
+ (inherit gash-utils-boot)
+ (name "gash-utils-tar-wrapper")
+ (source #f)
+ (inputs '())
+ (native-inputs `(("bash" ,bash-mesboot0)
+ ("coreutils" ,gash-utils-boot)
+ ("gzip" ,gzip-mesboot)
+ ("xz" ,xz-mesboot0)))
+ (arguments
+ `(#:implicit-inputs? #f
+ #:guile ,%bootstrap-guile
+ #:phases
+ (modify-phases %standard-phases
+ (delete 'unpack)
+ (delete 'configure)
+ (delete 'install)
+ (replace 'build
+ (lambda* (#:key outputs #:allow-other-keys)
+ (let* ((out (assoc-ref outputs "out"))
+ (bash (assoc-ref %build-inputs "bash"))
+ (coreutils (assoc-ref %build-inputs "coreutils"))
+ (xz (assoc-ref %build-inputs "xz"))
+ (gzip (assoc-ref %build-inputs "gzip"))
+ (bin (string-append out "/bin")))
+ (mkdir-p bin)
+ (for-each
+ (lambda (program)
+ (let ((wrapper (string-append bin "/" program)))
+ (with-output-to-file wrapper
+ (lambda _
+ (display (string-append "#!" bash "/bin/bash
+
+# Check if file is GZIP or XZ compressed
+if [[ \"$#\" -eq 2 && \"$1\" = xvf && \"$2\" = *.tar.xz ]]; then
+ # Decompress using xz to temporary file
+ if ! " xz "/bin/xz -dc -- \"$2\" > /tmp/tar_wrapper.tar; then
+ echo \"Error: failed to decompress $2\" >&2
+ rm -f /tmp/tar_wrapper.tar
+ exit 1
+ fi
+
+ # Extract using gash-utils tar
+ " coreutils "/bin/tar \"$1\" /tmp/tar_wrapper.tar
+ status=$?
+
+ # Clean up
+ rm -f /tmp/tar_wrapper.tar
+
+ exit $status
+elif [[ \"$#\" -eq 2 && \"$1\" = xvf && \"$2\" = *.tar.gz ]]; then
+ # Decompress using gzip to temporary file
+ if ! " gzip "/bin/gzip -dc \"$2\" > /tmp/tar_wrapper.tar; then
+ echo \"Error: failed to decompress $2\" >&2
+ rm -f /tmp/tar_wrapper.tar
+ exit 1
+ fi
+
+ # Extract using gash-utils tar
+ " coreutils "/bin/tar \"$1\" /tmp/tar_wrapper.tar
+ status=$?
+
+ # Clean up
+ rm -f /tmp/tar_wrapper.tar
+
+ exit $status
+else
+ # Fall back to direct gash-utils tar call
+ exec " coreutils "/bin/tar \"$@\"
+fi
+"))
+ (chmod wrapper #o555)))))
+ '("tar")))))
+ (replace 'check
+ (lambda* (#:key outputs #:allow-other-keys)
+ (let* ((bash (assoc-ref %build-inputs "bash"))
+ (bin (string-append bash "/bin"))
+ (program (string-append bin "/bash")))
+ (invoke program "--help")))))))))
+
+(define (%boot-mesboot2-inputs)
+ `(("xz" ,xz-mesboot0)
+ ("tar" ,gash-utils-tar-wrapper)
+ ;; we can drop bootar here; gzip + xz + gash-utils tar is enough to proceed
+ ,@(fold alist-delete (%boot-mesboot2-bootar-inputs)
+ '("bootar"))))
+
(define binutils-mesboot
(package
(inherit binutils-mesboot1)
@@ -1709,7 +1864,7 @@ SHELL := " shell "
(name "gcc-mesboot1-wrapper")
(source #f)
(inputs '())
- (native-inputs `(("bash" ,gash-boot)
+ (native-inputs `(("bash" ,bash-mesboot0)
("coreutils" ,gash-utils-boot)
("libc" ,glibc-mesboot)
("gcc" ,gcc-mesboot1)))
@@ -1848,7 +2003,7 @@ exec " gcc "/bin/" program
(version (package-version gcc-mesboot))
(source #f)
(inputs '())
- (native-inputs `(("bash" ,gash-boot)
+ (native-inputs `(("bash" ,bash-mesboot0)
("coreutils" ,gash-utils-boot)
("libc" ,glibc-mesboot)
("gcc" ,gcc-mesboot)))))
@@ -1966,7 +2121,7 @@ exec " gcc "/bin/" program
("tar" ,tar-mesboot)
("xz" ,xz-mesboot)
,@(fold alist-delete (%boot-mesboot5-inputs)
- '("bash" "coreutils" "bootar" "kernel-headers"))))
+ '("bash" "coreutils" "tar" "kernel-headers"))))
(define (%bootstrap-inputs+toolchain)
;; The traditional bootstrap-inputs. For the i686-linux, x86_64-linux

View file

@ -0,0 +1,13 @@
--- guix-1.5.0/gnu/packages/commencement.scm
+++ guix-1.5.0/gnu/packages/commencement.scm
@@ -3571,6 +3571,10 @@
("patch" ,patch/pinned)
("findutils" ,findutils)
("gawk" ,(package/inherit gawk
+ (arguments
+ (substitute-keyword-arguments
+ (package-arguments gawk)
+ ((#:tests? _ #f) #f)))
(native-inputs
(list (if (target-hurd?)
glibc-utf8-locales-final/hurd

View file

@ -0,0 +1,22 @@
diff --git guix-1.5.0/guix/channels.scm guix-1.5.0/guix/channels.scm
index 0d7bc541ccc..879dde1c00e 100644
--- guix-1.5.0/guix/channels.scm
+++ guix-1.5.0/guix/channels.scm
@@ -511,7 +511,7 @@ information."
(define* (latest-channel-instances store channels
#:key
(current-channels '())
- (authenticate? #t)
+ (authenticate? #f)
(validate-pull
ensure-forward-channel-update)
(verify-certificate? #t))
@@ -570,7 +570,7 @@ depending on the policy it implements."
(instance
(latest-channel-instance store channel
#:authenticate?
- authenticate?
+ #f ; authenticate?
#:validate-pull
validate-pull
#:starting-commit

View file

@ -0,0 +1,45 @@
--- guix-1.5.0/gnu/packages/bootstrap.scm
+++ guix-1.5.0/gnu/packages/bootstrap.scm
@@ -357,8 +357,9 @@
;;; Bootstrap packages.
;;;
-(define %bootstrap-base-urls
- ;; This is where the initial binaries come from.
+(define %bootstrap-linux-headers-base-urls
+ ;; Keep linux headers as an explicit exception: text headers can still come
+ ;; from the historical bootstrap mirrors.
'("https://ftpmirror.gnu.org/guix/bootstrap/"
"https://ftp.gnu.org/gnu/guix/bootstrap"
"https://alpha.gnu.org/gnu/guix/bootstrap"
@@ -369,6 +370,10 @@
"http://flashner.co.il/guix/bootstrap"
"http://lilypond.org/janneke/guix/"))
+(define %bootstrap-base-urls
+ ;; All bootstrap binaries must come from the local bootstrap mirror.
+ '("http://127.0.0.1:38445"))
+
(define (bootstrap-guile-url-path system)
"Return the URI for FILE."
(string-append "/" system
@@ -387,6 +392,10 @@
"/20210106/guile-static-stripped-2.0.14-powerpc64le-linux-gnu.tar.xz")
("riscv64-linux"
"/20210725/guile-3.0.2.tar.xz")
+ ("x86_64-linux"
+ "/guile-static-stripped-2.0.9-x86_64-linux.tar.xz")
+ ("i686-linux"
+ "/guile-static-stripped-2.0.9-i686-linux.tar.xz")
(_
"/20131110/guile-2.0.9.tar.xz"))))
@@ -684,7 +693,7 @@
(uri (map (cute string-append <>
"/i686-linux/20190815/"
"linux-libre-headers-stripped-4.14.67-i686-linux.tar.xz")
- %bootstrap-base-urls))
+ %bootstrap-linux-headers-base-urls))
(sha256
(base32
"0sm2z9x4wk45bh6qfs94p0w1d6hsy6dqx9sw38qsqbvxwa1qzk8s"))))

View file

@ -0,0 +1,14 @@
--- guix-1.5.0/m4/guix.m4
+++ guix-1.5.0/m4/guix.m4
@@ -207,8 +207,9 @@
[guix_cv_have_recent_guile_gcrypt],
[GUILE_CHECK([retval],
[(use-modules (gcrypt hash))
- (equal? (hash-algorithm sha256)
- (lookup-hash-algorithm 'sha256))])
+ (let ((algorithm (lookup-hash-algorithm 'sha256)))
+ (and algorithm
+ (= 32 (hash-size algorithm))))])
if test "$retval" = 0; then
guix_cv_have_recent_guile_gcrypt="yes"
else

View file

@ -0,0 +1,11 @@
--- guix-1.5.0/guix/build/gnu-build-system.scm
+++ guix-1.5.0/guix/build/gnu-build-system.scm
@@ -985,7 +985,7 @@
;; Dump the environment variables as a shell script,
;; for handy debugging.
- (system "export > $NIX_BUILD_TOP/environment-variables")))
+ ))
(format #t "starting phase `~a'~%" name)
(with-throw-handler #t

View file

@ -0,0 +1,19 @@
--- guix-1.5.0/gnu/packages/boost.scm
+++ guix-1.5.0/gnu/packages/boost.scm
@@ -247,9 +247,13 @@ across a broad spectrum of applications.")
version "/source/boost_"
(version-with-underscores version) ".tar.bz2"))
(patches
- (list (boost-patch
- "0001-unordered-fix-copy-assign.patch" version
- "09j61m5xh7099k5na9i43x5rra51znf7vm2nyh89yqpizcll9q66")))
+ (list (origin
+ (method url-fetch)
+ (uri "http://127.0.0.1:38445/0001-unordered-fix-copy-assign.patch")
+ (file-name "boost-0001-unordered-fix-copy-assign.patch")
+ (sha256
+ (base32
+ "09j61m5xh7099k5na9i43x5rra51znf7vm2nyh89yqpizcll9q66")))))
(patch-flags '("-p2"))
(sha256
(base32

View file

@ -0,0 +1,17 @@
--- a/gnu/packages/package-management.scm
+++ b/gnu/packages/package-management.scm
@@ -211,11 +211,11 @@
(source (origin
(method git-fetch)
(uri (git-reference
- (url "https://git.guix.gnu.org/guix.git")
- (commit commit)))
+ (url "@LOCAL_GUIX_CHECKOUT_URL@")
+ (commit "@LOCAL_GUIX_CHECKOUT_COMMIT@")))
(sha256
(base32
- "0z1ixlkzsaj978nh57179871xkzbf8zsf10xkcfs2647iznkx7az"))
+ "@LOCAL_GUIX_CHECKOUT_HASH@"))
(file-name (string-append "guix-" version "-checkout"))))
(build-system gnu-build-system)
(arguments

View file

@ -0,0 +1 @@
f https://ftpmirror.gnu.org/gnu/guix/guix-1.5.0.tar.gz df2102eed00aff0b17275654a42f094c8a1117ec065884eb1ff76005e47415c5

View file

@ -0,0 +1,570 @@
#define _POSIX_C_SOURCE 200809L
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define SHA256_BLOCK_SIZE 32
struct sha256_ctx {
uint8_t data[64];
uint32_t datalen;
uint64_t bitlen;
uint32_t state[8];
};
static const uint32_t k256[64] = {
0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U,
0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U,
0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U,
0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U,
0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU,
0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU,
0x983e5152U, 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U,
0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U,
0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU, 0x53380d13U,
0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,
0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U,
0xd192e819U, 0xd6990624U, 0xf40e3585U, 0x106aa070U,
0x19a4c116U, 0x1e376c08U, 0x2748774cU, 0x34b0bcb5U,
0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU, 0x682e6ff3U,
0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U,
0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U
};
#define ROTRIGHT(a, b) (((a) >> (b)) | ((a) << (32 - (b))))
#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define EP0(x) (ROTRIGHT((x), 2) ^ ROTRIGHT((x), 13) ^ ROTRIGHT((x), 22))
#define EP1(x) (ROTRIGHT((x), 6) ^ ROTRIGHT((x), 11) ^ ROTRIGHT((x), 25))
#define SIG0(x) (ROTRIGHT((x), 7) ^ ROTRIGHT((x), 18) ^ ((x) >> 3))
#define SIG1(x) (ROTRIGHT((x), 17) ^ ROTRIGHT((x), 19) ^ ((x) >> 10))
static void sha256_transform(struct sha256_ctx *ctx, const uint8_t data[]) {
uint32_t a, b, c, d, e, f, g, h;
uint32_t t1, t2, m[64];
uint32_t i;
for (i = 0; i < 16; ++i) {
m[i] = ((uint32_t)data[i * 4] << 24) |
((uint32_t)data[i * 4 + 1] << 16) |
((uint32_t)data[i * 4 + 2] << 8) |
((uint32_t)data[i * 4 + 3]);
}
for (; i < 64; ++i) {
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
}
a = ctx->state[0];
b = ctx->state[1];
c = ctx->state[2];
d = ctx->state[3];
e = ctx->state[4];
f = ctx->state[5];
g = ctx->state[6];
h = ctx->state[7];
for (i = 0; i < 64; ++i) {
t1 = h + EP1(e) + CH(e, f, g) + k256[i] + m[i];
t2 = EP0(a) + MAJ(a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
ctx->state[0] += a;
ctx->state[1] += b;
ctx->state[2] += c;
ctx->state[3] += d;
ctx->state[4] += e;
ctx->state[5] += f;
ctx->state[6] += g;
ctx->state[7] += h;
}
static void sha256_init(struct sha256_ctx *ctx) {
ctx->datalen = 0;
ctx->bitlen = 0;
ctx->state[0] = 0x6a09e667U;
ctx->state[1] = 0xbb67ae85U;
ctx->state[2] = 0x3c6ef372U;
ctx->state[3] = 0xa54ff53aU;
ctx->state[4] = 0x510e527fU;
ctx->state[5] = 0x9b05688cU;
ctx->state[6] = 0x1f83d9abU;
ctx->state[7] = 0x5be0cd19U;
}
static void sha256_update(struct sha256_ctx *ctx, const uint8_t *data, size_t len) {
size_t i;
for (i = 0; i < len; ++i) {
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen == 64) {
sha256_transform(ctx, ctx->data);
ctx->bitlen += 512;
ctx->datalen = 0;
}
}
}
static void sha256_final(struct sha256_ctx *ctx, uint8_t hash[SHA256_BLOCK_SIZE]) {
uint32_t i;
i = ctx->datalen;
if (ctx->datalen < 56) {
ctx->data[i++] = 0x80;
while (i < 56) {
ctx->data[i++] = 0;
}
} else {
ctx->data[i++] = 0x80;
while (i < 64) {
ctx->data[i++] = 0;
}
sha256_transform(ctx, ctx->data);
memset(ctx->data, 0, 56);
}
ctx->bitlen += (uint64_t)ctx->datalen * 8;
ctx->data[63] = (uint8_t)(ctx->bitlen);
ctx->data[62] = (uint8_t)(ctx->bitlen >> 8);
ctx->data[61] = (uint8_t)(ctx->bitlen >> 16);
ctx->data[60] = (uint8_t)(ctx->bitlen >> 24);
ctx->data[59] = (uint8_t)(ctx->bitlen >> 32);
ctx->data[58] = (uint8_t)(ctx->bitlen >> 40);
ctx->data[57] = (uint8_t)(ctx->bitlen >> 48);
ctx->data[56] = (uint8_t)(ctx->bitlen >> 56);
sha256_transform(ctx, ctx->data);
for (i = 0; i < 4; ++i) {
hash[i] = (uint8_t)((ctx->state[0] >> (24 - i * 8)) & 0xff);
hash[i + 4] = (uint8_t)((ctx->state[1] >> (24 - i * 8)) & 0xff);
hash[i + 8] = (uint8_t)((ctx->state[2] >> (24 - i * 8)) & 0xff);
hash[i + 12] = (uint8_t)((ctx->state[3] >> (24 - i * 8)) & 0xff);
hash[i + 16] = (uint8_t)((ctx->state[4] >> (24 - i * 8)) & 0xff);
hash[i + 20] = (uint8_t)((ctx->state[5] >> (24 - i * 8)) & 0xff);
hash[i + 24] = (uint8_t)((ctx->state[6] >> (24 - i * 8)) & 0xff);
hash[i + 28] = (uint8_t)((ctx->state[7] >> (24 - i * 8)) & 0xff);
}
}
static void die_perror(const char *msg) {
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(1);
}
static void die_msg(const char *msg) {
fprintf(stderr, "%s\n", msg);
exit(1);
}
static void sha_update_u32le_in_8(struct sha256_ctx *ctx, uint32_t n) {
uint8_t b[8] = {0, 0, 0, 0, 0, 0, 0, 0};
b[0] = (uint8_t)(n & 0xffU);
b[1] = (uint8_t)((n >> 8) & 0xffU);
b[2] = (uint8_t)((n >> 16) & 0xffU);
b[3] = (uint8_t)((n >> 24) & 0xffU);
sha256_update(ctx, b, sizeof(b));
}
static void sha_update_u64le(struct sha256_ctx *ctx, uint64_t n) {
uint8_t b[8];
b[0] = (uint8_t)(n & 0xffU);
b[1] = (uint8_t)((n >> 8) & 0xffU);
b[2] = (uint8_t)((n >> 16) & 0xffU);
b[3] = (uint8_t)((n >> 24) & 0xffU);
b[4] = (uint8_t)((n >> 32) & 0xffU);
b[5] = (uint8_t)((n >> 40) & 0xffU);
b[6] = (uint8_t)((n >> 48) & 0xffU);
b[7] = (uint8_t)((n >> 56) & 0xffU);
sha256_update(ctx, b, sizeof(b));
}
static void nar_write_padding(struct sha256_ctx *ctx, size_t n) {
static const uint8_t zeros[8] = {0, 0, 0, 0, 0, 0, 0, 0};
size_t m = n % 8;
if (m != 0) {
sha256_update(ctx, zeros, 8 - m);
}
}
static void nar_write_string_n(struct sha256_ctx *ctx, const char *s, size_t n) {
if (n > UINT32_MAX) {
die_msg("string too long for NAR serialization");
}
sha_update_u32le_in_8(ctx, (uint32_t)n);
if (n > 0) {
sha256_update(ctx, (const uint8_t *)s, n);
}
nar_write_padding(ctx, n);
}
static void nar_write_string(struct sha256_ctx *ctx, const char *s) {
nar_write_string_n(ctx, s, strlen(s));
}
static void sha_update_from_fd(struct sha256_ctx *ctx, int fd, uint64_t *out_size) {
uint8_t buf[65536];
ssize_t n;
uint64_t total = 0;
for (;;) {
n = read(fd, buf, sizeof(buf));
if (n == 0) {
break;
}
if (n < 0) {
die_perror("read failed");
}
sha256_update(ctx, buf, (size_t)n);
total += (uint64_t)n;
}
if (out_size != NULL) {
*out_size = total;
}
}
static char *join_path(const char *dir, const char *name) {
size_t a = strlen(dir);
size_t b = strlen(name);
int need_slash = (a > 0 && dir[a - 1] != '/');
char *out = malloc(a + (size_t)need_slash + b + 1);
if (out == NULL) {
die_msg("out of memory");
}
memcpy(out, dir, a);
if (need_slash) {
out[a] = '/';
}
memcpy(out + a + (size_t)need_slash, name, b);
out[a + (size_t)need_slash + b] = '\0';
return out;
}
static int cmp_cstring_ptr(const void *a, const void *b) {
const char *const *sa = (const char *const *)a;
const char *const *sb = (const char *const *)b;
return strcmp(*sa, *sb);
}
static void nar_dump_path(struct sha256_ctx *ctx, const char *path);
static void nar_dump_directory(struct sha256_ctx *ctx, const char *path) {
DIR *dir;
struct dirent *de;
char **entries = NULL;
size_t count = 0;
size_t cap = 0;
size_t i;
dir = opendir(path);
if (dir == NULL) {
die_perror("opendir failed");
}
for (;;) {
errno = 0;
de = readdir(dir);
if (de == NULL) {
if (errno != 0) {
closedir(dir);
die_perror("readdir failed");
}
break;
}
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) {
continue;
}
if (count == cap) {
size_t new_cap = (cap == 0) ? 16 : cap * 2;
char **new_entries = realloc(entries, new_cap * sizeof(char *));
if (new_entries == NULL) {
closedir(dir);
die_msg("out of memory");
}
entries = new_entries;
cap = new_cap;
}
entries[count] = strdup(de->d_name);
if (entries[count] == NULL) {
closedir(dir);
die_msg("out of memory");
}
count++;
}
if (closedir(dir) != 0) {
die_perror("closedir failed");
}
qsort(entries, count, sizeof(char *), cmp_cstring_ptr);
nar_write_string(ctx, "(");
nar_write_string(ctx, "type");
nar_write_string(ctx, "directory");
for (i = 0; i < count; ++i) {
char *child = join_path(path, entries[i]);
nar_write_string(ctx, "entry");
nar_write_string(ctx, "(");
nar_write_string(ctx, "name");
nar_write_string(ctx, entries[i]);
nar_write_string(ctx, "node");
nar_dump_path(ctx, child);
nar_write_string(ctx, ")");
free(child);
free(entries[i]);
}
free(entries);
nar_write_string(ctx, ")");
}
static void nar_dump_regular(struct sha256_ctx *ctx, const char *path, mode_t mode) {
int fd;
uint64_t size;
fd = open(path, O_RDONLY);
if (fd < 0) {
die_perror("open failed");
}
nar_write_string(ctx, "(");
nar_write_string(ctx, "type");
nar_write_string(ctx, "regular");
if ((mode & 0100) != 0) {
nar_write_string(ctx, "executable");
nar_write_string(ctx, "");
}
nar_write_string(ctx, "contents");
size = 0;
{
struct stat st;
if (fstat(fd, &st) != 0) {
close(fd);
die_perror("fstat failed");
}
size = (uint64_t)st.st_size;
}
sha_update_u64le(ctx, size);
sha_update_from_fd(ctx, fd, NULL);
nar_write_padding(ctx, (size_t)(size % 8));
if (close(fd) != 0) {
die_perror("close failed");
}
nar_write_string(ctx, ")");
}
static void nar_dump_symlink(struct sha256_ctx *ctx, const char *path) {
ssize_t n;
size_t buf_size = 256;
char *buf = NULL;
for (;;) {
char *new_buf = realloc(buf, buf_size);
if (new_buf == NULL) {
free(buf);
die_msg("out of memory");
}
buf = new_buf;
n = readlink(path, buf, buf_size);
if (n < 0) {
free(buf);
die_perror("readlink failed");
}
if ((size_t)n < buf_size) {
break;
}
buf_size *= 2;
}
nar_write_string(ctx, "(");
nar_write_string(ctx, "type");
nar_write_string(ctx, "symlink");
nar_write_string(ctx, "target");
nar_write_string_n(ctx, buf, (size_t)n);
nar_write_string(ctx, ")");
free(buf);
}
static void nar_dump_path(struct sha256_ctx *ctx, const char *path) {
struct stat st;
if (lstat(path, &st) != 0) {
die_perror("lstat failed");
}
if (S_ISDIR(st.st_mode)) {
nar_dump_directory(ctx, path);
return;
}
if (S_ISREG(st.st_mode)) {
nar_dump_regular(ctx, path, st.st_mode);
return;
}
if (S_ISLNK(st.st_mode)) {
nar_dump_symlink(ctx, path);
return;
}
fprintf(stderr, "unsupported file type: %s\n", path);
exit(1);
}
static void hash_flat_file(const char *path, uint8_t out[SHA256_BLOCK_SIZE]) {
struct sha256_ctx ctx;
int fd;
sha256_init(&ctx);
if (strcmp(path, "-") == 0) {
sha_update_from_fd(&ctx, STDIN_FILENO, NULL);
} else {
fd = open(path, O_RDONLY);
if (fd < 0) {
die_perror("open failed");
}
sha_update_from_fd(&ctx, fd, NULL);
if (close(fd) != 0) {
die_perror("close failed");
}
}
sha256_final(&ctx, out);
}
static void hash_nar_path(const char *path, uint8_t out[SHA256_BLOCK_SIZE]) {
struct sha256_ctx ctx;
sha256_init(&ctx);
nar_write_string(&ctx, "nix-archive-1");
nar_dump_path(&ctx, path);
sha256_final(&ctx, out);
}
static uint8_t bytevector_quintet_ref_right(const uint8_t *bv, size_t bv_len, size_t index) {
size_t offset = (index * 5) / 8;
uint8_t a = (offset < bv_len) ? bv[offset] : 0;
uint8_t b = ((offset + 1) < bv_len) ? bv[offset + 1] : 0;
switch (index % 8) {
case 0:
return a & 0x1fU;
case 1:
return (uint8_t)(((a >> 5) & 0x07U) | ((b & 0x03U) << 3));
case 2:
return (uint8_t)((a >> 2) & 0x1fU);
case 3:
return (uint8_t)(((a >> 7) & 0x01U) | ((b & 0x0fU) << 1));
case 4:
return (uint8_t)(((a >> 4) & 0x0fU) | ((b & 0x01U) << 4));
case 5:
return (uint8_t)((a >> 1) & 0x1fU);
case 6:
return (uint8_t)(((a >> 6) & 0x03U) | ((b & 0x07U) << 2));
case 7:
return (uint8_t)((a >> 3) & 0x1fU);
default:
return 0;
}
}
static void sha256_to_nix_base32(const uint8_t digest[SHA256_BLOCK_SIZE], char out[53]) {
static const char alphabet[] = "0123456789abcdfghijklmnpqrsvwxyz";
const size_t quintets = (SHA256_BLOCK_SIZE * 8 + 4) / 5;
size_t i;
for (i = 0; i < quintets; ++i) {
size_t idx = quintets - 1 - i;
uint8_t q = bytevector_quintet_ref_right(digest, SHA256_BLOCK_SIZE, idx);
out[i] = alphabet[q & 0x1fU];
}
out[quintets] = '\0';
}
static void usage(const char *prog) {
fprintf(stderr,
"Usage: %s [OPTION] FILE\n"
" -r, --recursive hash FILE using NAR serialization\n",
prog);
}
int main(int argc, char **argv) {
int recursive = 0;
int i;
int first_arg = 1;
for (i = 1; i < argc; ++i) {
if (strcmp(argv[i], "--") == 0) {
first_arg = i + 1;
break;
}
if (argv[i][0] != '-') {
first_arg = i;
break;
}
if (strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--recursive") == 0) {
recursive = 1;
continue;
}
if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
usage(argv[0]);
return 0;
}
fprintf(stderr, "unsupported option: %s\n", argv[i]);
usage(argv[0]);
return 1;
}
if (first_arg >= argc) {
fprintf(stderr, "no arguments specified\n");
usage(argv[0]);
return 1;
}
for (i = first_arg; i < argc; ++i) {
uint8_t digest[SHA256_BLOCK_SIZE];
char out[53];
if (recursive) {
hash_nar_path(argv[i], digest);
} else {
hash_flat_file(argv[i], digest);
}
sha256_to_nix_base32(digest, out);
puts(out);
}
return 0;
}

View file

@ -0,0 +1,24 @@
# SPDX-License-Identifier: GPL-3.0-or-later
src_prepare() {
default
}
src_configure() {
:
}
src_compile() {
gcc \
-O2 \
-std=c99 \
-Wall \
-Wextra \
-Werror \
-o guix-hash-compat \
guix-hash-compat.c
}
src_install() {
install -D -m 0755 guix-hash-compat "${DESTDIR}/usr/bin/guix-hash-compat"
}

Some files were not shown because too many files have changed in this diff Show more