0205-0208.html

来自「linux-unix130.linux.and.unix.ebooks130 l」· HTML 代码 · 共 291 行

HTML
291
字号




<HTML>

<HEAD>

<TITLE>Maximum RPM (RPM):Adding Dependency Information to a Package:EarthWeb Inc.-</TITLE>

<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<SCRIPT>
<!--
function displayWindow(url, width, height) {
        var Win = window.open(url,"displayWindow",'width=' + width +
',height=' + height + ',resizable=1,scrollbars=yes');
}
//-->
</SCRIPT>
</HEAD>

 -->




<!-- ISBN=0672311054 //-->

<!-- TITLE=Maximum RPM (RPM)//-->

<!-- AUTHOR=Edward Bailey//-->

<!-- PUBLISHER=Macmillan Computer Publishing//-->

<!-- IMPRINT=Sams//-->

<!-- CHAPTER=14 //-->

<!-- PAGES=0205-0214 //-->

<!-- UNASSIGNED1 //-->

<!-- UNASSIGNED2 //-->









<P><CENTER>

<a href="../ch13/0204-0204.html">Previous</A> | <a href="../ewtoc.html">Table of Contents</A> | <a href="0209-0211.html">Next</A>

</CENTER></P>



<A NAME="PAGENUM-205"><P>Page 205</P></A>







<H3><A NAME="ch14_ 1">

Chapter 14

</A></H3>



<H2>



Adding Dependency<BR> Information to a Package



</H2>



<A NAME="PAGENUM-206"><P>Page 206</P></A>











<P>Since the very first version of RPM hit the streets, one of the side effects of RPM's ease of

use was that it made it easier for people to break things. Because RPM made it so simple to

erase packages, it became common for people to joyfully erase packages until something broke.

</P>



<P>Usually this only bit people once, but even once was too much of a hassle if it could be

prevented. With this in mind, the RPM developers gave RPM the capability to

</P>



<UL>

<LI>          Build packages

that contain information on the capabilities they require.

<LI>          Build packages that contain information on the capabilities they provide.

<LI>          Store this

provides and requires information in the RPM database.

</UL>



<P>In addition, they made sure RPM was able to display dependency information, as well as

warn users if they were attempting to do something that would break a package's dependency

requirements.

</P>



<P>With these features in place, it became more difficult for someone to unknowingly erase

a package and wreak havoc on a system.

</P>



<H3><A NAME="ch14_ 2">

14.1. An Overview of Dependencies

</A></H3>



<P>We've already alluded to the underlying concept of RPM's dependency processing. It is

based on two key factors:

</P>



<UL>

<LI>          Packages advertise what capabilities they provide.

<LI>          Packages advertise what capabilities they require.

</UL>



<P>By simply checking these two types of information, you can avoid many problems. For

example, if a package requires a capability that is not provided by any already-installed

package, that package cannot be installed and expected to work properly.

</P>



<P>On the other hand, if a package is to be erased, but its capabilities are required by other

installed packages, then it cannot be erased without causing other packages to fail.

</P>



<P>As you might imagine, it's not quite that simple. But adding dependency information can

be easy. In fact, in most cases, it's automatic!

</P>



<H3><A NAME="ch14_ 3">

14.2. Automatic Dependencies

</A></H3>



<P>When a package is built by RPM, if any file in the package's

%files list is a shared library, the library's soname is automatically added to the list of capabilities the package provides.

The soname is the name used to determine compatibility between different versions of a library.

</P>



<P>Note that the soname is not a filename. In fact, no aspect of RPM's dependency processing

is based on filenames. Many people new to RPM assume that a failed dependency represents

a missing file. This is not the case.

</P>



<A NAME="PAGENUM-207"><P>Page 207</P></A>







<P>Remember that RPM's dependency processing is based on knowing what capabilities are

provided by a package and what capabilities a package requires. We've seen how RPM

automatically determines what shared library resources a package provides. But does it

automatically determine what shared libraries a package requires?

</P>



<P>Yes! RPM does this by running ldd on every executable program in a package's

%files list. Since ldd provides a list of the shared libraries each program requires, both halves of the

equation are complete&#151;that is, the packages that make shared libraries available, and the

packages that require those shared libraries, are tracked by RPM. RPM can then take that

information into account when packages are installed, upgraded, or erased.

</P>



<H4><A NAME="ch14_ 4">

14.2.1. The Automatic Dependency Scripts

</A></H4>



<P>RPM uses two scripts to handle automatic dependency processing. They reside in

/usr/bin and are called find-requires and

find-provides. We'll take a look at them in a minute,

but first let's look at why there are scripts to do this sort of thing. Wouldn't it be better to have

this built into RPM itself?

</P>



<P>Actually, creating scripts for this sort of thing is a better idea. The reason? RPM has

already been ported to a variety of different operating systems. Determining what shared libraries

an executable requires, and the soname of shared libraries, is simple, but the exact steps

required vary widely from one operating system to another. Putting this part of RPM into a script

makes it easier to port RPM.

</P>



<P>Let's take a look at the scripts that are used by RPM under the Linux operating system.

</P>



<B>

14.2.1.1. find-requires: Automatically Determine Shared

Library Requirements

</B>



<P>The find-requires script for Linux is quite simple:

</P>

<!-- CODE //-->

<PRE>

#!/bin/sh



# note this works for both a.out and ELF executables



ulimit -c 0



filelist=`xargs -r file | fgrep executable | cut -d: -f1 `



for f in $filelist; do

    ldd $f | awk `/=&gt;/ { print $1 }'

done | sort -u | xargs -r -n 1 basename | sort -u

</PRE>

<!-- END CODE //-->



<P>This script first creates a list of executable files. Then, for each file in the list,

ldd determines the file's shared library requirements, producing a list of sonames. Finally, the list of

sonames is sanitized by removing duplicates and any paths.

</P>



<A NAME="PAGENUM-208"><P>Page 208</P></A>







<B>

14.2.1.2. find-provides: Automatically Determine Shared Library Sonames

</B>



<P>The find-provides script for Linux is a bit more complex, but still

pretty straightforward:

</P>

<!-- CODE //-->

<PRE>

#!/bin/bash



# This script reads filenames from STDIN and outputs any relevant

# provides information that needs to be included in the package.



filelist=$(grep &quot;\\.so&quot; | grep -v &quot;^/lib/ld.so&quot; |

xargs file -L 2&gt;/dev/null | grep &quot;ELF.*shared object&quot; | cut -d: -f1)



for f in $filelist; do

    soname=$(objdump -p $f | awk `/SONAME/ {print $2}')



    if [ &quot;$soname&quot; != &quot;&quot; ]; then

        if [ ! -L $f ]; then

            echo $soname

        fi

     else

echo ${f##*/}

    fi

done | sort -u

</PRE>

<!-- END CODE //-->



<P>First, a list of shared libraries is created. Then, for each file on the list, the soname is

extracted and cleaned up, and duplicates are removed.

</P>



<H4><A NAME="ch14_ 5">

14.2.2. Automatic Dependencies: An Example

</A></H4>



<P>Let's take a widely used program, ls, the directory lister, as an example. On a Red Hat

Linux system, ls is part of the fileutils package and is installed in

/bin. Let's play the part of RPM during fileutils's package build and run

find-requires on /bin/ls. Here's what we'll see:

</P>

<!-- CODE SNIP //-->

<PRE>

# find-requires

/bin/ls

&lt;ctrl-d&gt;

libc.so.5

#

</PRE>

<!-- END CODE SNIP //-->



<P>The find-requires script returned libc.so.5. Therefore, RPM should add a requirement

for libc.so.5 when the fileutils package is built. We can verify that RPM did add

ls's requirement for libc.so.5 by using RPM's

--requires option to display fileutils's requirements:

</P>

<!-- CODE SNIP //-->

<PRE>

# rpm -q --requires fileutils

libc.so.5

#

</PRE>

<!-- END CODE SNIP //-->



<P>Okay, that's the first half of the equation: RPM automatically detecting a package's shared

library requirements. Now let's look at the second half of the equation: RPM detecting

packages that provide shared libraries. Since the

libc package includes, among others, the shared library

/lib/libc.so.5.3.12, RPM would obtain its soname. We can simulate this by

using find-provides to print out the library's soname:

</P>

<!-- CODE SNIP //-->

<PRE>

# find-provides

/lib/libc.so.5.3.12



</PRE>

<!-- END CODE SNIP //-->



<P><CENTER>

<a href="../ch13/0204-0204.html">Previous</A> | <a href="../ewtoc.html">Table of Contents</A> | <a href="0209-0211.html">Next</A>

</CENTER></P>











</td>
</tr>
</table>

<!-- begin footer information -->







</body></html>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?