From eb785ff23be8e1bdf9d98e514c4b8bc75e5e0018 Mon Sep 17 00:00:00 2001 From: Virendra Kakade Date: Thu, 10 Sep 2026 18:26:51 -0500 Subject: [PATCH] ci: Build UHD DEBs with B310 support Add nib310rio-dev to the Debian build dependencies so the UHD package build fails if the B310 userspace header is unavailable instead of silently disabling B300 support. The Ubuntu installer pipeline downloads the nib310rio Debian package artifact and exposes it to pbuilder as a local apt repository. This lets pbuilder satisfy the new dependency inside the clean build root where CMake checks for nib310rio/nib310rio.h. --- .ci/templates/job-uhd-build-installer.yml | 12 +++-- .../steps-build-uhd-installer-ubuntu-deb.yml | 14 ++++- host/cmake/debian/control | 1 + host/cmake/debian/control.jammy | 1 + host/cmake/debian/control.noble | 1 + tools/debs/uhd_ubuntu_deb.py | 51 ++++++++++++++++--- 6 files changed, 68 insertions(+), 12 deletions(-) diff --git a/.ci/templates/job-uhd-build-installer.yml b/.ci/templates/job-uhd-build-installer.yml index 2974706d8..85f63b89a 100644 --- a/.ci/templates/job-uhd-build-installer.yml +++ b/.ci/templates/job-uhd-build-installer.yml @@ -42,7 +42,7 @@ jobs: timeoutInMinutes: 120 variables: # Need to use list format to support inclusion of variable groups. - # Variable group used by .ci/templates/steps-windows-sbom.yml@ettus-rts + # Variable group used by .ci/templates/steps-windows-sbom.yml@ettus-rts - group: meta-ettus-vars # Variable group needed for code signing (signtool-p4-path) - ${{ if eq(parameters.toolset, 'msbuild') }}: @@ -102,9 +102,9 @@ jobs: # Job uses template which causes self checkout to result in different values # for $(Build.SourcesDirectory) due to single vs multiple repositories use. # Switching to use manual path definition $(Pipeline.Workspace)/s/ - # for consistent behavior to avoid + # for consistent behavior to avoid # $(Pipeline.Workspace)/s vs $(Pipeline.Workspace)/s/). - # Custom path now includes , which is now hardcoded, rather than + # Custom path now includes , which is now hardcoded, rather than # use name from git repo (avoids problem when building from public uhd repo). # Checkout path needs to be defined relative to $(Pipeline.Workspace). - checkout: self @@ -139,7 +139,7 @@ jobs: - ${{ if parameters.create_sbom }}: - template: .ci/templates/steps-linux-sbom.yml@ettus-rts parameters: - toolset: ${{ parameters.toolset }} + toolset: ${{ parameters.toolset }} installer: ${{ parameters.installer }} sbomComponentList: 'uhd libuhd libboost libusb' buildOSName: $(buildOSName) @@ -148,16 +148,18 @@ jobs: uhdInstallerDir: $(Build.BinariesDirectory)/uhddev-installer releaseBinaries: ${{ parameters.releaseBinaries }} - ${{ if eq(parameters.toolset, 'ubuntu_deb') }}: + - template: steps-install-nib310rio-dev.yml - template: steps-build-uhd-installer-ubuntu-deb.yml parameters: uhdSrcDir: $(uhdSrcDir) uhdInstallerDir: $(Build.BinariesDirectory)/uhddev-installer ubuntuReleaseName: $(ubuntuReleaseName) + nib310rioDebPackageDir: $(Pipeline.Workspace)/nib310rio_kernel_packages/nib310rio-deb-packages cmake_args: ${{ parameters.cmake_args }} - ${{ if parameters.create_sbom }}: - template: .ci/templates/steps-linux-sbom.yml@ettus-rts parameters: - toolset: ${{ parameters.toolset }} + toolset: ${{ parameters.toolset }} installer: ${{ parameters.installer }} sbomComponentList: 'uhd libuhd' buildOSName: $(buildOSName) diff --git a/.ci/templates/steps-build-uhd-installer-ubuntu-deb.yml b/.ci/templates/steps-build-uhd-installer-ubuntu-deb.yml index c1572ddad..0d4d5f791 100644 --- a/.ci/templates/steps-build-uhd-installer-ubuntu-deb.yml +++ b/.ci/templates/steps-build-uhd-installer-ubuntu-deb.yml @@ -8,13 +8,25 @@ parameters: - name: cmake_args type: string default: " " +- name: nib310rioDebPackageDir + type: string + default: "" steps: - script: | + set -euo pipefail sudo pbuilder create --debootstrapopts --variant=buildd --distribution ${{ parameters.ubuntuReleaseName }} displayName: Setup pbuilder - script: | + set -euo pipefail mkdir -p ${{ parameters.uhdInstallerDir }} cd ${{ parameters.uhdSrcDir }} - python3 tools/debs/uhd_ubuntu_deb.py ${{ parameters.ubuntuReleaseName }} --buildpath ${{ parameters.uhdInstallerDir }} + pbuilder_args=() + if [[ -n "${{ parameters.nib310rioDebPackageDir }}" ]]; then + pushd "${{ parameters.nib310rioDebPackageDir }}" + dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz + popd + pbuilder_args+=(--pbuilder-extra-apt-repo "${{ parameters.nib310rioDebPackageDir }}") + fi + python3 tools/debs/uhd_ubuntu_deb.py ${{ parameters.ubuntuReleaseName }} --buildpath ${{ parameters.uhdInstallerDir }} "${pbuilder_args[@]}" displayName: Build dsc and debs diff --git a/host/cmake/debian/control b/host/cmake/debian/control index c1a4f2877..f207974a1 100644 --- a/host/cmake/debian/control +++ b/host/cmake/debian/control @@ -16,6 +16,7 @@ Build-Depends: cmake, protobuf-compiler, protobuf-compiler-grpc, libncurses-dev, + nib310rio-dev [linux-any], libusb-1.0-0-dev [linux-any hurd-i386], pkgconf, python3-dev, diff --git a/host/cmake/debian/control.jammy b/host/cmake/debian/control.jammy index 43dd9a310..433f81f96 100644 --- a/host/cmake/debian/control.jammy +++ b/host/cmake/debian/control.jammy @@ -16,6 +16,7 @@ Build-Depends: cmake, protobuf-compiler, protobuf-compiler-grpc, libncurses-dev, + nib310rio-dev [linux-any], libusb-1.0-0-dev [linux-any hurd-i386], libusb2-dev [kfreebsd-any], pkgconf, diff --git a/host/cmake/debian/control.noble b/host/cmake/debian/control.noble index 43dd9a310..433f81f96 100644 --- a/host/cmake/debian/control.noble +++ b/host/cmake/debian/control.noble @@ -16,6 +16,7 @@ Build-Depends: cmake, protobuf-compiler, protobuf-compiler-grpc, libncurses-dev, + nib310rio-dev [linux-any], libusb-1.0-0-dev [linux-any hurd-i386], libusb2-dev [kfreebsd-any], pkgconf, diff --git a/tools/debs/uhd_ubuntu_deb.py b/tools/debs/uhd_ubuntu_deb.py index bdd720419..b767a93b7 100644 --- a/tools/debs/uhd_ubuntu_deb.py +++ b/tools/debs/uhd_ubuntu_deb.py @@ -16,9 +16,11 @@ import pathlib import re import shlex import shutil +import stat import subprocess import sys import tarfile +import tempfile 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 ." @@ -114,14 +116,45 @@ def main(args): 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 + pbuilder_command = [ + "sudo", + "pbuilder", + "build", + "--buildresult", + "./result", + ] + # --othermirror is silently ignored by "pbuilder build" (it only applies + # to "pbuilder create"/"update --override-config"), so a local apt repo + # for extra build-deps has to be added via a hook script instead. The D + # hook runs after bind mounts are active but before build-deps are + # resolved, which is the documented place to call apt-get update. + if args.pbuilder_extra_apt_repo: + repo_dir = os.path.abspath(args.pbuilder_extra_apt_repo) + hook_dir = tempfile.mkdtemp(prefix="uhd-pbuilder-hooks-") + hook_path = os.path.join(hook_dir, "D50uhd_local_apt_repo") + with open(hook_path, "w") as hook_file: + hook_file.write( + "#!/bin/bash\n" + "set -euo pipefail\n" + "echo 'deb [trusted=yes] file:{repo_dir} ./' " + "> /etc/apt/sources.list.d/uhd-local-extra.list\n" + "apt-get update\n".format(repo_dir=repo_dir) ) - ), - cwd=args.buildpath, + os.chmod( + hook_path, os.stat(hook_path).st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH + ) + pbuilder_command.extend( + [ + "--bindmounts", + repo_dir, + "--hookdir", + hook_dir, + ] + ) + pbuilder_command.append( + "uhd_{}-0ubuntu1~{}1.dsc".format(uhd_version, args.release) ) + result = subprocess.run(pbuilder_command, cwd=args.buildpath) if result.returncode: print("pbuilder failed") sys.exit(result.returncode) @@ -159,6 +192,12 @@ if __name__ == "__main__": required=True, help="Output path for build files. " "Will get nuked before creating packages.", ) + parser.add_argument( + "--pbuilder-extra-apt-repo", + type=str, + default="", + help="Extra apt repository path to bind mount into pbuilder and use for build dependencies.", + ) parser.add_argument( "release", type=str,