OpenGL error when trying to use QT_QPA_PLATFORM=offscreen
-
wrote on 17 Oct 2024, 11:38 last edited by
I have a QML application but I am not sure whether this is specific to QML so I am putting it in the general area.
I have some tests that involve running the GUI but replacing what would normally be input events from the presentation layer with scripted commands. This works fine on a local machine but fails when tests are run on CI machines as they generally do not have graphics capabilities.
The tests don't look at the presentation layer and no input is expected from the presentation layer, but the GUI needs to be there to exercise the workflow. I came across the "offscreen" plugin and thought it looked like it might address my use case. I set
QT_QPA_PLATFORM=offscreen
and it almost works:- I can run the same tests locally on Windows with the offscreen plugin. They run fine, I don't see a window.
- I can run the tests on Windows CI pipelines (this is on Azure DevOps).
- I can run the tests on a local Linux machine.
- I can log into the Linux build VM used in Linux pipelines and run the tests there.
However, if I run a Linux CI pipeline on ADO the tests fail with this error:
Fatal: Failed to create OpenGL context for format QSurfaceFormat(version 2.0, options QFlags<QSurfaceFormat::FormatOption>() ...
From what I have been able to understand, this error is seen when trying to run on machines with inadequate graphics capabilities. However, this is exactly why I am using
"offscreen"
- it shouldn't need any graphics capabilities.Something different is clearly happening between running as a user logged into the Linux build machine and a CI pipeline run, but I have no idea what.
Does anyone know why this OpenGL check might fail when running in this offscreen mode? I'm hoping to get some clue about where to look.
-
wrote on 30 Oct 2024, 12:35 last edited by
One final update on this as I have since realised that
QT_QUICK_BACKEND=software
alone was not sufficient on Linux. I had to set both that and the offscreen plugin to get it working. -
wrote on 17 Oct 2024, 18:47 last edited by
I suppose something that we (in software) learn to hope for is that "oops I just made a silly mistake."
In that spirit, it certainly seems like one explanation is simply that the
QT_QPA_PLATFORM
variable is simply not actually set as you intended.There could be a typo in a CI script or CI config file.
Or, perhaps more likely, there is some kind of character-escaping or string-quoting that isn't going according to plan, and so when the CI job runs it garbles either the name of your variable or its value, or both. There are many reasons this could happen. One example would be that when you log in on the VM, your
$SHELL
is/bin/bash
, but when the CI job runs, the shell issh
or any of various other shells, that might behave a bit differently.Maybe try making a more minimal CI task that simply exports that variable and then uses some dummy app (such as a single-file python script) to just demonstrate the launch of the dummy app and print that variable from the app, to prove that your method of variable export is propagating all the way through.
You might also try other QT env vars, (but its hard to think of one that might cause any visible difference in output before the app crashes). Maybe this:
export QT_DEBUG_PLUGINS=1
If you are able to see (that in the CI task), the setting of QT_DEBUG_PLUGINS is indeed causing some observable change in output, then you have more reason to suspect some issue that is somehow specifically related to QT_QPA_PLATFORM=offscreen.
If you are still stumped, perhaps share some snippets here that show how do you launch the task when you manually log into the Linux build VM used in Linux pipelines? How do you configure or script the CI task?
Lastly, if you exhaust all options in this regard and just need to change tactics entirely, I have had success launching Qt GUI apps in Linux CI using
Xvfb
, like so: https://github.com/219-design/qt-qml-project-template-with-ci/blob/a85e7f49a127ea/run_all_tests.sh#L77Xvfb
provides a "fake" display so that the app runs happily. -
wrote on 17 Oct 2024, 18:49 last edited by
Another thought:
Print out your environment (
set
andenv
) when you manually log into the Linux build VM used in Linux pipelines.Then print out the environment from a CI script on that VM.
Look for differences there. Maybe for some reason there is an unexpected extra variable getting set in CI that somehow contradicts or overrides the QT_QPA_PLATFORM=offscreen
-
Hi,
Beside the good hints already written, which CI system are you using ?
-
wrote on 18 Oct 2024, 09:16 last edited by Bob64
Thanks for the replies and the good suggestions.
@SGaist
The CI system is ADO - Azure DevOps. The Linux build machines are VMs running Rocky Linux.@KH-219Design
I should have said but I had already checked the "obvious" stuff like the environment variable not being passed through properly. I was pretty sure that this wasn't the issue anyway as (a) the majority of this is cross-platform and it is working fine on Windows and (b) the environment variable setting (in a Python driver script) is just one more variable added to a group of variables that were already being set, so I was confident that there were no general issues with propagation of environment variables. That being said, I had done my due diligence and confirmed it by adding logging to my Qt application to confirm the value ofQT_QPA_PLATFORM
. I can see this in the logs from the test run in the pipeline.Regarding your suggestion:
export QT_DEBUG_PLUGINS=1
Thanks! This is useful information - I will try this.
Also your suggestion for looking for differences in environment: I will try that - we already print out the full environment in our pipelines - but am not optimistic as we are generally pretty good about encapsulating environment in our scripts and so on and rely very little on the environment set on the machines themselves.
Thanks also for the
xvfb
suggestion. I knew of this as I had encountered it in a different context recently but hadn't thought of its applicability here. It's something to bear in mind but in the meantime I have found another workaround which is simply to start the application with software rendering enabled. In my case, at it is a QML app, I can do this usingQT_QUICK_BACKEND=software
. Maybe I could try this on Windows too to avoid the small niggle of a platform dependency, though the "offscreen" approach - if it works - feels like it is a better fit to my use case. But perhaps that is being a bit too academic about it. -
wrote on 30 Oct 2024, 12:35 last edited by
One final update on this as I have since realised that
QT_QUICK_BACKEND=software
alone was not sufficient on Linux. I had to set both that and the offscreen plugin to get it working. -