uhd/tools/debs/uhd_ubuntu_deb.py
Martin Anderseck c8a8a3d931 ci/tools: Enable Ubuntu 26.04 build
This enables building UHD in Ubuntu 26.04 in the test pipeline.
2026-08-03 12:55:00 +02:00

169 lines
6.4 KiB
Python

#!/usr/bin/env python3
# uhd_ubuntu_deb.py
# This script is used to generate UHD dsc, changes, and source archives for upload to Launchpad.
# After dsc generation, pbuilder is called to build the debs. This sets up an envionment similar to
# the Launchpad build process. To build the dsc you must have pbuilder, debootstrap, and devscripts
# installed and have run:
#
# pbuilder create --debootstrapopts --variant=buildd --distribution=<target distro>
#
# See here for more on pbuilder: https://wiki.ubuntu.com/PbuilderHowto
import argparse
import os
import pathlib
import re
import shlex
import shutil
import subprocess
import sys
import tarfile
supported_ubuntu_releases = ["jammy", "noble", "plucky", "resolute"]
tar_command = "tar --exclude='.git*' --exclude='./debian' --exclude='*.swp' --exclude='./fpga/usrp1' --exclude='./fpga/usrp2' --exclude='./fpga/usrp3/top/b200' --exclude='./fpga/usrp3/top/b2xxmini' --exclude='./fpga/usrp3/lib/*_200' --exclude='build' --exclude='./images/*.pyc' --exclude='./images/uhd-*' --exclude='tags' --exclude='.ci' --exclude='.clang*' -cJf {}/uhd_{}.orig.tar.xz ."
debuild_command = "debuild -S -i -sa"
debuild_nosign = " -uc -us"
def main(args):
if not pathlib.Path("host").exists():
print("Check path. This script must be run on uhd base path")
sys.exit(1)
if not args.release in supported_ubuntu_releases:
print(
"Unsupported release selected. Supported releases are {}".format(
supported_ubuntu_releases
)
)
sys.exit(1)
# Determine UHD version number
uhd_version = ""
orig_release = ""
with open("host/cmake/debian/changelog") as cl:
first_line = cl.readline()
uhd_version = re.findall(r"[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+", first_line)
if len(uhd_version) != 1:
print("uhd_version in changelog malformed. Check host/cmake/debian/changelog")
sys.exit(1)
uhd_version = uhd_version[0]
orig_release = re.findall("[A-Za-z_]*;", first_line)
if len(orig_release) != 1:
print("orig_release in changelog malformed. Check host/cmake/debian/changelog")
sys.exit(1)
orig_release = orig_release[0].replace(";", "")
# Compress UHD source
if pathlib.Path(args.buildpath).exists():
shutil.rmtree(args.buildpath)
os.mkdir(args.buildpath)
print("Compressing UHD Source...")
result = subprocess.run(shlex.split(tar_command.format(args.buildpath, uhd_version)))
if result.returncode:
print("Compressing source failed")
sys.exit(result.returncode)
# Extract UHD source to build folder
uhd_deb_build_path = pathlib.Path(args.buildpath, "uhd-{}".format(uhd_version))
if uhd_deb_build_path.exists():
shutil.rmtree(uhd_deb_build_path)
with tarfile.open(
args.buildpath + "/uhd_{}.orig.tar.xz".format(uhd_version), "r:xz"
) as uhd_archive:
uhd_archive.extractall(path=uhd_deb_build_path)
# Copy debian build files to build folder
shutil.copytree("host/cmake/debian", uhd_deb_build_path / "debian")
# Copy version specific files (e.g. debian/control.noble to debian/control)
for version_specific_file in pathlib.Path(uhd_deb_build_path / "debian").glob(
f"*.{args.release}"
):
shutil.copy2(version_specific_file, version_specific_file.with_suffix(""))
shutil.copy2("host/utils/uhd-usrp.rules", uhd_deb_build_path / "debian/uhd-host.udev")
with open(uhd_deb_build_path / "debian/uhd-host.manpages", "w") as man_file:
for file in uhd_deb_build_path.glob("host/docs/*.1"):
man_file.write(os.path.relpath(file, uhd_deb_build_path) + "\n")
man_file.write("\n")
for file in uhd_deb_build_path.glob("debian/*.in"):
os.remove(file)
# Modify changelog for selected release
with open(uhd_deb_build_path / "debian/changelog", "r+") as cl:
cl_text = cl.read()
cl_text = re.sub(orig_release, args.release, cl_text)
cl_text = re.sub("0ubuntu1", "0ubuntu1~{}1".format(args.release), cl_text)
cl.seek(0)
cl.write(cl_text)
cl.truncate()
# Generate dsc file
result = ""
print("Running debuild / dsc generation")
if args.sign:
result = subprocess.run(shlex.split(debuild_command), cwd=uhd_deb_build_path)
else:
result = subprocess.run(
shlex.split(debuild_command + debuild_nosign), cwd=uhd_deb_build_path
)
if result.returncode:
print("debuild / dsc generation failed")
sys.exit(result.returncode)
# Build debs using dsc
if not args.nobuild:
print("Building deb with dsc using pbuilder for {}".format(args.release))
os.mkdir(args.buildpath + "/result")
result = subprocess.run(
shlex.split(
"sudo pbuilder build --buildresult ./result uhd_{}-0ubuntu1~{}1.dsc".format(
uhd_version, args.release
)
),
cwd=args.buildpath,
)
if result.returncode:
print("pbuilder failed")
sys.exit(result.returncode)
# Upload dsc to Launchpad
if args.upload:
if not args.sign:
print("Uploading requires signing. Add --sign.")
sys.exit(1)
result = subprocess.run(
shlex.split(
"dput ppa:ettusresearch/uhd uhd_${}-0ubuntu1~${}1_source.changes".format(
uhd_version, args.release
)
),
cwd=args.buildpath,
)
if result.returncode:
print("PPA upload failed")
sys.exit(result.returncode)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"--sign", action="store_true", help="Signs files with GPG key. Not required for test builds"
)
parser.add_argument(
"--upload", action="store_true", help="Uploads to launchpad. Requires--sign"
)
parser.add_argument("--nobuild", action="store_true", help="Disables building using pbuilder")
parser.add_argument(
"--buildpath",
type=str,
required=True,
help="Output path for build files. " "Will get nuked before creating packages.",
)
parser.add_argument(
"release",
type=str,
help="Ubuntu release version. This must match pbuilder create --distribution if building.",
)
args = parser.parse_args()
main(args)