CMake's CPack can create RPM packages. It has the ability to use a spec file template to customize the RPM (by default it generates the spec file for you). This is often an easier way to integrate RPM creation into a software project.
fpm creates RPMs without having to build a proper spec. Sometimes this can be desirable; at other times, a traditional spec file is preferable. For instance, a spec file generally encourages you to build from a clean upstream source package.
Several tools are available in the
Spectool can be used to download the source files for an RPM spec. For example:
spectool -g haproxy.spec
rpmdev-newspec helps to create new spec files.
Mock can be used to build packages in an isolated chroot environment, ensuring they are build cleanly and have correct BuildRequires specified. One machine (probably RHEL7) can be used to build RPMs for multiple environments (e.g. RHEL5 i386, RHEL5 x86_64, RHEL6…).
Docker is another way to build packages in an isolated environment.
Examples of non-RPM packages built with Docker:
Spec files from e.g. Fedora may be useful to look at, even if they can't be used directly. You can download SRPMs from RHEL/CentOS, EPEL, or Fedora and extract them to get the specs; other specs are available directly in repositories online.
In general, RPMs can only be used with the specific version of the distro they were created for (e.g. don't try to install Fedora RPMs on RHEL). Spec files for other distros/versions often need to be modified to work elsewhere.
Architecture-specific Dependencies (note that the "_isa" macros are not defined on RHEL5).
These appear to be generated by AutoReq/AutoProv when there are files marked as configuration, but it's not exactly clear.
The only information I found so far on this is a mailing list message: https://www.redhat.com/archives/rpm-list/2002-October/msg00133.html
You can get the dist on RHEL/Fedora by running
Mock will set the dist variables, but rpmbuild will not. I have a wrapper script for rpmbuild that does it.