Este contenido no está disponible en el idioma seleccionado.
Chapter 2. Preparing software for RPM packaging
This section explains how to prepare software for RPM packaging. To do so, knowing how to code is not necessary. However, you need to understand the basic concepts, such as What source code is and How programs are made.
2.1. What source code is Copiar enlaceEnlace copiado en el portapapeles!
This part explains what source code is and shows example source codes of a program written in three different programming languages.
Source code is human-readable instructions to the computer, which describe how to perform a computation. Source code is expressed using a programming language.
2.1.1. Source code examples Copiar enlaceEnlace copiado en el portapapeles!
This document features three versions of the Hello World
program written in three different programming languages:
Each version is packaged differently.
These versions of the Hello World
program cover the three major use cases of an RPM packager.
2.1.1.1. Hello World written in bash Copiar enlaceEnlace copiado en el portapapeles!
The bello project implements Hello World
in bash. The implementation only contains the bello
shell script. The purpose of the program is to output Hello World
on the command line.
The bello
file has the following syntax:
#!/bin/bash printf "Hello World\n"
#!/bin/bash
printf "Hello World\n"
2.1.1.2. Hello World written in Python Copiar enlaceEnlace copiado en el portapapeles!
The pello project implements Hello World
in Python. The implementation only contains the pello.py
program. The purpose of the program is to output Hello World
on the command line.
The pello.py
file has the following syntax:
#!/usr/bin/python3 print("Hello World")
#!/usr/bin/python3
print("Hello World")
2.1.1.3. Hello World written in C Copiar enlaceEnlace copiado en el portapapeles!
The cello project implements Hello World
in C. The implementation only contains the cello.c
and the Makefile
files, so the resulting tar.gz
archive will have two files apart from the LICENSE
file.
The purpose of the program is to output Hello World
on the command line.
The cello.c
file has the following syntax:
2.2. How programs are made Copiar enlaceEnlace copiado en el portapapeles!
Methods of conversion from human-readable source code to machine code (instructions that the computer follows to execute the program) include the following:
- The program is natively compiled.
- The program is interpreted by raw interpreting.
- The program is interpreted by byte compiling.
2.2.1. Natively Compiled Code Copiar enlaceEnlace copiado en el portapapeles!
Natively compiled software is software written in a programming language that compiles to machine code with a resulting binary executable file. Such software can be run stand-alone.
RPM packages built this way are architecture-specific.
If you compile such software on a computer that uses a 64-bit (x86_64) AMD or Intel processor, it does not execute on a 32-bit (x86) AMD or Intel processor. The resulting package has architecture specified in its name.
2.2.2. Interpreted Code Copiar enlaceEnlace copiado en el portapapeles!
Some programming languages, such as bash or Python, do not compile to machine code. Instead, their programs' source code is executed step by step, without prior transformations, by a Language Interpreter or a Language Virtual Machine.
Software written entirely in interpreted programming languages is not architecture-specific. Hence, the resulting RPM Package has the noarch
string in its name.
Interpreted languages are either Raw-interpreted programs or Byte-compiled programs. These two types differ in program build process and in packaging procedure.
2.2.2.1. Raw-interpreted programs Copiar enlaceEnlace copiado en el portapapeles!
Raw-interpreted language programs do not need to be compiled and are directly executed by the interpreter.
2.2.2.2. Byte-compiled programs Copiar enlaceEnlace copiado en el portapapeles!
Byte-compiled languages need to be compiled into byte code, which is then executed by the language virtual machine.
Some languages offer a choice: they can be raw-interpreted or byte-compiled.
2.3. Building software from source Copiar enlaceEnlace copiado en el portapapeles!
This part describes how to build software from source code.
For software written in compiled languages, the source code goes through a build process, producing machine code. This process, commonly called compiling or translating, varies for different languages. The resulting built software can be run, which makes the computer perform the task specified by the programmer.
For software written in raw interpreted languages, the source code is not built, but executed directly.
For software written in byte-compiled interpreted languages, the source code is compiled into byte code, which is then executed by the language virtual machine.
2.3.1. Natively Compiled Code Copiar enlaceEnlace copiado en el portapapeles!
This section shows how to build the cello.c
program written in the C language into an executable.
cello.c
2.3.1.1. Manual building Copiar enlaceEnlace copiado en el portapapeles!
If you want to build the cello.c
program manually, use this procedure:
Procedure
Invoke the C compiler from the GNU Compiler Collection to compile the source code into binary:
gcc -g -o cello cello.c
gcc -g -o cello cello.c
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Execute the resulting output binary
cello
:./cello
$ ./cello Hello World
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
2.3.1.2. Automated building Copiar enlaceEnlace copiado en el portapapeles!
Large-scale software commonly uses automated building that is done by creating the Makefile
file and then running the GNU make
utility.
If you want to use the automated building to build the cello.c
program, use this procedure:
Procedure
To set up automated building, create the
Makefile
file with the following content in the same directory ascello.c
.Makefile
cello: gcc -g -o cello cello.c clean: rm cello
cello: gcc -g -o cello cello.c clean: rm cello
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Note that the lines under
cello:
andclean:
must begin with a tab space.To build the software, run the
make
command:make
$ make make: 'cello' is up to date.
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Since there is already a build available, run the
make clean
command, and after run themake
command again:make clean make
$ make clean rm cello $ make gcc -g -o cello cello.c
Copy to Clipboard Copied! Toggle word wrap Toggle overflow NoteTrying to build the program after another build has no effect.
make
$ make make: 'cello' is up to date.
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Execute the program:
./cello
$ ./cello Hello World
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
You have now compiled a program both manually and using a build tool.
2.3.2. Interpreting code Copiar enlaceEnlace copiado en el portapapeles!
This section shows how to byte-compile a program written in Python and raw-interpret a program written in bash.
In the two examples below, the #!
line at the top of the file is known as a shebang, and is not part of the programming language source code.
The shebang enables using a text file as an executable: the system program loader parses the line containing the shebang to get a path to the binary executable, which is then used as the programming language interpreter. The functionality requires the text file to be marked as executable.
2.3.2.1. Byte-compiling code Copiar enlaceEnlace copiado en el portapapeles!
This section shows how to compile the pello.py
program written in Python into byte code, which is then executed by the Python language virtual machine.
Python source code can also be raw-interpreted, but the byte-compiled version is faster. Hence, RPM Packagers prefer to package the byte-compiled version for distribution to end users.
pello.py
#!/usr/bin/python3 print("Hello World")
#!/usr/bin/python3
print("Hello World")
Procedure for byte-compiling programs varies depending on the following factors:
- Programming language
- Language’s virtual machine
- Tools and processes used with that language
Python is often byte-compiled, but not in the way described here. The following procedure aims not to conform to the community standards, but to be simple. For real-world Python guidelines, see Software Packaging and Distribution.
Use this procedure to compile pello.py
into byte code:
Procedure
Byte-compile the
pello.py
file:python -m compileall pello.py file pello.pyc
$ python -m compileall pello.py $ file pello.pyc pello.pyc: python 2.7 byte-compiled
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Execute the byte code in
pello.pyc
:python pello.pyc
$ python pello.pyc Hello World
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
2.3.2.2. Raw-interpreting code Copiar enlaceEnlace copiado en el portapapeles!
This section shows how to raw-interpret the bello
program written in the bash shell built-in language.
bello
#!/bin/bash printf "Hello World\n"
#!/bin/bash
printf "Hello World\n"
Programs written in shell scripting languages, like bash, are raw-interpreted.
Procedure
Make the file with source code executable and run it:
chmod +x bello ./bello
$ chmod +x bello $ ./bello Hello World
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
2.4. Patching software Copiar enlaceEnlace copiado en el portapapeles!
This section explains how to patch the software.
In RPM packaging, instead of modifying the original source code, we keep it, and use patches on it.
A patch is a source code that updates other source code. It is formatted as a diff, because it represents what is different between two versions of the text. A diff is created using the diff
utility, which is then applied to the source code using the patch utility.
Software developers often use Version Control Systems such as git to manage their code base. Such tools provide their own methods of creating diffs or patching software.
The following example shows how to create a patch from the original source code using diff
, and how to apply the patch using patch
. Patching is used in a later section when creating an RPM; see Section 3.2, “Working with SPEC files”.
This procedure shows how to create a patch from the original source code for cello.c
.
Procedure
Preserve the original source code:
cp -p cello.c cello.c.orig
$ cp -p cello.c cello.c.orig
Copy to Clipboard Copied! Toggle word wrap Toggle overflow The
-p
option is used to preserve mode, ownership, and timestamps.Modify
cello.c
as needed:Copy to Clipboard Copied! Toggle word wrap Toggle overflow Generate a patch using the
diff
utility:Copy to Clipboard Copied! Toggle word wrap Toggle overflow Lines starting with a
-
are removed from the original source code and replaced with the lines that start with+
.Using the
Naur
options with thediff
command is recommended because it fits the majority of usual use cases. However, in this particular case, only the-u
option is necessary. Particular options ensure the following:-
-N
(or--new-file
) - Handles absent files as if they were empty files. -
-a
(or--text
) - Treats all files as text. As a result, the files thatdiff
classifies as binaries are not ignored. -
-u
(or-U NUM
or--unified[=NUM]
) - Returns output in the form of output NUM (default 3) lines of unified context. This is an easily readable format that allows fuzzy matching when applying the patch to a changed source tree. -r
(or--recursive
) - Recursively compares any subdirectories that are found.For more information on common arguments for the
diff
utility, see thediff
manual page.
-
Save the patch to a file:
diff -Naur cello.c.orig cello.c > cello-output-first-patch.patch
$ diff -Naur cello.c.orig cello.c > cello-output-first-patch.patch
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Restore the original
cello.c
:cp cello.c.orig cello.c
$ cp cello.c.orig cello.c
Copy to Clipboard Copied! Toggle word wrap Toggle overflow The original
cello.c
must be retained, because when an RPM is built, the original file is used, not the modified one. For more information, see Section 3.2, “Working with SPEC files”.
The following procedure shows how to patch cello.c
using cello-output-first-patch.patch
, built the patched program, and run it.
Redirect the patch file to the
patch
command:patch < cello-output-first-patch.patch
$ patch < cello-output-first-patch.patch patching file cello.c
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Check that the contents of
cello.c
now reflect the patch:Copy to Clipboard Copied! Toggle word wrap Toggle overflow Build and run the patched
cello.c
:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
2.5. Installing arbitrary artifacts Copiar enlaceEnlace copiado en el portapapeles!
Unix-like systems use the Filesystem Hierarchy Standard (FHS) to specify a directory suitable for a particular file.
Files installed from the RPM packages are placed according to FHS. For example, an executable file should go into a directory that is in the system $PATH
variable.
In the context of this documentation, an Arbitrary Artifact is anything installed from an RPM to the system. For RPM and for the system it can be a script, a binary compiled from the package’s source code, a pre-compiled binary, or any other file.
This section describes two common ways of placing Arbitrary Artifacts in the system:
2.5.1. Using the install command Copiar enlaceEnlace copiado en el portapapeles!
Packagers often use the install
command in cases when build automation tooling such as GNU make is not optimal; for example if the packaged program does not need extra overhead.
The install
command is provided to the system by coreutils, which places the artifact to the specified directory in the file system with a specified set of permissions.
The following procedure uses the bello
file that was previously created as the arbitrary artifact as a subject to this installation method.
Procedure
Run the
install
command to place thebello
file into the/usr/bin
directory with permissions common for executable scripts:sudo install -m 0755 bello /usr/bin/bello
$ sudo install -m 0755 bello /usr/bin/bello
Copy to Clipboard Copied! Toggle word wrap Toggle overflow As a result,
bello
is now located in the directory that is listed in the$PATH
variable.Execute
bello
from any directory without specifying its full path:cd ~ bello
$ cd ~ $ bello Hello World
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
2.5.2. Using the make install command Copiar enlaceEnlace copiado en el portapapeles!
Using the make install
command is an automated way to install built software to the system. In this case, you need to specify how to install the arbitrary artifacts to the system in the Makefile
that is usually written by the developer.
This procedure shows how to install a build artifact into a chosen location on the system.
Procedure
Add the
install
section to theMakefile
:Makefile
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Note that the lines under
cello:
,clean:
, andinstall:
must begin with a tab space.NoteThe $(DESTDIR) variable is a GNU make built-in and is commonly used to specify installation to a directory different than the root directory.
Now you can use
Makefile
not only to build software, but also to install it to the target system.Build and install the
cello.c
program:make sudo make install
$ make gcc -g -o cello cello.c $ sudo make install install -m 0755 cello /usr/bin/cello
Copy to Clipboard Copied! Toggle word wrap Toggle overflow As a result,
cello
is now located in the directory that is listed in the$PATH
variable.Execute
cello
from any directory without specifying its full path:cd ~ cello
$ cd ~ $ cello Hello World
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
2.6. Preparing source code for packaging Copiar enlaceEnlace copiado en el portapapeles!
Developers often distribute software as compressed archives of source code, which are then used to create packages. RPM packagers work with a ready source code archive.
Software should be distributed with a software license.
This procedure uses the GPLv3 license text as an example content of the LICENSE
file.
Procedure
Create a
LICENSE
file, and make sure that it includes the following content:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
Additional resources
- The code created in this section can be found here.
2.7. Putting source code into tarball Copiar enlaceEnlace copiado en el portapapeles!
This section describes how to put each of the three Hello World
programs introduced in Section 2.1.1, “Source code examples” into a gzip-compressed tarball, which is a common way to release the software to be later packaged for distribution.
2.7.1. Putting the bello project into tarball Copiar enlaceEnlace copiado en el portapapeles!
The bello project implements Hello World
in bash. The implementation only contains the bello
shell script, so the resulting tar.gz
archive will have only one file apart from the LICENSE
file.
This procedure shows how to prepare the bello project for distribution.
Prerequisites
Considering that this is version 0.1
of the program.
Procedure
Put all required files into a single directory:
mkdir /tmp/bello-0.1 mv ~/bello /tmp/bello-0.1/ cp /tmp/LICENSE /tmp/bello-0.1/
$ mkdir /tmp/bello-0.1 $ mv ~/bello /tmp/bello-0.1/ $ cp /tmp/LICENSE /tmp/bello-0.1/
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Create the archive for distribution and move it to the
~/rpmbuild/SOURCES/
directory, which is the default directory where therpmbuild
command stores the files for building packages:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
For more information about the example source code written in bash, see Section 2.1.1.1, “Hello World written in bash”.
2.7.2. Putting the pello project into tarball Copiar enlaceEnlace copiado en el portapapeles!
The pello project implements Hello World
in Python. The implementation only contains the pello.py
program, so the resulting tar.gz
archive will have only one file apart from the LICENSE
file.
This procedure shows how to prepare the pello project for distribution.
Prerequisites
Considering that this is version 0.1.1
of the program.
Procedure
Put all required files into a single directory:
mkdir /tmp/pello-0.1.2 mv ~/pello.py /tmp/pello-0.1.2/ cp /tmp/LICENSE /tmp/pello-0.1.2/
$ mkdir /tmp/pello-0.1.2 $ mv ~/pello.py /tmp/pello-0.1.2/ $ cp /tmp/LICENSE /tmp/pello-0.1.2/
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Create the archive for distribution and move it to the
~/rpmbuild/SOURCES/
directory, which is the default directory where therpmbuild
command stores the files for building packages:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
For more information about the example source code written in Python, see Section 2.1.1.2, “Hello World written in Python”.
2.7.3. Putting the cello project into tarball Copiar enlaceEnlace copiado en el portapapeles!
The cello project implements Hello World
in C. The implementation only contains the cello.c
and the Makefile
files, so the resulting tar.gz
archive will have two files apart from the LICENSE
file.
The patch
file is not distributed in the archive with the program. The RPM Packager applies the patch when the RPM is built. The patch will be placed into the ~/rpmbuild/SOURCES/
directory alongside the .tar.gz
archive.
This procedure shows how to prepare the cello project for distribution.
Prerequisites
Considering that this is version 1.0
of the program.
Procedure
Put all required files into a single directory:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Create the archive for distribution and move it to the
~/rpmbuild/SOURCES/
directory, which is the default directory where therpmbuild
command stores the files for building packages:Copy to Clipboard Copied! Toggle word wrap Toggle overflow Add the patch:
mv ~/cello-output-first-patch.patch ~/rpmbuild/SOURCES/
$ mv ~/cello-output-first-patch.patch ~/rpmbuild/SOURCES/
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
For more information about the example source code written in C, see Section 2.1.1.3, “Hello World written in C”.