123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- #!/usr/bin/env python3
- import argparse
- import functools
- import operator
- import os
- import shutil
- import subprocess
- import time
- def system(cmd: str) -> None:
- subprocess.run(cmd, shell=True, check=True)
- parser = argparse.ArgumentParser(usage="Build a patched Fedora kernel")
- parser.add_argument(
- "--package-name",
- help="The name of the patched package (e.g. foo -> kernel-foo).",
- required=True,
- )
- parser.add_argument(
- "--package-tag",
- help="The upstream tag to build.",
- required=True,
- )
- parser.add_argument(
- "--package-release",
- help="The release suffix of the modified package.",
- required=True,
- )
- parser.add_argument(
- "--ark-dir",
- help="The local path to the kernel-ark repository.",
- default="kernel-ark",
- )
- parser.add_argument(
- "--ark-url",
- help="The remote path to the kernel-ark repository.",
- default="https://gitlab.com/cki-project/kernel-ark",
- )
- parser.add_argument(
- "--patch",
- help="Applies a patch to the kernel source.",
- action="append",
- nargs="+",
- )
- parser.add_argument(
- "--config",
- help="Applies a KConfig fragment to the kernel source.",
- action="append",
- nargs="+",
- )
- parser.add_argument(
- "--file",
- help="Copy a file into the RPM buildroot.",
- action="append",
- nargs="+",
- )
- parser.add_argument(
- "--buildopts",
- help="Enable or disable options of the kernel spec file.",
- action="append",
- nargs="+",
- )
- parser.add_argument(
- "--mode",
- help="Whether to build a source RPM or binary RPMs.",
- choices=["rpms", "srpm"],
- default="rpms",
- )
- parser.add_argument(
- "--outdir",
- help="The directory where the built RPM files will be saved.",
- default="out",
- )
- args = parser.parse_args()
- patches = [] if not args.patch else functools.reduce(operator.add, args.patch)
- configs = [] if not args.config else functools.reduce(operator.add, args.config)
- files = [] if not args.file else functools.reduce(operator.add, args.file)
- buildopts = [] if not args.buildopts else functools.reduce(operator.add, args.buildopts)
- # Make paths absolute.
- patches = [os.path.realpath(x) for x in patches]
- configs = [os.path.realpath(x) for x in configs]
- files = [os.path.realpath(x) for x in files]
- outdir = os.path.realpath(args.outdir)
- # Clone the kernel-ark repository if it doesn't exist.
- if not os.path.exists(args.ark_dir):
- system("git clone '%s' '%s'" % (args.ark_url, args.ark_dir))
- os.chdir(args.ark_dir)
- # Check out the requested tag.
- system("git fetch --tags")
- system("git clean -dfx")
- system("git checkout -b 'build/%s'" % time.time())
- system("git reset --hard '%s'" % args.package_tag)
- # Apply patches
- for patch in patches:
- system("git am '%s'" % patch)
- # Copy files
- for file in files:
- shutil.copy(file, "redhat/fedora_files/")
- # Apply config options
- #
- # The format that the kernel-ark tree expects is a bit different from
- # a standard kernel config. Every option is split into a single file
- # named after that config.
- #
- # Example:
- # $ cat redhat/configs/common/generic/CONFIG_PCI
- # CONFIG_PCI=y
- #
- # This supposedly makes things easier for Red Hat developers,
- # but it also ends up being really annoying for us.
- for config in configs:
- with open(config) as f:
- lines = f.readlines()
- # Filter out comments, this means only selecting lines that look like:
- # - CONFIG_FOO=b
- # - # CONFIG_FOO is not set
- for line in lines:
- enable = line.startswith("CONFIG_")
- disable = line.startswith("# CONFIG_")
- if not enable and not disable:
- continue
- NAME = ""
- if enable:
- NAME = line.split("=")[0]
- elif disable:
- NAME = line[2:].split(" ")[0]
- print("Applying %s" % line.rstrip("\n"))
- with open("redhat/configs/custom-overrides/generic/%s" % NAME, "w") as f:
- f.write(line)
- system("git add redhat/configs/custom-overrides/generic")
- system("git commit -m 'Merge %s config'" % args.package_name)
- cmd = ["make"]
- if args.mode == "rpms":
- cmd.append("dist-rpms")
- else:
- cmd.append("dist-srpm")
- cmd.append("SPECPACKAGE_NAME='kernel-%s'" % args.package_name)
- cmd.append("DISTLOCALVERSION='.%s'" % args.package_name)
- cmd.append("BUILD='%s'" % args.package_release)
- if len(buildopts) > 0:
- cmd.append("BUILDOPTS='%s'" % " ".join(buildopts))
- # Build RPMS
- system(" ".join(cmd))
- if args.mode == "rpms":
- rpmdir = "RPMS"
- else:
- rpmdir = "SRPMS"
- # Copy built RPMS to output directory
- os.makedirs(outdir, exist_ok=True)
- system("cp -r redhat/rpm/%s/* '%s'" % (rpmdir, outdir))
|