Merge branch 'master' into find_qmake_in_exepath
This commit is contained in:
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# download excludelist
|
||||
blacklisted=($(wget --quiet https://raw.githubusercontent.com/probonopd/AppImages/master/excludelist -O - | sort | uniq | grep -v "^#.*" | grep "[^-\s]"))
|
||||
|
||||
# sanity check
|
||||
if [ "$blacklisted" == "" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
filename=$(readlink -f $(dirname "$0"))/linuxdeployqt/excludelist.h
|
||||
|
||||
# overwrite existing source file
|
||||
cat > "$filename" <<EOF
|
||||
/*
|
||||
* List of libraries to exclude for different reasons.
|
||||
*
|
||||
* Automatically generated from
|
||||
* https://raw.githubusercontent.com/probonopd/AppImages/master/excludelist
|
||||
*
|
||||
* This file shall be committed by the developers occassionally,
|
||||
* otherwise systems without access to the internet won't be able to build
|
||||
* fully working versions of linuxdeployqt.
|
||||
*
|
||||
* See https://github.com/probonopd/linuxdeployqt/issues/274 for more
|
||||
* information.
|
||||
*/
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
static const QStringList generatedExcludelist = {
|
||||
EOF
|
||||
|
||||
# Create array
|
||||
for item in ${blacklisted[@]:0:${#blacklisted[@]}-1}; do
|
||||
echo -e ' "'"$item"'",' >> "$filename"
|
||||
done
|
||||
echo -e ' "'"${blacklisted[$((${#blacklisted[@]}-1))]}"'"' >> "$filename"
|
||||
|
||||
echo "};" >> "$filename"
|
||||
@@ -0,0 +1,30 @@
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# expose version data as compiler definition
|
||||
add_definitions("-DLINUXDEPLOYQT_VERSION=\"${GIT_TAG_NAME}\"")
|
||||
add_definitions("-DLINUXDEPLOYQT_GIT_COMMIT=\"${GIT_COMMIT}\"")
|
||||
add_definitions("-DBUILD_DATE=\"${DATE}\"")
|
||||
add_definitions("-DBUILD_NUMBER=\"${BUILD_NUMBER}\"")
|
||||
|
||||
find_package(Qt5 REQUIRED COMPONENTS Core)
|
||||
|
||||
# update excludelist
|
||||
message(STATUS "Updating excludelist...")
|
||||
execute_process(
|
||||
COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/../generate-excludelist.sh
|
||||
OUTPUT_VARIABLE EXCLUDELIST
|
||||
TIMEOUT 10
|
||||
RESULT_VARIABLE EXCLUDELIST_RESULT
|
||||
)
|
||||
if(NOT EXCLUDELIST_RESULT EQUAL 0)
|
||||
message(WARNING "Updating excludelist failed, using outdated copy")
|
||||
endif()
|
||||
mark_as_advanced(EXCLUDELIST EXCLUDELIST_RESULT)
|
||||
|
||||
add_executable(linuxdeployqt main.cpp shared.cpp)
|
||||
target_include_directories(linuxdeployqt PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(linuxdeployqt Qt5::Core)
|
||||
target_compile_definitions(linuxdeployqt PRIVATE -DEXCLUDELIST="${EXCLUDELIST}")
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* List of libraries to exclude for different reasons.
|
||||
*
|
||||
* Automatically generated from
|
||||
* https://raw.githubusercontent.com/probonopd/AppImages/master/excludelist
|
||||
*
|
||||
* This file shall be committed by the developers occassionally,
|
||||
* otherwise systems without access to the internet won't be able to build
|
||||
* fully working versions of linuxdeployqt.
|
||||
*
|
||||
* See https://github.com/probonopd/linuxdeployqt/issues/274 for more
|
||||
* information.
|
||||
*/
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
static const QStringList generatedExcludelist = {
|
||||
"ld-linux.so.2",
|
||||
"ld-linux-x86-64.so.2",
|
||||
"libanl.so.1",
|
||||
"libasound.so.2",
|
||||
"libBrokenLocale.so.1",
|
||||
"libcidn.so.1",
|
||||
"libcom_err.so.2",
|
||||
"libcrypt.so.1",
|
||||
"libc.so.6",
|
||||
"libdl.so.2",
|
||||
"libdrm.so.2",
|
||||
"libexpat.so.1",
|
||||
"libfontconfig.so.1",
|
||||
"libfreetype.so.6",
|
||||
"libgcc_s.so.1",
|
||||
"libgdk_pixbuf-2.0.so.0",
|
||||
"libgio-2.0.so.0",
|
||||
"libglib-2.0.so.0",
|
||||
"libGL.so.1",
|
||||
"libgobject-2.0.so.0",
|
||||
"libgpg-error.so.0",
|
||||
"libharfbuzz.so.0",
|
||||
"libICE.so.6",
|
||||
"libjack.so.0",
|
||||
"libkeyutils.so.1",
|
||||
"libm.so.6",
|
||||
"libmvec.so.1",
|
||||
"libnsl.so.1",
|
||||
"libnss_compat.so.2",
|
||||
"libnss_db.so.2",
|
||||
"libnss_dns.so.2",
|
||||
"libnss_files.so.2",
|
||||
"libnss_hesiod.so.2",
|
||||
"libnss_nisplus.so.2",
|
||||
"libnss_nis.so.2",
|
||||
"libp11-kit.so.0",
|
||||
"libpango-1.0.so.0",
|
||||
"libpangocairo-1.0.so.0",
|
||||
"libpangoft2-1.0.so.0",
|
||||
"libpthread.so.0",
|
||||
"libresolv.so.2",
|
||||
"librt.so.1",
|
||||
"libSM.so.6",
|
||||
"libstdc++.so.6",
|
||||
"libthread_db.so.1",
|
||||
"libusb-1.0.so.0",
|
||||
"libutil.so.1",
|
||||
"libuuid.so.1",
|
||||
"libX11.so.6",
|
||||
"libxcb.so.1",
|
||||
"libz.so.1"
|
||||
};
|
||||
@@ -12,6 +12,38 @@ load(qt_tool)
|
||||
|
||||
HEADERS += shared.h
|
||||
SOURCES += main.cpp \
|
||||
shared.cpp
|
||||
shared.cpp
|
||||
|
||||
DEFINES -= QT_USE_QSTRINGBUILDER #leads to compile errors if not disabled
|
||||
|
||||
# versioning
|
||||
# don't break the quotes -- at the moment, the shell commands are injected into the Makefile to have them run on every
|
||||
# build and not during configure time
|
||||
|
||||
DEFINES += LINUXDEPLOYQT_GIT_COMMIT="'\"$(shell cd $$PWD && git rev-parse --short HEAD)\"'"
|
||||
|
||||
DEFINES += BUILD_DATE="'\"$(shell env LC_ALL=C date -u '+%Y-%m-%d %H:%M:%S %Z')\"'"
|
||||
|
||||
_BUILD_NUMBER = $$(TRAVIS_BUILD_NUMBER)
|
||||
|
||||
isEmpty(_BUILD_NUMBER) {
|
||||
message("Not building on Travis CI, tagging build as local dev build")
|
||||
DEFINES += BUILD_NUMBER="'\"<local dev build>\"'"
|
||||
} else {
|
||||
message("Building on Travis CI build, build number $$_BUILD_NUMBER")
|
||||
DEFINES += BUILD_NUMBER="'\"$$_BUILD_NUMBER\"'"
|
||||
}
|
||||
|
||||
DEFINES += LINUXDEPLOYQT_VERSION="'\"$(shell cd $$PWD && git describe --tags $(shell cd $$PWD && git rev-list --tags --skip=1 --max-count=1) --abbrev=0)\"'"
|
||||
contains(DEFINES, EXCLUDELIST.*) {
|
||||
message("EXCLUDELIST specified, to use the most recent exclude list, please run qmake without EXCLUDELIST definition and with internet.")
|
||||
} else {
|
||||
message("Updating exclude list...")
|
||||
|
||||
# check whether command _would_ run successfully
|
||||
EXCLUDELIST_GENERATION_WORKS = FALSE
|
||||
system($$_PRO_FILE_PWD_/../generate-excludelist.sh): EXCLUDELIST_GENERATION_WORKS = TRUE
|
||||
isEqual(EXCLUDELIST_GENERATION_WORKS, FALSE) {
|
||||
warning("Updating excludelist failed, using outdated copy")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd. and Simon Peter
|
||||
** Copyright (C) 2016-18 The Qt Company Ltd. and Simon Peter
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the tools applications of the Qt Toolkit.
|
||||
@@ -33,6 +33,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <QSettings>
|
||||
#include <QDirIterator>
|
||||
#include <sstream>
|
||||
#include "excludelist.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@@ -43,37 +45,69 @@ int main(int argc, char **argv)
|
||||
|
||||
QString firstArgument = QString::fromLocal8Bit(argv[1]);
|
||||
|
||||
if (argc < 2 || firstArgument.startsWith("-")) {
|
||||
qDebug() << "Usage: linuxdeployqt <app-binary|desktop file> [options]";
|
||||
qDebug() << "";
|
||||
qDebug() << "Options:";
|
||||
qDebug() << " -verbose=<0-3> : 0 = no output, 1 = error/warning (default), 2 = normal, 3 = debug";
|
||||
qDebug() << " -no-plugins : Skip plugin deployment";
|
||||
qDebug() << " -appimage : Create an AppImage (implies -bundle-non-qt-libs)";
|
||||
qDebug() << " -no-strip : Don't run 'strip' on the binaries";
|
||||
qDebug() << " -bundle-non-qt-libs : Also bundle non-core, non-Qt libraries";
|
||||
qDebug() << " -executable=<path> : Let the given executable use the deployed libraries too";
|
||||
qDebug() << " -qmldir=<path> : Scan for QML imports in the given path";
|
||||
qDebug() << " -always-overwrite : Copy files even if the target file exists";
|
||||
qDebug() << " -qmake=<path> : The qmake executable to use";
|
||||
qDebug() << " -no-translations : Skip deployment of translations.";
|
||||
qDebug() << "";
|
||||
qDebug() << "linuxdeployqt takes an application as input and makes it";
|
||||
qDebug() << "self-contained by copying in the Qt libraries and plugins that";
|
||||
qDebug() << "the application uses.";
|
||||
qDebug() << "";
|
||||
qDebug() << "By default it deploys the Qt instance that qmake on the $PATH points to.";
|
||||
qDebug() << "The '-qmake' option can be used to point to the qmake executable";
|
||||
qDebug() << "to be used instead.";
|
||||
qDebug() << "";
|
||||
qDebug() << "Plugins related to a Qt library are copied in with the library.";
|
||||
// print version statement
|
||||
std::stringstream version;
|
||||
version << "linuxdeployqt " << LINUXDEPLOYQT_VERSION
|
||||
<< " (commit " << LINUXDEPLOYQT_GIT_COMMIT << "), "
|
||||
<< "build " << BUILD_NUMBER << " built on " << BUILD_DATE;
|
||||
qInfo().noquote() << QString::fromStdString(version.str());
|
||||
|
||||
// due to the structure of the argument parser, we have to check all arguments at first to check whether the user
|
||||
// wants to get the version only
|
||||
// TODO: replace argument parser with position independent, less error prone version
|
||||
for (int i = 0; i < argc; i++ ) {
|
||||
QString argument = argv[i];
|
||||
if (argument == "-version" || argument == "-V" || argument == "--version") {
|
||||
// can just exit normally, version has been printed above
|
||||
return 0;
|
||||
}
|
||||
if (argument == QByteArray("-show-exclude-libs")) {
|
||||
qInfo() << generatedExcludelist;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc < 2 || (firstArgument.startsWith("-"))) {
|
||||
qInfo() << "";
|
||||
qInfo() << "Usage: linuxdeployqt <app-binary|desktop file> [options]";
|
||||
qInfo() << "";
|
||||
qInfo() << "Options:";
|
||||
qInfo() << " -always-overwrite : Copy files even if the target file exists.";
|
||||
qInfo() << " -appimage : Create an AppImage (implies -bundle-non-qt-libs).";
|
||||
qInfo() << " -bundle-non-qt-libs : Also bundle non-core, non-Qt libraries.";
|
||||
qInfo() << " -exclude-libs=<list> : List of libraries which should be excluded,";
|
||||
qInfo() << " separated by comma.";
|
||||
qInfo() << " -executable=<path> : Let the given executable use the deployed libraries";
|
||||
qInfo() << " too";
|
||||
qInfo() << " -extra-plugins=<list> : List of extra plugins which should be deployed,";
|
||||
qInfo() << " separated by comma.";
|
||||
qInfo() << " -no-copy-copyright-files : Skip deployment of copyright files.";
|
||||
qInfo() << " -no-plugins : Skip plugin deployment.";
|
||||
qInfo() << " -no-strip : Don't run 'strip' on the binaries.";
|
||||
qInfo() << " -no-translations : Skip deployment of translations.";
|
||||
qInfo() << " -qmake=<path> : The qmake executable to use.";
|
||||
qInfo() << " -qmldir=<path> : Scan for QML imports in the given path.";
|
||||
qInfo() << " -show-exclude-libs : Print exclude libraries list.";
|
||||
qInfo() << " -verbose=<0-3> : 0 = no output, 1 = error/warning (default),";
|
||||
qInfo() << " 2 = normal, 3 = debug.";
|
||||
qInfo() << " -version : Print version statement and exit.";
|
||||
qInfo() << "";
|
||||
qInfo() << "linuxdeployqt takes an application as input and makes it";
|
||||
qInfo() << "self-contained by copying in the Qt libraries and plugins that";
|
||||
qInfo() << "the application uses.";
|
||||
qInfo() << "";
|
||||
qInfo() << "By default it deploys the Qt instance that qmake on the $PATH points to.";
|
||||
qInfo() << "The '-qmake' option can be used to point to the qmake executable";
|
||||
qInfo() << "to be used instead.";
|
||||
qInfo() << "";
|
||||
qInfo() << "Plugins related to a Qt library are copied in with the library.";
|
||||
/* TODO: To be implemented
|
||||
qDebug() << "The accessibility, image formats, and text codec";
|
||||
qDebug() << "plugins are always copied, unless \"-no-plugins\" is specified.";
|
||||
*/
|
||||
qDebug() << "";
|
||||
qDebug() << "See the \"Deploying Applications on Linux\" topic in the";
|
||||
qDebug() << "documentation for more information about deployment on Linux.";
|
||||
qInfo() << "";
|
||||
qInfo() << "See the \"Deploying Applications on Linux\" topic in the";
|
||||
qInfo() << "documentation for more information about deployment on Linux.";
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -88,6 +122,12 @@ int main(int argc, char **argv)
|
||||
* to do when using linuxdeployqt. */
|
||||
if (firstArgument.endsWith(".desktop")){
|
||||
qDebug() << "Desktop file as first argument:" << firstArgument;
|
||||
|
||||
/* Check if the desktop file really exists */
|
||||
if (! QFile::exists(firstArgument)) {
|
||||
LogError() << "Desktop file in first argument does not exist!";
|
||||
return 1;
|
||||
}
|
||||
QSettings * settings = 0;
|
||||
settings = new QSettings(firstArgument, QSettings::IniFormat);
|
||||
desktopExecEntry = settings->value("Desktop Entry/Exec", "r").toString().split(' ').first().split('/').last().trimmed();
|
||||
@@ -167,13 +207,16 @@ int main(int argc, char **argv)
|
||||
extern bool bundleAllButCoreLibs;
|
||||
extern bool fhsLikeMode;
|
||||
extern QString fhsPrefix;
|
||||
extern bool alwaysOwerwriteEnabled;
|
||||
extern QStringList librarySearchPath;
|
||||
extern bool alwaysOwerwriteEnabled;
|
||||
QStringList additionalExecutables;
|
||||
bool qmldirArgumentUsed = false;
|
||||
bool skipTranslations = false;
|
||||
QStringList qmlDirs;
|
||||
QString qmakeExecutable;
|
||||
extern QStringList extraQtPlugins;
|
||||
extern QStringList excludeLibs;
|
||||
extern bool copyCopyrightFiles;
|
||||
|
||||
/* FHS-like mode is for an application that has been installed to a $PREFIX which is otherwise empty, e.g., /path/to/usr.
|
||||
* In this case, we want to construct an AppDir in /path/to. */
|
||||
@@ -299,7 +342,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
if(QFileInfo(appDirPath + "/" + desktopIconEntry + ".svgz").exists() == true){
|
||||
preExistingToplevelIcon = appDirPath + "/" + desktopIconEntry + ".svgz";
|
||||
if(QFileInfo(appDirPath + "/.DirIcon").exists() == false) if(QFileInfo(appDirPath + "/.DirIcon").exists() == false) QFile::copy(preExistingToplevelIcon, appDirPath + "/.DirIcon");
|
||||
if(QFileInfo(appDirPath + "/.DirIcon").exists() == false) QFile::copy(preExistingToplevelIcon, appDirPath + "/.DirIcon");
|
||||
}
|
||||
if(QFileInfo(appDirPath + "/" + desktopIconEntry + ".svg").exists() == true){
|
||||
preExistingToplevelIcon = appDirPath + "/" + desktopIconEntry + ".svg";
|
||||
@@ -326,8 +369,10 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
// Check arguments
|
||||
for (int i = 2; i < argc; ++i) {
|
||||
QByteArray argument = QByteArray(argv[i]);
|
||||
|
||||
if (argument == QByteArray("-no-plugins")) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
plugins = false;
|
||||
@@ -365,6 +410,9 @@ int main(int argc, char **argv)
|
||||
LogError() << "Missing qml directory path";
|
||||
else
|
||||
qmlDirs << argument.mid(index+1);
|
||||
} else if (argument.startsWith("-no-copy-copyright-files")) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
copyCopyrightFiles = false;
|
||||
} else if (argument == QByteArray("-always-overwrite")) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
alwaysOwerwriteEnabled = true;
|
||||
@@ -375,11 +423,22 @@ int main(int argc, char **argv)
|
||||
} else if (argument == QByteArray("-no-translations")) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
skipTranslations = true;
|
||||
} else if (argument.startsWith("-")) {
|
||||
LogError() << "Unknown argument" << argument << "\n";
|
||||
} else if (argument.startsWith("-extra-plugins=")) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
int index = argument.indexOf("=");
|
||||
extraQtPlugins = QString(argument.mid(index + 1)).split(",");
|
||||
} else if (argument.startsWith("-exclude-libs=")) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
int index = argument.indexOf("=");
|
||||
excludeLibs = QString(argument.mid(index + 1)).split(",");
|
||||
} else if (argument.startsWith("--")) {
|
||||
LogError() << "Error: arguments must not start with --, only -:" << argument << "\n";
|
||||
return 1;
|
||||
} else {
|
||||
LogError() << "Unknown argument:" << argument << "\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (appimage) {
|
||||
if(checkAppImagePrerequisites(appDirPath) == false){
|
||||
@@ -388,6 +447,11 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (!excludeLibs.isEmpty())
|
||||
{
|
||||
qWarning() << "WARNING: Excluding the following libraries might break the AppImage. Please double-check the list:" << excludeLibs;
|
||||
}
|
||||
|
||||
DeploymentInfo deploymentInfo = deployQtLibraries(appDirPath, additionalExecutables,
|
||||
qmakeExecutable);
|
||||
|
||||
|
||||
+227
-76
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd. and Simon Peter
|
||||
** Copyright (C) 2016-18 The Qt Company Ltd. and Simon Peter
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the tools applications of the Qt Toolkit.
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <QRegularExpression>
|
||||
#include <QStandardPaths>
|
||||
#include "shared.h"
|
||||
#include "excludelist.h"
|
||||
|
||||
QString appBinaryPath;
|
||||
bool runStripEnabled = true;
|
||||
@@ -57,6 +58,9 @@ int logLevel = 1;
|
||||
int qtDetected = 0;
|
||||
bool qtDetectionComplete = 0; // As long as Qt is not detected yet, ldd may encounter "not found" messages, continue anyway
|
||||
bool deployLibrary = false;
|
||||
QStringList extraQtPlugins;
|
||||
QStringList excludeLibs;
|
||||
bool copyCopyrightFiles = true;
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
@@ -212,38 +216,22 @@ inline QDebug operator<<(QDebug debug, const AppDirInfo &info)
|
||||
return debug;
|
||||
}
|
||||
|
||||
// Determine whether the given 'ldd' output contains a Linux VDSO
|
||||
// shared object. The name of the VDSO object differs depending
|
||||
// on architecture. See "vDSO names" in the notes section of vdso(7)
|
||||
// for more information.
|
||||
static bool lddOutputContainsLinuxVDSO(const QString &lddOutput) {
|
||||
// aarch64, arm, mips, x86_64, x86/x32
|
||||
if (lddOutput.contains(QStringLiteral("linux-vdso.so.1"))) {
|
||||
return true;
|
||||
// ppc32, s390
|
||||
} else if (lddOutput.contains(QStringLiteral("linux-vdso32.so.1"))) {
|
||||
return true;
|
||||
// ppc64, s390x
|
||||
} else if (lddOutput.contains(QStringLiteral("linux-vdso64.so.1"))) {
|
||||
return true;
|
||||
// ia64, sh, i386
|
||||
} else if (lddOutput.contains(QStringLiteral("linux-gate.so.1"))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool copyFilePrintStatus(const QString &from, const QString &to)
|
||||
{
|
||||
if (QFile(to).exists()) {
|
||||
if (alwaysOwerwriteEnabled) {
|
||||
QFile(to).remove();
|
||||
} else {
|
||||
LogDebug() << QFileInfo(to).fileName() << "already deployed, skipping.";
|
||||
return false;
|
||||
LogDebug() << QFileInfo(to).fileName() << "already exists at target location";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
QDir dir(QDir::cleanPath(to + "/../"));
|
||||
if (!dir.exists()) {
|
||||
dir.mkpath(".");
|
||||
}
|
||||
|
||||
if (QFile::copy(from, to)) {
|
||||
QFile dest(to);
|
||||
dest.setPermissions(dest.permissions() | QFile::WriteOwner | QFile::WriteUser);
|
||||
@@ -270,6 +258,81 @@ bool copyFilePrintStatus(const QString &from, const QString &to)
|
||||
}
|
||||
}
|
||||
|
||||
bool copyCopyrightFile(QString libPath){
|
||||
|
||||
/* When deploying files (e.g., libraries) from the
|
||||
* system, then try to also deploy their copyright file.
|
||||
* This is currently only implemented for dpkg-based,
|
||||
* Debian-like systems. Pull requests welcome for other
|
||||
* systems. */
|
||||
|
||||
if (!copyCopyrightFiles) {
|
||||
LogNormal() << "Skipping copyright files deployment as requested by the user";
|
||||
return false;
|
||||
}
|
||||
|
||||
QString dpkgPath;
|
||||
dpkgPath = QStandardPaths::findExecutable("dpkg");
|
||||
if(dpkgPath == ""){
|
||||
LogNormal() << "dpkg not found, hence not deploying copyright files";
|
||||
return false;
|
||||
}
|
||||
|
||||
QString dpkgQueryPath;
|
||||
dpkgQueryPath = QStandardPaths::findExecutable("dpkg-query");
|
||||
if(dpkgQueryPath == ""){
|
||||
LogNormal() << "dpkg-query not found, hence not deploying copyright files";
|
||||
return false;
|
||||
}
|
||||
|
||||
QString copyrightFilePath;
|
||||
|
||||
/* Find out which package the file being deployed belongs to */
|
||||
|
||||
QStringList arguments;
|
||||
arguments << "-S" << libPath;
|
||||
QProcess *myProcess = new QProcess();
|
||||
myProcess->start(dpkgPath, arguments);
|
||||
myProcess->waitForFinished();
|
||||
QString strOut = myProcess->readAllStandardOutput().split(':')[0];
|
||||
if(strOut == "") return false;
|
||||
|
||||
/* Find out the copyright file in that package */
|
||||
arguments << "-L" << strOut;
|
||||
myProcess->start(dpkgQueryPath, arguments);
|
||||
myProcess->waitForFinished();
|
||||
strOut = myProcess->readAllStandardOutput();
|
||||
|
||||
QStringList outputLines = strOut.split("\n", QString::SkipEmptyParts);
|
||||
|
||||
foreach (QString outputLine, outputLines) {
|
||||
if((outputLine.contains("usr/share/doc")) && (outputLine.contains("/copyright")) && (outputLine.contains(" "))){
|
||||
// copyrightFilePath = outputLine.split(' ')[1]; // This is not working on multiarch systems; see https://github.com/probonopd/linuxdeployqt/issues/184#issuecomment-345293540
|
||||
QStringList parts = outputLine.split(' ');
|
||||
copyrightFilePath = parts[parts.size() - 1]; // Grab last element
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(copyrightFilePath == "") return false;
|
||||
|
||||
LogDebug() << "copyrightFilePath:" << copyrightFilePath;
|
||||
|
||||
/* Where should we copy this file to? We are assuming the Debian-like path contains
|
||||
* the name of the package like so: copyrightFilePath: "/usr/share/doc/libpcre3/copyright"
|
||||
* this assumption is most likely only true for Debian-like systems */
|
||||
QString packageName = copyrightFilePath.split("/")[copyrightFilePath.split("/").length()-2];
|
||||
QString copyrightFileTargetPath;
|
||||
if(fhsLikeMode){
|
||||
copyrightFileTargetPath = QDir::cleanPath(appBinaryPath + "/../../share/doc/" + packageName + "/copyright");
|
||||
} else {
|
||||
copyrightFileTargetPath = QDir::cleanPath(appBinaryPath + "/../doc/" + packageName + "/copyright");
|
||||
}
|
||||
|
||||
/* Do the actual copying */
|
||||
return(copyFilePrintStatus(copyrightFilePath, copyrightFileTargetPath));
|
||||
}
|
||||
|
||||
LddInfo findDependencyInfo(const QString &binaryPath)
|
||||
{
|
||||
LddInfo info;
|
||||
@@ -309,20 +372,19 @@ LddInfo findDependencyInfo(const QString &binaryPath)
|
||||
// LogDebug() << "ldd outputLine:" << outputLine;
|
||||
if ((outputLine.contains("not found")) && (qtDetectionComplete == 1)){
|
||||
LogError() << "ldd outputLine:" << outputLine.replace("\t", "");
|
||||
LogError() << "for binary:" << binaryPath;
|
||||
LogError() << "Please ensure that all libraries can be found by ldd. Aborting.";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if ((binaryPath.contains(".so.") || binaryPath.endsWith(".so")) && (!lddOutputContainsLinuxVDSO(output))) {
|
||||
const QRegularExpressionMatch match = regexp.match(outputLines.first());
|
||||
if (match.hasMatch()) {
|
||||
info.installName = match.captured(1);
|
||||
} else {
|
||||
LogError() << "Could not parse ldd output line:" << outputLines.first();
|
||||
}
|
||||
outputLines.removeFirst();
|
||||
/*
|
||||
FIXME: For unknown reasons, this segfaults; see https://travis-ci.org/probonopd/Labrador/builds/339803886#L1320
|
||||
if (binaryPath.contains("platformthemes")) {
|
||||
LogDebug() << "Not adding dependencies of" << binaryPath << "because we do not bundle dependencies of platformthemes";
|
||||
return info;
|
||||
}
|
||||
*/
|
||||
|
||||
foreach (const QString &outputLine, outputLines) {
|
||||
const QRegularExpressionMatch match = regexp.match(outputLine);
|
||||
@@ -373,16 +435,15 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath,
|
||||
This is more suitable for bundling in a way that is portable between different distributions and target systems.
|
||||
Along the way, this also takes care of non-Qt libraries.
|
||||
|
||||
The excludelist can be updated by running
|
||||
#/bin/bash
|
||||
blacklisted=$(wget https://raw.githubusercontent.com/probonopd/AppImages/master/excludelist -O - | sort | uniq | grep -v "^#.*" | grep "[^-\s]")
|
||||
for item in $blacklisted; do
|
||||
echo -ne '"'$item'" << '
|
||||
done
|
||||
The excludelist can be updated by running the bundled script generate-excludelist.sh
|
||||
*/
|
||||
|
||||
QStringList excludelist;
|
||||
excludelist << "libasound.so.2" << "libcom_err.so.2" << "libcrypt.so.1" << "libc.so.6" << "libdl.so.2" << "libdrm.so.2" << "libexpat.so.1" << "libfontconfig.so.1" << "libgcc_s.so.1" << "libgdk_pixbuf-2.0.so.0" << "libgdk-x11-2.0.so.0" << "libgio-2.0.so.0" << "libglib-2.0.so.0" << "libGL.so.1" << "libgobject-2.0.so.0" << "libgpg-error.so.0" << "libgssapi_krb5.so.2" << "libgtk-x11-2.0.so.0" << "libICE.so.6" << "libidn.so.11" << "libk5crypto.so.3" << "libkeyutils.so.1" << "libm.so.6" << "libnss3.so" << "libnssutil3.so" << "libp11-kit.so.0" << "libpangoft2-1.0.so.0" << "libpangocairo-1.0.so.0" << "libpango-1.0.so.0" << "libpthread.so.0" << "libresolv.so.2" << "librt.so.1" << "libSM.so.6" << "libstdc++.so.6" << "libusb-1.0.so.0" << "libuuid.so.1" << "libX11.so.6" << "libxcb.so.1" << "libz.so.1";
|
||||
// copy generated excludelist
|
||||
QStringList excludelist = generatedExcludelist;
|
||||
|
||||
// append exclude libs
|
||||
excludelist += excludeLibs;
|
||||
|
||||
LogDebug() << "excludelist:" << excludelist;
|
||||
if (! trimmed.contains("libicu")) {
|
||||
if (containsHowOften(excludelist, QFileInfo(trimmed).completeBaseName())) {
|
||||
@@ -575,10 +636,13 @@ QList<LibraryInfo> getQtLibrariesForPaths(const QStringList &paths, const QStrin
|
||||
QSet<QString> existing;
|
||||
|
||||
foreach (const QString &path, paths) {
|
||||
foreach (const LibraryInfo &info, getQtLibraries(path, appDirPath, rpaths)) {
|
||||
if (!existing.contains(info.libraryPath)) { // avoid duplicates
|
||||
existing.insert(info.libraryPath);
|
||||
result << info;
|
||||
if (!excludeLibs.contains(QFileInfo(path).baseName()))
|
||||
{
|
||||
foreach (const LibraryInfo &info, getQtLibraries(path, appDirPath, rpaths)) {
|
||||
if (!existing.contains(info.libraryPath)) { // avoid duplicates
|
||||
existing.insert(info.libraryPath);
|
||||
result << info;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -599,6 +663,8 @@ bool recursiveCopy(const QString &sourcePath, const QString &destinationPath)
|
||||
const QString fileSourcePath = sourcePath + "/" + file;
|
||||
const QString fileDestinationPath = destinationPath + "/" + file;
|
||||
copyFilePrintStatus(fileSourcePath, fileDestinationPath);
|
||||
LogDebug() << "copyCopyrightFile:" << fileSourcePath;
|
||||
copyCopyrightFile(fileSourcePath);
|
||||
}
|
||||
|
||||
QStringList subdirs = QDir(sourcePath).entryList(QStringList() << "*", QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
@@ -620,6 +686,8 @@ void recursiveCopyAndDeploy(const QString &appDirPath, const QSet<QString> &rpat
|
||||
|
||||
QString fileDestinationPath = destinationPath + QLatin1Char('/') + file;
|
||||
copyFilePrintStatus(fileSourcePath, fileDestinationPath);
|
||||
LogDebug() << "copyCopyrightFile:" << fileSourcePath;
|
||||
copyCopyrightFile(fileSourcePath);
|
||||
|
||||
if(fileDestinationPath.endsWith(".so")){
|
||||
|
||||
@@ -675,6 +743,8 @@ QString copyDylib(const LibraryInfo &library, const QString path)
|
||||
|
||||
// Copy dylib binary
|
||||
copyFilePrintStatus(library.sourceFilePath, dylibDestinationBinaryPath);
|
||||
LogDebug() << "copyCopyrightFile:" << library.sourceFilePath;
|
||||
copyCopyrightFile(library.sourceFilePath);
|
||||
return dylibDestinationBinaryPath;
|
||||
}
|
||||
|
||||
@@ -920,13 +990,12 @@ DeploymentInfo deployQtLibraries(QList<LibraryInfo> libraries,
|
||||
deploymentInfo.qtPath = library.libraryDirectory;
|
||||
}
|
||||
|
||||
if(library.libraryName.contains("libQt") and library.libraryName.contains("Widgets.so")) {
|
||||
if(library.libraryName.contains("libQt") and library.libraryName.contains("Widgets.so")) {
|
||||
deploymentInfo.requiresQtWidgetsLibrary = true;
|
||||
}
|
||||
|
||||
if (library.libraryDirectory.startsWith(bundlePath)) {
|
||||
LogNormal() << library.libraryName << "already deployed, skipping.";
|
||||
continue;
|
||||
LogNormal() << library.libraryName << "already at target location";
|
||||
}
|
||||
|
||||
if (library.rpathUsed.isEmpty() != true) {
|
||||
@@ -1071,9 +1140,16 @@ DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &a
|
||||
} else {
|
||||
libraryPath = QFileInfo(applicationBundle.binaryPath).dir().filePath("../lib/" + bundleLibraryDirectory);
|
||||
}
|
||||
foreach (const QString &executable, QStringList() << applicationBundle.binaryPath << additionalExecutables) {
|
||||
changeIdentification("$ORIGIN/" + QFileInfo(executable).dir().relativeFilePath(libraryPath) + "/" + bundleLibraryDirectory, QFileInfo(executable).canonicalFilePath());
|
||||
}
|
||||
|
||||
/* Make ldd detect pre-existing libraries in the AppDir.
|
||||
* TODO: Consider searching the AppDir for .so* files outside of libraryPath
|
||||
* and warning about them not being taken into consideration */
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
QString oldPath = env.value("LD_LIBRARY_PATH");
|
||||
QString newPath = libraryPath + ":" + oldPath; // FIXME: If we use a ldd replacement, we still need to observe this path
|
||||
LogDebug() << "Changed LD_LIBRARY_PATH:" << newPath;
|
||||
setenv("LD_LIBRARY_PATH",newPath.toUtf8().constData(),1);
|
||||
|
||||
applicationBundle.libraryPaths = findAppLibraries(appDirPath);
|
||||
LogDebug() << "applicationBundle.libraryPaths:" << applicationBundle.libraryPaths;
|
||||
|
||||
@@ -1088,17 +1164,24 @@ DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &a
|
||||
LogDebug() << "allRPaths:" << allRPaths;
|
||||
|
||||
QList<LibraryInfo> libraries = getQtLibrariesForPaths(allBinaryPaths, appDirPath, allRPaths);
|
||||
|
||||
DeploymentInfo depInfo;
|
||||
if (libraries.isEmpty() && !alwaysOwerwriteEnabled) {
|
||||
LogWarning() << "Could not find any external Qt libraries to deploy in" << appDirPath;
|
||||
LogWarning() << "Perhaps linuxdeployqt was already used on" << appDirPath << "?";
|
||||
LogWarning() << "If so, you will need to rebuild" << appDirPath << "before trying again.";
|
||||
LogWarning() << "Or ldd does not find the external Qt libraries but sees the system ones.";
|
||||
LogWarning() << "If so, you will need to set LD_LIBRARY_PATH to the directory containing the external Qt libraries before trying again.";
|
||||
LogWarning() << "FIXME: https://github.com/probonopd/linuxdeployqt/issues/2";
|
||||
return DeploymentInfo();
|
||||
LogWarning() << "Could not find any external Qt libraries to deploy in" << appDirPath;
|
||||
LogWarning() << "Perhaps linuxdeployqt was already used on" << appDirPath << "?";
|
||||
LogWarning() << "If so, you will need to rebuild" << appDirPath << "before trying again.";
|
||||
LogWarning() << "Or ldd does not find the external Qt libraries but sees the system ones.";
|
||||
LogWarning() << "If so, you will need to set LD_LIBRARY_PATH to the directory containing the external Qt libraries before trying again.";
|
||||
LogWarning() << "FIXME: https://github.com/probonopd/linuxdeployqt/issues/2";
|
||||
} else {
|
||||
return deployQtLibraries(libraries, applicationBundle.path, allBinaryPaths, !additionalExecutables.isEmpty());
|
||||
depInfo = deployQtLibraries(libraries, applicationBundle.path, allBinaryPaths, !additionalExecutables.isEmpty());
|
||||
}
|
||||
|
||||
foreach (const QString &executable, QStringList() << applicationBundle.binaryPath << additionalExecutables) {
|
||||
changeIdentification("$ORIGIN/" + QFileInfo(executable).dir().relativeFilePath(libraryPath), QFileInfo(executable).canonicalFilePath());
|
||||
}
|
||||
|
||||
return depInfo;
|
||||
}
|
||||
|
||||
void deployPlugins(const AppDirInfo &appDirInfo, const QString &pluginSourcePath,
|
||||
@@ -1118,6 +1201,20 @@ void deployPlugins(const AppDirInfo &appDirInfo, const QString &pluginSourcePath
|
||||
if (containsHowOften(deploymentInfo.deployedLibraries, "libQt5Gui")) {
|
||||
LogDebug() << "libQt5Gui detected";
|
||||
pluginList.append("platforms/libqxcb.so");
|
||||
// Platform plugin contexts - apparently needed to enter special characters
|
||||
QStringList platformPluginContexts = QDir(pluginSourcePath + QStringLiteral("/platforminputcontexts")).entryList(QStringList() << QStringLiteral("*.so"));
|
||||
foreach (const QString &plugin, platformPluginContexts) {
|
||||
pluginList.append(QStringLiteral("platforminputcontexts/") + plugin);
|
||||
}
|
||||
// Platform themes - make Qt look more native e.g., on Gtk+ 3 (if available in Qt installation)
|
||||
// FIXME: Do not do this until we find a good way to do this without also deploying their dependencies
|
||||
// See https://github.com/probonopd/linuxdeployqt/issues/236
|
||||
/*
|
||||
QStringList platformThemes = QDir(pluginSourcePath + QStringLiteral("/platformthemes")).entryList(QStringList() << QStringLiteral("*.so"));
|
||||
foreach (const QString &plugin, platformThemes) {
|
||||
pluginList.append(QStringLiteral("platformthemes/") + plugin);
|
||||
}
|
||||
*/
|
||||
// All image formats (svg if QtSvg library is used)
|
||||
QStringList imagePlugins = QDir(pluginSourcePath + QStringLiteral("/imageformats")).entryList(QStringList() << QStringLiteral("*.so"));
|
||||
foreach (const QString &plugin, imagePlugins) {
|
||||
@@ -1132,7 +1229,9 @@ void deployPlugins(const AppDirInfo &appDirInfo, const QString &pluginSourcePath
|
||||
}
|
||||
|
||||
// Platform OpenGL context
|
||||
if ((containsHowOften(deploymentInfo.deployedLibraries, "libQt5OpenGL")) or (containsHowOften(deploymentInfo.deployedLibraries, "libQt5XcbQpa"))) {
|
||||
if ((containsHowOften(deploymentInfo.deployedLibraries, "libQt5OpenGL"))
|
||||
or (containsHowOften(deploymentInfo.deployedLibraries, "libQt5XcbQpa"))
|
||||
or (containsHowOften(deploymentInfo.deployedLibraries, "libxcb-glx"))) {
|
||||
QStringList xcbglintegrationPlugins = QDir(pluginSourcePath + QStringLiteral("/xcbglintegrations")).entryList(QStringList() << QStringLiteral("*.so"));
|
||||
foreach (const QString &plugin, xcbglintegrationPlugins) {
|
||||
pluginList.append(QStringLiteral("xcbglintegrations/") + plugin);
|
||||
@@ -1166,6 +1265,14 @@ void deployPlugins(const AppDirInfo &appDirInfo, const QString &pluginSourcePath
|
||||
}
|
||||
}
|
||||
|
||||
// Positioning plugins if QtPositioning library is in use
|
||||
if (containsHowOften(deploymentInfo.deployedLibraries, "libQt5Positioning")) {
|
||||
QStringList posPlugins = QDir(pluginSourcePath + QStringLiteral("/position")).entryList(QStringList() << QStringLiteral("*.so"));
|
||||
foreach (const QString &plugin, posPlugins) {
|
||||
pluginList.append(QStringLiteral("position/") + plugin);
|
||||
}
|
||||
}
|
||||
|
||||
// multimedia plugins if QtMultimedia library is in use
|
||||
if (containsHowOften(deploymentInfo.deployedLibraries, "libQt5Multimedia")) {
|
||||
QStringList plugins = QDir(pluginSourcePath + QStringLiteral("/mediaservice")).entryList(QStringList() << QStringLiteral("*.so"));
|
||||
@@ -1238,25 +1345,60 @@ void deployPlugins(const AppDirInfo &appDirInfo, const QString &pluginSourcePath
|
||||
recursiveCopy(sourcePath, destinationPath);
|
||||
}
|
||||
|
||||
if (!extraQtPlugins.isEmpty()) {
|
||||
LogNormal() << "Deploying extra plugins.";
|
||||
foreach (const QString &plugin, extraQtPlugins) {
|
||||
QDir pluginDirectory(pluginSourcePath + "/" + plugin);
|
||||
if (pluginDirectory.exists()) {
|
||||
//If it is a plugin directory we will deploy the entire directory
|
||||
QStringList plugins = pluginDirectory.entryList(QStringList() << QStringLiteral("*.so"));
|
||||
foreach (const QString &pluginFile, plugins) {
|
||||
pluginList.append(plugin + "/" + pluginFile);
|
||||
LogDebug() << plugin + "/" + pluginFile << "appended";
|
||||
}
|
||||
}
|
||||
else {
|
||||
//If it isn't a directory we asume it is an explicit plugin and we will try to deploy that
|
||||
if (!pluginList.contains(plugin)) {
|
||||
if (QFile::exists(pluginSourcePath + "/" + plugin)) {
|
||||
pluginList.append(plugin);
|
||||
LogDebug() << plugin << "appended";
|
||||
}
|
||||
else {
|
||||
LogDebug() << "The plugin" << plugin << "was already deployed." ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LogWarning() << "The plugin" << pluginSourcePath + "/" + plugin << "could not be found. Please check spelling and try again!";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogNormal() << "pluginList after having detected hopefully all required plugins:" << pluginList;
|
||||
|
||||
foreach (const QString &plugin, pluginList) {
|
||||
sourcePath = pluginSourcePath + "/" + plugin;
|
||||
destinationPath = pluginDestinationPath + "/" + plugin;
|
||||
QDir dir;
|
||||
dir.mkpath(QFileInfo(destinationPath).path());
|
||||
QList<LibraryInfo> libraries = getQtLibraries(sourcePath, appDirInfo.path, deploymentInfo.rpathsUsed);
|
||||
LogDebug() << "Deploying plugin" << sourcePath;
|
||||
if (copyFilePrintStatus(sourcePath, destinationPath)) {
|
||||
runStrip(destinationPath);
|
||||
deployQtLibraries(libraries, appDirInfo.path, QStringList() << destinationPath, deploymentInfo.useLoaderPath);
|
||||
/* See whether this makes any difference */
|
||||
// Find out the relative path to the lib/ directory and set it as the rpath
|
||||
QDir dir(destinationPath);
|
||||
QString relativePath = dir.relativeFilePath(appDirInfo.path + "/" + libraries[0].libraryDestinationDirectory);
|
||||
relativePath.remove(0, 3); // remove initial '../'
|
||||
changeIdentification("$ORIGIN/" + relativePath, QFileInfo(destinationPath).canonicalFilePath());
|
||||
if(!excludeLibs.contains(QFileInfo(sourcePath).baseName()))
|
||||
{
|
||||
QDir dir;
|
||||
dir.mkpath(QFileInfo(destinationPath).path());
|
||||
QList<LibraryInfo> libraries = getQtLibraries(sourcePath, appDirInfo.path, deploymentInfo.rpathsUsed);
|
||||
LogDebug() << "Deploying plugin" << sourcePath;
|
||||
if (copyFilePrintStatus(sourcePath, destinationPath)) {
|
||||
runStrip(destinationPath);
|
||||
deployQtLibraries(libraries, appDirInfo.path, QStringList() << destinationPath, deploymentInfo.useLoaderPath);
|
||||
/* See whether this makes any difference */
|
||||
// Find out the relative path to the lib/ directory and set it as the rpath
|
||||
QDir dir(destinationPath);
|
||||
QString relativePath = dir.relativeFilePath(appDirInfo.path + "/" + libraries[0].libraryDestinationDirectory);
|
||||
relativePath.remove(0, 3); // remove initial '../'
|
||||
changeIdentification("$ORIGIN/" + relativePath, QFileInfo(destinationPath).canonicalFilePath());
|
||||
|
||||
}
|
||||
LogDebug() << "copyCopyrightFile:" << sourcePath;
|
||||
copyCopyrightFile(sourcePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1571,7 +1713,7 @@ bool checkAppImagePrerequisites(const QString &appDirPath)
|
||||
|
||||
int createAppImage(const QString &appDirPath)
|
||||
{
|
||||
QString appImageCommand = "appimagetool '" + appDirPath + "' --verbose -n"; // +"' '" + appImagePath + "'";
|
||||
QString appImageCommand = "appimagetool '" + appDirPath + "' --verbose -n -g"; // +"' '" + appImagePath + "'";
|
||||
int ret = system(appImageCommand.toUtf8().constData());
|
||||
LogNormal() << "ret" << ret;
|
||||
LogNormal() << "WEXITSTATUS(ret)" << WEXITSTATUS(ret);
|
||||
@@ -1613,9 +1755,18 @@ void deployTranslations(const QString &appDirPath, quint64 usedQtModules)
|
||||
return;
|
||||
}
|
||||
|
||||
QString translationsDirPath = appDirPath + QStringLiteral("/translations");
|
||||
LogDebug() << "Using" << translationsDirPath << "as translations directory for App";
|
||||
LogDebug() << "Using" << qtTranslationsPath << " to search for Qt translations";
|
||||
QString translationsDirPath;
|
||||
if (!fhsLikeMode) {
|
||||
translationsDirPath = appDirPath + QStringLiteral("/translations");
|
||||
} else {
|
||||
// TODO: refactor this global variables hack
|
||||
QFileInfo appBinaryFI(appBinaryPath);
|
||||
QString appRoot = appBinaryFI.absoluteDir().absolutePath() + "/../";
|
||||
translationsDirPath = appRoot + QStringLiteral("/translations");
|
||||
}
|
||||
|
||||
LogNormal() << "Using" << translationsDirPath << "as translations directory for App";
|
||||
LogNormal() << "Using" << qtTranslationsPath << " to search for Qt translations";
|
||||
|
||||
QFileInfo fi(translationsDirPath);
|
||||
if (!fi.isDir()) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd. and Simon Peter
|
||||
** Copyright (C) 2016-18 The Qt Company Ltd. and Simon Peter
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the tools applications of the Qt Toolkit.
|
||||
@@ -45,6 +45,8 @@ extern bool runStripEnabled;
|
||||
extern bool bundleAllButCoreLibs;
|
||||
extern bool fhsLikeMode;
|
||||
extern QString fhsPrefix;
|
||||
extern QStringList extraQtPlugins;
|
||||
extern QStringList excludeLibs;
|
||||
|
||||
class LibraryInfo
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user