Red Hat Training

A Red Hat training course is available for RHEL 8

Chapter 2. Creating software for RPM packaging

To prepare software for RPM packaging, you must understand what source code is and how to create software.

2.1. What is source code

Source code is human-readable instructions to the computer that describe how to perform a computation. Source code is expressed by using a programming language.

The following versions of the Hello World program written in three different programming languages cover major RPM Package Manager use cases:

  • Hello World written in Bash

    The bello project implements Hello World in Bash. The implementation contains only the bello shell script. The purpose of this program is to output Hello World on the command line.

    The bello file has the following contents:

    #!/bin/bash
    
    printf "Hello World\n"
  • Hello World written in Python

    The pello project implements Hello World in Python. The implementation contains only 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 contents:

    #!/usr/bin/python3
    
    print("Hello World")
  • Hello World written in C

    The cello project implements Hello World in C. The implementation contains only the cello.c and Makefile files. The resulting tar.gz archive therefore has two files in addition to the LICENSE file. The purpose of the program is to output Hello World on the command line.

    The cello.c file has the following contents:

    #include <stdio.h>
    
    int main(void) {
        printf("Hello World\n");
        return 0;
    }
Note

The packaging process is different for each version of the Hello World program.

2.2. Methods of creating software

You can convert the human-readable source code into machine code by using one the following methods:

2.2.1. Natively compiled software

Natively compiled software is software written in a programming language that compiles to machine code with a resulting binary executable file. Natively compiled software is standalone software.

Note

Natively compiled RPM packages 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 run on a 32-bit (x86) AMD or Intel processor. The resulting package has the architecture specified in its name.

2.2.2. Interpreted software

Some programming languages, such as Bash or Python, do not compile to machine code. Instead, a language interpreter or a language virtual machine executes the programs' source code step-by-step without prior transformations.

Note

Software written entirely in interpreted programming languages is not architecture-specific. Therefore, the resulting RPM package has the noarch string in its name.

You can either raw-interpret or byte-compile software written in interpreted languages:

  • Raw-interpreted software

    You do not need to compile this type of software. Raw-interpreted software is directly executed by the interpreter.

  • Byte-compiled software

    You must first compile this type of software into bytecode, which is then executed by the language virtual machine.

    Note

    Some byte-compiled languages can be either raw-interpreted or byte-compiled.

Note that the way you build and package software by using RPM is different for these two software types.

2.3. Building software from source

During the software building process, the source code is turned into software artifacts that you can package by using RPM.

2.3.1. Building software from natively compiled code

You can build software written in a compiled language into an executable by using one of the following methods:

  • Manual building
  • Automated building

In the following sections, learn how to build the Hello World program written in the C programming language by using either manual or automated building.

2.3.1.1. Manually building the cello software

You can use manual building to build software written in a compiled language.

Hello World written in C (cello.c) has the following contents:

#include <stdio.h>

int main(void) {
    printf("Hello World\n");
    return 0;
}

Procedure

  1. Invoke the C compiler from the GNU Compiler Collection to compile the source code into binary:

    $ gcc -g -o cello cello.c
  2. Run the resulting binary cello:

    $ ./cello
    Hello World

2.3.1.2. Setting up automated building for the cello program

Large-scale software commonly uses automated building. You can set up automated building by creating the Makefile file and then running the GNU make utility.

Procedure

  1. Create the Makefile file with the following content in the same directory as cello.c:

    cello:
    	gcc -g -o cello cello.c
    clean:
    	rm cello

    Note that the lines under cello: and clean: must begin with a tabulation character (tab).

  2. Build the software:

    $ make
    make: 'cello' is up to date.
  3. Because a build is already available in the current directory, enter the make clean command, and then enter the make command again:

    $ make clean
    rm cello
    
    $ make
    gcc -g -o cello cello.c

    Note that trying to build the program again at this point has no effect because the GNU make system detects the existing binary:

    $ make
    make: 'cello' is up to date.
  4. Run the program:

    $ ./cello
    Hello World

2.3.2. Interpreting source code

You can convert the source code written in an interpreted programming language into machine code by using one of the following methods:

  • Byte-compiling

    The procedure for byte-compiling software varies depending on the following factors:

    • Programming language
    • Language’s virtual machine
    • Tools and processes used with that language

      Note

      You can byte-compile software written, for example, in Python. Python software intended for distribution is often byte-compiled, but not in the way described in this document. The described procedure aims not to conform to the community standards, but to be simple. For real-world Python guidelines, see Software Packaging and Distribution.

    You can also raw-interpret Python source code. However, the byte-compiled version is faster. Therefore, RPM packagers prefer to package the byte-compiled version for distribution to end users.

  • Raw-interpreting

    Software written in shell scripting languages, such as Bash, is always executed by raw-interpreting.

In the following sections, learn how to byte-compile the Hello World program written in Python and how to raw-interpret the Hello World program written in Bash.

2.3.2.1. Byte-compiling the pello program

By choosing byte-compiling over raw-interpreting of Python source code, you can create faster software.

The Hello World program written in the Python programming language (pello.py) has the following contents:

print("Hello World")

Procedure

  1. Byte-compile the pello.py file:

    $ python -m compileall pello.py
  2. Verify that a byte-compiled version of the file is created:

    $ ls __pycache__
    pello.cpython-311.pyc

    Note that the package version in the output might differ depending on which Python version is installed.

  3. Run the program in pello.py:

    $ python pello.py
    Hello World

2.3.2.2. Raw-interpreting the bello program

The Hello World program written in Bash shell built-in language (bello) has the following contents:

#!/bin/bash

printf "Hello World\n"
Note

The shebang (#!) sign at the top of the bello file is not part of the programming language source code.

Use the shebang to turn a text file into 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.

Procedure

  1. Make the file with source code executable:

    $ chmod +x bello
  2. Run the created file:

    $ ./bello
    Hello World