Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 89 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
89
Dung lượng
1,41 MB
Nội dung
This directory is specific to Red Hat Linux. Other Linux distributions will use other directories, such as /usr/src/packages. Once we have gathered the sources for your RPM package, the next step is to create a spec file, the file that describes to the rpmbuild command exactly how to build our package. Creating an RPM Spec File Creating a spec file can be daunting, given that the RPM system supports thousands of options. Luckily, the RPM system provides reasonable defaults for most options. You can follow the simple example in this section, which should suffice for most packages you will build. In addition, you can copy com- mands from other spec files. Good sources for spec file examples are other RPM packages. Look at source RPMs, which are stored in files ending in .src.rpm. Install these RPMs and look through the spec files. You should find more complicated examples than you will ever need. Interesting spec files include those for anonftp, telnet, vnc, and sendmail. In addition, the designers of the RPM system wisely decided not to try to replace common build tools such as make or configure. The RPM system contains many shorthand features to take advantage of makefiles and configure scripts. In this example, we will create a spec file for the simple myapp application. Name your spec file myapp.spec. Start the spec file with a set of definitions of the name, version number, and other information about your package. For example, Vendor: Wrox Press Distribution: Any Name: myapp Version: 1.0 Release: 1 Packager: neil@provider.com License: Copyright 2003 by Wrox Press Group: Applications/Media This section of an RPM spec file is often called a preamble. In our preamble, the most important settings are the Name, Version, and Release. This example sets the name to myapp, the version number to 1.0, and the release of the RPM package at 1, our first attempt at making an RPM package. The Group setting is used to help graphical installation programs sort the thousands of Linux applica- tions by type. The Distribution is important if you build a package just for one Linux distribution, such as Red Hat or SuSE Linux. Adding comments to your spec file is a good idea. Like shell scripts and makefiles, the rpmbuild com- mand treats any line starting with a # character as a comment. For example, # This line is a comment. 403 Development Tools b544977 Ch09.qxd 12/1/03 8:56 AM Page 403 To help users decide whether to install your package, provide a Summary and a %description (note the inconsistency in the RPM syntax, with a percent sign before description). For example, we can describe our package as follows: Summary: Trivial application %description MyApp Trivial Application A trivial application used to demonstrate development tools. This version pretends it requires MySQL at or above 3.23. Authors: Neil Matthew and Richard Stones The %description section can take up multiple lines (and normally should). The spec file can contain dependency information, both what your package provides and what your package depends on. (You can also define what the source package depends on, such as special header files necessary for compiling.) The Provides setting defines what capabilities your system provides. For example, Provides: goodness This example states that our package provides the imaginary capability called goodness. The RPM sys- tem will also automatically add a Provides entry for the name of the package, myapp in our case. The Provides settings are useful for multiple packages that may provide the same thing. For example, the Apache Web server package provides the capability webserver. Other packages, such as Thy, may also provide the same capability. (To help deal with conflicting packages, RPM allows you to specify Conflicts and Obsoletes information as well.) The most important dependency information, though, is the Requires settings. You can state all the packages your package requires for operation. For example, a Web server requires networking and secu- rity packages. In our example, we define a requirement for the MySQL database, at version 3.23 or higher. The syntax for this follows: Requires: mysql >= 3.23 If you only want to require the MySQL database, at any version, you can use a setting like the following: Requires: mysql RPM will prevent users from installing packages if the required packages are not also installed. (Users can override this behavior, though.) The RPM system will automatically add dependencies such as /bin/sh for shell scripts, the Perl inter- preter for Perl scripts, and any shared libraries ( .so files) your application calls. Each release of the RPM system adds more smarts to the automatic dependency checks. After you have defined the requirements, you need to define the sources that make up your application. For most applications, you can simply copy the following setting: source: %{name}-%{version}.tar.gz 404 Chapter 9 b544977 Ch09.qxd 12/1/03 8:56 AM Page 404 The %{name} syntax refers to an RPM macro, in this case, the name of the package. Since we previously set the name to myapp, the rpmbuild command will expand %{name} to myapp, and similarly expand %{version} to 1.0, making for a file named myapp-1.0.tar.gz. The rpmbuild command will look for this file in the SOURCES directory described previously. Our example sets up a Buildroot, which defines a staging area to test the installation. You can copy the following for your packages: Buildroot: %{_tmppath}/%{name}-%{version}-root Once a Buildroot is set up, install your applications to the Buildroot directory. You can use the handy variable $RPM_BUILD_ROOT, which is defined for all the shell scripts in the spec file. After defining all these settings about the package, the next step is to define how to build the package. There are four main sections for building: %prep, %build, %install, and %clean. As the name implies, the %prep section is for preparing to build. In most cases, you can run the %setup macro, shown here with a -q parameter to set it to quiet mode: %prep %setup -q The %build section builds your application. In most cases, you can use a simple make command. For example, %build make This is one way that the RPM system takes advantage of the work you’ve already done in creating your makefile. The %install section installs your application, any manual pages, and any support files. You can often use the RPM macro %makeinstall, which calls the install target of the makefile. In our case, though, we can manually install the files to show more RPM macros: %install mkdir -p $RPM_BUILD_ROOT%{_bindir} mkdir -p $RPM_BUILD_ROOT%{_mandir} install -m755 myapp $RPM_BUILD_ROOT%{_bindir}/myapp install -m755 myapp.1 $RPM_BUILD_ROOT%{_mandir}/myapp.1 This example creates the directories for the files, if needed, and then installs the myapp executable and myapp.1 manual page. The $RPM_BUILD_ROOT environment variable holds the Buildroot location set previously. The %{_bindir} and %{_mandir} macros expand to the current binary directory and man- ual page directory, respectively. If you use a configure script to create the makefile, all the various directories get set properly into your makefile. In most cases, you will not need to set up all the installation commands manually in the spec file as shown in the previous example. 405 Development Tools b544977 Ch09.qxd 12/1/03 8:56 AM Page 405 The %clean target cleans up the files created by the rpmbuild command. For example, %clean rm -rf $RPM_BUILD_ROOT After specifying how to build the package, you need to define all the files that will be installed. RPM is very rigid on this; it has to be rigid so that it can properly track every file from every package. The %files section names the files to include in the package. In our case, we have only two files to distribute in the binary package: the myapp executable and myapp.1 manual page. For example, %files %{_bindir}/myapp %{_mandir}/myapp.1 The RPM system can run scripts before and after your package is installed. For example, if your package is a daemon process, you probably need to modify the system initialization scripts to start your daemon. Do that with a %post script. A simple example that merely sends an e-mail message follows: %post mail root -s “myapp installed - please register” </dev/null Look for examples in server RPM spec files. The complete spec file for our trivial application follows: # # spec file for package myapp (Version 1.0) # Vendor: Wrox Press Distribution: Any Name: myapp Version: 1.0 Release: 1 Packager: neil@provider.com License: Copyright 2003 by Wrox Press Group: Applications/Media Provides: goodness Requires: mysql >= 3.23 Buildroot: %{_tmppath}/%{name}-%{version}-root source: %{name}-%{version}.tar.gz Summary: Trivial application %description MyApp Trivial Application A trivial application used to demonstrate development tools. This version pretends it requires MySQL at or above 3.23. Authors: Neil Matthew and Richard Stones 406 Chapter 9 b544977 Ch09.qxd 12/1/03 8:56 AM Page 406 %prep %setup -q %build make %install mkdir -p $RPM_BUILD_ROOT%{_bindir} mkdir -p $RPM_BUILD_ROOT%{_mandir} install -m755 myapp $RPM_BUILD_ROOT%{_bindir}/myapp install -m755 myapp.1 $RPM_BUILD_ROOT%{_mandir}/myapp.1 %clean rm -rf $RPM_BUILD_ROOT %post mail root -s “myapp installed - please register” </dev/null %files %{_bindir}/myapp %{_mandir}/myapp.1 We are now ready to build the RPM package. Building an RPM Package with rpmbuild Build packages with the rpmbuild command, which uses the following syntax: rpmbuild -bBuildStage spec_file The -b option tells rpmbuild to build an RPM. The extra BuildStage option is a special code that tells the rpmbuild command how far to go when building. We list the options in the following table. Option Usage -ba Build all, both a binary and source RPM. -bb Build a binary RPM. -bc Build (compile) the program but do not make the full RPM. -bp Prepare for building a binary RPM. -bi Create a binary RPM and install it. -bl Check the listing of files for the RPM. -bs Build a source RPM only. Older versions of the RPM system used the rpm command to build packages in place of the rpmbuild command. With the more recent RPM releases, though, the rpm command will no longer build RPM packages. You must use the rpmbuild command. 407 Development Tools b544977 Ch09.qxd 12/1/03 8:56 AM Page 407 To build both a binary and a source RPM, use the -ba option. The source RPM allows you to recreate the binary RPM. The following shows the output from building our package: $ rpmbuild -ba myapp.spec Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.71108 + umask 022 + cd /usr/src/redhat/BUILD + LANG=C + export LANG + cd /usr/src/redhat/BUILD + rm -rf myapp-1.0 + /usr/bin/gzip -dc /usr/src/redhat/SOURCES/myapp-1.0.tar.gz + tar -xf - + STATUS=0 + ‘[‘ 0 -ne 0 ‘]’ + cd myapp-1.0 ++ /usr/bin/id -u + ‘[‘ 0 = 0 ‘]’ + /bin/chown -Rhf root . ++ /usr/bin/id -u + ‘[‘ 0 = 0 ‘]’ + /bin/chgrp -Rhf root . + /bin/chmod -Rf a+rX,g-w,o-w . + exit 0 Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.43788 + umask 022 + cd /usr/src/redhat/BUILD + cd myapp-1.0 + LANG=C + export LANG + make gcc -g -Wall -ansi -c -o main.o main.c gcc -g -Wall -ansi -c -o 2.o 2.c ar rv mylib.a 2.o a - 2.o gcc -g -Wall -ansi -c -o 3.o 3.c ar rv mylib.a 3.o a - 3.o gcc -o myapp main.o mylib.a + exit 0 Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.90688 + umask 022 + cd /usr/src/redhat/BUILD + cd myapp-1.0 + LANG=C + export LANG + mkdir -p /var/tmp/myapp-1.0-root/usr/bin + mkdir -p /var/tmp/myapp-1.0-root/usr/share/man + install -m755 myapp /var/tmp/myapp-1.0-root/usr/bin/myapp 408 Chapter 9 b544977 Ch09.qxd 12/1/03 8:56 AM Page 408 + install -m755 myapp.1 /var/tmp/myapp-1.0-root/usr/share/man/myapp.1 + /usr/lib/rpm/find-debuginfo.sh /usr/src/redhat/BUILD/myapp-1.0 extracting debug info from /var/tmp/myapp-1.0-root/usr/bin/myapp 1 block + /usr/lib/rpm/redhat/brp-compress + /usr/lib/rpm/redhat/brp-strip /usr/bin/strip + /usr/lib/rpm/redhat/brp-strip-static-archive /usr/bin/strip + /usr/lib/rpm/redhat/brp-strip-comment-note /usr/bin/strip /usr/bin/objdump Processing files: myapp-1.0-1 Provides: goodness Requires(interp): /bin/sh Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1 Requires(post): /bin/sh Requires: libc.so.6 libc.so.6(GLIBC_2.0) mysql >= 3.23 Processing files: myapp-debuginfo-1.0-1 Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1 Checking for unpackaged file(s): /usr/lib/rpm/check-files /var/tmp/myapp-1.0-root Wrote: /usr/src/redhat/SRPMS/myapp-1.0-1.src.rpm Wrote: /usr/src/redhat/RPMS/i386/myapp-1.0-1.i386.rpm Wrote: /usr/src/redhat/RPMS/i386/myapp-debuginfo-1.0-1.i386.rpm Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.17422 + umask 022 + cd /usr/src/redhat/BUILD + cd myapp-1.0 + rm -rf /var/tmp/myapp-1.0-root + exit 0 When the build is complete, you should see two packages: the binary RPM in the RPMS directory, under an architecture subdirectory such as RPMS/i386, and a source RPM in SRPMS. The binary RPM filename will appear something like the following: myapp-1.0-1.i386.rpm The architecture on your system may be different. The source RPM filename will appear as follows: myapp-1.0-1.src.rpm You need to install packages as the superuser. You do not have to build packages as root, so long as you have write access to the RPM directories, typically /usr/src/ redhat. Normally, you should not create RPM packages as root, since a spec file could have commands that may damage your system. 409 Development Tools b544977 Ch09.qxd 12/1/03 8:56 AM Page 409 Other Package Formats Although RPM is fast becoming the most popular way of distributing applications in a way that allows the user to control their installation, and deinstallation, there are competing packages out there. Some software is still distributed as gzipped tar files (tgz). Typically the installation steps consist of unpack- ing the archive into a temporary directory and running a script to perform the actual installation. The Debian Linux distributions (and some others) support another package format, similar in function- ality to RPM, called dpkg. The dpkg utility on Debian unpacks and installs package files that usually have a .deb extension. If you need to distribute an application using .deb file packages, it is possible to convert an RPM package to dpkg format using a utility called Alien. More details on Alien can be found at http://kitenet.net/programs/alien/. Development Environments Almost all of the tools we have looked at so far in this chapter are essentially command line tools. Developers that have experience with Windows will no doubt have some experience with integrated development environments, or IDEs for short. IDEs are graphical environments that typically bring together some or all of the tools needed to create, debug, and run an application. Usually, they provide at least an editor, a file browser, and a method of running the application and capturing the output. More complete environments add support for generating source code files from templates for certain types of application, integration with a source code control system, and automatic documentation. In this chapter, we will mention a few of the IDEs available for Linux today. These environments are under active development, with the most advanced of them beginning to rival the quality of commercial offerings. xwpe Way back in 1993 Fred Kruse developed a character-based file manager and text editor. It was small, easy to use, and colorful. Its style mimicked the MS-DOS tools of the day. Many programmers appreci- ated its speed and low demand on precious computer resources. Called “Window Editor,” and invoked as we, the editor is able to edit multiple files at once, search for text, automatically indent source code, and print it. Later developments added support for executing and debugging programs from within the editor. This version became the Window Programming Environment ( wpe). Both we and wpe run on Linux, either using a character mode console or inside a color xterm under the X Window System. Versions that run under X11 are also available as xwe and xwpe respectively. These versions retain all the function key–driven user interface of the originals. Figure 9-2 shows xwpe stepping through the execution of a simple program. As you can see, the editor uses color to highlight the syntax of the C source code and the current state of execution. Today, XWPE is being developed by Identical Software. You can find more details and download a version for Linux at http://www.identicalsoftware.com/xwpe/. 410 Chapter 9 b544977 Ch09.qxd 12/1/03 8:56 AM Page 410 Figure 9-2 C-Forge C-Forge is a commercial graphical IDE for C and C++ programs from Codeforge. There are a number of versions available for Linux, including a freeware one, which has limited but still useful functionality. C-Forge will generate a suitable makefile for projects and supports revision control using CVS so that projects developed with it can be readily and easily maintained. Figure 9-3 shows a C-Forge project under construction. You can download the free version of C-Forge from http://www.codeforge.com/. 411 Development Tools b544977 Ch09.qxd 12/1/03 8:56 AM Page 411 Figure 9-3 KDevelop KDevelop is an IDE for C and C++ programs. It includes particular support for the creation of applica- tions to run under the K Desktop Environment (KDE), one of the two main graphical user interfaces on Linux today. It can also be used for other project types, including simple C programs. KDevelop is free software released under the terms of the GNU General Public License (GPL) and is available with many Linux distributions. The latest version can be downloaded from http://www. kdevelop.org . Projects created with KDevelop by default follow the standard for GNU projects. For example, they will use the autoconf utility to generate makefiles that are tailored to the environ- ment for which they are being built. This means that the project is ready to be distributed as source code that stands a good chance of being able to be compiled on other systems. 412 Chapter 9 b544977 Ch09.qxd 12/1/03 8:56 AM Page 412 [...]... shown here: SYMBOL BASENID BINSIZE 4 36 FILE prog.c prog.c FUNCTION — — LINE *12 *30 * 96 197 124 198 1 26 199 1 46 2 06 1 56 166 Debugging BUFMAX BUFSIZ EOF argc argv calldata calls prog.c /usr/include/stdio.h /usr/include/stdio.h prog.c prog.c prog.c prog.c prog.c prog.c prog.c prog.c — — — — main — main — main — main *44 *4 *27 36 *37 36 *38 *5 64 *19 54 45 90 61 81 61 188 On the author’s machine, the... 0.10 0.08 0.05 0.04 0.04 0.04 0.02 0.02 0.01 0.01 total calls 866 4 ms/call 0.01 ms/call 0.03 43320 866 4 11 263 2 8757 1 53 0.00 0.01 0.00 0.00 40.00 0.38 0.00 0.01 0.00 0.00 390.02 0.38 260 34 866 4 0.00 0.00 0.00 0.00 name _doscan [4] mcount (60 ) _number [5] _format_arg [6] _ungetc [8] _memccpy [9] _main [2] _read [12] w4str [10] _strlen [ 16] strncmp [17] ... starting from the basic routine debug1.c /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ typedef struct { char *data; int key; } item;... of the problem 4 26 Debugging Depending on your kernel, C library, and compiler version, you may see the program fault at a slightly different place, for example, on line 25, when array items are exchanged, rather than line 23, when array item keys are compared If this is the case, you’ll see something like Program received signal SIGSEGV, Segmentation fault 0x800 061 3 in sort (a=0x8001 764 , n=5) at debug3.c:25... development capabilities These utilities and others mentioned in this chapter may not be present in your Linux distribution If not, you might like to search for implementations on the Internet A good place to start (for Linux distributions that support the RPM package format) is http://rufus.w3.org /linux/ RPM ctags The ctags program creates an index of functions For each function, you get a list of the... What happens when you do this will depend on your flavor of Linux (or UNIX) and on how it’s set up On one of the authors’ systems, we got array[0] array[1] array[2] array[3] array[4] = = = = = {john, 2} {alex, 1} {(null), -1} {bill, 3} {neil, 4} But on the other author’s system (running a different Linux kernel), we got Segmentation fault On your Linux system, you may see either of these outputs or a different... make a call to it It sounds complicated, but it really isn’t Here’s a sample 19 20 21 22 display_list {prcc.c 10 56} show_all_lists {prcc.c 1070} exit {} main {prcc.c 70} 437 Chapter 10 23 24 74 75 76 77 78 99 100 show_all_lists {prcc.c 1070} usage {prcc.c 59} printf {} display_list {prcc.c 10 56} maketag {prcc.c 487} show_all_lists {prcc.c 1070} main {prcc.c 70} usage {prcc.c 59} main {prcc.c 70} This... data to be an array of 4,0 96 characters, any access to a nonexistent array element will probably be to a memory location beyond that allocated Each element of the array is 4K in size, so the memory we use incorrectly will be 0–4K off the end If we do this, calling the result debug3.c, we get a segmentation fault on both the authors’ flavors of Linux /* 2 */ char data[40 96] ; $ cc -o debug3 debug3.c... 23 /* 24 /* 428 18 19 20 21 22 23 24 */ */ */ */ */ */ */ int s = 1; for(; i < n && s != 0; i++) { s = 0; for(j = 0; j < n; j++) { if(a[j].key > a[j+1].key) { item t = a[j]; Debugging 25 26 27 (gdb) /* /* /* 25 26 27 */ */ */ a[j] = a[j+1]; a[j+1] = t; s++; We can see that on line 22 that the loop is set to execute while the variable j is less than n In this case, n is 5, so j will have the final value... Here’s some sample output taken from a version of cflow (cflow-2.0) that is available on the Internet and maintained by Marty Leisner: 1 2 3 4 5 6 7 8 9 10 11 file_ungetc {prcc.c 997} main {prcc.c 70} getopt {} show_all_lists {prcc.c 1070} display_list {prcc.c 10 56} printf {} exit {} exit {} usage {prcc.c 59} fprintf {} exit {} This sample tells us that main calls (among others) show_all_lists and that . /usr/src/redhat/SRPMS/myapp-1.0-1.src.rpm Wrote: /usr/src/redhat/RPMS/i3 86/ myapp-1.0-1.i3 86. rpm Wrote: /usr/src/redhat/RPMS/i3 86/ myapp-debuginfo-1.0-1.i3 86. rpm Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.17422 +. requires MySQL at or above 3.23. Authors: Neil Matthew and Richard Stones 4 06 Chapter 9 b544977 Ch09.qxd 12/1/03 8: 56 AM Page 4 06 %prep %setup -q %build make %install mkdir -p $RPM_BUILD_ROOT%{_bindir} mkdir. programs sort the thousands of Linux applica- tions by type. The Distribution is important if you build a package just for one Linux distribution, such as Red Hat or SuSE Linux. Adding comments to