Initial commit

This commit is contained in:
jld3103 2021-08-04 18:36:37 +02:00
commit f9ba5a3cfd
14 changed files with 889 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
venv/
__pycache__/

36
Dockerfile Normal file
View file

@ -0,0 +1,36 @@
FROM archlinux:base-devel
RUN pacman -Syu --noconfirm \
python python-pip \
devtools rsync \
aarch64-linux-gnu-gcc aarch64-linux-gnu-binutils aarch64-linux-gnu-glibc aarch64-linux-gnu-linux-api-headers \
git
RUN sed -i "s/EUID == 0/EUID == -1/g" $(which makepkg)
RUN cd /tmp && \
git clone https://aur.archlinux.org/aarch64-linux-gnu-pkg-config.git && \
cd aarch64-linux-gnu-pkg-config && \
makepkg -s --skippgpcheck && \
pacman -U --noconfirm *.pkg*
RUN yes | pacman -Scc
RUN sed -i "s/SigLevel.*/SigLevel = Never/g" /etc/pacman.conf
RUN sed -i "s|run_pacman |run_pacman --root \"/chroot/copy\" --arch aarch64 --config \"/app/src/pacman_copy.conf\" |g" $(which makepkg)
RUN echo "Server = http://mirror.archlinuxarm.org/\$arch/\$repo" > /etc/pacman.d/aarch64_mirrorlist
RUN mkdir -p /app/bin
RUN ln -sf $(which aarch64-linux-gnu-strip) /app/bin/strip
RUN systemd-machine-id-setup
ENV KUPFERBOOTSTRAP_DOCKER=1
WORKDIR /app
ENV PATH=/app/bin:$PATH
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
WORKDIR /src

8
README.md Normal file
View file

@ -0,0 +1,8 @@
# kupferbootstrap
## Install
Install Docker and Python 3 and put `bin/` into your `PATH`.
Then use `kupferbootstrap`.
## Develop
Put `dev` into `version.txt` to always rebuild kupferboostrap from this directory and use `kupferbootstrap` as normal.

4
bin/kupferbootstrap Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
# shellcheck disable=SC2068
python3 "$(dirname "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")/wrapper.py" $@

26
cache.py Normal file
View file

@ -0,0 +1,26 @@
import shutil
from logger import *
import click
import os
@click.group(name='cache')
def cmd_cache():
pass
@click.command(name='clean')
@verbose_option
def cmd_clean(verbose):
setup_logging(verbose)
for dir in ['/chroot', '/var/cache/pacman/pkg']:
for file in os.listdir(dir):
path = os.path.join(dir, file)
if os.path.isdir(path):
shutil.rmtree(path)
else:
os.unlink(path)
cmd_cache.add_command(cmd_clean)

23
logger.py Normal file
View file

@ -0,0 +1,23 @@
import click
import logging
import sys
def setup_logging(verbose: bool):
level = logging.INFO
if verbose:
level = logging.DEBUG
logging.basicConfig(
stream=sys.stdout,
format='%(asctime)s %(levelname)s: %(message)s',
datefmt='%m/%d/%Y %H:%M:%S',
level=level
)
verbose_option = click.option(
'-v',
'--verbose',
is_flag=True,
help='Enables verbose logging'
)

12
main.py Normal file
View file

@ -0,0 +1,12 @@
from packages import cmd_packages
from cache import cmd_cache
import click
@click.group()
def cli():
pass
cli.add_command(cmd_cache)
cli.add_command(cmd_packages)

431
packages.py Normal file
View file

@ -0,0 +1,431 @@
from logger import *
import atexit
import click
import logging
import multiprocessing
import os
import shutil
import subprocess
makepkg_env = os.environ.copy() | {
'LANG': 'C',
'MAKEFLAGS': f'-j{multiprocessing.cpu_count()}',
}
makepkg_cmd = ['makepkg',
'--config', '/app/src/makepkg.conf',
'--noconfirm',
'--ignorearch',
'--needed']
pacman_cmd = ['pacman',
'--noconfirm',
'--overwrite=*',
'--needed', ]
class Package:
names = []
depends = []
local_depends = None
repo = ''
mode = ''
has_pkgver = False
def __init__(self, path: str) -> None:
self.path = path
self._loadinfo()
def _loadinfo(self):
result = subprocess.run(makepkg_cmd+['--printsrcinfo'],
cwd=self.path,
stdout=subprocess.PIPE)
lines = result.stdout.decode('utf-8').split('\n')
names = []
depends = []
for line in lines:
if line.startswith('pkgbase') or line.startswith('\tpkgname') or line.startswith('\tprovides'):
names.append(line.split(' = ')[1])
if line.startswith('\tdepends') or line.startswith('\tmakedepends') or line.startswith('\tcheckdepends') or line.startswith('\toptdepends'):
depends.append(line.split(' = ')[1].split('=')[0])
self.names = list(set(names))
self.depends = list(set(depends))
self.repo = self.path.split('/')[0]
mode = ''
with open(os.path.join(self.path, 'PKGBUILD'), 'r') as file:
for line in file.read().split('\n'):
if line.startswith('_mode='):
mode = line.split('=')[1]
break
if mode not in ['host', 'cross']:
logging.fatal(
f'Package {self.path} has an invalid mode configured: \'{mode}\'')
exit(1)
self.mode = mode
has_pkgver = False
with open(os.path.join(self.path, 'PKGBUILD'), 'r') as file:
for line in file.read().split('\n'):
if line.startswith('pkgver()'):
has_pkgver = True
break
self.has_pkgver = has_pkgver
def check_prebuilts():
if not os.path.exists('prebuilts'):
os.makedirs('prebuilts')
for repo in ['main', 'device']:
if not os.path.exists(os.path.join('prebuilts', repo)):
os.makedirs(os.path.join('prebuilts', repo))
for ext1 in ['db', 'files']:
for ext2 in ['', '.tar.xz']:
if not os.path.exists(os.path.join('prebuilts', repo, f'{repo}.{ext1}{ext2}')):
result = subprocess.run(['tar',
'-czf',
f'{repo}.{ext1}{ext2}',
'-T', '/dev/null'],
cwd=os.path.join('prebuilts', repo))
if result.returncode != 0:
logging.fatal('Failed create prebuilt repos')
exit(1)
def setup_chroot():
if not os.path.exists('/chroot/root'):
logging.info('Initializing root chroot')
result = subprocess.run(['mkarchroot',
'-s',
'-C', '/app/src/pacman.conf',
'-f', '/etc/locale.gen',
'/chroot/root',
'base-devel'])
if result.returncode != 0:
logging.fatal('Failed to initialize root chroot')
shutil.rmtree('/chroot/root')
exit(1)
else:
logging.info('Updating root chroot')
result = subprocess.run(pacman_cmd +
['-Syuu',
'--root', '/chroot/root',
'--arch', 'aarch64',
'--config', '/app/src/pacman.conf'])
if result.returncode != 0:
logging.fatal('Failed to update root chroot')
exit(1)
shutil.copyfile('/app/src/pacman.conf', '/app/src/pacman_copy.conf')
with open('/app/src/pacman_copy.conf', 'a') as file:
file.write('\n\n[main]\nServer = file:///src/prebuilts/main')
file.write('\n\n[device]\nServer = file:///src/prebuilts/device')
shutil.copyfile('/app/src/pacman_copy.conf',
'/chroot/root/etc/pacman.conf')
shutil.copyfile('/etc/pacman.d/aarch64_mirrorlist',
'/chroot/root/etc/pacman.d/aarch64_mirrorlist')
result = subprocess.run(pacman_cmd +
['-Sy',
'--root', '/chroot/root',
'--arch', 'aarch64',
'--config', '/chroot/root/etc/pacman.conf'])
if result.returncode != 0:
logging.fatal('Failed to update root chroot')
exit(1)
with open('/chroot/root/usr/bin/makepkg', 'r') as file:
data = file.read()
data = data.replace('EUID == 0', 'EUID == -1')
with open('/chroot/root/usr/bin/makepkg', 'w') as file:
file.write(data)
with open('/chroot/root/etc/makepkg.conf', 'r') as file:
data = file.read()
data = data.replace('xz -c', 'xz -T0 -c')
data = data.replace(' check ', ' !check ')
with open('/chroot/root/etc/makepkg.conf', 'w') as file:
file.write(data)
logging.info('Syncing chroot copy')
result = subprocess.run(
['rsync', '-a', '--delete', '-q', '-W', '-x', '/chroot/root/', '/chroot/copy'])
if result.returncode != 0:
logging.fatal('Failed to sync chroot copy')
exit(1)
def discover_packages() -> list[Package]:
packages = []
paths = []
for dir in os.listdir('main'):
paths.append(os.path.join('main', dir))
for dir1 in os.listdir('device'):
for dir2 in os.listdir(os.path.join('device', dir1)):
paths.append(os.path.join('device', dir1, dir2))
for path in paths:
logging.debug(f'Discovered {path}')
packages.append(Package(path))
# This filters the deps to only include the ones that are provided in this repo
for package in packages:
package.local_depends = package.depends.copy()
for dep in package.depends.copy():
found = False
for p in packages:
for name in p.names:
if dep == name:
found = True
break
if found:
break
if not found:
package.local_depends.remove(dep)
return packages
def generate_package_order(packages: list[Package]) -> list[Package]:
unsorted = packages.copy()
sorted = []
"""
It goes through all unsorted packages and checks if the dependencies have already been sorted.
If that is true, the package itself is added to the sorted packages
"""
while len(unsorted) > 0:
for package in unsorted.copy():
if len(package.local_depends) == 0:
sorted.append(package)
unsorted.remove(package)
for package in sorted:
for name in package.names:
for p in unsorted:
for dep in p.local_depends.copy():
if name == dep:
p.local_depends.remove(name)
return sorted
def update_package_version_and_sources(package: Package):
"""
This updates the package version and the sources.
It is done here already, because doing it while host-compiling takes longer.
We decided to even pin the commit of every -git package so this won't update any version, but it would if possible.
"""
cmd = makepkg_cmd+['--nobuild', '--noprepare', '--nodeps', '--skipinteg']
if not package.has_pkgver:
cmd.append('--noextract')
logging.info(f'Updating package version for {package.path}')
result = subprocess.run(cmd,
env=makepkg_env,
cwd=package.path)
if result.returncode != 0:
logging.fatal(f'Failed to update package version for {package.path}')
exit(1)
def check_package_version_built(package: Package) -> bool:
built = True
result = subprocess.run(makepkg_cmd +
['--nobuild',
'--noprepare',
'--packagelist'],
env=makepkg_env,
cwd=package.path,
capture_output=True)
if result.returncode != 0:
logging.fatal(f'Failed to get package list for {package.path}')
exit(1)
for line in result.stdout.decode('utf-8').split('\n'):
if line != "":
file = os.path.basename(line)
if not os.path.exists(os.path.join('prebuilts', package.repo, file)):
built = False
return built
def setup_dependencies_and_sources(package: Package):
logging.info(f'Setting up dependencies and sources for {package.path}')
"""
To make cross-compilation work for almost every package, the host needs to have the dependencies installed
so that the build tools can be used
"""
if package.mode == 'cross':
for p in package.depends:
subprocess.run(pacman_cmd + ['-Sw', p],
stderr=subprocess.DEVNULL)
result = subprocess.run(makepkg_cmd +
['--nobuild',
'--skipinteg',
'--holdver',
'--syncdeps'],
env=makepkg_env,
cwd=package.path)
if result.returncode != 0:
logging.fatal(
f'Failed to setup dependencies and sources for {package.path}')
exit(1)
def build_package(package: Package):
makepkg_compile_opts = ['--noextract',
'--skipinteg',
'--holdver',
'--nodeps']
if package.mode == 'cross':
logging.info(f'Cross-compiling {package.path}')
result = subprocess.run(makepkg_cmd+makepkg_compile_opts,
env=makepkg_env | {
'QEMU_LD_PREFIX': '/usr/aarch64-linux-gnu'},
cwd=package.path)
if result.returncode != 0:
logging.fatal(
f'Failed to cross-compile package {package.path}')
exit(1)
else:
logging.info(f'Host-compiling {package.path}')
def umount():
subprocess.run(['umount', '-lc', '/chroot/copy'],
stderr=subprocess.DEVNULL)
atexit.register(umount)
result = subprocess.run(
['mount', '-o', 'bind', '/chroot/copy', '/chroot/copy'])
if result.returncode != 0:
logging.fatal('Failed to bind mount chroot to itself')
exit(1)
os.makedirs('/chroot/copy/src')
result = subprocess.run(
['mount', '-o', 'bind', '.', '/chroot/copy/src'])
if result.returncode != 0:
logging.fatal(
f'Failed to bind mount folder to chroot')
exit(1)
env = []
for key in makepkg_env:
env.append(f'{key}={makepkg_env[key]}')
result = subprocess.run(
['arch-chroot', '/chroot/copy', '/bin/bash', '-c', f'cd /src/{package.path} && {" ".join(env)} makepkg --noconfirm --ignorearch {" ".join(makepkg_compile_opts)}'])
if result.returncode != 0:
logging.fatal(f'Failed to host-compile package {package.path}')
exit(1)
umount()
def add_package_to_repo(package: Package):
logging.info(f'Adding {package.path} to repo')
dir = os.path.join('prebuilts', package.repo)
if not os.path.exists(dir):
os.mkdir(dir)
for file in os.listdir(package.path):
# Forced extension by makepkg.conf
if file.endswith('.pkg.tar.xz'):
shutil.move(
os.path.join(package.path, file),
os.path.join(dir, file),
)
result = subprocess.run(['repo-add',
'--remove',
'--new',
'--prevent-downgrade',
os.path.join(
'prebuilts',
package.repo,
f'{package.repo}.db.tar.xz',
),
os.path.join(dir, file),
])
if result.returncode != 0:
logging.fatal(f'Failed add package {package.path} to repo')
exit(1)
for repo in ['main', 'device']:
for ext in ['db', 'files']:
if os.path.exists(os.path.join('prebuilts', repo, f'{repo}.{ext}.tar.xz')):
os.unlink(os.path.join('prebuilts', repo, f'{repo}.{ext}'))
shutil.copyfile(
os.path.join('prebuilts', repo, f'{repo}.{ext}.tar.xz'),
os.path.join('prebuilts', repo, f'{repo}.{ext}')
)
if os.path.exists(os.path.join('prebuilts', repo, f'{repo}.{ext}.tar.xz.old')):
os.unlink(os.path.join('prebuilts', repo,
f'{repo}.{ext}.tar.xz.old'))
@click.group(name='packages')
def cmd_packages():
pass
@click.command(name='build')
@verbose_option
@click.argument('path')
def cmd_build(verbose, path):
setup_logging(verbose)
check_prebuilts()
if path == 'all':
packages = generate_package_order(discover_packages())
need_build = []
for package in packages:
update_package_version_and_sources(package)
if not check_package_version_built(package):
need_build.append(package)
if len(need_build) == 0:
logging.info('Everything built already')
return
logging.info('Building %s', ', '.join(
map(lambda x: x.path, need_build)))
with open('.last_built', 'w') as file:
file.write('\n'.join(
map(lambda x: x.path, need_build)))
for package in need_build:
setup_chroot()
setup_dependencies_and_sources(package)
build_package(package)
add_package_to_repo(package)
else:
package = Package(path)
update_package_version_and_sources(package)
if not check_package_version_built(package):
with open('.last_built', 'w') as file:
file.write(package.path)
setup_chroot()
setup_dependencies_and_sources(package)
build_package(package)
add_package_to_repo(package)
@click.command(name='clean')
@verbose_option
def cmd_clean(verbose):
setup_logging(verbose)
result = subprocess.run(['git',
'clean',
'-dffX',
'main', 'device'])
if result.returncode != 0:
logging.fatal(f'Failed to git clean')
exit(1)
cmd_packages.add_command(cmd_build)
cmd_packages.add_command(cmd_clean)

2
requirements.txt Normal file
View file

@ -0,0 +1,2 @@
click==8.0.1
appdirs==1.4.4

169
src/makepkg.conf Normal file
View file

@ -0,0 +1,169 @@
#!/hint/bash
#
# /etc/makepkg.conf
#
#########################################################################
# SOURCE ACQUISITION
#########################################################################
#
#-- The download utilities that makepkg should use to acquire sources
# Format: 'protocol::agent'
DLAGENTS=('file::/usr/bin/curl -gqC - -o %o %u'
'ftp::/usr/bin/curl -gqfC - --ftp-pasv --retry 3 --retry-delay 3 -o %o %u'
'http::/usr/bin/curl -gqb "" -fLC - --retry 3 --retry-delay 3 -o %o %u'
'https::/usr/bin/curl -gqb "" -fLC - --retry 3 --retry-delay 3 -o %o %u'
'rsync::/usr/bin/rsync --no-motd -z %u %o'
'scp::/usr/bin/scp -C %u %o')
# Other common tools:
# /usr/bin/snarf
# /usr/bin/lftpget -c
# /usr/bin/wget
#-- The package required by makepkg to download VCS sources
# Format: 'protocol::package'
VCSCLIENTS=('bzr::bzr'
'fossil::fossil'
'git::git'
'hg::mercurial'
'svn::subversion')
#########################################################################
# ARCHITECTURE, COMPILE FLAGS
#########################################################################
#
CARCH="aarch64"
CHOST="aarch64-unknown-linux-gnu"
#-- Compiler and Linker Flags
# -march (or -mcpu) builds exclusively for an architecture
# -mtune optimizes for an architecture, but builds for whole processor family
CPPFLAGS=""
CFLAGS="-march=armv8-a -O2 -pipe -fstack-protector-strong -fno-plt -fexceptions \
-Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security \
-fstack-clash-protection"
CXXFLAGS="$CFLAGS -Wp,-D_GLIBCXX_ASSERTIONS"
LDFLAGS="-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now"
#RUSTFLAGS="-C opt-level=2"
#-- Make Flags: change this for DistCC/SMP systems
#MAKEFLAGS="-j2"
#-- Debugging flags
DEBUG_CFLAGS="-g -fvar-tracking-assignments"
DEBUG_CXXFLAGS="-g -fvar-tracking-assignments"
#DEBUG_RUSTFLAGS="-C debuginfo=2"
#########################################################################
# BUILD ENVIRONMENT
#########################################################################
#
# Makepkg defaults: BUILDENV=(!distcc !color !ccache !check !sign)
# A negated environment option will do the opposite of the comments below.
#
#-- distcc: Use the Distributed C/C++/ObjC compiler
#-- color: Colorize output messages
#-- ccache: Use ccache to cache compilation
#-- check: Run the check() function if present in the PKGBUILD
#-- sign: Generate PGP signature file
#
BUILDENV=(!distcc color !ccache !check !sign)
#
#-- If using DistCC, your MAKEFLAGS will also need modification. In addition,
#-- specify a space-delimited list of hosts running in the DistCC cluster.
#DISTCC_HOSTS=""
#
#-- Specify a directory for package building.
#BUILDDIR=/tmp/makepkg
#########################################################################
# GLOBAL PACKAGE OPTIONS
# These are default values for the options=() settings
#########################################################################
#
# Makepkg defaults: OPTIONS=(!strip docs libtool staticlibs emptydirs !zipman !purge !debug !lto)
# A negated option will do the opposite of the comments below.
#
#-- strip: Strip symbols from binaries/libraries
#-- docs: Save doc directories specified by DOC_DIRS
#-- libtool: Leave libtool (.la) files in packages
#-- staticlibs: Leave static library (.a) files in packages
#-- emptydirs: Leave empty directories in packages
#-- zipman: Compress manual (man and info) pages in MAN_DIRS with gzip
#-- purge: Remove files specified by PURGE_TARGETS
#-- debug: Add debugging flags as specified in DEBUG_* variables
#-- lto: Add compile flags for building with link time optimization
#
OPTIONS=(strip docs !libtool !staticlibs emptydirs zipman purge !debug !lto)
#-- File integrity checks to use. Valid: md5, sha1, sha224, sha256, sha384, sha512, b2
INTEGRITY_CHECK=(sha256)
#-- Options to be used when stripping binaries. See `man strip' for details.
STRIP_BINARIES="--strip-all"
#-- Options to be used when stripping shared libraries. See `man strip' for details.
STRIP_SHARED="--strip-unneeded"
#-- Options to be used when stripping static libraries. See `man strip' for details.
STRIP_STATIC="--strip-debug"
#-- Manual (man and info) directories to compress (if zipman is specified)
MAN_DIRS=({usr{,/local}{,/share},opt/*}/{man,info})
#-- Doc directories to remove (if !docs is specified)
DOC_DIRS=(usr/{,local/}{,share/}{doc,gtk-doc} opt/*/{doc,gtk-doc})
#-- Files to be removed from all packages (if purge is specified)
PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod)
#-- Directory to store source code in for debug packages
DBGSRCDIR="/usr/src/debug"
#########################################################################
# PACKAGE OUTPUT
#########################################################################
#
# Default: put built package and cached source in build directory
#
#-- Destination: specify a fixed directory where all packages will be placed
#PKGDEST=/home/packages
#-- Source cache: specify a fixed directory where source files will be cached
#SRCDEST=/home/sources
#-- Source packages: specify a fixed directory where all src packages will be placed
#SRCPKGDEST=/home/srcpackages
#-- Log files: specify a fixed directory where all log files will be placed
#LOGDEST=/home/makepkglogs
#-- Packager: name/email of the person or organization building packages
#PACKAGER="John Doe <john@doe.com>"
#-- Specify a key to use for package signing
#GPGKEY=""
#########################################################################
# COMPRESSION DEFAULTS
#########################################################################
#
COMPRESSGZ=(gzip -c -f -n)
COMPRESSBZ2=(bzip2 -c -f)
COMPRESSXZ=(xz -T0 -c -z -)
COMPRESSZST=(zstd -c -z -q -)
COMPRESSLRZ=(lrzip -q)
COMPRESSLZO=(lzop -q)
COMPRESSZ=(compress -c -f)
COMPRESSLZ4=(lz4 -q)
COMPRESSLZ=(lzip -c -f)
#########################################################################
# EXTENSION DEFAULTS
#########################################################################
#
PKGEXT='.pkg.tar.xz'
SRCEXT='.src.tar.gz'
#########################################################################
# OTHER
#########################################################################
#
#-- Command used to run pacman as root, instead of trying sudo and su
#PACMAN_AUTH=()
export CROOT="/usr/aarch64-linux-gnu"
export ARCH="arm64"
export CROSS_COMPILE="aarch64-linux-gnu-"
export CC="aarch64-linux-gnu-gcc -I${CROOT}/usr/include -I/chroot/copy/usr/include -L${CROOT}/lib -L/chroot/copy/usr/lib"
export CXX="aarch64-linux-gnu-g++ -I${CROOT}/usr/include -I/chroot/copy/usr/include -L${CROOT}/lib -L/chroot/copy/usr/lib"
export CFLAGS="$CFLAGS -I${CROOT}/usr/include -I/chroot/copy/usr/include"
export CXXFLAGS="$CXXFLAGS -I${CROOT}/usr/include -I/chroot/copy/usr/include"
export LDFLAGS="$LDFLAGS,-L${CROOT}/lib,-L/chroot/copy/usr/lib,-rpath-link,${CROOT}/lib,-rpath-link,/chroot/copy/usr/lib"

91
src/pacman.conf Normal file
View file

@ -0,0 +1,91 @@
#
# /etc/pacman.conf
#
# See the pacman.conf(5) manpage for option and repository directives
#
# GENERAL OPTIONS
#
[options]
# The following paths are commented out with their default values listed.
# If you wish to use different paths, uncomment and update the paths.
#RootDir = /
#DBPath = /var/lib/pacman/
#CacheDir = /var/cache/pacman/pkg/
#LogFile = /var/log/pacman.log
#GPGDir = /etc/pacman.d/gnupg/
#HookDir = /etc/pacman.d/hooks/
HoldPkg = pacman glibc
#XferCommand = /usr/bin/curl -L -C - -f -o %o %u
#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u
#CleanMethod = KeepInstalled
Architecture = aarch64
# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
#IgnorePkg =
#IgnoreGroup =
#NoUpgrade =
#NoExtract =
# Misc options
#UseSyslog
#Color
#NoProgressBar
#CheckSpace
#VerbosePkgLists
ParallelDownloads = 8
# By default, pacman accepts packages signed by keys that its local keyring
# trusts (see pacman-key and its man page), as well as unsigned packages.
SigLevel = Never
LocalFileSigLevel = Never
#RemoteFileSigLevel = Never
# NOTE: You must run `pacman-key --init` before first using pacman; the local
# keyring can then be populated with the keys of all official Arch Linux ARM
# packagers with `pacman-key --populate archlinuxarm`.
#
# REPOSITORIES
# - can be defined here or included from another file
# - pacman will search repositories in the order defined here
# - local/custom mirrors can be added here or in separate files
# - repositories listed first will take precedence when packages
# have identical names, regardless of version number
# - URLs will have $repo replaced by the name of the current repo
# - URLs will have $arch replaced by the name of the architecture
#
# Repository entries are of the format:
# [repo-name]
# Server = ServerName
# Include = IncludePath
#
# The header [repo-name] is crucial - it must be present and
# uncommented to enable the repo.
#
# The testing repositories are disabled by default. To enable, uncomment the
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
[core]
Include = /etc/pacman.d/aarch64_mirrorlist
[extra]
Include = /etc/pacman.d/aarch64_mirrorlist
[community]
Include = /etc/pacman.d/aarch64_mirrorlist
[alarm]
Include = /etc/pacman.d/aarch64_mirrorlist
[aur]
Include = /etc/pacman.d/aarch64_mirrorlist
# An example of a custom package repository. See the pacman manpage for
# tips on creating your own repositories.
#[custom]
#SigLevel = Never
#Server = file:///home/custompkgs

31
src/update-pacman-files.sh Executable file
View file

@ -0,0 +1,31 @@
#!/bin/sh
set -e
wget https://raw.githubusercontent.com/archlinuxarm/PKGBUILDs/master/core/pacman/makepkg.conf -O makepkg.conf
sed -i "s/@CARCH@/aarch64/g" makepkg.conf
sed -i "s/@CHOST@/aarch64-unknown-linux-gnu/g" makepkg.conf
sed -i "s/@CARCHFLAGS@/-march=armv8-a /g" makepkg.conf
sed -i "s/xz /xz -T0 /g" makepkg.conf
sed -i "s/ check / !check /g" makepkg.conf
chroot="/chroot/copy"
include="-I\${CROOT}/usr/include -I$chroot/usr/include"
lib_croot="\${CROOT}/lib"
lib_chroot="$chroot/usr/lib"
cat >>makepkg.conf <<EOF
export CROOT="/usr/aarch64-linux-gnu"
export ARCH="arm64"
export CROSS_COMPILE="aarch64-linux-gnu-"
export CC="aarch64-linux-gnu-gcc $include -L$lib_croot -L$lib_chroot"
export CXX="aarch64-linux-gnu-g++ $include -L$lib_croot -L$lib_chroot"
export CFLAGS="\$CFLAGS $include"
export CXXFLAGS="\$CXXFLAGS $include"
export LDFLAGS="\$LDFLAGS,-L$lib_croot,-L$lib_chroot,-rpath-link,$lib_croot,-rpath-link,$lib_chroot"
EOF
# TODO: Set PACKAGER
wget https://raw.githubusercontent.com/archlinuxarm/PKGBUILDs/master/core/pacman/pacman.conf -O pacman.conf
sed -i "s/@CARCH@/aarch64/g" pacman.conf
sed -i "s/#ParallelDownloads.*/ParallelDownloads = 8/g" pacman.conf
sed -i "s/SigLevel.*/SigLevel = Never/g" pacman.conf
sed -i "s/^CheckSpace/#CheckSpace/g" pacman.conf
sed -i "s|/mirrorlist|/aarch64_mirrorlist|g" pacman.conf

1
version.txt Normal file
View file

@ -0,0 +1 @@
dev

53
wrapper.py Normal file
View file

@ -0,0 +1,53 @@
import atexit
import os
import subprocess
import sys
import appdirs
if os.getenv('KUPFERBOOTSTRAP_DOCKER') == '1':
from main import cli
cli(prog_name='kupferbootstrap')
else:
script_path = os.path.dirname(os.path.abspath(__file__))
with open(os.path.join(script_path, 'version.txt')) as version_file:
version = version_file.read().replace('\n', '')
tag = f'gitlab.com/kupfer/kupferbootstrap:{version}'
if version == 'dev':
result = subprocess.run([
'docker',
'build',
'.',
'-t', tag
], cwd=script_path)
if result.returncode != 0:
print(f'Failed to build kupferbootstrap docker image')
exit(1)
else:
# Check if the image for the version already exists
result = subprocess.run(['docker', 'images', '-q', tag],
capture_output=True)
if result.stdout == b'':
print(
f'Pulling kupferbootstrap docker image version \'{version}\'')
subprocess.run(['docker', 'pull', tag])
def at_exit():
subprocess.run(['docker', 'kill', 'kupferbootstrap'],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,)
atexit.register(at_exit)
# TODO: Remove the mount of /usr/share/i18n/locales. It's a trick so we don't need to generate the locales in the chroot.
# Something like a prebuilt docker image as base or copying the files from it would be good.
subprocess.run(['docker',
'run',
'--name', 'kupferbootstrap',
'--rm',
'--privileged',
'-v', f'{os.getcwd()}:/src:z',
'-v', f'{os.path.join(appdirs.user_cache_dir("kupfer"),"chroot")}:/chroot:z',
'-v', f'{os.path.join(appdirs.user_cache_dir("kupfer"),"pacman")}:/var/cache/pacman/pkg:z',
'-v', '/usr/share/i18n/locales:/usr/share/i18n/locales:ro'] +
[tag,
'kupferbootstrap']
+ sys.argv[1:])