Warning, /graphics/krita/3rdparty/ext_qt/0116-Make-Qt-relocatable.patch is written in an unsupported language. File is not indexed.
0001 From 716dcf21b9c025be6038b06736eec90038ec3a11 Mon Sep 17 00:00:00 2001 0002 From: Alexandru Croitor <alexandru.croitor@qt.io> 0003 Date: Thu, 9 Nov 2017 18:00:46 +0100 0004 Subject: [PATCH 35/47] Make Qt relocatable 0005 0006 [ChangeLog][QtCore] Qt installations on the host system can now be 0007 relocated, i.e. moved to other directories. 0008 0009 Add a new feature 'relocatable' that's by default enabled for 0010 non-static builds 0011 - on platforms where libdl is available, 0012 - on macOS when configured with -framework, 0013 - on Windows. 0014 0015 If the feature is enabled, the directory where plugins, translations 0016 and other assets are loaded from is determined by the location of 0017 libQt5Core.so and the lib dir (bin dir on Windows) relative to the 0018 prefix. 0019 0020 For static builds, the feature 'relocatable' is off by default. It can 0021 be turned on manually by passing -feature-relocatable to configure. In 0022 that case, QLibraryInfo::location(QLibraryInfo::TranslationsPaths) and 0023 friends will return paths rooted in the user application's directory. 0024 0025 The installed and relocated qmake determines properties like 0026 QT_INSTALL_PREFIX and QT_HOST_PREFIX from the location of the qmake 0027 executable and the host bin dir relative to the host prefix. This is 0028 now always done, independent of the 'relocatable' feature. 0029 0030 Note that qmake is currently only relocatable within an environment 0031 that has the same layout as the original build machine due to absolute 0032 paths to the original prefix in .prl, .pc and .la files. 0033 This will be addressed in a separate patch. 0034 0035 Task-number: QTBUG-15234 0036 Change-Id: I7319e2856d8fe17f277082d71216442f52580633 0037 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io> 0038 --- 0039 configure.json | 27 ++++ 0040 configure.pri | 21 +++ 0041 qmake/option.cpp | 5 + 0042 src/corelib/configure.json | 20 --- 0043 src/corelib/global/qlibraryinfo.cpp | 208 +++++++++++++++++++++++----- 0044 5 files changed, 228 insertions(+), 53 deletions(-) 0045 0046 diff --git a/configure.json b/configure.json 0047 index 7279259484..0b06f3549a 100644 0048 --- a/configure.json 0049 +++ b/configure.json 0050 @@ -203,6 +203,21 @@ 0051 { "type": "pkgConfig", "args": "libudev" }, 0052 "-ludev" 0053 ] 0054 + }, 0055 + "libdl": { 0056 + "label": "dlopen()", 0057 + "test": { 0058 + "main": [ 0059 + "dlclose(dlopen(0, 0));", 0060 + "dlsym(RTLD_DEFAULT, 0);", 0061 + "dlerror();" 0062 + ] 0063 + }, 0064 + "headers": "dlfcn.h", 0065 + "sources": [ 0066 + "", 0067 + "-ldl" 0068 + ] 0069 } 0070 }, 0071 0072 @@ -1247,6 +1262,17 @@ 0073 "autoDetect": false, 0074 "condition": "!features.shared", 0075 "output": [ "publicConfig", "publicQtConfig" ] 0076 + }, 0077 + "dlopen": { 0078 + "label": "dlopen()", 0079 + "condition": "config.unix && libs.libdl", 0080 + "output": [ "privateFeature" ] 0081 + }, 0082 + "relocatable": { 0083 + "label": "Relocatable", 0084 + "autoDetect": "features.shared", 0085 + "condition": "features.dlopen || config.win32 || !features.shared", 0086 + "output": [ "privateFeature" ] 0087 } 0088 }, 0089 0090 @@ -1363,6 +1389,7 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5 0091 "args": "enable_gdb_index", 0092 "condition": "config.gcc && !config.clang && (features.debug || features.force_debug_info || features.debug_and_release)" 0093 }, 0094 + "relocatable", 0095 "precompile_header", 0096 "ltcg", 0097 { 0098 diff --git a/configure.pri b/configure.pri 0099 index 33c90a8c2f..57c750b104 100644 0100 --- a/configure.pri 0101 +++ b/configure.pri 0102 @@ -757,6 +757,11 @@ defineTest(qtConfOutput_preparePaths) { 0103 have_hostprefix = true 0104 } 0105 0106 + equals(config.input.prefix, $$config.input.extprefix): \ 0107 + qmake_crossbuild = false 0108 + else: \ 0109 + qmake_crossbuild = true 0110 + 0111 PREFIX_COMPLAINTS = 0112 PREFIX_REMINDER = false 0113 win32: \ 0114 @@ -796,6 +801,18 @@ defineTest(qtConfOutput_preparePaths) { 0115 processQtPath(host, hostdatadir, $$config.rel_input.archdatadir) 0116 } 0117 0118 + win32:$$qtConfEvaluate("features.shared") { 0119 + # Windows DLLs are in the bin dir. 0120 + libloc_absolute_path = $$absolute_path($$config.rel_input.bindir, $$config.input.prefix) 0121 + } else { 0122 + libloc_absolute_path = $$absolute_path($$config.rel_input.libdir, $$config.input.prefix) 0123 + } 0124 + config.input.liblocation_to_prefix = $$relative_path($$config.input.prefix, $$libloc_absolute_path) 0125 + 0126 + hostbindir_absolute_path = $$absolute_path($$config.rel_input.hostbindir, $$config.input.hostprefix) 0127 + config.input.hostbindir_to_hostprefix = $$relative_path($$config.input.hostprefix, $$hostbindir_absolute_path) 0128 + config.input.hostbindir_to_extprefix = $$relative_path($$config.input.extprefix, $$hostbindir_absolute_path) 0129 + 0130 !isEmpty(PREFIX_COMPLAINTS) { 0131 PREFIX_COMPLAINTS = "$$join(PREFIX_COMPLAINTS, "$$escape_expand(\\n)Note: ")" 0132 $$PREFIX_REMINDER: \ 0133 @@ -858,9 +875,13 @@ defineTest(qtConfOutput_preparePaths) { 0134 ";" \ 0135 "" \ 0136 "$${LITERAL_HASH}define QT_CONFIGURE_SETTINGS_PATH \"$$config.rel_input.sysconfdir\"" \ 0137 + "$${LITERAL_HASH}define QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH \"$$config.input.liblocation_to_prefix\"" \ 0138 + "$${LITERAL_HASH}define QT_CONFIGURE_HOSTBINDIR_TO_EXTPREFIX_PATH \"$$config.input.hostbindir_to_extprefix\"" \ 0139 + "$${LITERAL_HASH}define QT_CONFIGURE_HOSTBINDIR_TO_HOSTPREFIX_PATH \"$$config.input.hostbindir_to_hostprefix\"" \ 0140 "" \ 0141 "$${LITERAL_HASH}ifdef QT_BUILD_QMAKE" \ 0142 "$${LITERAL_HASH} define QT_CONFIGURE_SYSROOTIFY_PREFIX $$qmake_sysrootify" \ 0143 + "$${LITERAL_HASH} define QT_CONFIGURE_CROSSBUILD $$qmake_crossbuild" \ 0144 "$${LITERAL_HASH}endif" \ 0145 "" \ 0146 "$${LITERAL_HASH}define QT_CONFIGURE_PREFIX_PATH qt_configure_prefix_path_str + 12" \ 0147 diff --git a/qmake/option.cpp b/qmake/option.cpp 0148 index 626a2cec0d..e13fa47281 100644 0149 --- a/qmake/option.cpp 0150 +++ b/qmake/option.cpp 0151 @@ -661,4 +661,9 @@ QString qmake_libraryInfoFile() 0152 return QString(); 0153 } 0154 0155 +QString qmake_abslocation() 0156 +{ 0157 + return Option::globals->qmake_abslocation; 0158 +} 0159 + 0160 QT_END_NAMESPACE 0161 diff --git a/src/corelib/configure.json b/src/corelib/configure.json 0162 index 4de6cc19f3..5d657a13b5 100644 0163 --- a/src/corelib/configure.json 0164 +++ b/src/corelib/configure.json 0165 @@ -157,21 +157,6 @@ 0166 "-latomic" 0167 ] 0168 }, 0169 - "libdl": { 0170 - "label": "dlopen()", 0171 - "test": { 0172 - "main": [ 0173 - "dlclose(dlopen(0, 0));", 0174 - "dlsym(RTLD_DEFAULT, 0);", 0175 - "dlerror();" 0176 - ] 0177 - }, 0178 - "headers": "dlfcn.h", 0179 - "sources": [ 0180 - "", 0181 - "-ldl" 0182 - ] 0183 - }, 0184 "librt": { 0185 "label": "clock_gettime()", 0186 "test": { 0187 @@ -552,11 +537,6 @@ 0188 "condition": "features.clock-gettime && tests.clock-monotonic", 0189 "output": [ "feature" ] 0190 }, 0191 - "dlopen": { 0192 - "label": "dlopen()", 0193 - "condition": "config.unix && libs.libdl", 0194 - "output": [ "privateFeature" ] 0195 - }, 0196 "doubleconversion": { 0197 "label": "DoubleConversion", 0198 "output": [ "privateFeature", "feature" ] 0199 diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp 0200 index f2ada4ab30..9da9039f1a 100644 0201 --- a/src/corelib/global/qlibraryinfo.cpp 0202 +++ b/src/corelib/global/qlibraryinfo.cpp 0203 @@ -55,15 +55,24 @@ QT_END_NAMESPACE 0204 # include "qcoreapplication.h" 0205 #endif 0206 0207 +#ifndef QT_BUILD_QMAKE_BOOTSTRAP 0208 +# include "private/qglobal_p.h" 0209 +# include "qconfig.cpp" 0210 +#endif 0211 + 0212 #ifdef Q_OS_DARWIN 0213 # include "private/qcore_mac_p.h" 0214 -#endif 0215 +#endif // Q_OS_DARWIN 0216 0217 -#ifndef QT_BUILD_QMAKE_BOOTSTRAP 0218 -# include "qconfig.cpp" 0219 +#include "archdetect.cpp" 0220 + 0221 +#if !defined(QT_BUILD_QMAKE) && QT_CONFIG(relocatable) && QT_CONFIG(dlopen) && !QT_CONFIG(framework) 0222 +# include <dlfcn.h> 0223 #endif 0224 0225 -#include "archdetect.cpp" 0226 +#if !defined(QT_BUILD_QMAKE) && QT_CONFIG(relocatable) && defined(Q_OS_WIN) 0227 +# include <qt_windows.h> 0228 +#endif 0229 0230 QT_BEGIN_NAMESPACE 0231 0232 @@ -453,6 +462,160 @@ void QLibraryInfo::sysrootify(QString *path) 0233 } 0234 #endif // QT_BUILD_QMAKE 0235 0236 +#ifndef QT_BUILD_QMAKE 0237 +static QString prefixFromAppDirHelper() 0238 +{ 0239 + QString appDir; 0240 + 0241 + if (QCoreApplication::instance()) { 0242 +#ifdef Q_OS_DARWIN 0243 + CFBundleRef bundleRef = CFBundleGetMainBundle(); 0244 + if (bundleRef) { 0245 + QCFType<CFURLRef> urlRef = CFBundleCopyBundleURL(bundleRef); 0246 + if (urlRef) { 0247 + QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle); 0248 +#ifdef Q_OS_MACOS 0249 + QString bundleContentsDir = QString(path) + QLatin1String("/Contents/"); 0250 + if (QDir(bundleContentsDir).exists()) 0251 + return QDir::cleanPath(bundleContentsDir); 0252 +#else 0253 + return QDir::cleanPath(QString(path)); // iOS 0254 +#endif // Q_OS_MACOS 0255 + } 0256 + } 0257 +#endif // Q_OS_DARWIN 0258 + // We make the prefix path absolute to the executable's directory. 0259 + appDir = QCoreApplication::applicationDirPath(); 0260 + } else { 0261 + appDir = QDir::currentPath(); 0262 + } 0263 + 0264 + return appDir; 0265 +} 0266 +#endif 0267 + 0268 +#if !defined(QT_BUILD_QMAKE) && QT_CONFIG(relocatable) 0269 +static QString prefixFromQtCoreLibraryHelper(const QString &qtCoreLibraryPath) 0270 +{ 0271 + const QString qtCoreLibrary = QDir::fromNativeSeparators(qtCoreLibraryPath); 0272 + const QString libDir = QFileInfo(qtCoreLibrary).absolutePath(); 0273 + const QString prefixDir = libDir + QLatin1Char('/') 0274 + + QLatin1String(QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH); 0275 + return QDir::cleanPath(prefixDir); 0276 +} 0277 + 0278 +#if defined(Q_OS_WIN) 0279 +#if defined(Q_OS_WINRT) 0280 +EXTERN_C IMAGE_DOS_HEADER __ImageBase; 0281 +static HMODULE getWindowsModuleHandle() 0282 +{ 0283 + return reinterpret_cast<HMODULE>(&__ImageBase); 0284 +} 0285 +#else // Q_OS_WINRT 0286 +static HMODULE getWindowsModuleHandle() 0287 +{ 0288 + HMODULE hModule = NULL; 0289 + GetModuleHandleEx( 0290 + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, 0291 + (LPCTSTR)&QLibraryInfo::isDebugBuild, &hModule); 0292 + return hModule; 0293 +} 0294 +#endif // !Q_OS_WINRT 0295 +#endif // Q_OS_WIN 0296 + 0297 +static QString getRelocatablePrefix() 0298 +{ 0299 + QString prefixPath; 0300 + 0301 + // For static builds, the prefix will be the app directory. 0302 + // For regular builds, the prefix will be relative to the location of the QtCore shared library. 0303 +#if defined(QT_STATIC) 0304 + prefixPath = prefixFromAppDirHelper(); 0305 +#elif defined(Q_OS_DARWIN) && QT_CONFIG(framework) 0306 + CFBundleRef qtCoreBundle = CFBundleGetBundleWithIdentifier( 0307 + CFSTR("org.qt-project.QtCore")); 0308 + Q_ASSERT(qtCoreBundle); 0309 + 0310 + QCFType<CFURLRef> qtCorePath = CFBundleCopyBundleURL(qtCoreBundle); 0311 + Q_ASSERT(qtCorePath); 0312 + 0313 + QCFType<CFURLRef> qtCorePathAbsolute = CFURLCopyAbsoluteURL(qtCorePath); 0314 + Q_ASSERT(qtCorePathAbsolute); 0315 + 0316 + QCFType<CFURLRef> libDirCFPath = CFURLCreateCopyDeletingLastPathComponent(NULL, qtCorePathAbsolute); 0317 + 0318 + const QCFString libDirCFString = CFURLCopyFileSystemPath(libDirCFPath, kCFURLPOSIXPathStyle); 0319 + 0320 + const QString prefixDir = QString(libDirCFString) + QLatin1Char('/') 0321 + + QLatin1String(QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH); 0322 + 0323 + prefixPath = QDir::cleanPath(prefixDir); 0324 +#elif QT_CONFIG(dlopen) 0325 + Dl_info info; 0326 + int result = dladdr(reinterpret_cast<void *>(&QLibraryInfo::isDebugBuild), &info); 0327 + if (result > 0 && info.dli_fname) 0328 + prefixPath = prefixFromQtCoreLibraryHelper(QString::fromLatin1(info.dli_fname)); 0329 +#elif defined(Q_OS_WIN) 0330 + HMODULE hModule = getWindowsModuleHandle(); 0331 + const int kBufferSize = 4096; 0332 + wchar_t buffer[kBufferSize]; 0333 + const int pathSize = GetModuleFileName(hModule, buffer, kBufferSize); 0334 + if (pathSize > 0) 0335 + prefixPath = prefixFromQtCoreLibraryHelper(QString::fromWCharArray(buffer, pathSize)); 0336 +#else 0337 +#error "The chosen platform / config does not support querying for a dynamic prefix." 0338 +#endif 0339 + 0340 + Q_ASSERT_X(!prefixPath.isEmpty(), "getRelocatablePrefix", 0341 + "Failed to find the Qt prefix path."); 0342 + return prefixPath; 0343 +} 0344 +#endif 0345 + 0346 +#if defined(QT_BUILD_QMAKE) && !defined(QT_BUILD_QMAKE_BOOTSTRAP) 0347 +QString qmake_abslocation(); 0348 + 0349 +static QString getPrefixFromHostBinDir(const char *hostBinDirToPrefixPath) 0350 +{ 0351 + const QFileInfo qmfi = QFileInfo(qmake_abslocation()).canonicalFilePath(); 0352 + return QDir::cleanPath(qmfi.absolutePath() + QLatin1Char('/') 0353 + + QLatin1String(hostBinDirToPrefixPath)); 0354 +} 0355 + 0356 +static QString getExtPrefixFromHostBinDir() 0357 +{ 0358 + return getPrefixFromHostBinDir(QT_CONFIGURE_HOSTBINDIR_TO_EXTPREFIX_PATH); 0359 +} 0360 + 0361 +static QString getHostPrefixFromHostBinDir() 0362 +{ 0363 + return getPrefixFromHostBinDir(QT_CONFIGURE_HOSTBINDIR_TO_HOSTPREFIX_PATH); 0364 +} 0365 +#endif 0366 + 0367 +#ifndef QT_BUILD_QMAKE_BOOTSTRAP 0368 +static const char *getPrefix( 0369 +#ifdef QT_BUILD_QMAKE 0370 + QLibraryInfo::PathGroup group 0371 +#endif 0372 + ) 0373 +{ 0374 +#if defined(QT_BUILD_QMAKE) 0375 +# if QT_CONFIGURE_CROSSBUILD 0376 + if (group == QLibraryInfo::DevicePaths) 0377 + return QT_CONFIGURE_PREFIX_PATH; 0378 +# endif 0379 + static QByteArray extPrefixPath = getExtPrefixFromHostBinDir().toLatin1(); 0380 + return extPrefixPath.constData(); 0381 +#elif QT_CONFIG(relocatable) 0382 + static QByteArray prefixPath = getRelocatablePrefix().toLatin1(); 0383 + return prefixPath.constData(); 0384 +#else 0385 + return QT_CONFIGURE_PREFIX_PATH; 0386 +#endif 0387 +} 0388 +#endif // QT_BUILD_QMAKE_BOOTSTRAP 0389 + 0390 /*! 0391 Returns the location specified by \a loc. 0392 */ 0393 @@ -564,12 +727,11 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group) 0394 if (!fromConf) { 0395 const char * volatile path = 0; 0396 if (loc == PrefixPath) { 0397 - path = 0398 -# ifdef QT_BUILD_QMAKE 0399 - (group != DevicePaths) ? 0400 - QT_CONFIGURE_EXT_PREFIX_PATH : 0401 -# endif 0402 - QT_CONFIGURE_PREFIX_PATH; 0403 + path = getPrefix( 0404 +#ifdef QT_BUILD_QMAKE 0405 + group 0406 +#endif 0407 + ); 0408 } else if (unsigned(loc) <= sizeof(qt_configure_str_offsets)/sizeof(qt_configure_str_offsets[0])) { 0409 path = qt_configure_strs + qt_configure_str_offsets[loc - 1]; 0410 #ifndef Q_OS_WIN // On Windows we use the registry 0411 @@ -578,7 +740,8 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group) 0412 #endif 0413 # ifdef QT_BUILD_QMAKE 0414 } else if (loc == HostPrefixPath) { 0415 - path = QT_CONFIGURE_HOST_PREFIX_PATH; 0416 + static const QByteArray hostPrefixPath = getHostPrefixFromHostBinDir().toLatin1(); 0417 + path = hostPrefixPath.constData(); 0418 # endif 0419 } 0420 0421 @@ -612,28 +775,7 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group) 0422 } 0423 #else 0424 if (loc == PrefixPath) { 0425 - if (QCoreApplication::instance()) { 0426 -#ifdef Q_OS_DARWIN 0427 - CFBundleRef bundleRef = CFBundleGetMainBundle(); 0428 - if (bundleRef) { 0429 - QCFType<CFURLRef> urlRef = CFBundleCopyBundleURL(bundleRef); 0430 - if (urlRef) { 0431 - QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle); 0432 -#ifdef Q_OS_OSX 0433 - QString bundleContentsDir = QString(path) + QLatin1String("/Contents/"); 0434 - if (QDir(bundleContentsDir).exists()) 0435 - return QDir::cleanPath(bundleContentsDir + ret); 0436 -#else 0437 - return QDir::cleanPath(QString(path) + QLatin1Char('/') + ret); // iOS 0438 -#endif // Q_OS_OSX 0439 - } 0440 - } 0441 -#endif // Q_OS_DARWIN 0442 - // We make the prefix path absolute to the executable's directory. 0443 - baseDir = QCoreApplication::applicationDirPath(); 0444 - } else { 0445 - baseDir = QDir::currentPath(); 0446 - } 0447 + baseDir = prefixFromAppDirHelper(); 0448 } else { 0449 // we make any other path absolute to the prefix directory 0450 baseDir = location(PrefixPath); 0451 -- 0452 2.20.1.windows.1 0453