<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2020-11-12T11:45:30+00:00</updated><id>/feed.xml</id><title type="html">Package Ninja Blog</title><subtitle>Welcome!</subtitle><entry><title type="html">News in openSUSE Packaging</title><link href="/packaging/2020/10/13/news-in-packaging.html" rel="alternate" type="text/html" title="News in openSUSE Packaging" /><published>2020-10-13T12:24:16+00:00</published><updated>2020-10-13T12:24:16+00:00</updated><id>/packaging/2020/10/13/news-in-packaging</id><content type="html" xml:base="/packaging/2020/10/13/news-in-packaging.html">&lt;p&gt;If you are interested in openSUSE, sooner or later you will probably learn how packages and specfiles work. But packaging is not static knowledge that you learn once and are good to go. The rules change over time, new macros are created and old ones are erased from history, new file paths are used and the old ones are forgotten. So how can one keep up with these changes?&lt;/p&gt;

&lt;p&gt;In this article, we will serve you with all recent news and important changes in openSUSE packaging on a silver platter. Whether you are a pro package maintainer or just a casual packager who wants to catch up, you will definitely find something you didn’t know here. We promise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table of contents&lt;/strong&gt;&lt;/p&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#opensuse-macros&quot; id=&quot;markdown-toc-opensuse-macros&quot;&gt;openSUSE macros&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#_libexecdir&quot; id=&quot;markdown-toc-_libexecdir&quot;&gt;%_libexecdir&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#systemd-macros&quot; id=&quot;markdown-toc-systemd-macros&quot;&gt;systemd macros&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#cross-distribution-macros&quot; id=&quot;markdown-toc-cross-distribution-macros&quot;&gt;Cross-distribution macros&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#deprecated-macros&quot; id=&quot;markdown-toc-deprecated-macros&quot;&gt;Deprecated macros&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#databasecache-updating-macros&quot; id=&quot;markdown-toc-databasecache-updating-macros&quot;&gt;Database/cache updating macros&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#make_jobs&quot; id=&quot;markdown-toc-make_jobs&quot;&gt;%make_jobs&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#paths-and-tags&quot; id=&quot;markdown-toc-paths-and-tags&quot;&gt;Paths and Tags&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#configuration-files-in-etc-and-usretc&quot; id=&quot;markdown-toc-configuration-files-in-etc-and-usretc&quot;&gt;Configuration files in /etc and /usr/etc&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#group-tag&quot; id=&quot;markdown-toc-group-tag&quot;&gt;Group: tag&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#news-in-rpm&quot; id=&quot;markdown-toc-news-in-rpm&quot;&gt;News in RPM&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#file-triggers&quot; id=&quot;markdown-toc-file-triggers&quot;&gt;File Triggers&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#autopatch-and-autosetup&quot; id=&quot;markdown-toc-autopatch-and-autosetup&quot;&gt;%autopatch and %autosetup&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#patchlist-and-sourcelist&quot; id=&quot;markdown-toc-patchlist-and-sourcelist&quot;&gt;%patchlist and %sourcelist&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#elif&quot; id=&quot;markdown-toc-elif&quot;&gt;%elif&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#boolean-dependencies&quot; id=&quot;markdown-toc-boolean-dependencies&quot;&gt;Boolean dependencies&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#license&quot; id=&quot;markdown-toc-license&quot;&gt;%license&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#obs&quot; id=&quot;markdown-toc-obs&quot;&gt;OBS&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#new-osc-options&quot; id=&quot;markdown-toc-new-osc-options&quot;&gt;New osc options&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#osc-maintained-version&quot; id=&quot;markdown-toc-osc-maintained-version&quot;&gt;osc maintained –version&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#osc-request-incoming&quot; id=&quot;markdown-toc-osc-request-incoming&quot;&gt;osc request –incoming&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#osc-browse&quot; id=&quot;markdown-toc-osc-browse&quot;&gt;osc browse&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#delete-requests-for-entire-projects&quot; id=&quot;markdown-toc-delete-requests-for-entire-projects&quot;&gt;Delete requests for entire projects&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#real-names-in-changelogs&quot; id=&quot;markdown-toc-real-names-in-changelogs&quot;&gt;Real names in changelogs&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#rdiff-and-diff-enhancements&quot; id=&quot;markdown-toc-rdiff-and-diff-enhancements&quot;&gt;rdiff and diff enhancements&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#osc-blame&quot; id=&quot;markdown-toc-osc-blame&quot;&gt;osc blame&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#osc-comment&quot; id=&quot;markdown-toc-osc-comment&quot;&gt;osc comment&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#examining-workers-and-constraints&quot; id=&quot;markdown-toc-examining-workers-and-constraints&quot;&gt;Examining workers and constraints&lt;/a&gt;            &lt;ul&gt;
              &lt;li&gt;&lt;a href=&quot;#osc-checkconstraints&quot; id=&quot;markdown-toc-osc-checkconstraints&quot;&gt;osc checkconstraints&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#osc-workerinfo&quot; id=&quot;markdown-toc-osc-workerinfo&quot;&gt;osc workerinfo&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#multibuild&quot; id=&quot;markdown-toc-multibuild&quot;&gt;Multibuild&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#oldies&quot; id=&quot;markdown-toc-oldies&quot;&gt;Oldies&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#prereq--requirespre&quot; id=&quot;markdown-toc-prereq--requirespre&quot;&gt;PreReq → Requires(pre)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#varrun--run&quot; id=&quot;markdown-toc-varrun--run&quot;&gt;/var/run → /run&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#usr-merge&quot; id=&quot;markdown-toc-usr-merge&quot;&gt;/usr Merge&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#sysv-is-dead&quot; id=&quot;markdown-toc-sysv-is-dead&quot;&gt;SysV is dead&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#automatic-tools-for-cleaning&quot; id=&quot;markdown-toc-automatic-tools-for-cleaning&quot;&gt;Automatic tools for cleaning&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#spec-cleaner&quot; id=&quot;markdown-toc-spec-cleaner&quot;&gt;spec-cleaner&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#rpmlint&quot; id=&quot;markdown-toc-rpmlint&quot;&gt;rpmlint&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#acknowledgment&quot; id=&quot;markdown-toc-acknowledgment&quot;&gt;Acknowledgment&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;opensuse-macros&quot;&gt;openSUSE macros&lt;/h1&gt;

&lt;p align=&quot;center&quot;&gt;
  &lt;img src=&quot;/assets/geeko-color.png&quot; /&gt;
&lt;/p&gt;

&lt;h2 id=&quot;_libexecdir&quot;&gt;%_libexecdir&lt;/h2&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%_libexecdir&lt;/code&gt; macro expands to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/libexec&lt;/code&gt; now (not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/lib&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;We will start with the most recent change, which is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%_libexecdir&lt;/code&gt; macro. In the past, it was a standard practice to store binaries that are not intended to be executed directly by users or shell scripts in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/lib&lt;/code&gt; directory. This has been changed with a release of FHS 3.0 that now &lt;a href=&quot;https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch04s07.html&quot;&gt;defines&lt;/a&gt; that applications should store these internal binaries in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/libexec&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;In openSUSE, the first discussions about changing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%_libexecdir&lt;/code&gt; macro from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/lib&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/libexec&lt;/code&gt; appeared in fall 2019 but it took several months for all affected packages to be fixed and the change to be adopted. It was fully &lt;a href=&quot;https://lists.opensuse.org/opensuse-factory/2020-08/msg00226.html&quot;&gt;merged&lt;/a&gt; in TW 0825 in August 2020.&lt;/p&gt;

&lt;p&gt;Please note, openSUSE Leap distributions, including upcoming Leap 15.3, still expand &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%_libexecdir&lt;/code&gt; to the old &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/lib&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;systemd-macros&quot;&gt;systemd macros&lt;/h2&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%{?systemd_ordering}&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%{?systemd_requires}&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pkgconfig(libsystemd)&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pkgconfig(systemd-devel)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuildRequires: systemd-rpm-macros&lt;/code&gt; is not needed&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;
&lt;p&gt;In the past, you’ve been told that if your package uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt;, you should just add the following lines to your spec file and you are good to go:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;BuildRequires: systemd-rpm-macros
%{?systemd_requires}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Times are changing, though, and modern times require a bit of a different approach, especially if you want your package to be ready for inclusion inside a container. To explain it, we need to know what the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%{?systemd_requires}&lt;/code&gt; macro looks like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ rpm --eval %{?systemd_requires}

Requires(pre): systemd 
Requires(post): systemd 
Requires(preun): systemd 
Requires(postun): systemd 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This creates a hard dependency on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt;. In the case of containers, this can be counterproductive as we don’t want to force &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; to be included when it’s not needed. That’s why the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%{?systemd_ordering}&lt;/code&gt; macro started being used instead:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ rpm --eval %{?systemd_ordering}

OrderWithRequires(post): systemd 
OrderWithRequires(preun): systemd 
OrderWithRequires(postun): systemd 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OrderWithRequires&lt;/code&gt; is similar to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Requires&lt;/code&gt; tag but it doesn’t generate actual dependencies. It just supplies ordering hints for calculating the transaction order, but only if the package is present in the same transaction. In the case of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; it means that if you need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; to be installed early in the transaction (e.g. creating an installation), this will ensure that it’s ordered early.&lt;/p&gt;

&lt;p&gt;Unless you need to explicitly call the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl&lt;/code&gt; command from the specfile (which you probably don’t because of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%service_*&lt;/code&gt; macros that can deal with it), you shouldn’t use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%{?systemd_requires}&lt;/code&gt; anymore.&lt;/p&gt;

&lt;p&gt;Also note, that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-rpm-macros&lt;/code&gt; has been required by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpm&lt;/code&gt; package for some time, so it’s not necessary to explicitly require it. You can safely omit it unless you are afraid that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpm&lt;/code&gt; will drop it in the future, which is highly unlikely.&lt;/p&gt;

&lt;p&gt;The last is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuildRequires&lt;/code&gt;, this is needed in cases where your package needs to link against &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; libraries. In this case, you should use:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;BuildRequires: pkgconfig(libsystemd)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;instead of the older&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;BuildRequires: pkgconfig(systemd-devel)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;as the new variant can help to shorten the build chain in OBS.&lt;/p&gt;

&lt;h2 id=&quot;cross-distribution-macros&quot;&gt;Cross-distribution macros&lt;/h2&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%leap_version&lt;/code&gt; macro is deprecated&lt;/li&gt;
  &lt;li&gt;See this &lt;a href=&quot;https://en.opensuse.org/openSUSE:Packaging_for_Leap#RPM_Distro_Version_Macros&quot;&gt;table&lt;/a&gt; for all distribution macros and their values for specific distros&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;Commonly, you want to build your package for multiple target distributions. But if you want to support both bleeding-edge Tumbleweed and Leap or SLE, you need to adjust your specfile accordingly. That is why you need to know the distribution version macros.&lt;/p&gt;

&lt;p&gt;The best source of information is the &lt;a href=&quot;https://en.opensuse.org/openSUSE:Packaging_for_Leap#RPM_Distro_Version_Macros&quot;&gt;table&lt;/a&gt; on the openSUSE wiki that will show you the values of these distribution macros for every SLE/openSUSE version. If you want examples on how to identify a specific distro, see this &lt;a href=&quot;https://en.opensuse.org/openSUSE:Build_Service_cross_distribution_howto#Detect_a_distribution_flavor_for_special_code&quot;&gt;table&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The biggest change between Leap 42 (SLE-12) and Leap 15 (SLE-15) is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%leap_version&lt;/code&gt; macro is deprecated. If you want to address e.g. openSUSE Leap 15.2, you should use:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;%if 0%{?sle_version} == 150200 &amp;amp;&amp;amp; 0%{?is_opensuse}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, to distinguish specific Leap minor versions, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%sle_version&lt;/code&gt; macro is used. The value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%sle_version&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%nil&lt;/code&gt; in Tumbleweed as it’s not based on SLE.&lt;/p&gt;

&lt;p&gt;If you want to identify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SLE-15-SP2&lt;/code&gt;, you just negate the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%is_opensuse&lt;/code&gt; macro:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;%if 0%{?sle_version} == 150200 &amp;amp;&amp;amp; !0%{?is_opensuse}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The current Tumbleweed release (which is changing, obviously) can be identified via:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;%if 0%{?suse_version} &amp;gt; 1500
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In general, if you want to show the value of these macros on your system, you can do it via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpm --eval&lt;/code&gt; macro:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ rpm --eval %suse_version 
1550
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;deprecated-macros&quot;&gt;Deprecated macros&lt;/h2&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These macros are deprecated&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%install_info&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%install_info_delete&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%desktop_database_post&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%desktop_database_postun&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%icon_theme_cache_post&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%icon_theme_cache_postun&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%glib2_gsettings_schema&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%make_jobs&lt;/code&gt; (is now known as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%cmake_build&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%make_build&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;If you have been interested in packaging for some time, you probably learned a lot of macros. The bad thing is that some of them shouldn’t be used anymore. In this section, we will cover the most common of them.&lt;/p&gt;

&lt;h3 id=&quot;databasecache-updating-macros&quot;&gt;Database/cache updating macros&lt;/h3&gt;

&lt;p&gt;The biggest group of deprecated macros is probably those that called commands for updating databases and caches when new files appeared in specific directory:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%install_info&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%install_info_delete&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;update info/dir entries&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%desktop_database_post&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%desktop_database_postun&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;update desktop database cache when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.desktop&lt;/code&gt; files is added/removed to/from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share/applications&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%icon_theme_cache_post&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%icon_theme_cache_postun&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;update the icon cache when icon is added to  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share/icons&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%glib2_gsettings_schema&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;compile schemas installed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share/glib-2.0/schemas&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, in the past whenever you installed a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.desktop&lt;/code&gt; file in your package, you should have called:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;%post
%desktop_database_post

%postun
%desktop_database_postun
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since 2017, these macros have started being &lt;a href=&quot;https://lists.opensuse.org/opensuse-factory/2017-06/msg00898.html&quot;&gt;replaced&lt;/a&gt; with file triggers, which is a new feature of RPM 4.13. See &lt;a href=&quot;#file-triggers&quot;&gt;File triggers&lt;/a&gt; section for more info.&lt;/p&gt;

&lt;h3 id=&quot;make_jobs&quot;&gt;%make_jobs&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%make_jobs&lt;/code&gt; macro was initially used in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; packaging, but was later adopted in a number of other packages, confusingly sometimes with a slightly different definition. To make matters more confusing it also ended up being more complex than the expected &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/bin/make -jX&lt;/code&gt;. Because of this and to bring the macro more inline with other macros such as meson’s, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%make_jobs&lt;/code&gt; has been replaced with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%cmake_build&lt;/code&gt; when using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%make_build&lt;/code&gt; for all other usages.&lt;/p&gt;

&lt;p&gt;In the past, you called: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%cmake&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%make_jobs&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%cmake_install.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now it’s more coherent and you call:  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%cmake&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%cmake_build&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%cmake_install&lt;/code&gt; when using cmake and just replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%make_jobs&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%make_build&lt;/code&gt; in other cases.&lt;/p&gt;

&lt;p&gt;For completeness, we will add that the naming is also nicely aligned with the meson and automake macros, that are:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%meson&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%meson_build&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%meson_install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%configure&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%make_build&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%make_install&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%make_jobs&lt;/code&gt; macro is still provided by KDE Framework &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kf5-filesystem&lt;/code&gt; package and is used by about 250 Factory packages, but its use is being phased out.&lt;/p&gt;

&lt;h1 id=&quot;paths-and-tags&quot;&gt;Paths and Tags&lt;/h1&gt;

&lt;h2 id=&quot;configuration-files-in-etc-and-usretc&quot;&gt;Configuration files in /etc and /usr/etc&lt;/h2&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/etc&lt;/code&gt; will be the new directory for the distribution provided configuration files&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc&lt;/code&gt; directory will contain configuration files changed by an administrator&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;Historically, configuration files were always installed in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc&lt;/code&gt; directory. Then if you edited this configuration file and updated the package, you often ended up with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.rpmsave&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.rpmnew&lt;/code&gt; extra files that you had to solve manually.&lt;/p&gt;

&lt;p&gt;Due to this suboptimal situation and mainly because of the need to fulfill new requirements of &lt;a href=&quot;https://en.opensuse.org/openSUSE:Packaging_for_transactional-updates&quot;&gt;transactional updates&lt;/a&gt; (atomic updates), the handling of configuration files had to be changed.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.opensuse.org/openSUSE:Packaging_UsrEtc&quot;&gt;The new solution&lt;/a&gt; is to separate distribution provided configuration (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/etc&lt;/code&gt;) that is not modifiable and host-specific configuration changed by  admins (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This change of course requires a lot of work. First, the applications per se need to be adjusted to read the configuration from multiple locations rather than just good old &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc&lt;/code&gt; and there are of course a lot of packaging changes needed as well. There are &lt;a href=&quot;https://en.opensuse.org/openSUSE:Packaging_UsrEtc#Variant_1_.28ideal_case.29&quot;&gt;3 variants&lt;/a&gt; of how to implement the change within packaging and you as a packager should choose one that fits the best for your package.&lt;/p&gt;

&lt;p&gt;Also, there is a new RPM macro that refers to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/etc&lt;/code&gt; location:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;%_distconfdir  /usr/etc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;group-tag&quot;&gt;Group: tag&lt;/h2&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Group:&lt;/code&gt; tag is optional now&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;Maybe you noticed a wild discussion about removing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Group:&lt;/code&gt; tag that hit the opensuse-factory mailing list in Fall 2019. It aroused emotions to such an extent that the openSUSE Board had to step in and helped to resolve this conflict.&lt;/p&gt;

&lt;p&gt;They decided that including groups in spec files should be optional with the final decision resting with the maintainer.&lt;/p&gt;

&lt;h1 id=&quot;news-in-rpm&quot;&gt;News in RPM&lt;/h1&gt;

&lt;p align=&quot;center&quot;&gt;
  &lt;img src=&quot;/assets/RPM_Logo.png&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;RPM minor version updates are released approximately once every two years and they always bring lots of interesting news that will make packaging even easier. Sometimes it’s a little harder to put some of these changes into practice as it can mean a lot of work or hundreds of packages or dealing with backward compatibility issues. This is why you should find more information about their current adoption status in openSUSE before you use new features in your packages.&lt;/p&gt;

&lt;p&gt;Current SUSE and openSUSE status of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpm&lt;/code&gt; package is as follows:&lt;/p&gt;

&lt;table&gt;
  &lt;tr&gt;
   &lt;td&gt;&lt;strong&gt;Distribution&lt;/strong&gt;
   &lt;/td&gt;
   &lt;td&gt;&lt;strong&gt;RPM version&lt;/strong&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;openSUSE:Factory
   &lt;/td&gt;
   &lt;td&gt;4.15.1
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;SLE-15 / openSUSE:Leap:15.*
   &lt;/td&gt;
   &lt;td&gt;4.14.1
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;SLE-12
   &lt;/td&gt;
   &lt;td&gt;4.11.2
   &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;The following paragraphs present a couple of the most interesting features introduced in recent RPM versions.&lt;/p&gt;

&lt;h2 id=&quot;file-triggers&quot;&gt;File Triggers&lt;/h2&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;File trigger is a scriptlet that gets executed whenever a package installs/removes a file in a specific location&lt;/li&gt;
  &lt;li&gt;Used e.g. in Factory for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;texinfo&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;glib schemas&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mime&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;icons&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;desktop&lt;/code&gt; files, so your package doesn’t have to call database/cache updating macros anymore&lt;/li&gt;
  &lt;li&gt;Currently (Nov, 2020), zypper &lt;a href=&quot;https://bugzilla.opensuse.org/show_bug.cgi?id=1041742&quot;&gt;doesn’t handle&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transfiletrigger&lt;/code&gt; properly.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;RPM 4.13 introduced file triggers, rpm scriptlets that get executed whenever a package installs or removes a file in a specific location (and also if a package with the trigger gets installed/removed).&lt;/p&gt;

&lt;p&gt;The main advantage of this concept is that a single package introduces a file trigger and it is then automatically applied to all newly installed/reinstalled packages. So, instead of each package carrying a macro for certain post-processing, the code resides in the package implementing the file trigger and is transparently run everywhere.&lt;/p&gt;

&lt;p&gt;The trigger types are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filetrigger{in, un, postun}&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transfiletrigger{in, un, postun}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*in/*un/*postun&lt;/code&gt; scriptlets are executed similarly to regular rpm scriptlets, before package installation/uninstallation/after uninstallation, depending on the variant.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trans*&lt;/code&gt; variants get executed once per transaction, after all the packages with files matching the trigger get processed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; (Factory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shared-mime-info&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;%filetriggerin -- %{_datadir}/mime                                                                                                                                              
export PKGSYSTEM_ENABLE_FSYNC=0
%{_bindir}/update-mime-database &quot;%{_datadir}/mime&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This file trigger will update the mime database right after the installation of a package that contains a file under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share/mime&lt;/code&gt;. The file trigger will be executed once for each package (no matter how many files in the package match).&lt;/p&gt;

&lt;p&gt;File triggers can easily replace database/cache updating macros (like e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%icon_theme_cache_post&lt;/code&gt;). This approach has been &lt;a href=&quot;https://lists.opensuse.org/opensuse-factory/2017-06/msg00898.html&quot;&gt;used in Factory since 2017&lt;/a&gt;. File triggers are used for processing icons, mime and desktop files, glib schemas, and others.&lt;/p&gt;

&lt;p&gt;You probably haven’t noticed this change at all, as in general having these database/cache updating macros in your specfile doesn’t harm anything now. The change has been made in corresponding packages (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;texinfo&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shared-mime-info&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;desktop-file-utils&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;glib2&lt;/code&gt;) by adding a file trigger while all these old macros are now expanded to command without action. So you can safely remove them from your specfiles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;! IMPORTANT !&lt;/strong&gt;
Currently (Nov, 2020), zypper doesn’t handle &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transfiletrigger&lt;/code&gt; properly. If there is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%transfiletrigger&lt;/code&gt; and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%post&lt;/code&gt; scriptlet in the transaction, then zypper will only call the scriptlet and not your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%transfiletrigger&lt;/code&gt;. See more information in &lt;a href=&quot;https://bugzilla.opensuse.org/show_bug.cgi?id=1041742&quot;&gt;Bug#1041742&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;autopatch-and-autosetup&quot;&gt;%autopatch and %autosetup&lt;/h2&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autopatch&lt;/code&gt; to automatically apply all patches in the spec file&lt;/li&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autosetup&lt;/code&gt; to automatically run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%setup&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autopatch&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;The old and classic way to apply patches was:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Patch1:     	openssl-1.1.0-no-html.patch
Patch2:     	openssl-truststore.patch
Patch3:     	openssl-pkgconfig.patch

%prep
%setup -q
%patch1 -p1
%patch2 -p1
%patch3 -p1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With the recent RPM, you can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autosetup&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autopatch&lt;/code&gt; macros to automate source unpacking and patch application. There is no need to specify each patch by name.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autopatch&lt;/code&gt; applies all patches from the spec. The disadvantage is that it’s not natively usable with conditional patches or patches with differing fuzz levels.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; (Factory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl-1_1.spec&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Patch1:     	openssl-1.1.0-no-html.patch
Patch2:     	openssl-truststore.patch
Patch3:     	openssl-pkgconfig.patch

%prep
%setup -q
%autopatch -p1 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p&lt;/code&gt; option controls the patch level passed to the patch program.&lt;/p&gt;

&lt;p&gt;The most powerful is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autosetup&lt;/code&gt; macro that combines &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%setup&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autopatch&lt;/code&gt; so that it can unpack the tarball and apply the patchset in one command.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autosetup&lt;/code&gt; accepts virtually the same arguments as %setup except for:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-v&lt;/code&gt; for verbose source unpacking, the quiet mode is the default, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-q&lt;/code&gt; is not applicable&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-N&lt;/code&gt; disables automatic patch application. The patches can be later applied manually using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%patch&lt;/code&gt; or with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autopatch&lt;/code&gt;. It comes in handy in cases where some kind of preprocessing is needed on the upstream sources before applying the patches.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-S&lt;/code&gt; specifies a VCS to use in the build directory. Supported are for example  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hg&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;quilt&lt;/code&gt;. The default is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;patch&lt;/code&gt;, where the patches are simply applied in the directory using patch. Setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; will create a git repository within the build directory with each patch represented as a git commit, which can be useful e.g. for bisecting the patches&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the simplest patch application using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autosetup&lt;/code&gt; will look like this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; (Factory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl-1_1&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Patch1:     	openssl-1.1.0-no-html.patch
Patch2:     	openssl-truststore.patch
Patch3:     	openssl-pkgconfig.patch

%prep
%autosetup -p1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;patchlist-and-sourcelist&quot;&gt;%patchlist and %sourcelist&lt;/h2&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%patchlist&lt;/code&gt; section directive for marking a plain list of patches&lt;/li&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%sourcelist&lt;/code&gt; section directive for marking a plain list of sources&lt;/li&gt;
  &lt;li&gt;Then use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autosetup&lt;/code&gt; instead of %setup and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%patch&amp;lt;number&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;These are new spec file sections for declaring patches and sources with minimal boilerplate. They’re intended to be used in conjunction with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autopatch&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autosetup&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; - normal way (Factory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl-1_1&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Source:     	https://www.%{_rname}.org/source/%{_rname}-%{version}.tar.gz
Source2:    	baselibs.conf
Source3:    	https://www.%{_rname}.org/source/%{_rname}-%{version}.tar.gz.asc
Source4:    	%{_rname}.keyring
Source5:    	showciphers.c

Patch1:     	openssl-1.1.0-no-html.patch
Patch2:     	openssl-truststore.patch
Patch3:     	openssl-pkgconfig.patch

%prep
%autosetup -p1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The files need to be tagged with numbers, so adding a patch in the middle of a series requires renumbering all the consecutive tags.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; - with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%sourcelist&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%patchlist&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;%sourcelist
https://www.%{_rname}.org/source/%{_rname}-%{version}.tar.gz
baselibs.conf
https://www.%{_rname}.org/source/%{_rname}-%{version}.tar.gz.asc
%{_rname}.keyring
showciphers.c

%patchlist
openssl-1.1.0-no-html.patch
openssl-truststore.patch
openssl-pkgconfig.patch

%prep
%autosetup -p1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here the source files don’t need any tagging. The patches are then applied by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%autopatch&lt;/code&gt; in the same order as listed in the section. The disadvantage is that it’s not possible to refer to the sources by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%{SOURCE}&lt;/code&gt; macros or to apply the patches conditionally.&lt;/p&gt;

&lt;h2 id=&quot;elif&quot;&gt;%elif&lt;/h2&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;RPM now supports &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%elif&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%elifos&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%elifarch&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;After 22 years of development, RPM 4.15 finally implemented &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%elif&lt;/code&gt;. It’s now possible to simplify conditions which were only possible with another &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%if&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%else&lt;/code&gt; pair.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%if&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%else&lt;/code&gt; only (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Java:packages/ant&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;%if %{with junit}                                                                                                                                                               	 
%description 
This package contains optional JUnit tasks for Apache Ant.

%else
  %if %{with junit5}

%description
This package contains optional JUnit5 tasks for Apache Ant.

  %else

%description
Apache Ant is a Java-based build tool.

  %endif
%endif
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%elif&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;%if %{with junit}                                                                                                                                                               	 
%description
This package contains optional JUnit tasks for Apache Ant.

%elif %{with junit5}

%description
This package contains optional JUnit5 tasks for Apache Ant.

%else

%description
Apache Ant is a Java-based build tool.

%endif
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;else if&lt;/code&gt; versions were implemented also for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%ifos&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%elifos&lt;/code&gt;) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%ifarch&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%elifarch&lt;/code&gt;).&lt;/p&gt;

&lt;h2 id=&quot;boolean-dependencies&quot;&gt;Boolean dependencies&lt;/h2&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Factory now supports boolean dependency operators that allow rich dependencies&lt;/li&gt;
  &lt;li&gt;Example: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Requires: (sles-release or openSUSE-release)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;RPM 4.13 introduced support for boolean dependencies (also called “rich dependencies”). These expressions are usable in all dependency tags except &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Provides.&lt;/code&gt; This includes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Requires&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Recommends&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Suggests&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Supplements&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enhances&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Conflicts&lt;/code&gt;. Boolean expressions are always enclosed with parentheses. The dependency string can contain package names, comparison, and version description.&lt;/p&gt;

&lt;p&gt;How does it help? It greatly simplifies conditional dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practical example&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Your package needs either of two packages &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pack1&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pack2&lt;/code&gt; to work. Until recently, there wasn’t an elegant way to express this kind of dependency in RPM.&lt;/p&gt;

&lt;p&gt;The idiomatic way was to introduce a new capability, which both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pack1&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pack2&lt;/code&gt; would provide, and which can then be required from your package.&lt;/p&gt;

&lt;p&gt;Both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pack1&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pack2&lt;/code&gt; packages would need adding:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Provides:    pack-capability 	
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And your package would require this capability:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Requires:    pack-capability 	
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So in order to require one of a set of packages, you had to modify each of them to introduce the new capability. That was a lot of extra effort and might not have always been possible.&lt;/p&gt;

&lt;p&gt;Nowadays, using boolean dependencies, you can just simply add&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Requires:    (pack1 or pack2)                                                                                                                                                        
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;to your package and everything will work as expected, no need to touch any other package.&lt;/p&gt;

&lt;p&gt;The following boolean operators were introduced in RPM 4.13. Any set of available packages can match the requirements.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;and&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;all operands must be met&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Conflicts: (pack1 &amp;gt;= 1.1 and pack2)&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;or&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;one of the operands must be met&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Requires: (sles-release or openSUSE-release)&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;The package requires (at least one of) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sles-release&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openSUSE-release&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;the first operand must be met if the second is fulfilled&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Requires: (grub2-snapper-plugin if snapper)&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if-else&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;same as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; above, plus requires the third operand to be met if the second one isn’t fulfilled&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Requires: (subpack1 if pack1 else pack2)&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RPM 4.14 added operators that work on single packages. Unlike the operators above, there must be a single package that fulfills all the operands&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;and&lt;/code&gt;, both conditions need to be met&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuildRequires: (python3-prometheus_client &amp;gt;= 0.4.0 with python3-prometheus_client &amp;lt; 0.9.0)&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python3-prometheus_client&lt;/code&gt; must be in the range &amp;lt;0.4.0, 0.9.0)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;without&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;the first operand needs to be met, the second must not&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Conflicts: (python2 without python2_split_startup)&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unless&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;the first operand must be met if the second is not&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Conflicts: (pack1 unless pack2)&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unless-else&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;same as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unless&lt;/code&gt; above, plus requires the third operand to be met if the second isn’t fulfilled&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Conflicts: (pack1 unless pack2 else pack3)&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The operands can be nested. They need to be surrounded by parentheses, except for chains of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;and&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;or&lt;/code&gt; operators.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Recommends: (gdm or lightdm or sddm)
Requires: ((pack1) or (pack2 without func2))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Until recently, Factory only allowed boolean dependencies in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Recommends&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Suggests&lt;/code&gt; (aka soft dependencies), as it would have otherwise caused issues when doing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zypper dup&lt;/code&gt; from older distros. Now all operators above are supported.&lt;/p&gt;

&lt;h2 id=&quot;license&quot;&gt;%license&lt;/h2&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Pack license files via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%license&lt;/code&gt; directive, not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%doc&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A %license&lt;/code&gt; directive was added to RPM in &lt;a href=&quot;https://lwn.net/Articles/535284/&quot;&gt;4.11.0&lt;/a&gt; (2013) but openSUSE and other distributions adopted it later, in &lt;a href=&quot;https://lists.opensuse.org/opensuse-factory/2016-02/msg00167.html&quot;&gt;2016&lt;/a&gt;. The main reason for it is to allow easy separation of licenses from normal documentation. Before this directive, license texts used to be marked with the  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%doc&lt;/code&gt; directive, that managed copying of the license to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%_defaultdocdir&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share/doc/packages)&lt;/code&gt;. With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%license&lt;/code&gt;, it’s nicely separated as is copied to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%_defaultlicensedir&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share/licenses&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;That’s also useful for limited systems (e.g. containers), which are built without doc files, but still need to ship package licenses for legal reasons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;%files
%license LICENSE COPYING
%doc NEWS README.SUSE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The license files are annotated in the rpm, which allows a search for the license files of a specific package:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ rpm -qL sudo
/usr/share/licenses/sudo/LICENSE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;obs&quot;&gt;OBS&lt;/h1&gt;

&lt;p align=&quot;center&quot;&gt;
  &lt;img width=&quot;500&quot; height=&quot;229&quot; src=&quot;/assets/OBS_logo.png&quot; /&gt;
&lt;/p&gt;

&lt;h2 id=&quot;new-osc-options&quot;&gt;New osc options&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;osc&lt;/code&gt; command-line tool received several new features as well. Let’s have a quick look at the most interesting changes.&lt;/p&gt;

&lt;h3 id=&quot;osc-maintained-version&quot;&gt;osc maintained –version&lt;/h3&gt;

&lt;p&gt;New &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--version&lt;/code&gt; option prints versions of the maintained package in each codestream, which is very useful e.g. when you want to find out which codestreams are affected by a specific issue. The only problem is that it’s not very reliable yet - sometimes it prints just “&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unknown&lt;/code&gt;”.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ osc maintained --version sudo
openSUSE:Leap:15.1:Update/sudo (version: unknown)
openSUSE:Leap:15.2:Update/sudo (version: 1.8.22)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;osc-request-incoming&quot;&gt;osc request –incoming&lt;/h3&gt;

&lt;p&gt;New &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--incoming&lt;/code&gt; option for request command shows only requests/reviews where the project is the target.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; List all incoming request in the new or review state for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Base:System&lt;/code&gt; project:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ osc request list Base:System --incoming -s new,review
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;osc-browse&quot;&gt;osc browse&lt;/h3&gt;

&lt;p&gt;Sometimes it’s just easier to watch the build status or build log in OBS GUI than via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;osc&lt;/code&gt;. With this new option, you can easily open specific packages in your browser. Just run:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ osc browse [PROJECT [PACKAGE]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you run it without any parameters, it will open the package in your current working directory.&lt;/p&gt;

&lt;h3 id=&quot;delete-requests-for-entire-projects&quot;&gt;Delete requests for entire projects&lt;/h3&gt;

&lt;p&gt;This is not something you want to call every day. But if you need to delete the entire project with all packages inside, you can just call:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ osc deletereq PROJECT --all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;real-names-in-changelogs&quot;&gt;Real names in changelogs&lt;/h3&gt;

&lt;p&gt;This is a change you probably noticed. If you create a changelog entry via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;osc vc&lt;/code&gt;, it adds not just your email to the changelog entry header but also your full name.&lt;/p&gt;

&lt;h3 id=&quot;rdiff-and-diff-enhancements&quot;&gt;rdiff and diff enhancements&lt;/h3&gt;

&lt;p&gt;Also, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rdiff&lt;/code&gt; subcommand comes with new options. Probably the most useful is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rdiff --issues-only&lt;/code&gt; that instead of printing the whole diff, shows just a list of fixed (mentioned really) issues (bugs, CVEs, Jiras):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;osc rdiff --issues-only&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# osc rdiff -c 124 --issues-only openSUSE:Factory/gnutls      
CVE-2020-13777
boo#1171565
boo#1172461
boo#1172506
boo#1172663
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;More new options were added for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;osc diff&lt;/code&gt; command. The first is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--unexpand&lt;/code&gt; that performs a local diff, ignoring linked package sources. The second is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff --meta&lt;/code&gt; that performs a diff only on meta files.&lt;/p&gt;

&lt;h3 id=&quot;osc-blame&quot;&gt;osc blame&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;osc&lt;/code&gt; finally comes with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blame&lt;/code&gt; command that you probably know from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;. It shows who last modified each line of a tracked file.&lt;/p&gt;

&lt;p&gt;It uses the same invocation as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;osc cat&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ osc blame &amp;lt;file&amp;gt;
$ osc blame &amp;lt;project&amp;gt; &amp;lt;package&amp;gt; &amp;lt;file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The drawback is that it shows the user who checked in the revision, such as the person who accepted the submission, not its actual author. But it also shows the revision number in the first column, so you can easily show the specific revision with the original author.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# osc blame openssl-fips-DH_selftest_shared_secret_KAT.patch
[...]
   2 (jsikes       2020-09-17 10:51:27    62) +
   5 (jsikes       2020-09-22 19:07:01    63) +    if ((len = DH_compute_key(shared_secret, dh-&amp;gt;pub_key, dh)) == -1)
   2 (jsikes       2020-09-17 10:51:27    64) +        goto err;
   2 (jsikes       2020-09-17 10:51:27    65) +
[...]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s say we’re interested in line 63, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DH_compute_key()&lt;/code&gt; is called. It was last changed in revision 5, so we’ll examine that revision:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; osc log -r 5
----------------------------------------------------------------------------
r5 | jsikes | 2020-09-22 17:07:01 | 16a582f1397aa14674261a54c74056ce | unknown | rq227064

Fix a porting bug in openssl-fips-DH_selftest_shared_secret_KAT.patch
----------------------------------------------------------------------------
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The change was created by request 227064, so we can finally find the author of the actual code:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ osc rq show -b 227064
227064  State:accepted   By:jsikes       When:2020-09-22T17:07:07
        submit:          
        From: Request created: vitezslav_cizek -&amp;gt; Request got accepted: jsikes
        Descr: Fix a porting bug in openssl-fips-
               DH_selftest_shared_secret_KAT.patch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also blame the meta files and show the author of each line of the meta file, where it shows the author, as the metadata is edited directly.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ osc meta pkg &amp;lt;project&amp;gt; &amp;lt;package&amp;gt; --blame
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Please note that it works on project and package metadata but it doesn’t work on attributes.&lt;/p&gt;

&lt;h3 id=&quot;osc-comment&quot;&gt;osc comment&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;osc&lt;/code&gt; allows you to work with comments on projects, packages, and requests from the command line. That’s particularly useful for writing bots and other automatic handling.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;osc comment list&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Prints comments for a project, package, or a request.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;osc comment create&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Adds a new top-level comment, or using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p&lt;/code&gt; option, a reply to an existing one.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;osc comment delete&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Removes a comment with the given ID.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;examining-workers-and-constraints&quot;&gt;Examining workers and constraints&lt;/h3&gt;

&lt;h4 id=&quot;osc-checkconstraints&quot;&gt;osc checkconstraints&lt;/h4&gt;

&lt;p&gt;When you have a package that has special build constraints, you might be curious about how many OBS workers are able to build it. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;osc checkconstraints&lt;/code&gt; does exactly that.&lt;/p&gt;

&lt;p&gt;It can either print the list of matching workers&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ osc checkconstraints LibreOffice:Factory libreoffice openSUSE_Tumbleweed x86_64
Worker     	 
------     	 
x86_64:cloud137:1
x86_64:cloud138:1
x86_64:goat01:1
x86_64:goat01:2
[...]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;or even a per-repo summary (when called from a package checkout):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ osc checkconstraints
Repository            	Arch                  	Worker
----------            	----                  	------
openSUSE_Tumbleweed   	x86_64                	94
openSUSE_Factory_zSystems  s390x                   	18
[...]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;osc-workerinfo&quot;&gt;osc workerinfo&lt;/h4&gt;

&lt;p&gt;This command prints out detailed information about the worker’s hardware, which can be useful when searching for proper build constraints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ osc workerinfo x86_64:goat01:1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It will print &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lamb51's&lt;/code&gt; kernel version, CPU flags, amount of CPUs, and available memory and disk space.&lt;/p&gt;

&lt;h2 id=&quot;multibuild&quot;&gt;Multibuild&lt;/h2&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Multibuild is an OBS feature that allows you to build the same spec file with different flavors (e.g. once with GUI and then without GUI)&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;multibuild&lt;/code&gt;  is an OBS feature introduced in &lt;a href=&quot;https://openbuildservice.org/2017/04/07/version-2.8/&quot;&gt;OBS 2.8 (2017)&lt;/a&gt;  that offers the ability to build the same source in the same repo with different flavors. Such a spec file is easier to maintain than separate spec files for each flavor.&lt;/p&gt;

&lt;p&gt;The flavors are defined in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_multibuild&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xml&lt;/code&gt; file in the package source directory. In addition to the normal package, each of the specified flavors will be built for each repository and architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_multibuild&lt;/code&gt; file (from Factory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-pbr&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;multibuild&amp;gt;
  &amp;lt;package&amp;gt;test&amp;lt;/package&amp;gt;
&amp;lt;/multibuild&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here OBS will build the regular &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-pbr&lt;/code&gt; package and additionally the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; flavored RPM. Users can then distinguish the different flavors in spec using and perform corresponding actions (adjusting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuildRequires&lt;/code&gt;, package names/descriptions, turning on additional build switches, etc.).&lt;/p&gt;

&lt;p&gt;Here we can see, that an additional flavor is getting built:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ osc r -r standard -a x86_64
standard         	x86_64 	python-pbr                 	succeeded
standard         	x86_64 	python-pbr:test            	succeeded
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; of spec file usage (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-pbr&lt;/code&gt; again):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;%global flavor @BUILD_FLAVOR@%{nil}
%if &quot;%{flavor}&quot; == &quot;test&quot;
%define psuffix -test
%bcond_without test
%else
%define psuffix %{nil}
%bcond_with test
%endif
Name:       	python-pbr%{psuffix}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;First, the spec defines a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flavor&lt;/code&gt; macro as the value it got from OBS. Then it branches the spec depending on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flavor&lt;/code&gt; value. It sets a name suffix for the test flavor and defines a build conditional for easier further handling in the build and install sections.&lt;/p&gt;

&lt;p&gt;If you need inspiration for your package, you can have a look at the following packages:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python39&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libssh&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-pbr&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;glibc&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;oldies&quot;&gt;Oldies&lt;/h1&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PreReq&lt;/code&gt; is now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Requires(pre)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/run&lt;/code&gt;, not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/run&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/bin&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/sbin&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/lib&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/lib64&lt;/code&gt; were merged into their counterpart directories under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SysV&lt;/code&gt; is dead, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;We realize that the changes described below are very, &lt;em&gt;very&lt;/em&gt;, VERY old. But we put this section here anyway as we are still seeing it in some spec files from time to time. So let’s take it quickly.&lt;/p&gt;

&lt;h2 id=&quot;prereq--requirespre&quot;&gt;PreReq → Requires(pre)&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PreReq &lt;/code&gt;is not used anymore, it was deprecated and remapped to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Requires(pre)&lt;/code&gt; in RPM 4.8.0 (2010).&lt;/p&gt;

&lt;h2 id=&quot;varrun--run&quot;&gt;/var/run → /run&lt;/h2&gt;

&lt;p&gt;Since openSUSE 12.2 (2012), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/run&lt;/code&gt; directory was top-leveled as it was agreed across the distributions, that it doesn’t belong under&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt; /var.&lt;/code&gt; It’s still symlinked for backward compatibility but you should definitely use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/run&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%_rundir&lt;/code&gt; macro).&lt;/p&gt;

&lt;h2 id=&quot;usr-merge&quot;&gt;/usr Merge&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge/&quot;&gt;/usr Merge&lt;/a&gt; was a big step in the history of all Linux distributions that helped to improve compatibility with other Unixes/Linuxes, GNU build systems or general upstream development.&lt;/p&gt;

&lt;p&gt;In short, it aimed to merge and move content from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/bin&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/sbin&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/lib&lt;/code&gt; and /&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lib64&lt;/code&gt; into their counterpart directories under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr&lt;/code&gt; (and creating backward compatibility symbolic links of course). In openSUSE it happened around 2012.&lt;/p&gt;

&lt;h2 id=&quot;sysv-is-dead&quot;&gt;SysV is dead&lt;/h2&gt;

&lt;p&gt;The only excuse for missing the fact that SysV is dead is just that you’ve been in cryogenic hibernation for the last 10 years. If yes, then it’s the year 2020 and since openSUSE 12.3 (2013) we use &lt;a href=&quot;https://en.opensuse.org/openSUSE:Systemd_packaging_guidelines&quot;&gt;systemd&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;automatic-tools-for-cleaning&quot;&gt;Automatic tools for cleaning&lt;/h1&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spec-cleaner -i mypackage.spec&lt;/code&gt; to clean your specfile according to the openSUSE style guide.&lt;/li&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpmlint mypackage.rpm&lt;/code&gt; or inspect the rpmlint report generated after the OBS build for common packaging errors/warnings.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;If you read as far as here, you are probably a bit overwhelmed with all these new things in packaging. Maybe you ask yourself how you should remember all of it or more importantly, how you should keep all your maintained packages consistent with all these changes. We have good news for you. There are automated tools for it.&lt;/p&gt;

&lt;h2 id=&quot;spec-cleaner&quot;&gt;spec-cleaner&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/rpm-software-management/spec-cleaner&quot;&gt;spec-cleaner&lt;/a&gt; is a tool that cleans the RPM spec file according to the style guide. It can put the lines in the right order, transform hardcoded paths with the correct macros, and mainly replace all old macros with new ones. And it can do much more.&lt;/p&gt;

&lt;p&gt;It’s also very easy to use it, just call&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ spec-cleaner -i mypackage.spec
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;for applying all changes inline directly to your spec file.&lt;/p&gt;

&lt;p&gt;If you just want to watch the diff of the changes that spec-cleaner would make, call:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ spec-cleaner -d mypackage.spec 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;rpmlint&quot;&gt;rpmlint&lt;/h2&gt;

&lt;p&gt;Another tool that will help you keep your package in a good shape is &lt;a href=&quot;https://github.com/rpm-software-management/rpmlint&quot;&gt;rpmlint&lt;/a&gt;. It checks common errors in RPM packages and specfiles. It can find file duplicates, check that  binaries are in the proper location, keep an eye on correct libraries, systemd, tmpfiles packaging and much more. Inspecting your package from top to bottom, it reports any error or warning.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpmlint&lt;/code&gt; runs automatically during the OBS build so it can fail the whole build if there are serious problems. It works as a tool for enforcing specific standards in packages built within OBS. If you want to run it on your own, call:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ rpmlint mypackage.rpm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spec-cleaner&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpmlint&lt;/code&gt; implement the new packaging changes and new rules as soon as possible. But it’s possible that maintainers may miss something. In that case, feel free to report it as an issue on their github.&lt;/p&gt;

&lt;h1 id=&quot;acknowledgment&quot;&gt;Acknowledgment&lt;/h1&gt;

&lt;p&gt;Thanks, &lt;a href=&quot;mailto:sflees@suse.de&quot;&gt;Simon Lees&lt;/a&gt;, &lt;a href=&quot;mailto:tchvatal@suse.com&quot;&gt;Tomáš Chvátal&lt;/a&gt;, and &lt;a href=&quot;mailto:dimstar@opensuse.org&quot;&gt;Dominique Leuenberger&lt;/a&gt; for suggestions, corrections, and proofreading.&lt;/p&gt;</content><author><name></name></author><category term="packaging" /><summary type="html">If you are interested in openSUSE, sooner or later you will probably learn how packages and specfiles work. But packaging is not static knowledge that you learn once and are good to go. The rules change over time, new macros are created and old ones are erased from history, new file paths are used and the old ones are forgotten. So how can one keep up with these changes?</summary></entry></feed>