From Fedora Project Wiki

m (Tweak libipt doc.)
(18 intermediate revisions by 3 users not shown)
Line 8: Line 8:
  
 
There are a few things worth mentioning before we start.
 
There are a few things worth mentioning before we start.
 +
 +
=== RPM conditionals ===
 +
 +
First, it's important to explain a little bit how the RPM conditionals work.  You can read more about them by seeing [https://rpm-packaging-guide.github.io/#rpm-conditionals].
 +
 +
Throughout the spec file, you will see things like:
 +
 +
<pre>
 +
%if 0%{!?rhel:1} || 0%{?rhel} < 8
 +
...
 +
%endif
 +
</pre>
 +
 +
What this test is checking is:
 +
 +
<pre>
 +
%if we are NOT building on a RHEL system || we are building on a RHEL system whose version is less than 8
 +
...
 +
%endif
 +
</pre>
 +
 +
The reason for the <code>0</code> in front of the conditional is because when the conditional evaluates to false, it will expand to nothing.  For example, suppose that we building GDB on a Fedora system.  Without the leading <code>0</code>, the <code>%if</code> statement above would expand to:
 +
 +
<pre>
 +
%if 1 || < 8
 +
...
 +
%endif
 +
</pre>
 +
 +
Which would cause an error.  With the leading <code>0</code>, we have:
 +
 +
<pre>
 +
%if 1 || 0 < 8
 +
...
 +
</pre>
 +
 +
Which would evaluate to true.
 +
 +
=== Variables ===
  
 
* <code>Version:</code>: this is the upstream version.  On Rawhide, it is usually the snapshot version (e.g., <code>10.0.50</code>) followed by <code>%{snapsrc}</code> (see below).  On a released Fedora, this is usually a regular upstream version (e.g., <code>9.1</code>).
 
* <code>Version:</code>: this is the upstream version.  On Rawhide, it is usually the snapshot version (e.g., <code>10.0.50</code>) followed by <code>%{snapsrc}</code> (see below).  On a released Fedora, this is usually a regular upstream version (e.g., <code>9.1</code>).
 
* <code>Release:</code>: this is the Fedora GDB release.  It should be bumped whenever a new release of the package is made.  When a new upstream release is prepared (e.g., when upstream releases a new GDB and you import it), the Fedora release should be reset to 1.
 
* <code>Release:</code>: this is the Fedora GDB release.  It should be bumped whenever a new release of the package is made.  When a new upstream release is prepared (e.g., when upstream releases a new GDB and you import it), the Fedora release should be reset to 1.
* <code>%{snapsrc}</code>: This is used when the we're working with upstream snapshots, which is usually the case on Rawhide.  This variable contains the date when the snapshot was taken, and is used to compose the <code>Version</code> of  
+
* <code>%{snapsrc}</code>: this is used when the we're working with upstream snapshots, which is usually the case on Rawhide.  This variable contains the date when the snapshot was taken, and is used to compose the <code>Version</code> of the package.  For example, for a release whose snapshot (version <code>10.0.50</code>) was taken on April 2nd, 2020, the <code>Version</code> would be <code>10.0.50.%{snapsrc}</code>, which would translate as <code>10.0.50.20200402</code> when compiled.
* <code>%{snapgnulib}</code>:
+
* <code>%{snapgnulib}</code>: this is the date of the gnulib copy that upstream GDB is carrying.  You can find this out by looking at the <code>GNULIB_COMMIT_SHA1</code> variable inside the <code>gnulib/update-gnulib.sh</code> script, and then checking this commit's date on gnulib's upstream repository.
  
 
== Getting ready ==
 
== Getting ready ==
Line 52: Line 91:
 
After this, you will see a <code>gdb</code> directory, where you can use <code>git switch</code> to switch to a specific release branch.  The <code>master</code> branch is always the Rawhide distribution; the other branches start with the letter <code>f</code> and a number, which correspond to the Fedora release.
 
After this, you will see a <code>gdb</code> directory, where you can use <code>git switch</code> to switch to a specific release branch.  The <code>master</code> branch is always the Rawhide distribution; the other branches start with the letter <code>f</code> and a number, which correspond to the Fedora release.
  
If you are like me and prefers to have each branch in its own directory, you can do that using:
+
If you are like me and prefer to have each branch in its own directory, you can do that using:
  
 
<pre>
 
<pre>
Line 83: Line 122:
 
</pre>
 
</pre>
  
Notice the <code>--with testsuite</code> option.  This will generate a source RPM whose list of dependencies includes the packages needed to run GDB's testsuite.
+
Notice the <code>--with testsuite</code> option (and notice that '''there is a whitespace''' between <code>--with</code> and <code>testsuite</code>!).  This will generate a source RPM whose list of dependencies includes the packages needed to run GDB's testsuite.
  
 
== Dealing with patches ==
 
== Dealing with patches ==
Line 145: Line 184:
 
</pre>
 
</pre>
  
It's a good idea to use <code>--no-commit</code> because it lets you revert the changes made to the <code>ChangeLog</code> files.  They are not needed (because they are already listed in the commit message), and can easily cause conflicts in the future.  You can do that by using the <code>git checkout</code> command, by the way.
+
It's a good idea to use <code>--no-commit</code> because it lets you revert the changes made to the <code>ChangeLog</code> files.  They are not needed (because they are already listed in the commit message), and can easily cause conflicts in the future.  You can do that by using doing something like
 +
 
 +
<pre>
 +
git reset gdb/ChangeLog # Necessary if the file is staged for commit already
 +
git checkout gdb/ChangeLog
 +
</pre>
 +
 
 +
Remember to do that for every ChangeLog file that's been modified.
  
 
Once everything is fine, you can commit the changes:
 
Once everything is fine, you can commit the changes:
Line 338: Line 384:
  
 
Don't forget to <code>git add</code> these files if you edit them.
 
Don't forget to <code>git add</code> these files if you edit them.
 +
 +
== Performing a scratch build (optional) ==
 +
 +
Sometimes you want to make sure that updated Fedora GDB will build fine on all architectures.  For this, you can perform a scratch build, which is just a "test" build that will not be used for anything else.
 +
 +
If you would like to just do a scratch build in order to check if the package is compiling OK, and you still haven't pushed any changes to the official git repository, you can:
 +
 +
<pre>
 +
fedpkg srpm
 +
fedpkg scratch-build --srpm GENERATED_SRPM
 +
</pre>
 +
 +
The first command will generate an SRPM from the current tree (even if there are unpushed commits).  You can get the SRPM and feed it to the <code>fedpkg scratch-build --srpm</code> command, and that's it!
 +
 +
If you have already pushed the changes, you don't need to generate an SRPM; just do a <code>fedpkg scratch-build</code> and it will use the latest changes.
 +
 +
Just to reinforce: this will be a scratch build, meaning that it will not be considered official and will not be used for anything.
  
 
== Testing Fedora GDB ==
 
== Testing Fedora GDB ==
Line 344: Line 407:
  
 
* '''fedora-rawhide''', always tracking the Rawhide distribution.
 
* '''fedora-rawhide''', always tracking the Rawhide distribution.
* '''fedora-stable''', almost always tracking the the last Fedora released.  However, when a new Fedora is branched, I usually update this VM to track it.
+
* '''fedora-stable''', almost always tracking the last Fedora released.  However, when a new Fedora is branched, I usually update this VM to track it.
 
* '''fedora-oldstable''', almost always tracking the last-but-one Fedora released.  When a new Fedora is branched, I usually update this VM to track the last Fedora released.  This means that, for a certain period during development, I don't have easy access to an oldstable system, but that's usually fine since most of the bugs are reported against the stable releases.
 
* '''fedora-oldstable''', almost always tracking the last-but-one Fedora released.  When a new Fedora is branched, I usually update this VM to track the last Fedora released.  This means that, for a certain period during development, I don't have easy access to an oldstable system, but that's usually fine since most of the bugs are reported against the stable releases.
  
Line 382: Line 445:
 
=== Testing a new release ===
 
=== Testing a new release ===
  
'''TODO'''
+
==== Copying the patch containing the new release to the VM ====
 +
 
 +
After you've prepared the new release and ran <code>git add</code> on all of the files that will eventually be committed and pushed to the git repository, you should be able to generate a full patch containing all of the modifications by doing:
 +
 
 +
<pre>
 +
git diff --cached > /tmp/fedora-gdb.patch
 +
</pre>
 +
 
 +
You can <code>scp</code> the patch to the proper VM where you will test the new release, along with the new upstream tarball (if applicable).  Of course, you can also download the tarball from inside the VM.
 +
 
 +
==== Test the current release (if necessary) ====
 +
 
 +
If you don't have previous results for the current Fedora GDB release, it's a good idea to run a testsuite against it so that we can have results which can be used to compare the new release's testsuite run against.
 +
 
 +
Assuming you're inside the Fedora GDB cloned directory (probably named <code>gdb</code>), you can:
 +
 
 +
<pre>
 +
rpmbuildlocal -bb --with testsuite gdb.spec |& tee gdb-VERSION-RELEASE.log
 +
</pre>
 +
 
 +
I like to redirect the output to <code>tee</code> and save it to a file so that I can analyze if something went wrong.
 +
 
 +
You will notice that you will have a new directory called <code>gdb-VERSION/</code>, which is where the source code and the build directory will be.  In order to obtain the test results, you will need to extract a tarball from this directory.  I suggest creating a directory called <code>log-gdb-VERSION-RELEASE</code>, and extract the file there.
 +
 
 +
<pre>
 +
mkdir log-gdb-VERSION-RELEASE
 +
tar xf gdb-VERSION/build-x86_64-redhat-linux-gnu/gdb/gdb-x86_64-redhat-linux-gnu.tar.bz2 -C log-gdb-VERSION-RELEASE
 +
</pre>
 +
 
 +
Of course, if you're running the tests under a non-x86_64 architecture, the directory and the file will be named differently.
 +
 
 +
You will find many files under the <code>log-gdb-VERSION-RELEASE</code> directory.  For example:
 +
 
 +
<pre>
 +
gdb-x86_64-redhat-linux-gnu.native-extended-gdbserver.-m32.log
 +
gdb-x86_64-redhat-linux-gnu.native-extended-gdbserver.-m32.sum
 +
gdb-x86_64-redhat-linux-gnu.native-extended-gdbserver.-m64.log
 +
gdb-x86_64-redhat-linux-gnu.native-extended-gdbserver.-m64.sum
 +
gdb-x86_64-redhat-linux-gnu.native-gdbserver.-m32.log
 +
gdb-x86_64-redhat-linux-gnu.native-gdbserver.-m32.sum
 +
gdb-x86_64-redhat-linux-gnu.native-gdbserver.-m64.log
 +
gdb-x86_64-redhat-linux-gnu.native-gdbserver.-m64.sum
 +
gdb-x86_64-redhat-linux-gnu.unix.-m32.log
 +
gdb-x86_64-redhat-linux-gnu.unix.-m32.sum
 +
gdb-x86_64-redhat-linux-gnu.unix.-m64.log
 +
gdb-x86_64-redhat-linux-gnu.unix.-m64.sum
 +
</pre>
 +
 
 +
Each testing configuration has a <code>log</code> and a <code>sum</code> files.  It should be straightforward to use them.
 +
 
 +
==== Test the next release ====
 +
 
 +
Testing the next release is almost like testing the current release, except that you have to apply the patch you generated before:
 +
 
 +
<pre>
 +
patch -p1 ~/fedora-gdb.patch
 +
</pre>
 +
 
 +
And you also have to download the upstream tarball of the next release, if applicable.  Otherwise, you can repeat the steps from the last section:
 +
 
 +
<pre>
 +
rpmbuildlocal -bb --with testsuite gdb.spec |& tee gdb-VERSION-NEXTRELEASE.log
 +
mkdir log-gdb-VERSION-NEXTRELEASE
 +
tar xf gdb-VERSION/build-x86_64-redhat-linux-gnu/gdb/gdb-x86_64-redhat-linux-gnu.tar.bz2 -C log-gdb-VERSION-NEXTRELEASE
 +
</pre>
 +
 
 +
Now, you can use <code>diff</code> to identify possible regressions between the releases.  For example:
 +
 
 +
<pre>
 +
diff -u -I '^Running' log-gdb-VERSION-RELEASE/gdb-x86_64-redhat-linux-gnu.unix.-m64.sum log-gdb-VERSION-NEXTRELEASE/gdb-x86_64-redhat-linux-gnu.unix.-m64.sum | less
 +
</pre>
 +
 
 +
Ideally, you should check all of the testing configurations.  Beware that you will likely find '''many''' racy results, including from our local patches.
 +
 
 +
=== Testing in other architectures ===
 +
 
 +
In the ideal world, we should test every new release of Fedora GDB in every supported Fedora architecture.  Unfortunately, that's not always feasible, so we end up testing only x86_64 releases.  However, sometimes you will have to deal with architecture-specific bugs and will find yourself wanting a PowerPC or s390x machine to test a release.
 +
 
 +
If you're a Red Hat employee, you can try to use the internal Beaker instance and reserve a machine there.  Sometimes Beaker has trouble reserving a Fedora Rawhide machine, though.
 +
 
 +
Another (limited) option is to try to find a suitable machine at [[Test_Machine_Resources_For_Package_Maintainers]].  At the time of this writing, they only had x86_64 and ARM (32 and 64-bit) machines.
  
 
== Committing & pushing the changes ==
 
== Committing & pushing the changes ==
  
 
If everything went well, you should now commit and push your changes to the Fedora GDB repository.  Make sure you add all of the necessary files before committing.  For example, <code>gdb.spec</code> will need to be added by hand.
 
If everything went well, you should now commit and push your changes to the Fedora GDB repository.  Make sure you add all of the necessary files before committing.  For example, <code>gdb.spec</code> will need to be added by hand.
 +
 +
{{admon/note||If you're like me and prefer to review everything before you commit, you can use check what's been changed by using <code>git status</code> and manually use <code>git add</code> whenever necessary.  For example, the <code>gdb.spec</code> file and the other files starting with <code>_</code> (like <code>_gdb.spec.Patch.include</code>, <code>_gdb.spec.patch.include</code>, <code>_patch_order</code>, etc.) shall be staged for commit.  Of course, you can also use <code>git commit -a</code> below and add everything at once.}}
  
 
The convention is to use the <code>%changelog</code> entry as the commit message, and there is a handy <code>fedpkg</code> that can extract it for you:
 
The convention is to use the <code>%changelog</code> entry as the commit message, and there is a handy <code>fedpkg</code> that can extract it for you:
Line 414: Line 559:
 
</pre>
 
</pre>
  
You should see the progress of the command as the builds are completed.  You can safely interrupt the program if you want; the builds will keep running on Koji.
+
You should see the progress of the command as the builds are completed.  The command will also print a link where you can go to follow the build progress.  You can safely interrupt the program if you want; the builds will keep running on Koji.
 +
 
 +
For more information about Koji, you can read [[Using_the_Koji_build_system]].
  
 
== Prepare an update (for released Fedoras) ==
 
== Prepare an update (for released Fedoras) ==
Line 479: Line 626:
  
 
You can save the file, and you will probably be prompted for your FAS password.  If everything is OK, you will see the update request created.
 
You can save the file, and you will probably be prompted for your FAS password.  If everything is OK, you will see the update request created.
 +
 +
== Appendix ==
 +
 +
=== libipt maintenance ===
 +
 +
You will probably have to maintain <code>libipt</code> as well.  Fortunately, this is a simple package to maintain and it doesn't involve any special procedure.  When there is a new upstream release available, an automatic bug report will be filed against the package and you will receive an email.  You will then have to perform the regular package upgrade procedure: download the new tarball, prepare a release with it, test to see if no regressions happen, upload the tarball, commit and push the changes to dist-git, and then trigger a build.
 +
 +
As of 2021-03-30, the libipt documentation also needs to be generated. To do this, do:
 +
 +
<pre>
 +
rpmbuildlocal -bb --with docs libipt.spec
 +
</pre>
 +
 +
Once that is done, find doc-vVERSION.tar.xz created by the build, and then do the following to upload it:
 +
 +
<pre>
 +
fedpkg upload doc-vVERSION.tar.xz
 +
</pre>
 +
 +
The Fedora GDB package also carries a copy of libipt, so you will also have to update it there.  Testing it might prove a bit challenging because this libipt copy is only built and used when you're building for DTS on RHEL-7.  Perhaps this copy could be removed, since we always link against the system libipt when building for Fedora or for RHEL >= 8.
 +
 +
=== Why is there a gdb-minimal package? ===
 +
 +
The reason we have two Fedora GDB packages (<code>gdb</code> and <code>gdb-minimal</code>) is because GDB is considered a '''critical-path''' package, which means that it is a dependency of the Fedora buildroot (where all of Fedora's packages are built).  In order to minimize breakages, dependencies and the buildroot size, it was decided that there should be a <code>gdb-minimal</code> package which contained just the bare minimal, only what is necessary to perform what the buildroot needs (which is to be able to run the <code>gdb-add-index</code> script).
 +
 +
The need for this separation became apparent when a new version of libipt was released, and I innocently tried to upgrade it.  I did all of the upgrade process for the new libipt, submitted the build, and was happy when everything succeeded.  However, the GDB that was currently present at the Rawhide repository still depended on the old version of libipt.  I thought this was easily solvable by submitting a new build for GDB, but was surprised when the build failed.  The reason for the failure was because, even before building anything, the Fedora buildroot could not be set up because it depends on GDB, and the current GDB could not find the old libipt.
 +
 +
Anyway, in order to solve this problem, <code>gdb-minimal</code> does not link against libipt.  In fact, it does not link against Python, Guile, source-highlight, etc. neither.  So now, even if you upgrade libipt alone, there will be no problem.
 +
 +
In the interest of being complete, I think it's important to say that the right way to solve the problem of upgrading libipt without having a <code>gdb-minimal</code> package would have been to use the <code>fedpkg chain-build</code> command, which takes two or more packages and makes sure that they are built in the same buildroot.
 +
 +
=== Testing upstream GDB using the same flags that Fedora GDB uses ===
 +
 +
Sometimes it's useful to test upstream GDB using the same configuration flags that are used to build Fedora GDB.  In order to do that, you can use the <code>rpm --eval</code> command to obtain the flags for the architecture/system you're using.  For example:
 +
 +
<pre>
 +
git clone binutils-gdb...
 +
mkdir build && cd build
 +
../binutils-gdb/configure \
 +
  --disable-{binutils,gas,ld,gprof,gold,sim} \
 +
  --with-python=/usr/bin/python3  \
 +
  --with-separate-debug-dir=/usr/lib/debug/ \
 +
  CFLAGS="$(rpm --eval '%{build_cflags}')" \
 +
  CXXFLAGS="$(rpm --eval '%{build_cxxflags}')" \
 +
  LDFLAGS="$(rpm --eval '%{build_ldflags}')"
 +
make
 +
</pre>
 +
 +
You can read more about the <code>%{build_*}</code> variables at [https://src.fedoraproject.org/rpms/redhat-rpm-config/blob/master/f/buildflags.md].

Revision as of 19:59, 30 March 2021

Introduction

This is a guide for the Fedora GDB package maintainer. The reason we have a specific document for the package (which builds on top of the existing official Fedora packaging documentation) is because we carry several local patches along with the project's official codebase.

Warning.png
This guide is not meant to cover everything related to general package maintenance. Its purpose is to cover specific scenarios that can happen when maintaining Fedora GDB. It is strongly recommended that you also read Package_maintenance_guide in order to obtain more information about packaging.

gdb.spec glossary

There are a few things worth mentioning before we start.

RPM conditionals

First, it's important to explain a little bit how the RPM conditionals work. You can read more about them by seeing [1].

Throughout the spec file, you will see things like:

%if 0%{!?rhel:1} || 0%{?rhel} < 8
...
%endif

What this test is checking is:

%if we are NOT building on a RHEL system || we are building on a RHEL system whose version is less than 8
...
%endif

The reason for the 0 in front of the conditional is because when the conditional evaluates to false, it will expand to nothing. For example, suppose that we building GDB on a Fedora system. Without the leading 0, the %if statement above would expand to:

%if 1 || < 8
...
%endif

Which would cause an error. With the leading 0, we have:

%if 1 || 0 < 8
...

Which would evaluate to true.

Variables

  • Version:: this is the upstream version. On Rawhide, it is usually the snapshot version (e.g., 10.0.50) followed by %{snapsrc} (see below). On a released Fedora, this is usually a regular upstream version (e.g., 9.1).
  • Release:: this is the Fedora GDB release. It should be bumped whenever a new release of the package is made. When a new upstream release is prepared (e.g., when upstream releases a new GDB and you import it), the Fedora release should be reset to 1.
  • %{snapsrc}: this is used when the we're working with upstream snapshots, which is usually the case on Rawhide. This variable contains the date when the snapshot was taken, and is used to compose the Version of the package. For example, for a release whose snapshot (version 10.0.50) was taken on April 2nd, 2020, the Version would be 10.0.50.%{snapsrc}, which would translate as 10.0.50.20200402 when compiled.
  • %{snapgnulib}: this is the date of the gnulib copy that upstream GDB is carrying. You can find this out by looking at the GNULIB_COMMIT_SHA1 variable inside the gnulib/update-gnulib.sh script, and then checking this commit's date on gnulib's upstream repository.

Getting ready

You will need to install some packages before we start.

dnf install fedpkg rpm-build

You will also need to configure Kerberos authentication in order to use fedpkg. See Infrastructure/Kerberos for details.

I personally like to use the following bash function when building the package. It guarantees that the full build will happen at the current directory, instead of ~/rpmbuild/ or something else.

# Function for building an RPM at $PWD.
function rpmbuildlocal
{
  MAKEFLAGS= rpmbuild \
    --define "_topdir $PWD" \
    --define "_builddir $PWD" \
    --define "_rpmdir $PWD" \
    --define "_sourcedir $PWD" \
    --define "_specdir $PWD" \
    --define "_srcrpmdir $PWD" \
    --define "_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm" \
    "$@"; rmdir &>/dev/null BUILDROOT;
}

Cloning the repository

The Fedora GDB repository is located at [2]. You can clone it by doing:

fedpkg clone gdb

After this, you will see a gdb directory, where you can use git switch to switch to a specific release branch. The master branch is always the Rawhide distribution; the other branches start with the letter f and a number, which correspond to the Fedora release.

If you are like me and prefer to have each branch in its own directory, you can do that using:

fedpkg clone --branches gdb

You should see several directories named like f28/, f29/, f30/, etc. If you choose this approach, you will have to manually clone every time Fedora branches. For example, supposing that Fedora branches f30, you will have to do:

fedpkg clone --branch f30 gdb && mv gdb f30

Downloading the sources

Fedora stores the source files (i.e., the tarballs) for the package in a separate cache. This means that when you clone the repository, you will not automatically obtain the tarballs necessary to build the package. In order to do that, you should execute:

fedpkg sources

The command should be executed inside the cloned directory. If you used the --branches option when cloning, then you should enter the directory related to the Fedora version you are working on.

Satisfying the build-dependencies

You can do:

rpmbuildlocal -bs --with testsuite gdb.spec
sudo dnf builddep gdb-*.src.rpm

Notice the --with testsuite option (and notice that there is a whitespace between --with and testsuite!). This will generate a source RPM whose list of dependencies includes the packages needed to run GDB's testsuite.

Dealing with patches

Because we have several local patches, it is necessary to understand how to handle them in a way that doesn't cause too many conflicts.

To help with the job, Fedora GDB carries two shell scripts that automate the process of applying patches to and extracting patches from a tree.

Applying patches to a repository

You should use the script called generate-git-repo-from-patches.sh for this task. It requires one argument, REPOSITORY, which points to a cloned upstream GDB git repo. All it does is enter the directory, checkout a specific commit (the one pointed by the file _git_upstream_commit, itearate over the list of local patches and apply them sequentially.

If you already have a cloned upstream GDB repository, you can do:

git clone git://sourceware.org/git/binutils-gdb.git --reference=/path/to/local/gdb/repo new-fedora-release
./generate-git-repo-from-patches.sh new-fedora-release

I like calling the cloned directory new-fedora-release, but that's just a personal preference.

Extracting patches from a repository

You should use the script called generate-patches-from-git-repo.sh for this task. It takes two arguments:

  • REPOSITORY, the directory where you cloned the upstream GDB git repository (and where the local patches are applied). This argument is required.
  • COMMIT_OR_TAG_OR_BRANCH, which is the commit/tag/branch against which the rebase was performed. If no rebase was performed (e.g., if you just backported a patch and placed it on top of the others), you don't need to provide this argument.

Mandatory patch header

When extracting the patches, the script automatically generates the *.patch files, along with other two files: _gdb.spec.patch.include (which contains the %patch directives), and _gdb.spec.Patch.include (which contains the Patch: directives).

In order to generate the patches, the script must know how to name them. The script must also know if there should be any comment on top of the Patch: directive for each patch. The way we do that is by having two mandatory headers in the commit message:

  • The first line (subject) of the commit message must be the patch filename. The convention is to use gdb-rhbzNNNNNN-short-desc.patch.
  • The first line(s) of the commit body can be the comment that will be placed on top of the Patch: directive. It must start with two semicolons ;;.

An example of a proper commit message would be:

gdb-rhbz1553104-s390x-arch12-test.patch

;; [s390x] Backport arch12 instructions decoding (RH BZ 1553104).
;; =fedoratest

Preparing a new release

There are a few ways to prepare a new release, depending on what you want to do.

Case 1: Backport an upstream fix (no rebase)

Update origin and cherry-pick the patch

If you just want to backport an upstream fix, but don't want to rebase the code, then you would:

cd new-fedora-release
git fetch origin
git cherry-pick --no-commit 0a1b2c3d

It's a good idea to use --no-commit because it lets you revert the changes made to the ChangeLog files. They are not needed (because they are already listed in the commit message), and can easily cause conflicts in the future. You can do that by using doing something like

git reset gdb/ChangeLog # Necessary if the file is staged for commit already
git checkout gdb/ChangeLog

Remember to do that for every ChangeLog file that's been modified.

Once everything is fine, you can commit the changes:

git commit

Remember to add the necessary headers (i.e., patch filename + comments) when editing the commit message.

Generate the backported patch and update gdb.spec

After that, you can generate the backported patch:

cd ..
./generate-patches-from-git-repo.sh new-fedora-release
Note.png
Notice how the second argument was omitted when invoking the script. We don't need it because we are not rebasing.

Run a git status if you would like to see which files were added/changed, and then edit the gdb.spec file. Since this does not involve a rebase, all you have to do is:

  • Bump the Release: number. If you are using Emacs, you can do a C-c C-r.
  • Write a %changelog entry. If you are using Emacs, you can get a template ready by doing C-c C-w. I mention which bug has been fixed by the backport, and who authored the patch. For example:
* Thu Feb 13 2020 Sergio Durigan Junior <sergiodj@redhat.com> - 9.1-3
- Fix 'Recursive call to 'missing_rpm_list_print' when pagination is
  on and missing RPM list is big' (RHBZ 1801974, Sergio Durigan
  Junior).

Case 2: Rebase Rawhide GDB against upstream master

Update origin and start the rebase

The rebasing process is a bit more involved. It starts just like the previous case:

cd new-fedora-release
git fetch origin

But then you have to decided the upstream commit you will rebase against. In 99.9% of the cases, my approach was to pick the most recent commit by GDB Administrator (which is the bot that automatically updates the upstream version date every night). So just do a git log --author=gdbadmin and pick the first commit that shows up. For example, let's say the commit is 0a2b3c4d. You would then do:

git rebase 0a2b3c4d

This will start a rebase process, of course. Beware, due to the high number of local patches, you will most certainly see a few conflicts that will need to be solved by hand.

When I'm rebasing and there's a conflict, I find it useful to do a quick compilation of the tree in order to make sure that I solved everything correctly. Because we're dealing with Fedora GDB (and not upstream GDB), the compilation command differs a little bit. Here's what I use (assuming you're inside the new-fedora-release directory):

mkdir build-test && cd build-test
../configure \
  --disable-binutils \
  --disable-ld \
  --disable-gold \
  --disable-gas \
  --disable-sim \
  --disable-gprof \
  --with-system-readline \
  --with-separate-debug-dir=/usr/lib/debug \
  CFLAGS='-D_GLIBCXX_DEBUG -g3 -O0' \
  CXXFLAGS='-D_GLIBCXX_DEBUG -g3 -O0' \
  --enable-targets=s390-linux-gnu,powerpc-linux-gnu,arm-linux-gnu,aarch64-linux-gnu,amd64-linux-gnu
make -j10

Every time there's a conflict and I solve it, I just go inside build-test and do a make -j10 to check if the code is compiling correctly. If you want, you can also run some testcase and check for regressions. This is a good idea, but of course a more formal/correct way to do a regression testing is to run the full testsuite inside a Fedora Rawhide VM (more on that later).

Regenerate the patches and update gdb.spec

Once the rebase is done, you need to regenerate the patches that were affected by it. The way to do this is by invoking:

cd ..
./generate-patches-from-git-repo.sh new-fedora-release 0a2b3c4d
Note.png
Notice how we have to provide the second argument containing the commit against which the rebase happened.

Again, it's a good idea to perform a git status in order to check which files have been changed/deleted.

You will also need to update gdb.spec. The instructions are very similar to the ones that were given in case above:

  • Bump the Release: number. If you are using Emacs, you can do a C-c C-r.
  • Update the Version: field (if necessary). If you are rebasing against upstream master but the last Fedora GDB was a stable one (e.g., 9.1), then you will have to update this field and put the snapshot version (e.g., 10.0.50.%{snapsrc}). Remember that the %{snapsrc} must be included in the version.
  • Update the %global snapsrc variable. You should update it to contain the date of the commit you used to rebase Fedora GDB against. For example, 20200402 if the commit was made on April 2nd, 2020.
  • Update the %global snapgnulib variable (if necessary). If GDB's copy of gnulib has been updated since the last Fedora GDB release, you should update this variable. It has to contain the date of the gnulib copy that upstream GDB is carrying. You can find this out by looking at the GNULIB_COMMIT_SHA1 variable inside the gnulib/update-gnulib.sh script, and the check this commit's date on gnulib's repository.
  • Write a %changelog entry. If you are using Emacs, you can get a template ready by doing C-c C-w. If a patch has been automatically updated by the rebase process, I don't mention it in the changelog. However, if a patch has been dropped/upstreamed (yay!) or if I had to manually adjust it in order to make it usable again, I put a line saying what I did. This makes it easier later to follow the progress of the patch upstreaming effort.

Case 3: When there is a new upstream GDB release

When there is a new upstream GDB release, you will want to rebase Fedora GDB Rawhide (or the last branched-but-unreleased Fedora) against it. Why? Because Fedora tries to release a new distribution every 6 months, and upstream GDB also tries to release a new version every 6 months. This means that we are usually able to ship the latest upstream GDB in the new Fedora.

For the sake of this example, let's suppose the latest Fedora stable release is Fedora 31, and that Fedora 32 has not been branched yet (i.e., Fedora Rawhide == Fedora 32). Let's also assume that upstream GDB 9.1 has just been released.

Updating origin and starting the rebase

In this scenario, our Fedora GDB Rawhide (i.e., master) branch would be tracking upstream GDB's master branch, as expected. You have to make Fedora GDB Rawhide start tracking gdb-9.1-branch instead, since we want Fedora 32 to contain GDB 9.1 when it's branched.

In order to do that, you will need to rebase Fedora's master branch onto upstream's release branch/tag (in our example, gdb-9.1-branch). Let's suppose that the Fedora GDB local patches are rebased against commit 0a1b2c3d (from upstream's master).

cd new-fedora-release
git fetch origin
git rebase --onto gdb-9.1-branch 0a1b2c3d HEAD

That's it. You will now have all of Fedora GDB's local patches rebased against the gdb-9.1-branch.

Regenerate the patches and update gdb.spec

The way to regenerate the patches is pretty much the same as in the previous case. The only thing that changes is that you will use gdb-9.1-branch as the second argument to the script.

cd ..
./generate-patches-from-git-repo.sh new-fedora-release gdb-9.1-branch

And now you have to update gdb.spec.

  • Reset the Release: number to 1. This is a new release, so the Fedora GDB package release number should be reset.
  • Update the Version: field. In our example, you'd be setting it to 9.1. If upstream has only create a new branch, but has not released GDB yet, then your Version: will be something like VER.%{snapsrc}, where VER is the snapshot version for the branch (something like 10.0.90).
  • Update the %{snapsrc} field, if applicable. If upstream GDB has only created a new branch for the next GDB release, but has not released GDB yet, then you will need to update this field, because in this case the Fedora branch will be tracking a snapshot of upstream's branch. However, if upstream GDB has released a new GDB (i.e., there is a gdb-VERSION-release tag), then you don't need to worry about %{snapsrc} because your Version: field will not contain it.
  • Update the %global snapgnulib variable (if necessary). See more details about this in the previous case.
  • Write a %changelog entry. If you are using Emacs, you can get a template ready by doing C-c C-w. If a patch has been automatically updated by the rebase process, I don't mention it in the changelog. However, if a patch has been dropped/upstreamed (yay!) or if I had to manually adjust it in order to make it usable again, I put a line saying what I did. This makes it easier later to follow the progress of the patch upstreaming effort.

Case 4: When Fedora is branched

When Fedora Rawhide is branched, this means that there will be a new Fedora branch that is still unreleased, and that the master branch will point to the next Fedora release.

The new Fedora branch should ideally track the new upstream GDB release/branch. If there was no new upstream release/branch before the Fedora branch was made, then this means that both the new Fedora branch and the Fedora master branch will be tracking upstream's master branch, and you will be making rebases like the one described on Case 2 for both Fedora branches. It's important to keep both in sync in this case.

However, if the new Fedora branch is already tracking a new upstream release/branch, then you will need to make the Fedora master branch track upstream's master branch again.

Updating origin and rebasing onto master

Fortunately, we can use git rebase in order to perform this task for us. Remember, your Fedora master branch is currently tracking a specific upstream release/branch (e.g., gdb-9.1-branch), and you want to rebase it onto upstream's master. Suppose you want to rebase it against commit 0a1b2c3d from master (which should be a commit from GDB Administrator, as explained on Case 2). You need to:

cd new-fedora-release
git fetch origin
git rebase --onto 0a1b2c3d gdb-9.1-release HEAD

Here:

  • 0a1b2c3d is the commit from the master branch that you want to rebase on top of.
  • gdb-9.1-release is the commit/tag/branch on top of which the local patches are currently based. It's like a starting point.
  • HEAD is the last commit to be considered when rebasing on top of 0a1b2c3d. It's like an ending point (in other words, you're specifying a range with the second and the third arguments).

Depending on how long you wait to make this rebase, you will probably see quite a number of conflicts due to our local patches.

Regenerate the patches and update gdb.spec

The way to regenerate the patches is pretty much the same as in the previous case. The only thing that changes is that you will use 0a1b2c3d as the second argument to the script.

cd ..
./generate-patches-from-git-repo.sh new-fedora-release 0a1b2c3d

And now you have to update gdb.spec.

  • Reset the Release: number to 1. This is a new release, so the Fedora GDB package release number should be reset.
  • Update the Version: field. In our example, you'd be setting it to contain the date of the GDB Administrator commit, plus %{snapsrc}. So, for example, 20200402.%{snapsrc}.
  • Update the %global snapgnulib variable (if necessary). See more details about this on Case 2.
  • Write a %changelog entry. If you are using Emacs, you can get a template ready by doing C-c C-w. If a patch has been automatically updated by the rebase process, I don't mention it in the changelog. However, if a patch has been dropped/upstreamed (yay!) or if I had to manually adjust it in order to make it usable again, I put a line saying what I did. This makes it easier later to follow the progress of the patch upstreaming effort.

Upload the new upstream GDB tarball (when rebasing)

Warning.png
You only need to do this step when you're rebasing Fedora GDB.

After the rebase is completed, it's time to upload the new upstream GDB tarball to the lookaside cache. If you've followed the steps above, you will remember that you chose to rebase Fedora GDB against one of the GDB Administrator commits. The reason I suggest you to do that is because that commit also triggers the generation of the official upstream GDB snapshot tarball, which can be uploaded as the base for the new Fedora GDB release.

The snapshots can be found at:

  • [3] for upstream's master branch.
  • [4] for branch snapshots (for example, gdb-9.1-branch).

After you've downloaded the corresponding tarball, you have to upload it to Fedora's lookaside cache:

fedpkg upload gdb-VERSION.tar.xz

After the upload, you will notice that two files will have been modified: sources and .gitignore. I prefer to edit these files and remove the entry for the old tarball, to keep them clean and concise.

Don't forget to git add these files if you edit them.

Performing a scratch build (optional)

Sometimes you want to make sure that updated Fedora GDB will build fine on all architectures. For this, you can perform a scratch build, which is just a "test" build that will not be used for anything else.

If you would like to just do a scratch build in order to check if the package is compiling OK, and you still haven't pushed any changes to the official git repository, you can:

fedpkg srpm
fedpkg scratch-build --srpm GENERATED_SRPM

The first command will generate an SRPM from the current tree (even if there are unpushed commits). You can get the SRPM and feed it to the fedpkg scratch-build --srpm command, and that's it!

If you have already pushed the changes, you don't need to generate an SRPM; just do a fedpkg scratch-build and it will use the latest changes.

Just to reinforce: this will be a scratch build, meaning that it will not be considered official and will not be used for anything.

Testing Fedora GDB

It is really important to test every release to make sure no regressions are introduced. I personally like to maintain 3 VMs ready to test Fedora GDB:

  • fedora-rawhide, always tracking the Rawhide distribution.
  • fedora-stable, almost always tracking the last Fedora released. However, when a new Fedora is branched, I usually update this VM to track it.
  • fedora-oldstable, almost always tracking the last-but-one Fedora released. When a new Fedora is branched, I usually update this VM to track the last Fedora released. This means that, for a certain period during development, I don't have easy access to an oldstable system, but that's usually fine since most of the bugs are reported against the stable releases.

Before every test, you should run a dnf upgrade and reboot the VM to make sure it's running the latest software available in the distro. This is especially important for the rawhide VM, because of how fast changes are introduced there.

Prepare the VM for first use

Inside the VM, it isn't necessary to configure Kerberos authentication to clone the Fedora GDB repository. You can use fedpkg's -a option, which allows you to clone the repository anonymously:

fedpkg clone -a gdb

Since we're not going to do any development in the VM, you can clone without using --branches and just git switch to the desired branch.

You should also download the sources. This step is only necessary because you have to build an initial source RPM in order to be able to install all of the build dependencies necessary to build and test Fedora GDB.

cd gdb
fedpkg sources

Then, generate a source RPM:

rpmbuildlocal -bs --with testsuite gdb.spec

And install the build deps:

dnf builddep gdb-*.src.rpm

This should be enough to build and test GDB.

Testing a new release

Copying the patch containing the new release to the VM

After you've prepared the new release and ran git add on all of the files that will eventually be committed and pushed to the git repository, you should be able to generate a full patch containing all of the modifications by doing:

git diff --cached > /tmp/fedora-gdb.patch

You can scp the patch to the proper VM where you will test the new release, along with the new upstream tarball (if applicable). Of course, you can also download the tarball from inside the VM.

Test the current release (if necessary)

If you don't have previous results for the current Fedora GDB release, it's a good idea to run a testsuite against it so that we can have results which can be used to compare the new release's testsuite run against.

Assuming you're inside the Fedora GDB cloned directory (probably named gdb), you can:

rpmbuildlocal -bb --with testsuite gdb.spec |& tee gdb-VERSION-RELEASE.log

I like to redirect the output to tee and save it to a file so that I can analyze if something went wrong.

You will notice that you will have a new directory called gdb-VERSION/, which is where the source code and the build directory will be. In order to obtain the test results, you will need to extract a tarball from this directory. I suggest creating a directory called log-gdb-VERSION-RELEASE, and extract the file there.

mkdir log-gdb-VERSION-RELEASE
tar xf gdb-VERSION/build-x86_64-redhat-linux-gnu/gdb/gdb-x86_64-redhat-linux-gnu.tar.bz2 -C log-gdb-VERSION-RELEASE

Of course, if you're running the tests under a non-x86_64 architecture, the directory and the file will be named differently.

You will find many files under the log-gdb-VERSION-RELEASE directory. For example:

gdb-x86_64-redhat-linux-gnu.native-extended-gdbserver.-m32.log
gdb-x86_64-redhat-linux-gnu.native-extended-gdbserver.-m32.sum
gdb-x86_64-redhat-linux-gnu.native-extended-gdbserver.-m64.log
gdb-x86_64-redhat-linux-gnu.native-extended-gdbserver.-m64.sum
gdb-x86_64-redhat-linux-gnu.native-gdbserver.-m32.log
gdb-x86_64-redhat-linux-gnu.native-gdbserver.-m32.sum
gdb-x86_64-redhat-linux-gnu.native-gdbserver.-m64.log
gdb-x86_64-redhat-linux-gnu.native-gdbserver.-m64.sum
gdb-x86_64-redhat-linux-gnu.unix.-m32.log
gdb-x86_64-redhat-linux-gnu.unix.-m32.sum
gdb-x86_64-redhat-linux-gnu.unix.-m64.log
gdb-x86_64-redhat-linux-gnu.unix.-m64.sum

Each testing configuration has a log and a sum files. It should be straightforward to use them.

Test the next release

Testing the next release is almost like testing the current release, except that you have to apply the patch you generated before:

patch -p1 ~/fedora-gdb.patch

And you also have to download the upstream tarball of the next release, if applicable. Otherwise, you can repeat the steps from the last section:

rpmbuildlocal -bb --with testsuite gdb.spec |& tee gdb-VERSION-NEXTRELEASE.log
mkdir log-gdb-VERSION-NEXTRELEASE
tar xf gdb-VERSION/build-x86_64-redhat-linux-gnu/gdb/gdb-x86_64-redhat-linux-gnu.tar.bz2 -C log-gdb-VERSION-NEXTRELEASE

Now, you can use diff to identify possible regressions between the releases. For example:

diff -u -I '^Running' log-gdb-VERSION-RELEASE/gdb-x86_64-redhat-linux-gnu.unix.-m64.sum log-gdb-VERSION-NEXTRELEASE/gdb-x86_64-redhat-linux-gnu.unix.-m64.sum | less

Ideally, you should check all of the testing configurations. Beware that you will likely find many racy results, including from our local patches.

Testing in other architectures

In the ideal world, we should test every new release of Fedora GDB in every supported Fedora architecture. Unfortunately, that's not always feasible, so we end up testing only x86_64 releases. However, sometimes you will have to deal with architecture-specific bugs and will find yourself wanting a PowerPC or s390x machine to test a release.

If you're a Red Hat employee, you can try to use the internal Beaker instance and reserve a machine there. Sometimes Beaker has trouble reserving a Fedora Rawhide machine, though.

Another (limited) option is to try to find a suitable machine at Test_Machine_Resources_For_Package_Maintainers. At the time of this writing, they only had x86_64 and ARM (32 and 64-bit) machines.

Committing & pushing the changes

If everything went well, you should now commit and push your changes to the Fedora GDB repository. Make sure you add all of the necessary files before committing. For example, gdb.spec will need to be added by hand.

Note.png
If you're like me and prefer to review everything before you commit, you can use check what's been changed by using git status and manually use git add whenever necessary. For example, the gdb.spec file and the other files starting with _ (like _gdb.spec.Patch.include, _gdb.spec.patch.include, _patch_order, etc.) shall be staged for commit. Of course, you can also use git commit -a below and add everything at once.

The convention is to use the %changelog entry as the commit message, and there is a handy fedpkg that can extract it for you:

fedpkg clog

This will generate a file named clog, which you can use to make the commit:

git commit -F clog

After that, you can push:

git push

Building the new release

If the push went well, you can now build an official release. To do that, simply:

fedpkg build

You should see the progress of the command as the builds are completed. The command will also print a link where you can go to follow the build progress. You can safely interrupt the program if you want; the builds will keep running on Koji.

For more information about Koji, you can read Using_the_Koji_build_system.

Prepare an update (for released Fedoras)

If you're building a new Fedora GDB for a Fedora distribution that has already been released, then you will also need to create an update request to make sure that the new release will be shipped to users.

Warning.png
This process is not necessary if you are preparing a new release for Rawhide or for an unreleased (but branched) Fedora.

To do that, you should issue the following command:

fedpkg update

You will be presented with a template like this:

[ gdb-10.0.50.20200307-1.fc33 ]

# bugfix, security, enhancement, newpackage (required)
type=

# testing, stable
request=testing

# Bug numbers: 1234,9876
bugs=

# Severity: low, medium, high, urgent
# This is required for security updates.
# severity=unspecified

display_name=

# Changelog:
# - Rebase to FSF GDB 10.0.50.20200307 (10.1pre).
# Bump snapgnulib version (20200221).
#
# Here is where you give an explanation of your update.
# Content can span multiple lines, as long as they are indented deeper than
# the first line. For example,
# notes=first line
#     second line
#     and so on
notes=Rebase to FSF GDB 10.0.50.20200307 (10.1pre).

# Enable request automation based on the stable/unstable karma thresholds
autokarma=True
stable_karma=3
unstable_karma=-3

# Automatically close bugs when this marked as stable
close_bugs=True

# Suggest that users restart after update
suggest_reboot=False

You usually just have to:

  • Set type to bugfix.
  • Set bugs to contain the bug numbers you're fixing.
  • Write notes. Usually it's OK to just put the changelog entry.

You can save the file, and you will probably be prompted for your FAS password. If everything is OK, you will see the update request created.

Appendix

libipt maintenance

You will probably have to maintain libipt as well. Fortunately, this is a simple package to maintain and it doesn't involve any special procedure. When there is a new upstream release available, an automatic bug report will be filed against the package and you will receive an email. You will then have to perform the regular package upgrade procedure: download the new tarball, prepare a release with it, test to see if no regressions happen, upload the tarball, commit and push the changes to dist-git, and then trigger a build.

As of 2021-03-30, the libipt documentation also needs to be generated. To do this, do:

rpmbuildlocal -bb --with docs libipt.spec

Once that is done, find doc-vVERSION.tar.xz created by the build, and then do the following to upload it:

fedpkg upload doc-vVERSION.tar.xz

The Fedora GDB package also carries a copy of libipt, so you will also have to update it there. Testing it might prove a bit challenging because this libipt copy is only built and used when you're building for DTS on RHEL-7. Perhaps this copy could be removed, since we always link against the system libipt when building for Fedora or for RHEL >= 8.

Why is there a gdb-minimal package?

The reason we have two Fedora GDB packages (gdb and gdb-minimal) is because GDB is considered a critical-path package, which means that it is a dependency of the Fedora buildroot (where all of Fedora's packages are built). In order to minimize breakages, dependencies and the buildroot size, it was decided that there should be a gdb-minimal package which contained just the bare minimal, only what is necessary to perform what the buildroot needs (which is to be able to run the gdb-add-index script).

The need for this separation became apparent when a new version of libipt was released, and I innocently tried to upgrade it. I did all of the upgrade process for the new libipt, submitted the build, and was happy when everything succeeded. However, the GDB that was currently present at the Rawhide repository still depended on the old version of libipt. I thought this was easily solvable by submitting a new build for GDB, but was surprised when the build failed. The reason for the failure was because, even before building anything, the Fedora buildroot could not be set up because it depends on GDB, and the current GDB could not find the old libipt.

Anyway, in order to solve this problem, gdb-minimal does not link against libipt. In fact, it does not link against Python, Guile, source-highlight, etc. neither. So now, even if you upgrade libipt alone, there will be no problem.

In the interest of being complete, I think it's important to say that the right way to solve the problem of upgrading libipt without having a gdb-minimal package would have been to use the fedpkg chain-build command, which takes two or more packages and makes sure that they are built in the same buildroot.

Testing upstream GDB using the same flags that Fedora GDB uses

Sometimes it's useful to test upstream GDB using the same configuration flags that are used to build Fedora GDB. In order to do that, you can use the rpm --eval command to obtain the flags for the architecture/system you're using. For example:

git clone binutils-gdb...
mkdir build && cd build
../binutils-gdb/configure \
  --disable-{binutils,gas,ld,gprof,gold,sim} \
  --with-python=/usr/bin/python3  \
  --with-separate-debug-dir=/usr/lib/debug/ \
  CFLAGS="$(rpm --eval '%{build_cflags}')" \
  CXXFLAGS="$(rpm --eval '%{build_cxxflags}')" \
  LDFLAGS="$(rpm --eval '%{build_ldflags}')"
make

You can read more about the %{build_*} variables at [5].