Пары для библиотек платформы Linux, вызывающие неправильное поведение приложения Qt

В настоящее время у меня возникают трудности с очень простым приложением запуска, которое предназначено для отображения веб-страницы и имеет несколько кнопок для запуска игры. Когда вы нажимаете ссылку внутри пусковой установки, она предназначена для просто запуска вашего веб-браузера по умолчанию со ссылкой, а не для приема и обработки запросов навигации.

Однако при запуске через Steam ссылки не могут открываться в новом веб-браузере. Точное поведение зависит от среды, у меня были отчеты о копиях тэгов gvfs-open и xdg-open, хотя в моей среде он просто дает указание мыши, что firefox открывается на долю секунды и ничего не делает (в том числе никаких процессов, запущенных на все в соответствии с strace, возможно, имеет какое-то отношение к системе передачи сообщений KDE, я не знаю). Довольно неприятно, есть также сообщения, что он просто отлично работает. И поэтому у меня возникла проблема, затрудняющая точный вопрос в результате.

Мне удалось сузить проблемы до Steam, изменив LD_LIBARRY_PATH исполняемого файла на использование платформ Steam Linux. Я связал все библиотеки, необходимые для запуска с помощью пусковой установки.

Вот минимальное воспроизводимое руководство:

main.cpp

#include <QApplication>
#include <QWebFrame>
#include <QDesktopServices>
#include <QNetworkRequest>
#include <QMessageBox>
#include <QWebView>

class WebPage : public QWebPage {
public:
  bool acceptNavigationRequest(QWebFrame*, const QNetworkRequest &request, NavigationType) {
    QDesktopServices::openUrl(request.url());
    return false;
  }
};

class WebView : public QWebView {
public:
  QWebView* createWindow(QWebPage::WebWindowType) {
    WebView* res = new WebView;
    WebPage* page = new WebPage;
    res->setPage(page);
    return res;
  }
};

int main(int argc, char *argv[]) {
  QApplication a(argc, argv);

  WebView v;
  v.load(QUrl("http://example.com/"));
  v.show();

  return a.exec();
}

launcher.pro

QT += core gui network webkitwidgets widgets

TARGET = launcher
TEMPLATE = app

SOURCES = main.cpp

Вам также потребуется скопировать и объединить следующие библиотеки (стандартное развертывание Qt):

libQt5Widgets.so libQt5Gui.so libQt5Core.so libQt5Network.so libQt5WebKitWidgets.so libQt5WebKit.so libQt5MultimediaWidgets.so libQt5OpenGL.so libQt5PrintSupport.so libQt5Multimedia.so libQt5Sensors.so libQt5Quick.so libQt5Qml.so libQt5Sql.so libQt5Positioning.so libQt5DBus. поэтому libicui18n.so libicuuc.so libicudata.so libssl.so libcrypto.so libstdС++. поэтому libgcc_s.so

И в подкаталоге, называемом платформами:

libqxcb.so

И наконец, script, чтобы связать его:

launch_launcher.sh

#!/bin/sh -e

cd "$(dirname "$0")"

LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./launcher

Наконец, установите пар и установите его LD_LIBRARY_PATH как свой собственный, и экспортируйте его, и запустите launch_launcher.sh(эти точные пути зависят от вашей установки пара).

По сути, если вы удаляете $LD_LIBRARY_PATH из start_launcher script, чтобы строка читала только LD_LIBRARY_PATH=. ./launcher, тогда работают ссылки. Однако с $LD_LIBRARY_PATH включенными ссылками не работает. Нам нужно $LD_LIBRARY_PATH работать, чтобы использовать библиотеки платформы Steam Linux (что заставляет игру работать.)

Какой лучший способ устранить эту проблему? Как я могу найти ответственную библиотеку и исключить ее или иным образом решить эту проблему?

Ответ 1

Итак, я обращаюсь к этой части (как объяснялось в более раннем вопросе)

Какой лучший способ устранить эту проблему? Как найти ответственную библиотеку

а не

и исключить его или иным образом решить эту проблему?

аргументация состоит в том, что если вы используете конфигурацию Linux с поддержкой Steam, LD_LIBRARY_PATH должны быть последним средством для любого приложения (особенно коммерческого). Если это противоречит другим библиотекам/приложениям, это их ошибка.

Ваш подход к изоляции воспроизведения в принципе важен именно таким образом. Логическое расширение должно (как в комментарии) продолжать:

LD_LIBRARY_PATH={myentry}:A:B:C
./launcher

вместо

LD_LIBRARY_PATH={myentry}:${LD_LIBRARY_PATH}
./launcher

это позволяет вам выбирать черт среди "A: B: C" (который является текущим LD_LIBRARY_PATH, включая записи в библиотеке Steam), и определить, какие из этих записей заставляют ваше приложение снова работать.

Что касается адресации, это зависит от нескольких переменных в вашей системе (ваш дистрибутив, другие установленные библиотеки под LD_LIBRARY_PATH, ваша версия Qt и версия KDE Qt). Вы можете попробовать:

  • googling для обходных путей - это может быть так же просто, как файл с заменой библиотеки, или патч Qt, или одна функция, которую вы вызываете из своей основной функции (аналогично ответу @fbucek).
  • logging bug-reports с Steam и Qt - поэтому это обходное решение не является специфичным для вашей системы и не будет снова повреждено при следующем обновлении Steam.

edit: вы заметили, что это влияет на QDesktopServices - скорее всего, у меня будут разные версии Qt между двумя KDE, вашими и Steam.

Ответ 2

Я думаю, что проблема сложнее. Просто подумал, что вы можете попробовать.

1) Возможно, вам не нужно использовать LD_LIBRARY_PATH

Не путайтесь с LD_LIBRARY_PATH в своем приложении, вы можете поместить путь поиска библиотеки в свою программу. (решение linux)

App structue
/app/bin
/app/lib    // where all my libraries are including Qt libraries

.pro файл

QMAKE_RPATHDIR = \$\$ORIGIN/../lib
QMAKE_LFLAGS_RELEASE += \'-Wl,-rpath,$${QMAKE_RPATHDIR}\'
QMAKE_RPATHDIR =

(не помню, почему он выглядит глупым в моем старом приложении, но он работает, и в данный момент я не на Linux, чтобы упростить его)

2) Установите LD_LIBRARY_PATH только для процессов в вашем приложении (чтобы не сделать LD_LIBARY_PATH слишком сложным. путь к вашему приложению, пар и т.д.)

Я не знаю, в каком контексте выполняется новый браузер, но если это ваше приложение, вы можете использовать этот aproach. Это гарантирует, что только процессы в вашем приложении будут иметь этот LD_LIBRARY_PATH

Вы можете установить LD_LIBRARY_PATH в своем приложении, используя

setenv("LD_LIBRARY_PATH", yourPath.toLatin1().data(), 1)
// You can test it using
QProcessEnvironment::systemEnvironment().value("LD_LIBRARY_PATH");

Я предполагаю, что вы не используете QProcess, поэтому установка среды для самого процесса не может быть и речи.