This is a fairly boring research as I need it at work. I would like to have a single RPM, which reports correct dependences for each O/S its run on. The code that I creating is the same code, which is why only one RPM seems correct. A theoretical answer is to specify the required file (e.g. gcc); rather than what package it is shipped in; but I am unable to achieve this today. I am constrained to base everything on RH family servers, as they have the best OS support contract for many enterprises.

High speed intro: RPMs, spec files, grammar

RPMs are built from raw files that go in the RPM; and a spec file 1 which is the same idea as a written recipe. Most of the complex behaviour is copying the content of the spec file. The spec defines a number of state change code-blocks 2 3 4 (e.g. to build the code, to erase the package etc). Redhat call these “directives”.
These blocks are effectively sh scripts 5; but cannot be used to manage dependencies as the rest of package system couldn't see this. The block names start with a '%' char; if you use a text editor with the relevant syntax highlighting; this saves time. As a normal shell script, there are variables and branching; RPM defines things like %RPM_BUILD_ROOT 6. Some real spec files 7 , to use as an example. The RPM header allow the definition of %patch blocks; but assuming European DSL, this seems like a fairly pointless feature (patch files saw most use under historical low-bandwidth usenet, but are quite fiddly).

Managing OS version in spec files

The RPM system supports several layers of macros 8 (or maybe its same same structure but accessed in different methods). Like the old fashioned init.d scripts, any value can contain %{name} blobs, which are like PHP/Perl/bash string interpolation. Secondly to this the blobs can be pulled in from the CLI env of rpmbuild, or from each other 9.
For my specific use case I need to know what operating system, and version of operating system the current RPM is being deployed to. I can create branches outside of the sh scripts, using RPM macros 10, which include a %if structure 11 and %{error:...}. RPM support lua, via %{lua:...} 12, and have some variables that look a lot like traditional make , e.g. %_bindir 13 14.
I can look at the “prime OS package”, in quite a few RH operating systems. This is exposed in a variable e.g. “redhat-release-server-6Server” 15. To use this, I can check the existence of variables; this solution is not concise as each different variant would need to be held separately. A better reference 16; lists all the variable names. In 2011, it was claimed that there was complex clause support in the RPM system 17 (pls read article, the samples are too long to quote here).
It is possible to probe the file-system, using bash 18. I can script solutions using Lua, or whatever the “define” language is called e.g. 19.

This isn't the focal point of this text; but its sometimes useful to know whether an RPM process is an upgrade, an install, or a remove operation. I thought there was different macros for those state changes; but as plan B; one can tell due to an extra variable 20.

Manage version on other tool

A dependency may change due to a third tool (e.g., if Apache is present do X, if NginX is present do Y). Some people solve this problem by building two separate RPMs; but this can be confusing to business clients (who are buying a solution not a lifestyle). Meta packages are a way that this is managed with “core platform things”, e.g. “install libC” will map to: if 32bit kernel use libC_386; if 64bit kernel use libC_amd64.
Obviously the previous sentences mentioning bash and lua maybe applied here.

Some similar articles in research