summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.json27
-rw-r--r--configure.pri21
-rw-r--r--qmake/option.cpp5
-rw-r--r--src/corelib/configure.json20
-rw-r--r--src/corelib/global/qlibraryinfo.cpp208
5 files changed, 228 insertions, 53 deletions
diff --git a/configure.json b/configure.json
index 5fc35a1658..13cca852f6 100644
--- a/configure.json
+++ b/configure.json
@@ -222,6 +222,21 @@
{ "type": "pkgConfig", "args": "libudev" },
"-ludev"
]
+ },
+ "libdl": {
+ "label": "dlopen()",
+ "test": {
+ "main": [
+ "dlclose(dlopen(0, 0));",
+ "dlsym(RTLD_DEFAULT, 0);",
+ "dlerror();"
+ ]
+ },
+ "headers": "dlfcn.h",
+ "sources": [
+ "",
+ "-ldl"
+ ]
}
},
@@ -1340,6 +1355,17 @@
"autoDetect": false,
"condition": "!features.shared",
"output": [ "publicConfig", "publicQtConfig" ]
+ },
+ "dlopen": {
+ "label": "dlopen()",
+ "condition": "config.unix && libs.libdl",
+ "output": [ "privateFeature" ]
+ },
+ "relocatable": {
+ "label": "Relocatable",
+ "autoDetect": "features.shared",
+ "condition": "features.dlopen || config.win32 || !features.shared",
+ "output": [ "privateFeature" ]
}
},
@@ -1466,6 +1492,7 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
"args": "enable_gdb_index",
"condition": "config.gcc && !config.clang && (features.debug || features.force_debug_info || features.debug_and_release)"
},
+ "relocatable",
"precompile_header",
"ltcg",
{
diff --git a/configure.pri b/configure.pri
index e26b557705..5f82efbf07 100644
--- a/configure.pri
+++ b/configure.pri
@@ -763,6 +763,11 @@ defineTest(qtConfOutput_preparePaths) {
have_hostprefix = true
}
+ equals(config.input.prefix, $$config.input.extprefix): \
+ qmake_crossbuild = false
+ else: \
+ qmake_crossbuild = true
+
PREFIX_COMPLAINTS =
PREFIX_REMINDER = false
win32: \
@@ -802,6 +807,18 @@ defineTest(qtConfOutput_preparePaths) {
processQtPath(host, hostdatadir, $$config.rel_input.archdatadir)
}
+ win32:$$qtConfEvaluate("features.shared") {
+ # Windows DLLs are in the bin dir.
+ libloc_absolute_path = $$absolute_path($$config.rel_input.bindir, $$config.input.prefix)
+ } else {
+ libloc_absolute_path = $$absolute_path($$config.rel_input.libdir, $$config.input.prefix)
+ }
+ config.input.liblocation_to_prefix = $$relative_path($$config.input.prefix, $$libloc_absolute_path)
+
+ hostbindir_absolute_path = $$absolute_path($$config.rel_input.hostbindir, $$config.input.hostprefix)
+ config.input.hostbindir_to_hostprefix = $$relative_path($$config.input.hostprefix, $$hostbindir_absolute_path)
+ config.input.hostbindir_to_extprefix = $$relative_path($$config.input.extprefix, $$hostbindir_absolute_path)
+
!isEmpty(PREFIX_COMPLAINTS) {
PREFIX_COMPLAINTS = "$$join(PREFIX_COMPLAINTS, "$$escape_expand(\\n)Note: ")"
$$PREFIX_REMINDER: \
@@ -864,9 +881,13 @@ defineTest(qtConfOutput_preparePaths) {
";" \
"" \
"$${LITERAL_HASH}define QT_CONFIGURE_SETTINGS_PATH \"$$config.rel_input.sysconfdir\"" \
+ "$${LITERAL_HASH}define QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH \"$$config.input.liblocation_to_prefix\"" \
+ "$${LITERAL_HASH}define QT_CONFIGURE_HOSTBINDIR_TO_EXTPREFIX_PATH \"$$config.input.hostbindir_to_extprefix\"" \
+ "$${LITERAL_HASH}define QT_CONFIGURE_HOSTBINDIR_TO_HOSTPREFIX_PATH \"$$config.input.hostbindir_to_hostprefix\"" \
"" \
"$${LITERAL_HASH}ifdef QT_BUILD_QMAKE" \
"$${LITERAL_HASH} define QT_CONFIGURE_SYSROOTIFY_PREFIX $$qmake_sysrootify" \
+ "$${LITERAL_HASH} define QT_CONFIGURE_CROSSBUILD $$qmake_crossbuild" \
"$${LITERAL_HASH}endif" \
"" \
"$${LITERAL_HASH}define QT_CONFIGURE_PREFIX_PATH qt_configure_prefix_path_str + 12" \
diff --git a/qmake/option.cpp b/qmake/option.cpp
index d8143468e6..9ec2fe6411 100644
--- a/qmake/option.cpp
+++ b/qmake/option.cpp
@@ -658,4 +658,9 @@ QString qmake_libraryInfoFile()
return QString();
}
+QString qmake_abslocation()
+{
+ return Option::globals->qmake_abslocation;
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/configure.json b/src/corelib/configure.json
index f7b6d41534..ae360239c6 100644
--- a/src/corelib/configure.json
+++ b/src/corelib/configure.json
@@ -158,21 +158,6 @@
"-latomic"
]
},
- "libdl": {
- "label": "dlopen()",
- "test": {
- "main": [
- "dlclose(dlopen(0, 0));",
- "dlsym(RTLD_DEFAULT, 0);",
- "dlerror();"
- ]
- },
- "headers": "dlfcn.h",
- "sources": [
- "",
- "-ldl"
- ]
- },
"librt": {
"label": "clock_gettime()",
"test": {
@@ -612,11 +597,6 @@
"condition": "features.clock-gettime && tests.clock-monotonic",
"output": [ "feature" ]
},
- "dlopen": {
- "label": "dlopen()",
- "condition": "config.unix && libs.libdl",
- "output": [ "privateFeature" ]
- },
"doubleconversion": {
"label": "DoubleConversion",
"output": [ "privateFeature", "feature" ]
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index 4c1b04f05e..c7357f9d13 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -55,15 +55,24 @@ QT_END_NAMESPACE
# include "qcoreapplication.h"
#endif
+#ifndef QT_BUILD_QMAKE_BOOTSTRAP
+# include "private/qglobal_p.h"
+# include "qconfig.cpp"
+#endif
+
#ifdef Q_OS_DARWIN
# include "private/qcore_mac_p.h"
-#endif
+#endif // Q_OS_DARWIN
-#ifndef QT_BUILD_QMAKE_BOOTSTRAP
-# include "qconfig.cpp"
+#include "archdetect.cpp"
+
+#if !defined(QT_BUILD_QMAKE) && QT_CONFIG(relocatable) && QT_CONFIG(dlopen) && !QT_CONFIG(framework)
+# include <dlfcn.h>
#endif
-#include "archdetect.cpp"
+#if !defined(QT_BUILD_QMAKE) && QT_CONFIG(relocatable) && defined(Q_OS_WIN)
+# include <qt_windows.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -453,6 +462,160 @@ void QLibraryInfo::sysrootify(QString *path)
}
#endif // QT_BUILD_QMAKE
+#ifndef QT_BUILD_QMAKE
+static QString prefixFromAppDirHelper()
+{
+ QString appDir;
+
+ if (QCoreApplication::instance()) {
+#ifdef Q_OS_DARWIN
+ CFBundleRef bundleRef = CFBundleGetMainBundle();
+ if (bundleRef) {
+ QCFType<CFURLRef> urlRef = CFBundleCopyBundleURL(bundleRef);
+ if (urlRef) {
+ QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
+#ifdef Q_OS_MACOS
+ QString bundleContentsDir = QString(path) + QLatin1String("/Contents/");
+ if (QDir(bundleContentsDir).exists())
+ return QDir::cleanPath(bundleContentsDir);
+#else
+ return QDir::cleanPath(QString(path)); // iOS
+#endif // Q_OS_MACOS
+ }
+ }
+#endif // Q_OS_DARWIN
+ // We make the prefix path absolute to the executable's directory.
+ appDir = QCoreApplication::applicationDirPath();
+ } else {
+ appDir = QDir::currentPath();
+ }
+
+ return appDir;
+}
+#endif
+
+#if !defined(QT_BUILD_QMAKE) && QT_CONFIG(relocatable)
+static QString prefixFromQtCoreLibraryHelper(const QString &qtCoreLibraryPath)
+{
+ const QString qtCoreLibrary = QDir::fromNativeSeparators(qtCoreLibraryPath);
+ const QString libDir = QFileInfo(qtCoreLibrary).absolutePath();
+ const QString prefixDir = libDir + QLatin1Char('/')
+ + QLatin1String(QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH);
+ return QDir::cleanPath(prefixDir);
+}
+
+#if defined(Q_OS_WIN)
+#if defined(Q_OS_WINRT)
+EXTERN_C IMAGE_DOS_HEADER __ImageBase;
+static HMODULE getWindowsModuleHandle()
+{
+ return reinterpret_cast<HMODULE>(&__ImageBase);
+}
+#else // Q_OS_WINRT
+static HMODULE getWindowsModuleHandle()
+{
+ HMODULE hModule = NULL;
+ GetModuleHandleEx(
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ (LPCTSTR)&QLibraryInfo::isDebugBuild, &hModule);
+ return hModule;
+}
+#endif // !Q_OS_WINRT
+#endif // Q_OS_WIN
+
+static QString getRelocatablePrefix()
+{
+ QString prefixPath;
+
+ // For static builds, the prefix will be the app directory.
+ // For regular builds, the prefix will be relative to the location of the QtCore shared library.
+#if defined(QT_STATIC)
+ prefixPath = prefixFromAppDirHelper();
+#elif defined(Q_OS_DARWIN) && QT_CONFIG(framework)
+ CFBundleRef qtCoreBundle = CFBundleGetBundleWithIdentifier(
+ CFSTR("org.qt-project.QtCore"));
+ Q_ASSERT(qtCoreBundle);
+
+ QCFType<CFURLRef> qtCorePath = CFBundleCopyBundleURL(qtCoreBundle);
+ Q_ASSERT(qtCorePath);
+
+ QCFType<CFURLRef> qtCorePathAbsolute = CFURLCopyAbsoluteURL(qtCorePath);
+ Q_ASSERT(qtCorePathAbsolute);
+
+ QCFType<CFURLRef> libDirCFPath = CFURLCreateCopyDeletingLastPathComponent(NULL, qtCorePathAbsolute);
+
+ const QCFString libDirCFString = CFURLCopyFileSystemPath(libDirCFPath, kCFURLPOSIXPathStyle);
+
+ const QString prefixDir = QString(libDirCFString) + QLatin1Char('/')
+ + QLatin1String(QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH);
+
+ prefixPath = QDir::cleanPath(prefixDir);
+#elif QT_CONFIG(dlopen)
+ Dl_info info;
+ int result = dladdr(reinterpret_cast<void *>(&QLibraryInfo::isDebugBuild), &info);
+ if (result > 0 && info.dli_fname)
+ prefixPath = prefixFromQtCoreLibraryHelper(QString::fromLatin1(info.dli_fname));
+#elif defined(Q_OS_WIN)
+ HMODULE hModule = getWindowsModuleHandle();
+ const int kBufferSize = 4096;
+ wchar_t buffer[kBufferSize];
+ const int pathSize = GetModuleFileName(hModule, buffer, kBufferSize);
+ if (pathSize > 0)
+ prefixPath = prefixFromQtCoreLibraryHelper(QString::fromWCharArray(buffer, pathSize));
+#else
+#error "The chosen platform / config does not support querying for a dynamic prefix."
+#endif
+
+ Q_ASSERT_X(!prefixPath.isEmpty(), "getRelocatablePrefix",
+ "Failed to find the Qt prefix path.");
+ return prefixPath;
+}
+#endif
+
+#if defined(QT_BUILD_QMAKE) && !defined(QT_BUILD_QMAKE_BOOTSTRAP)
+QString qmake_abslocation();
+
+static QString getPrefixFromHostBinDir(const char *hostBinDirToPrefixPath)
+{
+ const QFileInfo qmfi = QFileInfo(qmake_abslocation()).canonicalFilePath();
+ return QDir::cleanPath(qmfi.absolutePath() + QLatin1Char('/')
+ + QLatin1String(hostBinDirToPrefixPath));
+}
+
+static QString getExtPrefixFromHostBinDir()
+{
+ return getPrefixFromHostBinDir(QT_CONFIGURE_HOSTBINDIR_TO_EXTPREFIX_PATH);
+}
+
+static QString getHostPrefixFromHostBinDir()
+{
+ return getPrefixFromHostBinDir(QT_CONFIGURE_HOSTBINDIR_TO_HOSTPREFIX_PATH);
+}
+#endif
+
+#ifndef QT_BUILD_QMAKE_BOOTSTRAP
+static const char *getPrefix(
+#ifdef QT_BUILD_QMAKE
+ QLibraryInfo::PathGroup group
+#endif
+ )
+{
+#if defined(QT_BUILD_QMAKE)
+# if QT_CONFIGURE_CROSSBUILD
+ if (group == QLibraryInfo::DevicePaths)
+ return QT_CONFIGURE_PREFIX_PATH;
+# endif
+ static QByteArray extPrefixPath = getExtPrefixFromHostBinDir().toLatin1();
+ return extPrefixPath.constData();
+#elif QT_CONFIG(relocatable)
+ static QByteArray prefixPath = getRelocatablePrefix().toLatin1();
+ return prefixPath.constData();
+#else
+ return QT_CONFIGURE_PREFIX_PATH;
+#endif
+}
+#endif // QT_BUILD_QMAKE_BOOTSTRAP
+
/*!
Returns the location specified by \a loc.
*/
@@ -564,12 +727,11 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group)
if (!fromConf) {
const char * volatile path = 0;
if (loc == PrefixPath) {
- path =
-# ifdef QT_BUILD_QMAKE
- (group != DevicePaths) ?
- QT_CONFIGURE_EXT_PREFIX_PATH :
-# endif
- QT_CONFIGURE_PREFIX_PATH;
+ path = getPrefix(
+#ifdef QT_BUILD_QMAKE
+ group
+#endif
+ );
} else if (unsigned(loc) <= sizeof(qt_configure_str_offsets)/sizeof(qt_configure_str_offsets[0])) {
path = qt_configure_strs + qt_configure_str_offsets[loc - 1];
#ifndef Q_OS_WIN // On Windows we use the registry
@@ -578,7 +740,8 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group)
#endif
# ifdef QT_BUILD_QMAKE
} else if (loc == HostPrefixPath) {
- path = QT_CONFIGURE_HOST_PREFIX_PATH;
+ static const QByteArray hostPrefixPath = getHostPrefixFromHostBinDir().toLatin1();
+ path = hostPrefixPath.constData();
# endif
}
@@ -612,28 +775,7 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group)
}
#else
if (loc == PrefixPath) {
- if (QCoreApplication::instance()) {
-#ifdef Q_OS_DARWIN
- CFBundleRef bundleRef = CFBundleGetMainBundle();
- if (bundleRef) {
- QCFType<CFURLRef> urlRef = CFBundleCopyBundleURL(bundleRef);
- if (urlRef) {
- QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
-#ifdef Q_OS_OSX
- QString bundleContentsDir = QString(path) + QLatin1String("/Contents/");
- if (QDir(bundleContentsDir).exists())
- return QDir::cleanPath(bundleContentsDir + ret);
-#else
- return QDir::cleanPath(QString(path) + QLatin1Char('/') + ret); // iOS
-#endif // Q_OS_OSX
- }
- }
-#endif // Q_OS_DARWIN
- // We make the prefix path absolute to the executable's directory.
- baseDir = QCoreApplication::applicationDirPath();
- } else {
- baseDir = QDir::currentPath();
- }
+ baseDir = prefixFromAppDirHelper();
} else {
// we make any other path absolute to the prefix directory
baseDir = location(PrefixPath);