[Rpm-maint] [rpm-software-management/rpm] RFE: A native %foreach approach (Discussion #4158)

Miro Hrončok notifications at github.com
Wed Mar 18 15:39:06 UTC 2026


Hi. In the past, I found myself in a position where I had to do [something](https://src.fedoraproject.org/rpms/python3-rpm/blob/epel9/f/python3-rpm.spec) like this:

```specfile
%global python3_pkgversion 3.11
%py3_build
%global python3_pkgversion 3.12
%py3_build
%global python3_pkgversion 3.13
%py3_build
%global python3_pkgversion 3.14
%py3_build
```

For more complex spec snippets, I defined a helper macro:

```specfile
%define python3x_package %{?name:%package -n python%{python3_pkgversion}-rpm
Summary: Python %{python3_pkgversion} bindings for apps which will manipulate RPM packages
BuildRequires: python%{python3_pkgversion}-devel
%if v"%{python3_pkgversion}" >= v"3.12"
BuildRequires: python%{python3_pkgversion}-setuptools
%endif
...

%description -n python%{python3_pkgversion}-rpm
The python%{python3_pkgversion}-rpm package contains...}

%global python3_pkgversion 3.11
%python3x_package
%global python3_pkgversion 3.12
%python3x_package
%global python3_pkgversion 3.13
%python3x_package
%global python3_pkgversion 3.14
%python3x_package
```

Yet this seemed horrible so later I [went with](https://src.fedoraproject.org/rpms/python3-rpm/blob/bd64780478c4b52ffe2c3ae50b898335b6591c33/f/macros.foreach) something like this:

Macros:

```lua
%foreach(m:) %{lua:
  if opt.m == nil or opt.m == "" then
    rpm.expand("%{error:%%foreach requires -m <macro_name>}")
  end
  if #arg < 2 then
    rpm.expand("%{error:%%foreach requires at least one macro value and a template string}")
  end
  -- The string template is the last argument
  local template = arg[#arg]
  for i = 1, #arg-1 do
    rpm.define(opt.m .. " " .. arg[i])
    print(rpm.expand(template))
    print("\\n")
    rpm.undefine(opt.m)
  end
}

%foreachpy() %{foreach -m python3_pkgversion %{python3_pkgversions} %{quote:%1}}
```

Usage:

```specfile
%global python3_pkgversions 3.13 3.14

%{foreachpy %{quote:
%package -n python%%{python3_pkgversion}-rpm
Summary: Python %%{python3_pkgversion} bindings for apps which will manipulate RPM packages
BuildRequires: python%%{python3_pkgversion}-devel
...

%description -n python%%{python3_pkgversion}-rpm
The python%%{python3_pkgversion}-rpm package contains...
}}

...

%{foreachpy %{quote:
%files -n python%%{python3_pkgversion}-rpm
%%%%license COPYING
%dir %%{python3_sitearch}/rpm
%%{python3_sitearch}/rpm-%{rpmver}*.egg-info
%%{python3_sitearch}/rpm/__init__.py
%%{python3_sitearch}/rpm/transaction.py
%%{python3_sitearch}/rpm/_rpm.so
%artifact %%{python3_sitearch}/rpm/__pycache__/
}}
```

It works, but it's a bit tedious to use. Particularly, the need to `%%%%`-escape the `%license` declaration in files is :exploding_head:  (or else it expands to the License value).

----

I was wondering if we could have some native mechanism of a foreach block in RPM, that would:

 - eliminate the need to pass everything in `%quote`
 - eliminate the need to escape everything within

E.g. I would love to be able to do:

```specfile
%global python3_pkgversions 3.13 3.14
...

%foreach python3_pkgversion %{python3_pkgversions}
%files -n python%{python3_pkgversion}-rpm
%license COPYING
%dir %{python3_sitearch}/rpm
%{python3_sitearch}/rpm-%{rpmver}*.egg-info
%{python3_sitearch}/rpm/__init__.py
%{python3_sitearch}/rpm/transaction.py
%{python3_sitearch}/rpm/_rpm.so
%artifact %{python3_sitearch}/rpm/__pycache__/
%endforeach
```

-- 
Reply to this email directly or view it on GitHub:
https://github.com/rpm-software-management/rpm/discussions/4158
You are receiving this because you are subscribed to this thread.

Message ID: <rpm-software-management/rpm/repo-discussions/4158 at github.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rpm.org/pipermail/rpm-maint/attachments/20260318/de01ccda/attachment-0001.htm>


More information about the Rpm-maint mailing list