How to build the Qt6 library that comes with Leap 16.0?

Can anybody please point me to a set of instructions on how to build the Qt6 library that comes with Leap 16.0?
I want to do this on a fresh install of Leap 16.0, so anything that needs to be installed should be listed.
The result should be the exact files as the ones in /usr/lib64/libQt6*.

@kls The openSUSE Build Service and osc, or just grab the src rpm and build locally with rpmbuild. zypper if <some_rpm> will show the src rpm to download or zypper in <src_rpm after you enable the source repo…

Look at the .spec file for the source package what it does, what BuildRequires it uses and more. Also note that a source package contains the source tarballs from upstream PLUS a number of patches that need to be applied in the correct order, as described in the .spec file.

You can do all that by yourself, but it’s not trivial. Consider creating an account on build.opensuse.org and cloning the Qt source package to your home project to let the OBS do the hard work for you.

Once that works, you can start modifying things, preferably with a patch of your own that sits on top of the original sources (the upstream tarball) and the SUSE patches.

1 Like

That sounds great! With the help of ChatGPT I got as far as

zypper install osc
mkdir -p ~/obs/Qt6
cd ~/obs/Qt6
osc checkout KDE:Qt6 qt6-base
osc checkout KDE:Qt6 qt6-tools

but when I try

osc build --local --noservice --root ~/obs/build openSUSE_Leap_16.0

I get into some sort of “signature hell”, and ChatGPT starts talking about Leap 16.0 being “several years old now” and that there would be a version 16.3, but all the links to that version are 404.

Please forgive my total beginner’s problems, but I have never used OBS before. It looks like a great tool, but I’m afraid I’m running into a dead end - maybe I just took a wrong turn. Could somebody please give me a hand to overcome these initial hurdles?

Looks like ChatGPT is confused about Leap 15.x which is indeed partially based on very old code and the brand-new Leap 16.0 based on very up-to-date upstream code.

I assume you already discovered the official OBS tutorials:

1 Like

The idea behind OBS (and RPM) is to work with pristine sources from upstream and possibly add patches (diffs) to make it work for your distro or environment, and to build them all together. Try to keep the patches minimalistic, and maybe separate for separate problems.

From time to time, there will be a new upstream version that comes as a completely new tarball. The upstream authors may have integrated one or more of your patches (especially if you asked them to do so), so that patch won’t be needed anymore; it’s in the original sources now, so it won’t apply anymore. That’s why it’s a good idea to keep different changes in different patches, so you can easily omit such a patch that is now no longer needed.

This is when you remove that patch from the sources and from your .spec file.

Since the new upstream tarball will have a new version number, you now have the old tarball foo-47.11.tgz and the new one foo-47.12.tgz, and you don’t need your old patch fix-foobar-handling.patch anymore.

So what you do is to go to your OBS checkout directory and

  • remove the unneeded patch: rm fix-foobar-handling.patch
  • remove the old upstream tarball: rm foo-47.11.tgz
  • add the new upstream tarball here: cp ~/tmp/foo-47.12.tgz .
  • edit the .spec file, change the Version: line to 47.12
  • remove the fix-foobar-handling.patch from the .spec file
  • check your changes: osc status; it will tell you about the modified, missing or new files; make sure there are no leftover files here like editor backup files!
  • maybe check the exact changes: osc diff
  • tell osc to add all new files and get rid of the ones that you just deleted: osc addremove or osc ar
  • check again with osc status to make sure you are not about to check in anything accidentially
  • commit your changes: osc ci

If everything works well, OBS will now build your new package with its own build workers. Open your home project in a web browser and observe the build status (building, finished / success or failed) there for all your build targets (distros and architectures).

You can then fetch the newly built binary (and also source if you wish) RPMs for the build target project and architecture that you want:

cd ~/rpm
osc getbinaries -d . home:kilroy:myproject foo Leap_16 x86_64

You can now install that RPM: sudo rpm -Uhv ./foo*.rpm

Since it’s built by OBS, it will be signed with the OBS build key. If you build locally, AFAIK (but I may be wrong) it won’t, so you have to deal with unsigned RPMs.

This is the procedure if you are the packager for somebody else’s code. If you are upstream, it works very much the same except that there are no patches, you always work in your GitHub (or whatever you use) source repo and create a fresh tarball.

See also my description of the Myrlyn OBS workflow where I am my own upstream.

HTH and I am sure I will have missed something, and there may be typos. But you get the idea.

2 Likes

Thanks for your help (and patience ;-).
With the help of " A start to end example of a simple change" in openSUSE:Build Service Tutorial - openSUSE Wiki I was able to put together the command sequence

zypper install osc
mkdir ~/obs
cd ~/obs
osc branch KDE:Qt6 qt6-base
osc co home:kls:branches:KDE:Qt6/qt6-base
cd ~/obs/home:kls:branches:KDE:Qt6/qt6-base
osc build

which apparently successfully built qt6-base.

I assume the build result is in

/var/tmp/build-root/openSUSE_Tumbleweed-x86_64/home/abuild/rpmbuild/RPMS

How can I install these locally (like in /usr/local/lib64), so that I can have programs use these instead of the ones in /usr/lib64?

The classic way is to build with a /usr/local prefix. IIRC Qt6 uses CMake, so you will need to set a CMAKE_INSTALL_PREFIX.

https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html

This will also affect the file list in the .spec file. Probably you can set some more variables to make the .spec macros aware of that, but I don’t know how.

Alternatively, you could also check out if rpm -Uhv --prefix /usr/local ... does what you want (see man rpm), but I never tried that before. It sounds promising, though.

Which will invalidate %files section (and quite possibly some code in %build / %install sections). And %files / %build / %install sections are heavily based on macros defined elsewhere, so one ends up with either rewriting half of spec hardcoding the new location or rewriting packages where these macros are defined. This is snowball.

It may be possible to redefine these macros in the project config, I am not sure. It starts with need to know which macros to redefine :slight_smile:

This only works for packages explicitly built to be relocatable. Besides, it won’t change paths embedded in the binaries or configuration files, so they end up loading their plugins from /usr/libexec, configuration from /etc and so on instead of /usr/local.

I guess it’s probably the best then to just install the resulting RPMs to their standard locations. This is a test installation, anyway.

Peeking into one of the newly built RPMs shows, e.g.

> rpm -qlp libQt6DBus6-6.10.0-0.x86_64.rpm
/usr/lib64/libQt6DBus.so.6
/usr/lib64/libQt6DBus.so.6.10.0

while in /usr/lib64 there is

> ls /usr/lib64/libQt6DBus*
/usr/lib64/libQt6DBus.so.6 -> libQt6DBus.so.6.9.1
/usr/lib64/libQt6DBus.so.6.9.1

So apparently the build resulted in a newer version of Qt6, but to have a solid starting point I would like to build the exact version that is installed in Leap 16.0 by default. Is there a way to do that?

Of course. You branched the development project which exists for the purpose of testing and providing newer versions.

pool/qt6-base - qt6-base - openSUSE Gitea
I do not have experience with osc and GIT, there are some tutorials on openSUSE wiki and there are several long discussions on the Factory mailing list.

Out of curiosity: what is the reason why you want to replace the supplied Qt6 packages by your own (with the exact same version). Is it to learn how to build packages? Or do you want a special build flag or patch? Or any other reason? Maybe we can provide you an easier solution…

openSUSE:Git Packaging Workflow - openSUSE Wiki

I want to make Qt6 read file names encoded in iso8859-15 (or any other local single byte character set) correctly, just like Qt5 did. For that I first want to establish that I am able to build the current version of Qt6 correctly, and then patch it to behave like Qt5 did in that area.

I am fully aware that “modern” systems are supposed to use “UTF-8 everywhere”, but personally I don’t like that. I’m perfectly fine with iso8859-15. Maybe I’m the only person in the world who insists in being “old fashined”, but hey, this is open source, so I can have it my way ;-).

Meanwhile I found out how to get the exact revision used in Leap 16.0:

ls /usr/lib64/libQt6Core.so.6.*
-> note the number at the end, e.g. "6.9.1"
osc co KDE:Qt6 qt6-base
cd KDE:Qt6/qt6-base
osc log | grep -i '6\.9\.1' -B2
-> find the revision number immediately before the line "Qt 6.9.1" (e.g. "r138")

cd ~/obs
rm -r KDE:Qt6
osc co KDE:Qt6 qt6-base -r 138
osc branch KDE:Qt6 qt6-base -r 138
osc co home:$USR:branches:KDE:Qt6/qt6-base

Now if I do

cd ~/obs
osc branch KDE:Qt6 qt6-base -r 138

I get
BuildService API error: failed to branch: conflict in file qt6-base.spec
However, if I do
osc branch KDE:Qt6 qt6-base
(without “-r 138”) I get

A working copy of the branched package can be checked out with:

osc co home:kls:branches:KDE:Qt6/qt6-base

Pending requests for package: KDE:Qt6/qt6-base (1)
1311343  State:review     By:dimstar_suse When:2025-10-14T11:50:19
        Created by: krop
        submit:          KDE:Qt6/qt6-base@77dcfd6b7db61a249815c7956b0a682b -> openSUSE:Factory
        Review by User       is accepted:  licensedigger(licensedigger)
        Review by User       is accepted:  factory-auto(factory-auto)
        Review by Group      is accepted:  factory-staging(dimstar_suse)
        Review by Group      is accepted:  opensuse-review-team(dimstar)
        Review by Project    is new:       openSUSE:Factory:Staging:G(dimstar_suse)
        Descr: - Install the adwaita decorationplugin when both
               libQt6WaylandClient6 and gnome-shell are present
        Comment: Being evaluated by staging project "openSUSE:Factory:Staging:G"

which appears to be right.

What causes the error message if I try to check out revision 138?

Please forgive me if these are stupid questions, but I’m a total beginner when it comes to OBS, and I’m pretty much just doing trial and error here, with some help from ChatGPT - which is also wrong most of the time…

That’s wrong. Development project and Leap may have different patches, different specs etc even if the base upstream version is the same.

Could be because the target project exists already and OBS attempts to merge it.

Anyway, the sources of Leap 16.0 packages are no more in OBS, but in GIT.

@arvidjaar I looked at your earlier link (openSUSE:Git Packaging Workflow - openSUSE Wiki), but I’m afraid I can’t figure out how to use this to check out the Qt6.9.1 package.
Trying the very first command fails already:

> git clone gitea@src.opensuse.org:xmpp/libstrophe.git
Cloning into 'libstrophe'...
The authenticity of host 'src.opensuse.org (195.135.223.224)' can't be established.
ED25519 key fingerprint is SHA256:xSb4tAF2lermLnaxLLgngbHB+wXipkpISeIi7+RQH8c.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'src.opensuse.org' (ED25519) to the list of known hosts.
gitea@src.opensuse.org: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Assuming “xmpp/libstrophe.git” is an example, but what would I have to insert here to get Qt6.9.1?
I guess this also fails because I’m not a maintainer. And I don’t want/need to be a maintainer, I just want to build the Leap 16.0 package for Qt6.9.1, so that I can make a small adjustment for my local system. I’m pretty sure this will never be accepted upstream, because it is “old fashioned”, but it would help me a lot.

Is it really “rocket science” to check out and build a Leap 16.0 package?

All the tutorials and Wikis are more confusing than helping, but I think I found a starting point now.
SLFO-pool/qt6-base - qt6-base - openSUSE Gitea contains files that have 6.9.1 in qt6-base.spec. So I downloaded that version and it looks very much like the files I previously checked out with “osc co home:$USR:branches:KDE:Qt6/qt6-base”, just now with the correct version number.

In the earlier workflow I was told to change into the qt6-base directory and do “osc build” but that doesn’t work here:

kls@localhost:/home/kls/obs/qt6-base > ls -l
total 116
-rw-r--r-- 1 kls kls  2287 Jul 18 11:41 0001-Add-clamping-to-QColorTransferGenericFunction.patch
-rw-r--r-- 1 kls kls  2450 Jul 18 11:41 0001-CMake-Install-objects-files-into-ARCHDATADIR.patch
-rw-r--r-- 1 kls kls  2486 Jul 18 11:41 0001-Change-default-settings-for-Qt-packages.patch
-rw-r--r-- 1 kls kls  1206 Jul 18 11:41 0001-Don-t-strip-binaries-when-building-with-qmake.patch
-rw-r--r-- 1 kls kls  2223 Jul 18 11:41 0001-Rename-variable-being-shadowed.patch
-rw-r--r-- 1 kls kls  1837 Jul 18 11:41 0001-Use-newer-GCC-on-Leap.patch
-rw-r--r-- 1 kls kls   750 Jul 18 11:41 _constraints
-rw-r--r-- 1 kls kls    52 Jul 18 11:41 _multibuild
-rw-r--r-- 1 kls kls   460 Jul 18 11:41 qt6-base-rpmlintrc
-rw-r--r-- 1 kls kls 28034 Jul 18 11:41 qt6-base.changes
-rw-r--r-- 1 kls kls 47066 Jul 18 11:41 qt6-base.spec
-rw-r--r-- 1 kls kls   133 Jul 18 11:41 qtbase-everywhere-src-6.9.1.tar.xz
kls@localhost:/home/kls/obs/qt6-base > osc build
Directory '/home/kls/obs/qt6-base' is not a working copy

I guess this is because now I just have the bare files, outside of any OBS structure.
Is it possible to build the Qt6 packages from this?

Yes, you need to setup public keys. It is also documented (well, mentioned) on the wiki.

git clone -b slfo-1.2 gitea@src.opensuse.org:pool/qt6-base.git

It is the basic GIT, nothing openSUSE specific. But you do need to know that Leap 16.0 sources are in the branch slfo-1.2.

Historically Open Build Service had two components - the build engine and the Source Code Management system. The package sources that build engine on the build.opensuse.org were using were kept on the build.opensuse.org and associated with the build project.

It was decided to migrate SCM to GIT. But to build using sources from GIT you still need the build project on build.opensuse.org. You can create this project manually and import sources, but then you also need to replicate project config to match Leap 16.0 manually. For this reason it is always better to fork existing project (I hope it will inherit the proper config like with osc branch).

Then why are you following the instructions for the maintainer?

### As a maintainer, you may want to work directly in your repository

And it quite clearly says later

### If you are not the maintainer, you will not have write permission later on. So you may want
### to fork instead the repository and setup a build project.

“Looked” is not enough. You need to actually read it and understand. It is not suitable for blind copy-paste.

Make a step at a time. Use the sources from the KDE:Qt6 project you already built successfully. Implement your changes there. When you succeed, you can then return to the “true” Leap sources. Maybe something will improve until then (documentation, workflows) to make it easier.

You hit it in the middle of OBS to GIT transition. There is no established workflow, there is no good documentation. The existing wiki articles assume previous experience with traditional OBS. Even seasoned packagers have problems with the current state. For this reason ignore it for the moment - focus on solving your problem with Qt and try to integrate the fix later.

And this topic really belongs to Open Build Service, not to Open Chat.