From c558ac3b15cdccd8aae7b2d73dce768324d3eb84 Mon Sep 17 00:00:00 2001 From: Cheng Li Date: Sun, 12 Jul 2026 23:07:29 +0900 Subject: [PATCH 1/2] feat(packaging): add openEuler 24.03 RPM build support - flagsparse.spec: fall back to a pip-based build on distros without pyproject-rpm-macros (openEuler 24.03, EL8-family); the Fedora/EL9 pyproject-macros path is unchanged. - Dockerfile.rpm: install pyproject-rpm-macros opportunistically and reconstruct the empty %dist tag on openEuler images (.oe2403). - build-flagsparse-rpm.sh: BASE_IMAGE/BASE_IMAGE_VERSION/OUTPUT_DIR env overrides; default single-arg Fedora flow preserved. - build-rpm.yml: build matrix fedora43 + openeuler2403; the Fedora artifact name is unchanged for downstream collectors. Verified locally: fedora43 build unchanged (python3-flagsparse-1.0.0-1.fc43, python(abi)=3.14); openeuler2403 build installs and imports on an openEuler 24.03 container (python3-flagsparse-1.0.0-1.oe2403, python(abi)=3.11, /usr/lib/python3.11/site-packages). --- .github/workflows/build-rpm.yml | 21 +++++++++++++-- packaging/rpm/build-flagsparse-rpm.sh | 16 ++++++++--- packaging/rpm/dockerfiles/Dockerfile.rpm | 17 +++++++++++- packaging/rpm/specs/flagsparse.spec | 34 ++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index 5dc7f31..b4f007f 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -16,6 +16,20 @@ on: jobs: build-rpm: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + # Original Fedora target — artifact name unchanged so + # downstream collectors keep working. + - target: fedora43 + base_image: fedora + base_image_version: "43" + artifact: flagsparse-amd64-rpm-packages + - target: openeuler2403 + base_image: openeuler/openeuler + base_image_version: 24.03-lts + artifact: flagsparse-amd64-oe2403-rpm-packages steps: - name: Checkout repository uses: actions/checkout@v4 @@ -25,12 +39,15 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Build .rpm + - name: Build .rpm (${{ matrix.target }}) run: bash packaging/rpm/build-flagsparse-rpm.sh + env: + BASE_IMAGE: ${{ matrix.base_image }} + BASE_IMAGE_VERSION: ${{ matrix.base_image_version }} - name: Upload artifacts uses: actions/upload-artifact@v4 with: - name: flagsparse-amd64-rpm-packages + name: ${{ matrix.artifact }} path: rpm-packages/*.rpm retention-days: 7 diff --git a/packaging/rpm/build-flagsparse-rpm.sh b/packaging/rpm/build-flagsparse-rpm.sh index add80d2..b87a9e7 100644 --- a/packaging/rpm/build-flagsparse-rpm.sh +++ b/packaging/rpm/build-flagsparse-rpm.sh @@ -2,12 +2,22 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")" -BASE_IMAGE_VERSION="${1:-43}" -IMAGE_TAG="flagsparse-rpm:f${BASE_IMAGE_VERSION}" -OUTPUT_DIR="${PROJECT_DIR}/rpm-packages" +# Defaults preserve the original single-arg Fedora flow: +# ./build-flagsparse-rpm.sh [fedora-version] +# Other distros via env, e.g. openEuler 24.03: +# BASE_IMAGE=openeuler/openeuler BASE_IMAGE_VERSION=24.03-lts ./build-flagsparse-rpm.sh +BASE_IMAGE="${BASE_IMAGE:-fedora}" +BASE_IMAGE_VERSION="${BASE_IMAGE_VERSION:-${1:-43}}" +if [ "${BASE_IMAGE}" = "fedora" ]; then + IMAGE_TAG="flagsparse-rpm:f${BASE_IMAGE_VERSION}" +else + IMAGE_TAG="flagsparse-rpm:$(echo "${BASE_IMAGE}-${BASE_IMAGE_VERSION}" | tr '/' '-')" +fi +OUTPUT_DIR="${OUTPUT_DIR:-${PROJECT_DIR}/rpm-packages}" docker build --network=host \ -f "${SCRIPT_DIR}/dockerfiles/Dockerfile.rpm" \ + --build-arg BASE_IMAGE="$BASE_IMAGE" \ --build-arg BASE_IMAGE_VERSION="$BASE_IMAGE_VERSION" \ -t "$IMAGE_TAG" "$PROJECT_DIR" diff --git a/packaging/rpm/dockerfiles/Dockerfile.rpm b/packaging/rpm/dockerfiles/Dockerfile.rpm index 3f4ccf8..a56f8dc 100644 --- a/packaging/rpm/dockerfiles/Dockerfile.rpm +++ b/packaging/rpm/dockerfiles/Dockerfile.rpm @@ -4,10 +4,25 @@ ARG BASE_IMAGE_VERSION=43 FROM ${BASE_IMAGE}:${BASE_IMAGE_VERSION} RUN dnf install -y \ - rpm-build rpmdevtools pyproject-rpm-macros \ + rpm-build rpmdevtools \ python3-devel python3-setuptools python3-wheel python3-pip \ && dnf clean all +# pyproject-rpm-macros exists on Fedora/EL9+ but not openEuler 24.03; +# the spec falls back to a pip-based build when it is absent. +RUN dnf install -y pyproject-rpm-macros && dnf clean all \ + || echo "pyproject-rpm-macros unavailable; spec uses pip fallback" + +# openEuler images define %dist as empty (official .oe* tags are +# injected by EulerMaker); reconstruct it so local/CI builds get +# distro-tagged Release fields like official packages. +RUN if [ -z "$(rpm --eval '%{?dist}')" ]; then \ + . /etc/os-release && \ + case "${ID}" in \ + openEuler) echo "%dist .oe$(echo "${VERSION_ID}" | tr -d '.')" >> /root/.rpmmacros ;; \ + esac; \ + fi + RUN rpmdev-setuptree COPY . /workspace/FlagSparse diff --git a/packaging/rpm/specs/flagsparse.spec b/packaging/rpm/specs/flagsparse.spec index 7d86c1b..598704d 100644 --- a/packaging/rpm/specs/flagsparse.spec +++ b/packaging/rpm/specs/flagsparse.spec @@ -1,5 +1,17 @@ %global debug_package %{nil} +# Distros that ship pyproject-rpm-macros (Fedora, EL9+) build via the +# %%pyproject_* macro family — that path is unchanged. Distros without +# it (openEuler 24.03, EL8-family) fall back to a plain pip +# wheel/install build. Capability-detected at parse time, so the build +# container must have its python toolchain installed before rpmbuild +# runs (both Dockerfile.rpm paths do). +%if %{defined pyproject_wheel} +%global has_pyproject_macros 1 +%else +%global has_pyproject_macros 0 +%endif + Name: python3-flagsparse Version: 1.0.0 Release: 1%{?dist} @@ -13,7 +25,9 @@ BuildRequires: python3-devel BuildRequires: python3-setuptools >= 60 BuildRequires: python3-wheel BuildRequires: python3-pip +%if %{has_pyproject_macros} BuildRequires: pyproject-rpm-macros +%endif %description Sparse matrix operators (SpMM, SpMV, sampled dense-dense) for FlagOS-supported accelerators. @@ -22,11 +36,20 @@ Sparse matrix operators (SpMM, SpMV, sampled dense-dense) for FlagOS-supported a %autosetup -n flagsparse-%{version} %build +%if %{has_pyproject_macros} %pyproject_wheel +%else +%{__python3} -m pip wheel --no-deps --no-build-isolation --wheel-dir dist . +%endif %install +%if %{has_pyproject_macros} %pyproject_install %pyproject_save_files flagsparse +%else +%{__python3} -m pip install --no-deps --no-index --no-warn-script-location \ + --root %{buildroot} dist/*.whl +%endif %check # Smoke find_spec test (no actual import) — verifies the built module @@ -37,9 +60,20 @@ PYTHONDONTWRITEBYTECODE=1 \ PYTHONPATH=%{buildroot}%{python3_sitelib} \ python3 -c "import importlib.util; s = importlib.util.find_spec('flagsparse'); assert s and s.origin, 'flagsparse not findable'; print('OK: flagsparse at', s.origin)" +%if %{has_pyproject_macros} %files -f %{pyproject_files} %license LICENSE +%else +%files +%license LICENSE +%{python3_sitelib}/flagsparse/ +%{python3_sitelib}/flagsparse-%{version}.dist-info/ +%endif %changelog +* Sat Jul 11 2026 FlagOS Contributors - 1.0.0-1 +- Add pip-based fallback for distros without pyproject-rpm-macros + (openEuler 24.03); Fedora build path unchanged. + * Wed May 13 2026 FlagOS Contributors - 1.0.0-1 - Initial RPM packaging. From 7a4d597685c8efa79bdb9131676419b2d4ae5bfc Mon Sep 17 00:00:00 2001 From: Cheng Li Date: Mon, 13 Jul 2026 13:02:03 +0900 Subject: [PATCH 2/2] fix(packaging): fold pyproject-rpm-macros attempt into the toolchain dnf layer A separate RUN re-downloads all repo metadata after dnf clean all; on slow openEuler mirrors from CI runners this costs tens of minutes (observed 43 min for a failing install in FlagAttention's CI). --- packaging/rpm/dockerfiles/Dockerfile.rpm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packaging/rpm/dockerfiles/Dockerfile.rpm b/packaging/rpm/dockerfiles/Dockerfile.rpm index a56f8dc..f5b9666 100644 --- a/packaging/rpm/dockerfiles/Dockerfile.rpm +++ b/packaging/rpm/dockerfiles/Dockerfile.rpm @@ -3,16 +3,17 @@ ARG BASE_IMAGE_VERSION=43 FROM ${BASE_IMAGE}:${BASE_IMAGE_VERSION} +# pyproject-rpm-macros exists on Fedora/EL9+ but not openEuler 24.03; +# the spec falls back to a pip-based build when it is absent. Same RUN +# as the toolchain install: a separate layer would re-download all repo +# metadata (dnf clean all), which on slow mirrors costs tens of minutes. RUN dnf install -y \ rpm-build rpmdevtools \ python3-devel python3-setuptools python3-wheel python3-pip \ + && (dnf install -y pyproject-rpm-macros \ + || echo "pyproject-rpm-macros unavailable; spec uses pip fallback") \ && dnf clean all -# pyproject-rpm-macros exists on Fedora/EL9+ but not openEuler 24.03; -# the spec falls back to a pip-based build when it is absent. -RUN dnf install -y pyproject-rpm-macros && dnf clean all \ - || echo "pyproject-rpm-macros unavailable; spec uses pip fallback" - # openEuler images define %dist as empty (official .oe* tags are # injected by EulerMaker); reconstruct it so local/CI builds get # distro-tagged Release fields like official packages.