{"id":4520,"date":"2018-01-08T11:13:51","date_gmt":"2018-01-08T11:13:51","guid":{"rendered":"http:\/\/www.scmgalaxy.com\/tutorials\/?p=4520"},"modified":"2018-09-25T10:16:52","modified_gmt":"2018-09-25T10:16:52","slug":"basic-rpm-tutorials","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/basic-rpm-tutorials\/","title":{"rendered":"Basic RPM Tutorials"},"content":{"rendered":"<h2>Basic RPM Tutorials<\/h2>\n<h2>Introduction:<\/h2>\n<p><a id=\"INTRO\" name=\"INTRO\"><\/a>RPM is the\u00a0<em>R<\/em>PM\u00a0<em>P<\/em>ackage\u00a0<em>M<\/em>anager. It is an open packaging system available for anyone to use. It allows users to take source code for new software and package it into source and binary form such that binaries can be easily installed and tracked and source can be rebuilt easily. It also maintains a database of all packages and their files that can be used for verifying packages and querying for information about files and\/or packages.<br \/>\nRed Hat, Inc. encourages other distribution vendors to take the time to look at RPM and use it for their own distributions. RPM is quite flexible and easy to use, though it provides the base for a very extensive system.<\/p>\n<p><strong>RPM Basic usage command<\/strong><br \/>\n<a id=\"USE\" name=\"USE\"><\/a><strong>In its simplest form, RPM can be used to install packages:<\/strong><br \/>\nrpm -i foobar-1.0-1.i386.rpm<br \/>\n<strong>The next simplest command is to uninstall a package:<\/strong><\/p>\n<pre>rpm -e foobar<\/pre>\n<p><strong>While these are simple commands, rpm can be used in a multitude of ways. To see which options are available in your version of RPM, type:<\/strong><\/p>\n<pre>rpm \u2013help<\/pre>\n<pre><strong>You can find more details on what those options do in the RPM man page, found by typing:<\/strong><\/pre>\n<pre>man rpm<\/pre>\n<p><a id=\"RPM-DO\" name=\"RPM-DO\"><\/a><strong>Let&#8217;s say you delete some files by accident, but you aren&#8217;t sure what you deleted. If you want to verify your entire system and see what might be missing, you would do:<\/strong><\/p>\n<pre>rpm -Va<\/pre>\n<p><strong>Let&#8217;s say you run across a file that you don&#8217;t recognize. To find out which package owns it, you would do:<\/strong><\/p>\n<pre>rpm -qf \/usr\/X11R6\/bin\/xjewel<\/pre>\n<p><strong>Now you want to see what files the koules RPM installs. You would do:<\/strong><\/p>\n<pre>rpm -qpi koules-1.2-2.i386.rpm<\/pre>\n<pre><\/pre>\n<h2>Building RPMs<\/h2>\n<p><a id=\"BUILD\" name=\"BUILD\"><\/a>The basic procedure to build an RPM is as follows:<\/p>\n<ul>\n<li>Get the source code you are building the RPM for to build on your system.<\/li>\n<li>Make a patch of any changes you had to make to the sources to get them to build properly.<\/li>\n<li>Make a spec file for the package.<\/li>\n<li>Make sure everything is in its proper place.<\/li>\n<li>Build the package using RPM.<\/li>\n<\/ul>\n<h2>The Spec File<\/h2>\n<pre><a id=\"SPEC-FILE\" name=\"SPEC-FILE\"><\/a>Here is a small spec file (eject-2.0.2-1.spec):<\/pre>\n<pre><\/pre>\n<pre>Summary: A program that ejects removable media using software control.<\/pre>\n<pre>Name: eject<\/pre>\n<pre>Version: 2.0.2<\/pre>\n<pre>Release: 3<\/pre>\n<pre>Copyright: GPL<\/pre>\n<pre>Group: System Environment\/Base<\/pre>\n<pre>Source: http:\/\/metalab.unc.edu\/pub\/Linux\/utils\/disk-management\/eject-2.0.2.tar.gz<\/pre>\n<pre>Patch: eject-2.0.2-buildroot.patch<\/pre>\n<pre>BuildRoot: \/var\/tmp\/%{name}-buildroot<\/pre>\n<pre>%description<\/pre>\n<pre>The eject program allows the user to eject removable media<\/pre>\n<pre>(typically CD-ROMs, floppy disks or Iomega Jaz or Zip disks)<\/pre>\n<pre>using software control. Eject can also control some multi-<\/pre>\n<pre>disk CD changers and even some devices' auto-eject features.<\/pre>\n<pre>Install eject if you'd like to eject removable media using<\/pre>\n<pre>software control.<\/pre>\n<pre>%prep<\/pre>\n<pre>%setup -q<\/pre>\n<pre>%patch -p1 -b .buildroot<\/pre>\n<pre>%build<\/pre>\n<pre>make RPM_OPT_FLAGS=\"$RPM_OPT_FLAGS\"<\/pre>\n<pre><\/pre>\n<pre>%install<\/pre>\n<pre>rm -rf $RPM_BUILD_ROOT<\/pre>\n<pre>mkdir -p $RPM_BUILD_ROOT\/usr\/bin<\/pre>\n<pre>mkdir -p $RPM_BUILD_ROOT\/usr\/man\/man1<\/pre>\n<pre><\/pre>\n<pre>install -s -m 755 eject $RPM_BUILD_ROOT\/usr\/bin\/eject<\/pre>\n<pre>install -m 644 eject.1 $RPM_BUILD_ROOT\/usr\/man\/man1\/eject.1<\/pre>\n<pre><\/pre>\n<pre>%clean<\/pre>\n<pre>rm -rf $RPM_BUILD_ROOT<\/pre>\n<pre><\/pre>\n<pre>%files<\/pre>\n<pre>%defattr(-,root,root)<\/pre>\n<pre>%doc README TODO COPYING ChangeLog<\/pre>\n<pre><\/pre>\n<pre>\/usr\/bin\/eject<\/pre>\n<pre>\/usr\/man\/man1\/eject.1<\/pre>\n<pre><\/pre>\n<pre>%changelog<\/pre>\n<pre>* Sun Mar 21 1999 Cristian Gafton &lt;gafton@redhat.com&gt;<\/pre>\n<pre>- auto rebuild in the new build environment (release 3)<\/pre>\n<pre><\/pre>\n<pre>* Wed Feb 24 1999 Preston Brown &lt;pbrown@redhat.com&gt;<\/pre>\n<pre>- Injected new description and group.<\/pre>\n<pre><\/pre>\n<pre>[ Some changelog entries trimmed for brevity.\u00a0 -Editor. ]<\/pre>\n<pre><strong>\u00a0<\/strong><\/pre>\n<p><a id=\"HEADER\" name=\"HEADER\"><\/a><strong>The Header<\/strong><br \/>\nThe header has some standard fields in it that you need to fill in. There are a few caveats as well. The fields must be filled in as follows:<br \/>\nThe header has some standard fields in it that you need to fill in. There are a few caveats as well. The fields must be filled in as follows:<\/p>\n<ul>\n<li><em>Summary:<\/em>\u00a0This is a one line description of the package.<\/li>\n<li><em>Name:<\/em>\u00a0This must be the name string from the rpm filename you plan to use.<\/li>\n<li><em>Version:<\/em>\u00a0This must be the version string from the rpm filename you plan to use.<\/li>\n<li><em>Release:<\/em>\u00a0This is the release number for a package of the same version (ie. if we make a package and find it to be slightly broken and need to make it again, the next package would be release number 2).<\/li>\n<li><em>Copyright:<\/em>\u00a0This line tells how a package is copyrighted. You should use something like GPL, BSD, MIT, public domain, distributable, or commercial.<\/li>\n<li><em>Group:<\/em>\u00a0This is a group that the package belongs to in a higher level package tool or the Red Hat installer.<\/li>\n<li><em>Source:<\/em>\u00a0This line points at the HOME location of the pristine source file. It is used if you ever want to get the source again or check for newer versions. Caveat: The filename in this line MUST match the filename you have on your own system (ie. don&#8217;t download the source file and change its name). You can also specify more than one source file using lines like:<\/li>\n<\/ul>\n<pre>Source0: blah-0.tar.gz<\/pre>\n<pre>Source1: blah-1.tar.gz<\/pre>\n<pre>Source2: fooblah.tar.gz<\/pre>\n<p>These files would go in the SOURCES directory. (The directory structure is discussed in a later section, &#8220;The Source Directory Tree&#8221;.)<br \/>\n\u00b7\u00a0\u00a0<em>Patch:<\/em>\u00a0This is the place you can find the patch if you need to download it again. Caveat: The filename here must match the one you use when you make YOUR patch. You may also want to note that you can have multiple patch files much as you can have multiple sources. ] You would have something like:<\/p>\n<pre>Patch0: blah-0.patch<\/pre>\n<pre>Patch1: blah-1.patch<\/pre>\n<pre>Patch2: fooblah.patch<\/pre>\n<p>These files would go in the SOURCES directory.<br \/>\n<em>Group:<\/em>\u00a0This line is used to tell high level installation programs (such as Red Hat&#8217;s gnorpm) where to place this particular program in its hierarchical structure. You can find the latest description in \/usr\/doc\/rpm*\/GROUPS.<br \/>\n\u00b7\u00a0\u00a0<em>BuildRoot:<\/em>\u00a0This line allows you to specify a directory as the &#8220;root&#8221; for building and installing the new package. You can use this to help test your package before having it installed on your machine.<br \/>\n\u00b7\u00a0\u00a0<em>%description<\/em>\u00a0It&#8217;s not really a header item, but should be described with the rest of the header. You need one description tag per package and\/or subpackage. This is a multi-line field that should be used to give a comprehensive description of the package.<\/p>\n<h2><a id=\"PREP\" name=\"PREP\"><\/a>Prep<\/h2>\n<p>This is the second section in the spec file. It is used to get the sources ready to build. Here you need to do anything necessary to get the sources patched and setup like they need to be setup to do a\u00a0<strong>make<\/strong>.<br \/>\nOne thing to note: Each of these sections is really just a place to execute shell scripts. You could simply make an sh script and put it after the\u00a0<em>%prep<\/em>\u00a0tag to unpack and patch your sources. We have made macros to aid in this, however.<br \/>\nThe first of these macros is the\u00a0<em>%setup<\/em>\u00a0macro. In its simplest form (no command line options), it simply unpacks the sources and\u00a0<strong>cd<\/strong>&#8216;s into the source directory. It also takes the following options:<\/p>\n<ul>\n<li><em>-n name<\/em>\u00a0will set the name of the build directory to the listed\u00a0<em>name<\/em>. The default is\u00a0<em>$NAME-$VERSION<\/em>. Other possibilities include\u00a0<em>$NAME<\/em>,\u00a0<em>${NAME}${VERSION}<\/em>, or whatever the main tar file uses. (Please note that these &#8220;$&#8221; variables are\u00a0<em>not<\/em>real variables available within the spec file. They are really just used here in place of a sample name. You need to use the real name and version in your package, not a variable.)<\/li>\n<li><em>-c<\/em>\u00a0will create and cd to the named directory\u00a0<em>before<\/em>\u00a0doing the untar.<\/li>\n<li><em>-b #<\/em>\u00a0will untar Source#\u00a0<em>before<\/em>\u00a0<strong>cd<\/strong>&#8216;ing into the directory (and this makes no sense with\u00a0<em>-c<\/em>\u00a0so don&#8217;t do it). This is only useful with multiple source files.<\/li>\n<li><em>-a #<\/em>\u00a0will untar Source#\u00a0<em>after<\/em>\u00a0cd&#8217;ing into the directory.<\/li>\n<li><em>-T<\/em>\u00a0This option overrides the default action of untarring the Source and requires a\u00a0<em>-b 0<\/em>\u00a0or\u00a0<em>-a 0<\/em>\u00a0to get the main source file untarred. You need this when there are secondary sources.<\/li>\n<li><em>-D<\/em>\u00a0Do\u00a0<em>not<\/em>\u00a0delete the directory before unpacking. This is only useful where you have more than one setup macro. It should\u00a0<em>only<\/em>\u00a0be used in setup macros\u00a0<em>after<\/em>\u00a0the first one (but never in the first one).<\/li>\n<\/ul>\n<p>The next of the available macros is the\u00a0<em>%patch<\/em>\u00a0macro. This macro helps automate the process of applying patches to the sources. It takes several options, listed below:<\/p>\n<ul>\n<li><em>#<\/em>\u00a0will apply Patch# as the patch file.<\/li>\n<li><em>-p #<\/em>\u00a0specifies the number of directories to strip for the patch(1) command.<\/li>\n<li><em>-P<\/em>\u00a0The default action is to apply\u00a0<strong>Patch<\/strong>\u00a0(or\u00a0<strong>Patch0<\/strong>). This flag inhibits the default action and will require a\u00a0<em>0<\/em>\u00a0to get the main source file untarred. This option is useful in a second (or later)\u00a0<strong>%patch<\/strong>\u00a0macro that required a different number than the first macro.<\/li>\n<li>You can also do\u00a0<strong>%patch#<\/strong>\u00a0instead of doing the real command:\u00a0<strong>%patch # -P<\/strong><\/li>\n<li><em>-b extension<\/em>\u00a0will save originals as filename.extension before patching.<\/li>\n<\/ul>\n<p>That should be all the macros you need. After you have those right, you can also do any other setup you need to do via sh type scripting. Anything you include up until the\u00a0<em>%build<\/em>\u00a0macro (discussed in the next section) is executed via sh. Look at the example above for the types of things you might want to do here.<\/p>\n<h2>Build<\/h2>\n<p><a id=\"BUILD-SPEC\" name=\"BUILD-SPEC\"><\/a>There aren&#8217;t really any macros for this section. You should just put any commands here that you would need to use to build the software once you had untarred the source, patched it, and cd&#8217;ed into the directory. This is just another set of commands passed to sh, so any legal sh commands can go here (including comments).<br \/>\nThe variable RPM_OPT_FLAGS is set using values in \/usr\/lib\/rpm\/rpmrc. Look there to make sure you are using values appropriate for your system (in most cases you are). Or simply don&#8217;t use this variable in your spec file. It is optional.<\/p>\n<h2><a id=\"INSTALL\" name=\"INSTALL\"><\/a>Install<\/h2>\n<p>There aren&#8217;t really any macros here, either. You basically just want to put whatever commands here that are necessary to install. If you have\u00a0<strong>make install<\/strong>\u00a0available to you in the package you are building, put that here. If not, you can either patch the makefile for a\u00a0<strong>make install<\/strong>\u00a0and just do a\u00a0<strong>make install<\/strong>\u00a0here, or you can hand install them here with sh commands. You can consider your current directory to be the toplevel of the source directory.<br \/>\nThe variable RPM_BUILD_ROOT is available to tell you the path set as the\u00a0<em>Buildroot:<\/em>\u00a0in the header. Using build roots are optional but are highly recommended because they keep you from cluttering your system with software that isn&#8217;t in your RPM database (building an RPM doesn&#8217;t touch your database&#8230;you must go install the binary RPM you just built to do that).<\/p>\n<h2><a id=\"SCRIPTS\" name=\"SCRIPTS\"><\/a>Optional pre and post Install\/Uninstall Scripts<\/h2>\n<p>You can put scripts in that get run before and after the installation and uninstallation of binary packages. A main reason for this is to do things like run\u00a0<strong>ldconfig<\/strong>\u00a0after installing or removing packages that contain shared libraries. The macros for each of the scripts is as follows:<\/p>\n<ul>\n<li>%pre is the macro to do pre-install scripts.<\/li>\n<li>%post is the macro to do post-install scripts.<\/li>\n<li>%preun is the macro to do pre-uninstall scripts.<\/li>\n<li>%postun is the macro to do post-uninstall scripts.<\/li>\n<\/ul>\n<p>The contents of these sections should just be any sh style script, though you do\u00a0<em>not<\/em>\u00a0need the #!\/bin\/sh.<\/p>\n<h2><a id=\"FILES\" name=\"FILES\"><\/a>Files<\/h2>\n<p>This is the section where you\u00a0<em>must<\/em>\u00a0list the files for the binary package. RPM has no way to know what binaries get installed as a result of\u00a0<strong>make install<\/strong>. There is\u00a0<em>NO<\/em>\u00a0way to do this. Some have suggested doing a\u00a0<strong>find<\/strong>\u00a0before and after the package install. With a multiuser system, this is unacceptable as other files may be created during a package building process that have nothing to do with the package itself.<br \/>\nThere are some macros available to do some special things as well. They are listed and described here:<\/p>\n<ul>\n<li>%doc is used to mark documentation in the source package that you want installed in a binary install. The documents will be installed in \/usr\/doc\/$NAME-$VERSION-$RELEASE. You can list multiple documents on the command line with this macro, or you can list them all separately using a macro for each of them.<\/li>\n<li>%config is used to mark configuration files in a package. This includes files like sendmail.cf, passwd, etc. If you later uninstall a package containing config files, any unchanged files will be removed and any changed files will get moved to their old name with a .rpmsave appended to the filename. You can list multiple files with this macro as well.<\/li>\n<li>%dir marks a single directory in a file list to be included as being owned by a package. By default, if you list a directory name\u00a0<em>WITHOUT<\/em>\u00a0a %dir macro,\u00a0<em>EVERYTHING<\/em>\u00a0in that directory is included in the file list and later installed as part of that package.<\/li>\n<li>%defattr allows you to set default attributes for files listed after the defattr declaration. The attributes are listed in the form\u00a0<em>(mode, owner, group)<\/em>\u00a0where the mode is the octal number representing the bit pattern for the new permissions (like\u00a0<strong>chmod<\/strong>\u00a0would use), owner is the username of the owner, and group is the group you would like assigned. You may leave any field to the installed default by simply placing a\u00a0<em>&#8211;<\/em>\u00a0in its place, as was done in the mode field for the example package.<\/li>\n<li>%files -f &lt;filename&gt; will allow you to list your files in some arbitrary file within the build directory of the sources. This is nice in cases where you have a package that can build it&#8217;s own filelist. You then just include that filelist here and you don&#8217;t have to specifically list the files.<\/li>\n<\/ul>\n<p>The\u00a0<em>biggest caveat<\/em>\u00a0in the file list is listing directories. If you list \/usr\/bin by accident, your binary package will contain\u00a0<em>every<\/em>\u00a0file in \/usr\/bin on your system.<\/p>\n<h1><a id=\"BUILD-IT\" name=\"BUILD-IT\"><\/a>Building It<\/h1>\n<h2>The Source Directory Tree<\/h2>\n<p>The first thing you need is a properly configured build tree. This is configurable using the \/etc\/rpmrc file. Most people will just use \/usr\/src.<br \/>\nYou may need to create the following directories to make a build tree:<\/p>\n<ul>\n<li>BUILD is the directory where all building occurs by RPM. You don&#8217;t have to do your test building anywhere in particular, but this is where RPM will do it&#8217;s building.<\/li>\n<li>SOURCES is the directory where you should put your original source tar files and your patches. This is where RPM will look by default.<\/li>\n<li>SPECS is the directory where all spec files should go.<\/li>\n<li>RPMS is where RPM will put all binary RPMs when built.<\/li>\n<li><a id=\"SOURCE-TREE\" name=\"SOURCE-TREE\"><\/a>SRPMS is where all source RPMs will be put.<\/li>\n<\/ul>\n<h2><a id=\"BUILD-PKG\" name=\"BUILD-PKG\"><\/a>Building the Package with RPM<\/h2>\n<p>nce you have a spec file, you are ready to try and build your package. The most useful way to do it is with a command like the following:<\/p>\n<table border=\"0\" width=\"100%\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td>rpm -ba foobar-1.0.spec<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>There are other options useful with the\u00a0<em>-b<\/em>\u00a0switch as well:<\/p>\n<ul>\n<li><em>p<\/em>\u00a0means just run the prep section of the specfile.<\/li>\n<li><em>l<\/em>\u00a0is a list check that does some checks on %files.<\/li>\n<li><em>c<\/em>\u00a0do a prep and compile. This is useful when you are unsure of whether your source will build at all. It seems useless because you might want to just keep playing with the source itself until it builds and then start using RPM, but once you become accustomed to using RPM you will find instances when you will use it.<\/li>\n<li><em>i<\/em>do a prep, compile, and install.<\/li>\n<li><em>b<\/em>\u00a0prep, compile, install, and build a binary package only.<\/li>\n<li><em>a<\/em>build it all (both source and binary packages).<\/li>\n<\/ul>\n<p>There are several modifiers to the\u00a0<em>-b<\/em>\u00a0switch. They are as follows:<\/p>\n<ul>\n<li><em>&#8211;short-circuit<\/em>\u00a0will skip straight to a specified stage (can only be used with c and i).<\/li>\n<li><em>&#8211;clean<\/em>\u00a0removes the build tree when done.<\/li>\n<li><em>&#8211;keep-temps<\/em>\u00a0will keep all the temp files and scripts that were made in \/tmp. You can actually see what files were created in \/tmp using the\u00a0<em>-v<\/em>\u00a0option.<\/li>\n<li><em>&#8211;test<\/em>\u00a0does not execute any real stages, but does keep-temp.<\/li>\n<\/ul>\n<p><strong>Reference:<\/strong><br \/>\n<a href=\"http:\/\/www.ibiblio.org\/pub\/linux\/docs\/HOWTO\/other-formats\/html_single\/RPM-HOWTO.html\" target=\"_blank\" rel=\"noopener\">http:\/\/www.ibiblio.org\/pub\/linux\/docs\/HOWTO\/other-formats\/html_single\/RPM-HOWTO.html<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Basic RPM Tutorials Introduction: RPM is the\u00a0RPM\u00a0Package\u00a0Manager. It is an open packaging system available for anyone to use. It allows users to take source code for new software and package&#8230; <\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[4957],"tags":[4420,91,4421,4423,4425,4426,4424,4422],"class_list":["post-4520","post","type-post","status-publish","format-standard","hentry","category-linux","tag-basic-rpm-tutorials","tag-build","tag-building-rpms","tag-rpm","tag-rpm-guide","tag-rpm-reference","tag-rpm-tutorials","tag-the-spec-file"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/4520","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=4520"}],"version-history":[{"count":2,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/4520\/revisions"}],"predecessor-version":[{"id":4522,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/4520\/revisions\/4522"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=4520"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=4520"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=4520"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}