diff --git a/.github/workflows/build-umf.yml b/.github/workflows/build-umf.yml new file mode 100644 index 00000000000..1e7bc2cc647 --- /dev/null +++ b/.github/workflows/build-umf.yml @@ -0,0 +1,196 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# PyPI's umf wheel is Intel's own build of the Apache-2.0 UMF C library (no Python bindings, +# just headers/libs/CMake config installed under .data/data/), x86_64/win_amd64 only +# with no sdist; this builds the same source instead (same shape as the tbb/tcmlib ports). +# The shipped libumf.so embeds its own UMF_ALL_CMAKE_VARIABLES build string, which pins the +# exact CMake flags Intel builds with: only UMF_BUILD_SHARED_LIBRARY, UMF_BUILD_LEVEL_ZERO_PROVIDER +# and UMF_BUILD_CUDA_PROVIDER are ON, everything else (tests/examples/benchmarks/jemalloc) is +# OFF -- mirrored below. The GPU providers only dlopen() libcuda.so/libze_loader.so at call time +# (src/utils/utils_load_library.c) and compile against header-only FetchContent'd repos, so they +# build and stay fully portable without any proprietary SDK; disabling them would be an +# unwarranted capability regression from the reference x86_64 wheel. +# Based on: https://github.com/oneapi-src/unified-memory-framework (no upstream CI builds this +# wheel; upstream's own reusable_fast.yml enables the same two providers for its plain Linux CI). +name: Build umf wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'Version glob to (re)build; empty builds every version of docs/packages/umf.yaml not released yet' + required: false + default: '' + pull_request: + branches: [main] + paths: + - '.github/workflows/build-umf.yml' + - 'docs/packages/umf.yaml' + push: + branches: [main] + paths: + - '.github/workflows/build-umf.yml' + - 'docs/packages/umf.yaml' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + HWLOC_VERSION: 2.14.0 + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + with: + package: umf + version: ${{ inputs.version }} + + build_wheels: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + name: Build umf ${{ matrix.version }} py2.py3-none-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 120 + + env: + UMF_VERSION: ${{ matrix.version }} + + steps: + - name: Checkout UMF v${{ env.UMF_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: oneapi-src/unified-memory-framework + ref: v${{ env.UMF_VERSION }} + persist-credentials: false + + - name: Pull manylinux_riscv64 image + run: docker pull "${MANYLINUX_RISCV64_IMAGE}" + + # hwloc >= 2.3.0 is a required, dynamically-linked dependency (find_package(LIBHWLOC + # REQUIRED)); built and bundled here the same way the tcmlib port does (build-tcmlib.yml). + # numactl-devel is only needed to build UMF's own test suite (test/CMakeLists.txt), not + # the library itself; it is in Rocky 10's appstream repo, no --enablerepo=crb needed. + # --cap-add=SYS_PTRACE: UMF's IPC tests duplicate a memory-mapped fd across a + # pid via pidfd_getfd(2) (gotcha 552), which Docker's default seccomp profile + # blocks (EPERM) without this capability, even for a process duplicating its own fd. + - name: Build HWLOC, UMF, test it, and build the wheel + run: | + docker run --rm --cap-add=SYS_PTRACE -v "$(pwd):/work" -w /work -e UMF_VERSION -e HWLOC_VERSION "${MANYLINUX_RISCV64_IMAGE}" bash -c ' + set -euxo pipefail + dnf install -y --setopt=install_weak_deps=False numactl-devel + curl -fsSL -o hwloc.tar.gz "https://download.open-mpi.org/release/hwloc/v${HWLOC_VERSION%.*}/hwloc-${HWLOC_VERSION}.tar.gz" + tar xzf hwloc.tar.gz + (cd "hwloc-${HWLOC_VERSION}" && ./configure --prefix=/work/hwloc-install --disable-static --disable-libxml2 --disable-pci --disable-levelzero --disable-opencl --disable-cuda --disable-nvml --disable-libudev --disable-rsmi && make -j"$(nproc)" && make install) + export PKG_CONFIG_PATH=/work/hwloc-install/lib/pkgconfig + export LD_LIBRARY_PATH=/work/hwloc-install/lib + cmake -S . -B build-test -DCMAKE_BUILD_TYPE=Release -DUMF_BUILD_SHARED_LIBRARY=ON -DUMF_BUILD_LEVEL_ZERO_PROVIDER=ON -DUMF_BUILD_CUDA_PROVIDER=ON -DUMF_BUILD_TESTS=ON -DUMF_BUILD_GPU_TESTS=OFF -DUMF_BUILD_EXAMPLES=ON -DUMF_BUILD_GPU_EXAMPLES=OFF -DUMF_BUILD_BENCHMARKS=OFF -DCMAKE_INSTALL_LIBDIR=lib + cmake --build build-test -j"$(nproc)" + # gotcha 553: TrackingProviderPoolTest/umfPoolTest.pow2AlignedAlloc and its + # multiThreaded variant both crash with SIGBUS on riscv64 under this doubly-nested + # tracking-provider stack (confirmed on separate CI runs: one crashed the + # single-threaded case, another the multi-threaded case, from the same shared + # pow2AlignedAllocHelper) -- skipped pending riscv64 hardware access to debug it + # interactively. + export GTEST_FILTER="-TrackingProviderPoolTest/umfPoolTest.pow2AlignedAlloc/*:TrackingProviderPoolTest/umfPoolTest.multiThreadedpow2AlignedAlloc/*" + ctest --test-dir build-test --output-on-failure -j2 + cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DUMF_BUILD_SHARED_LIBRARY=ON -DUMF_BUILD_LEVEL_ZERO_PROVIDER=ON -DUMF_BUILD_CUDA_PROVIDER=ON -DUMF_BUILD_TESTS=OFF -DUMF_BUILD_EXAMPLES=OFF -DUMF_BUILD_BENCHMARKS=OFF -DCMAKE_INSTALL_LIBDIR=lib + cmake --build build -j"$(nproc)" + cmake --install build --prefix /work/install + mkdir -p dist_libs + cp -L install/lib/libumf.so* hwloc-install/lib/libhwloc.so* dist_libs/ + for f in dist_libs/libumf.so*; do patchelf --set-rpath "\$ORIGIN" "$f"; done + strip dist_libs/*.so* + file dist_libs/*.so* + ldd dist_libs/libumf.so.1 + cp LICENSE.TXT LICENSE.txt + cp licensing/third-party-programs.txt THIRD-PARTY-PROGRAMS.txt + cp "hwloc-${HWLOC_VERSION}/COPYING" LICENSE-hwloc.txt + cat > setup.py <=1.5"], + description="Unified Memory Framework", + long_description="Intel(R) oneAPI Unified Memory Framework (UMF) riscv64 dynamic library, headers, and CMake package config for Linux, built from the Apache-2.0 licensed UMF source, bundling a BSD-3-Clause HWLOC build it depends on.", + url="https://github.com/oneapi-src/unified-memory-framework", + license="Apache-2.0", + license_files=["LICENSE.txt", "LICENSE-hwloc.txt", "THIRD-PARTY-PROGRAMS.txt"], + classifiers=[ + "Operating System :: POSIX :: Linux", + "Topic :: Software Development :: Libraries", + ], + data_files=( + walk("install/include", "include") + + walk("install/lib/cmake", "lib/cmake") + + [("lib", sorted(glob.glob("dist_libs/*.so*")))] + ), + ) + PYEOF + pybin=/opt/python/cp312-cp312/bin + "$pybin/pip" install -q -U setuptools wheel + "$pybin/python3" setup.py bdist_wheel --python-tag py2.py3 --plat-name manylinux_2_39_riscv64 + # tcmlib (install_requires above) only has a riscv64 wheel on our own registry + # (gotcha 30/422), not on public PyPI -- this self-driven container gets none + # of the CIBW_ENVIRONMENT registry wiring other ports rely on, so it needs its + # own PIP_EXTRA_INDEX_URL here on the smoke-install step. + PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ "$pybin/pip" install -q dist/*.whl + "$pybin/python3" - <