Пары для библиотек платформы 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, поэтому установка среды для самого процесса не может быть и речи.