summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-06-29 20:12:41 +0200
committerLiang Qi <liang.qi@theqtcompany.com>2015-06-29 20:12:41 +0200
commiteeeaf56e1ed300dd86040b976d278434387070c1 (patch)
treeddfb5aaf66351fd5b224cca5da72475b6a7f1714
parentd56636976643498b9fa688eb9b3029ed9669a8a2 (diff)
parente863246ebd58192d202933a9f32b57fd811dc9ea (diff)
Merge remote-tracking branch 'origin/5.5' into dev
Conflicts: .qmake.conf Change-Id: I2424cf97743b3f998bf7b10a21f8075ed76b613f
-rw-r--r--src/assistant/3rdparty/clucene/src/CLucene/StdHeader.h5
-rw-r--r--src/assistant/3rdparty/clucene/src/CLucene/config/CompilerGcc.h2
-rw-r--r--src/assistant/3rdparty/clucene/src/CLucene/config/CompilerMsvc.h16
-rw-r--r--src/assistant/3rdparty/clucene/src/CLucene/debug/condition.cpp2
-rw-r--r--src/assistant/3rdparty/clucene/src/CLucene/util/VoidList.h4
-rw-r--r--src/assistant/3rdparty/clucene/src/CLucene/util/VoidMap.h24
-rw-r--r--src/assistant/help/qclucenefieldnames_p.h11
-rw-r--r--src/macdeployqt/shared/shared.cpp17
-rw-r--r--src/qtdiag/qtdiag.cpp9
-rw-r--r--src/windeployqt/main.cpp20
-rw-r--r--src/windeployqt/utils.cpp97
-rw-r--r--src/windeployqt/utils.h3
-rw-r--r--tests/auto/auto.pro4
-rw-r--r--tests/auto/windeployqt/test/test.pro5
-rw-r--r--tests/auto/windeployqt/testapp/main.cpp51
-rw-r--r--tests/auto/windeployqt/testapp/testapp.pro2
-rw-r--r--tests/auto/windeployqt/tst_windeployqt.cpp190
-rw-r--r--tests/auto/windeployqt/windeployqt.pro3
18 files changed, 404 insertions, 61 deletions
diff --git a/src/assistant/3rdparty/clucene/src/CLucene/StdHeader.h b/src/assistant/3rdparty/clucene/src/CLucene/StdHeader.h
index 439bc948a..97799142b 100644
--- a/src/assistant/3rdparty/clucene/src/CLucene/StdHeader.h
+++ b/src/assistant/3rdparty/clucene/src/CLucene/StdHeader.h
@@ -122,7 +122,10 @@ extern int _lucene_counter_break; //can set a watch on this
#error "CLucene can't compile without the vector header"
#endif
-#if !defined(LUCENE_DISABLE_HASHING) && defined(_CL_HAVE_HASH_MAP) && defined(_CL_HAVE_HASH_SET)
+#if !defined(LUCENE_DISABLE_HASHING) && defined(_CL_HAVE_STD_UNORDERED_MAP) && defined(_CL_HAVE_STD_UNORDERED_SET)
+ #include <unordered_map>
+ #include <unordered_set>
+#elif !defined(LUCENE_DISABLE_HASHING) && defined(_CL_HAVE_HASH_MAP) && defined(_CL_HAVE_HASH_SET)
//hashing is all or nothing!
#include <hash_map>
#include <hash_set>
diff --git a/src/assistant/3rdparty/clucene/src/CLucene/config/CompilerGcc.h b/src/assistant/3rdparty/clucene/src/CLucene/config/CompilerGcc.h
index 3bf91b369..6aac690e2 100644
--- a/src/assistant/3rdparty/clucene/src/CLucene/config/CompilerGcc.h
+++ b/src/assistant/3rdparty/clucene/src/CLucene/config/CompilerGcc.h
@@ -45,6 +45,8 @@
#define CL_NS_HASHING(func) __gnu_cxx::func
#define LUCENE_DISABLE_HASHING //we could enable this, but so far test show that the hashing is slower :(
+#define CL_HASH_MAP hash_map
+#define CL_HASH_SET hash_set
//define the file functions
#define fileSeek lseek
diff --git a/src/assistant/3rdparty/clucene/src/CLucene/config/CompilerMsvc.h b/src/assistant/3rdparty/clucene/src/CLucene/config/CompilerMsvc.h
index 8578859f0..6b3f7683e 100644
--- a/src/assistant/3rdparty/clucene/src/CLucene/config/CompilerMsvc.h
+++ b/src/assistant/3rdparty/clucene/src/CLucene/config/CompilerMsvc.h
@@ -27,8 +27,22 @@
#if (_MSC_VER < 1310) || defined(_STLPORT_VERSION)
#define CL_NS_HASHING(func) std::func //the namespace is different on VC 7.0
#else
- #define CL_NS_HASHING(func) stdext::func
+ #if _MSC_VER >= 1900
+ #undef _CL_HAVE_EXT_HASH_MAP
+ #undef _CL_HAVE_EXT_HASH_SET
+
+ #define CL_HASH_MAP unordered_map
+ #define CL_HASH_SET unordered_set
+ #define _CL_HAVE_STD_UNORDERED_MAP 1
+ #define _CL_HAVE_STD_UNORDERED_SET 1
+ #define CL_NS_HASHING(func) std::func
+ #else
+ #define CL_HASH_MAP hash_map
+ #define CL_HASH_SET hash_set
+ #define CL_NS_HASHING(func) stdext::func
+ #endif
#endif
+
#define LUCENE_STATIC_CONSTANT_SYNTAX 1
#if _MSC_FULL_VER >= 140050320
diff --git a/src/assistant/3rdparty/clucene/src/CLucene/debug/condition.cpp b/src/assistant/3rdparty/clucene/src/CLucene/debug/condition.cpp
index 855419451..7fab8d71d 100644
--- a/src/assistant/3rdparty/clucene/src/CLucene/debug/condition.cpp
+++ b/src/assistant/3rdparty/clucene/src/CLucene/debug/condition.cpp
@@ -37,7 +37,7 @@ void _Cnd_OutDebug( const char* FormattedMsg, const char* StrTitle, const char*
void __cnd_FormatDebug( const char* File, int32_t Line, int32_t Title, const char* Mes2, int32_t fatal ) {
char M[512];
- char* StrTitle = NULL;
+ const char* StrTitle = NULL;
if( Mes2 )
_snprintf(M,512,"file:%s line:%d\n%s",File,Line,Mes2);
diff --git a/src/assistant/3rdparty/clucene/src/CLucene/util/VoidList.h b/src/assistant/3rdparty/clucene/src/CLucene/util/VoidList.h
index b31baba8a..5deb69dae 100644
--- a/src/assistant/3rdparty/clucene/src/CLucene/util/VoidList.h
+++ b/src/assistant/3rdparty/clucene/src/CLucene/util/VoidList.h
@@ -139,11 +139,11 @@ public:
template<typename _kt,
typename _Comparator=CL_NS(util)::Compare::TChar,
typename _valueDeletor=CL_NS(util)::Deletor::Dummy>
-class CLHashList:public __CLList<_kt, CL_NS_HASHING(hash_set)<_kt,_Comparator> , _valueDeletor>
+class CLHashList:public __CLList<_kt, CL_NS_HASHING(CL_HASH_SET)<_kt,_Comparator> , _valueDeletor>
{
public:
CLHashList ( const bool deleteValue=true ):
- __CLList<_kt, CL_NS_HASHING(hash_set)<_kt,_Comparator> , _valueDeletor>(deleteValue)
+ __CLList<_kt, CL_NS_HASHING(CL_HASH_SET)<_kt,_Comparator> , _valueDeletor>(deleteValue)
{
}
};
diff --git a/src/assistant/3rdparty/clucene/src/CLucene/util/VoidMap.h b/src/assistant/3rdparty/clucene/src/CLucene/util/VoidMap.h
index 1153a0160..223670204 100644
--- a/src/assistant/3rdparty/clucene/src/CLucene/util/VoidMap.h
+++ b/src/assistant/3rdparty/clucene/src/CLucene/util/VoidMap.h
@@ -153,16 +153,16 @@ public:
//a CLSet with CLHashMap traits
template<typename _kt, typename _vt,
- typename _Compare,
+ typename CL_Compare,
typename _EqualDummy,
typename _KeyDeletor=CL_NS(util)::Deletor::Dummy,
typename _ValueDeletor=CL_NS(util)::Deletor::Dummy>
class CLHashMap:public __CLMap<_kt,_vt,
- CL_NS_STD(map)<_kt,_vt, _Compare>,
+ CL_NS_STD(map)<_kt,_vt, CL_Compare>,
_KeyDeletor,_ValueDeletor>
{
- typedef typename CL_NS_STD(map)<_kt,_vt,_Compare> _base;
- typedef __CLMap<_kt, _vt, CL_NS_STD(map)<_kt,_vt, _Compare>,
+ typedef typename CL_NS_STD(map)<_kt,_vt,CL_Compare> _base;
+ typedef __CLMap<_kt, _vt, CL_NS_STD(map)<_kt,_vt, CL_Compare>,
_KeyDeletor,_ValueDeletor> _this;
public:
CLHashMap ( const bool deleteKey=false, const bool deleteValue=false )
@@ -180,10 +180,10 @@ template<typename _kt, typename _vt,
typename _KeyDeletor=CL_NS(util)::Deletor::Dummy,
typename _ValueDeletor=CL_NS(util)::Deletor::Dummy>
class CLHashMap:public __CLMap<_kt,_vt,
- CL_NS_HASHING(hash_map)<_kt,_vt, _Hasher,_Equals>,
+ CL_NS_HASHING(CL_HASH_MAP)<_kt,_vt, _Hasher,_Equals>,
_KeyDeletor,_ValueDeletor>
{
- typedef __CLMap<_kt,_vt, CL_NS_HASHING(hash_map)<_kt,_vt, _Hasher,_Equals>,
+ typedef __CLMap<_kt,_vt, CL_NS_HASHING(CL_HASH_MAP)<_kt,_vt, _Hasher,_Equals>,
_KeyDeletor,_ValueDeletor> _this;
public:
CLHashMap ( const bool deleteKey=false, const bool deleteValue=false )
@@ -201,10 +201,10 @@ template<typename _kt, typename _vt,
typename _KeyDeletor=CL_NS(util)::Deletor::Dummy,
typename _ValueDeletor=CL_NS(util)::Deletor::Dummy>
class CLHashMap:public __CLMap<_kt,_vt,
- CL_NS_HASHING(hash_map)<_kt,_vt, _Hasher>,
+ CL_NS_HASHING(CL_HASH_MAP)<_kt,_vt, _Hasher>,
_KeyDeletor,_ValueDeletor>
{
- typedef __CLMap<_kt,_vt, CL_NS_HASHING(hash_map)<_kt,_vt, _Hasher>,
+ typedef __CLMap<_kt,_vt, CL_NS_HASHING(CL_HASH_MAP)<_kt,_vt, _Hasher>,
_KeyDeletor,_ValueDeletor> _this;
public:
CLHashMap ( const bool deleteKey=false, const bool deleteValue=false )
@@ -218,15 +218,15 @@ public:
//A collection that contains no duplicates
//does not guarantee that the order will remain constant over time
template<typename _kt, typename _vt,
- typename _Compare,
+ typename CL_Compare,
typename _KeyDeletor=CL_NS(util)::Deletor::Dummy,
typename _ValueDeletor=CL_NS(util)::Deletor::Dummy>
class CLSet:public __CLMap<_kt,_vt,
- CL_NS_STD(map)<_kt,_vt, _Compare>,
+ CL_NS_STD(map)<_kt,_vt, CL_Compare>,
_KeyDeletor,_ValueDeletor>
{
- typedef typename CL_NS_STD(map)<_kt,_vt,_Compare> _base;
- typedef __CLMap<_kt, _vt, CL_NS_STD(map)<_kt,_vt, _Compare>,
+ typedef typename CL_NS_STD(map)<_kt,_vt,CL_Compare> _base;
+ typedef __CLMap<_kt, _vt, CL_NS_STD(map)<_kt,_vt, CL_Compare>,
_KeyDeletor,_ValueDeletor> _this;
public:
CLSet ( const bool deleteKey=false, const bool deleteValue=false )
diff --git a/src/assistant/help/qclucenefieldnames_p.h b/src/assistant/help/qclucenefieldnames_p.h
index d72ce3c89..7d2a64e48 100644
--- a/src/assistant/help/qclucenefieldnames_p.h
+++ b/src/assistant/help/qclucenefieldnames_p.h
@@ -34,6 +34,17 @@
#ifndef QCLUCENEFIELDNAMES_P_H
#define QCLUCENEFIELDNAMES_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/QtGlobal>
#include <QtCore/QString>
diff --git a/src/macdeployqt/shared/shared.cpp b/src/macdeployqt/shared/shared.cpp
index 1c9b319ad..e2c4a19bc 100644
--- a/src/macdeployqt/shared/shared.cpp
+++ b/src/macdeployqt/shared/shared.cpp
@@ -739,13 +739,17 @@ void changeInstallName(const QString &bundlePath, const FrameworkInfo &framework
}
}
-void deployRPaths(const QSet<QString> &rpaths, const QString &binaryPath, bool useLoaderPath)
+void deployRPaths(const QString &bundlePath, const QSet<QString> &rpaths, const QString &binaryPath, bool useLoaderPath)
{
+ const QString absFrameworksPath = QFileInfo(bundlePath).absoluteFilePath()
+ + QLatin1String("/Contents/Frameworks");
+ const QString relativeFrameworkPath = QFileInfo(binaryPath).absoluteDir().relativeFilePath(absFrameworksPath);
+ const QString loaderPathToFrameworks = QLatin1String("@loader_path/") + relativeFrameworkPath;
bool rpathToFrameworksFound = false;
QStringList args;
foreach (const QString &rpath, getBinaryRPaths(binaryPath, false)) {
if (rpath == "@executable_path/../Frameworks" ||
- rpath == "@loader_path/../Frameworks") {
+ rpath == loaderPathToFrameworks) {
rpathToFrameworksFound = true;
continue;
}
@@ -760,7 +764,7 @@ void deployRPaths(const QSet<QString> &rpaths, const QString &binaryPath, bool u
if (!useLoaderPath) {
args << "-add_rpath" << "@executable_path/../Frameworks";
} else {
- args << "-add_rpath" << "@loader_path/../Frameworks";
+ args << "-add_rpath" << loaderPathToFrameworks;
}
}
LogDebug() << "Using install_name_tool:";
@@ -769,10 +773,10 @@ void deployRPaths(const QSet<QString> &rpaths, const QString &binaryPath, bool u
runInstallNameTool(QStringList() << args << binaryPath);
}
-void deployRPaths(const QSet<QString> &rpaths, const QStringList &binaryPaths, bool useLoaderPath)
+void deployRPaths(const QString &bundlePath, const QSet<QString> &rpaths, const QStringList &binaryPaths, bool useLoaderPath)
{
foreach (const QString &binary, binaryPaths) {
- deployRPaths(rpaths, binary, useLoaderPath);
+ deployRPaths(bundlePath, rpaths, binary, useLoaderPath);
}
}
@@ -873,7 +877,8 @@ DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks,
}
}
}
- deployRPaths(rpathsUsed, binaryPaths, useLoaderPath);
+ deploymentInfo.deployedFrameworks = copiedFrameworks;
+ deployRPaths(bundlePath, rpathsUsed, binaryPaths, useLoaderPath);
deploymentInfo.rpathsUsed += rpathsUsed;
return deploymentInfo;
}
diff --git a/src/qtdiag/qtdiag.cpp b/src/qtdiag/qtdiag.cpp
index 6af3eccd7..d4e25759d 100644
--- a/src/qtdiag/qtdiag.cpp
+++ b/src/qtdiag/qtdiag.cpp
@@ -313,6 +313,7 @@ QString qtDiag(unsigned flags)
DUMP_CAPABILITY(str, platformIntegration, SyncState)
DUMP_CAPABILITY(str, platformIntegration, RasterGLSurface)
DUMP_CAPABILITY(str, platformIntegration, AllGLFunctionsQueryable)
+ DUMP_CAPABILITY(str, platformIntegration, ApplicationIcon)
str << '\n';
const QStyleHints *styleHints = QGuiApplication::styleHints();
@@ -336,7 +337,13 @@ QString qtDiag(unsigned flags)
<< " fontSmoothingGamma: " << styleHints->fontSmoothingGamma() << '\n'
<< " useRtlExtensions: " << styleHints->useRtlExtensions() << '\n'
<< " setFocusOnTouchRelease: " << styleHints->setFocusOnTouchRelease() << '\n'
- << " tabFocusBehavior: " << formatQDebug(styleHints->tabFocusBehavior()) << '\n';
+ << " tabFocusBehavior: " << formatQDebug(styleHints->tabFocusBehavior()) << '\n'
+ << " singleClickActivation: " << styleHints->singleClickActivation() << '\n';
+ str << "\nAdditional style hints (QPlatformIntegration):\n"
+ << " ShowIsMaximized: "
+ << platformIntegration->styleHint(QPlatformIntegration::ShowIsMaximized).toBool() << '\n'
+ << " ReplayMousePressOutsidePopup: "
+ << platformIntegration->styleHint(QPlatformIntegration::ReplayMousePressOutsidePopup).toBool() << '\n';
const QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme();
str << "\nTheme:\n Styles: " << platformTheme->themeHint(QPlatformTheme::StyleNames).toStringList();
diff --git a/src/windeployqt/main.cpp b/src/windeployqt/main.cpp
index f1b4b39e2..8414a9afe 100644
--- a/src/windeployqt/main.cpp
+++ b/src/windeployqt/main.cpp
@@ -196,8 +196,12 @@ static Platform platformFromMkSpec(const QString &xSpec)
return WinPhoneIntel;
if (xSpec.startsWith(QLatin1String("winphone-arm")))
return WinPhoneArm;
- if (xSpec.startsWith(QLatin1String("wince")))
- return WinCE;
+ if (xSpec.startsWith(QLatin1String("wince"))) {
+ if (xSpec.contains(QLatin1String("-x86-")))
+ return WinCEIntel;
+ if (xSpec.contains(QLatin1String("-arm")))
+ return WinCEArm;
+ }
return UnknownPlatform;
}
@@ -789,7 +793,8 @@ QStringList findQtPlugins(quint64 *usedQtModules, quint64 disabledQtModules,
switch (platform) {
case Windows:
case WindowsMinGW:
- case WinCE:
+ case WinCEIntel:
+ case WinCEArm:
filter = QStringLiteral("qwindows");
break;
case WinRtIntel:
@@ -928,8 +933,10 @@ static QStringList compilerRunTimeLibs(Platform platform, unsigned wordSize)
case WindowsMinGW: { // MinGW: Add runtime libraries
static const char *minGwRuntimes[] = {"*gcc_", "*stdc++", "*winpthread"};
const QString gcc = findInPath(QStringLiteral("g++.exe"));
- if (gcc.isEmpty())
+ if (gcc.isEmpty()) {
+ std::wcerr << "Warning: Cannot find GCC installation directory. g++.exe must be in the path.\n";
break;
+ }
const QString binPath = QFileInfo(gcc).absolutePath();
QDir dir(binPath);
QStringList filters;
@@ -1179,13 +1186,14 @@ static DeployResult deploy(const Options &options,
}
// Check for ANGLE on the Qt5Gui library.
- if ((options.platform & WindowsBased) && !qtGuiLibrary.isEmpty()) {
+ if ((options.platform & WindowsBased) && options.platform != WinCEIntel
+ && options.platform != WinCEArm && !qtGuiLibrary.isEmpty()) {
QString libGlesName = QStringLiteral("libGLESV2");
if (isDebug)
libGlesName += QLatin1Char('d');
libGlesName += QLatin1String(windowsSharedLibrarySuffix);
const QStringList guiLibraries = findDependentLibraries(qtGuiLibrary, options.platform, errorMessage);
- const bool dependsOnAngle = !guiLibraries.filter(libGlesName, Qt::CaseInsensitive).isEmpty() && !(options.platform & WinCE);
+ const bool dependsOnAngle = !guiLibraries.filter(libGlesName, Qt::CaseInsensitive).isEmpty();
const bool dependsOnOpenGl = !guiLibraries.filter(QStringLiteral("opengl32"), Qt::CaseInsensitive).isEmpty();
if (options.angleDetection != Options::AngleDetectionForceOff
&& (dependsOnAngle || !dependsOnOpenGl || options.angleDetection == Options::AngleDetectionForceOn)) {
diff --git a/src/windeployqt/utils.cpp b/src/windeployqt/utils.cpp
index 081c9c475..e7a755500 100644
--- a/src/windeployqt/utils.cpp
+++ b/src/windeployqt/utils.cpp
@@ -35,6 +35,8 @@
#include "elfreader.h"
#include <QtCore/QString>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QTemporaryFile>
@@ -723,6 +725,52 @@ inline QStringList readImportSections(const ImageNtHeader *ntHeaders, const void
return result;
}
+// Check for MSCV runtime (MSVCP90D.dll/MSVCP90.dll, MSVCP120D.dll/MSVCP120.dll
+// or msvcp120d_app.dll/msvcp120_app.dll).
+enum MsvcDebugRuntimeResult { MsvcDebugRuntime, MsvcReleaseRuntime, NoMsvcRuntime };
+
+static inline MsvcDebugRuntimeResult checkMsvcDebugRuntime(const QStringList &dependentLibraries)
+{
+ foreach (const QString &lib, dependentLibraries) {
+ if (lib.startsWith(QLatin1String("MSVCR"), Qt::CaseInsensitive)
+ || lib.startsWith(QLatin1String("MSVCP"), Qt::CaseInsensitive)) {
+ int pos = 5;
+ if (lib.at(pos).isDigit()) {
+ for (++pos; lib.at(pos).isDigit(); ++pos)
+ ;
+ return lib.at(pos).toLower() == QLatin1Char('d')
+ ? MsvcDebugRuntime : MsvcReleaseRuntime;
+ }
+ }
+ }
+ return NoMsvcRuntime;
+}
+
+template <class ImageNtHeader>
+inline void determineDebugAndDependentLibs(const ImageNtHeader *nth, const void *fileMemory,
+ bool isMinGW,
+ QStringList *dependentLibrariesIn,
+ bool *isDebugIn, QString *errorMessage)
+{
+ const bool hasDebugEntry = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+ QStringList dependentLibraries;
+ if (dependentLibrariesIn || (isDebugIn && hasDebugEntry && !isMinGW))
+ dependentLibraries = readImportSections(nth, fileMemory, errorMessage);
+
+ if (dependentLibrariesIn)
+ *dependentLibrariesIn = dependentLibraries;
+ if (isDebugIn) {
+ if (isMinGW) {
+ // Use logic that's used e.g. in objdump / pfd library
+ *isDebugIn = !(nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED);
+ } else {
+ // When an MSVC debug entry is present, check whether the debug runtime
+ // is actually used to detect -release / -force-debug-info builds.
+ *isDebugIn = hasDebugEntry && checkMsvcDebugRuntime(dependentLibraries) != MsvcReleaseRuntime;
+ }
+ }
+}
+
// Read a PE executable and determine dependent libraries, word size
// and debug flags.
bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage,
@@ -769,40 +817,31 @@ bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage
const unsigned wordSize = ntHeaderWordSize(ntHeaders);
if (wordSizeIn)
*wordSizeIn = wordSize;
- bool debug = false;
if (wordSize == 32) {
- const IMAGE_NT_HEADERS32 *ntHeaders32 = reinterpret_cast<const IMAGE_NT_HEADERS32 *>(ntHeaders);
-
- if (!isMinGW) {
- debug = ntHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
- } else {
- // Use logic that's used e.g. in objdump / pfd library
- debug = !(ntHeaders32->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED);
- }
-
- if (dependentLibrariesIn)
- *dependentLibrariesIn = readImportSections(ntHeaders32, fileMemory, errorMessage);
-
+ determineDebugAndDependentLibs(reinterpret_cast<const IMAGE_NT_HEADERS32 *>(ntHeaders),
+ fileMemory, isMinGW, dependentLibrariesIn, isDebugIn, errorMessage);
} else {
- const IMAGE_NT_HEADERS64 *ntHeaders64 = reinterpret_cast<const IMAGE_NT_HEADERS64 *>(ntHeaders);
-
- if (!isMinGW) {
- debug = ntHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
- } else {
- // Use logic that's used e.g. in objdump / pfd library
- debug = !(ntHeaders64->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED);
- }
-
- if (dependentLibrariesIn)
- *dependentLibrariesIn = readImportSections(ntHeaders64, fileMemory, errorMessage);
+ determineDebugAndDependentLibs(reinterpret_cast<const IMAGE_NT_HEADERS64 *>(ntHeaders),
+ fileMemory, isMinGW, dependentLibrariesIn, isDebugIn, errorMessage);
}
- if (isDebugIn)
- *isDebugIn = debug;
result = true;
- if (optVerboseLevel > 1)
- std::wcout << __FUNCTION__ << ": " << peExecutableFileName
- << ' ' << wordSize << " bit, debug: " << debug << '\n';
+ if (optVerboseLevel > 1) {
+ std::wcout << __FUNCTION__ << ": " << QDir::toNativeSeparators(peExecutableFileName)
+ << ' ' << wordSize << " bit";
+ if (isMinGW)
+ std::wcout << ", MinGW";
+ if (dependentLibrariesIn) {
+ std::wcout << ", dependent libraries: ";
+ if (optVerboseLevel > 2)
+ std::wcout << dependentLibrariesIn->join(QLatin1Char(' '));
+ else
+ std::wcout << dependentLibrariesIn->size();
+ }
+ if (isDebugIn)
+ std::wcout << (*isDebugIn ? ", debug" : ", release");
+ std::wcout << '\n';
+ }
} while (false);
if (fileMemory)
diff --git a/src/windeployqt/utils.h b/src/windeployqt/utils.h
index 76e003abc..e7c2776a9 100644
--- a/src/windeployqt/utils.h
+++ b/src/windeployqt/utils.h
@@ -62,7 +62,8 @@ enum Platform {
WinRtArm = WindowsBased + ArmBased + 2,
WinPhoneIntel = WindowsBased + IntelBased + 3,
WinPhoneArm = WindowsBased + ArmBased + 4,
- WinCE = WindowsBased + ArmBased + 5,
+ WinCEIntel = WindowsBased + IntelBased + 5,
+ WinCEArm = WindowsBased + ArmBased + 6,
Unix = UnixBased,
UnknownPlatform
};
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index a703a0609..20b5fec90 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -8,7 +8,8 @@ SUBDIRS=\
qhelpprojectdata \
cmake \
installed_cmake \
- qtdiag
+ qtdiag \
+ windeployqt
installed_cmake.depends = cmake
@@ -24,3 +25,4 @@ cross_compile:SUBDIRS -= linguist
qhelpprojectdata \
android|ios|qnx|wince*|winrt*:SUBDIRS -= qtdiag
+!win32|wince*|winrt*:SUBDIRS -= windeployqt
diff --git a/tests/auto/windeployqt/test/test.pro b/tests/auto/windeployqt/test/test.pro
new file mode 100644
index 000000000..7aac19a0d
--- /dev/null
+++ b/tests/auto/windeployqt/test/test.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+QT = core testlib
+DESTDIR = ..
+TARGET = tst_windeployqt
+SOURCES += ../tst_windeployqt.cpp
diff --git a/tests/auto/windeployqt/testapp/main.cpp b/tests/auto/windeployqt/testapp/main.cpp
new file mode 100644
index 000000000..4655408ba
--- /dev/null
+++ b/tests/auto/windeployqt/testapp/main.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QRasterWindow>
+#include <QScreen>
+#include <QTimer>
+
+// Simple test application just to verify that it comes up properly
+
+int main(int argc, char ** argv)
+{
+ QGuiApplication app(argc, argv);
+ QRasterWindow w;
+ w.setTitle("windeployqt test application");
+ const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
+ w.resize(availableGeometry.size() / 4);
+ w.show();
+ QTimer::singleShot(200, &w, &QCoreApplication::quit);
+ return app.exec();
+}
diff --git a/tests/auto/windeployqt/testapp/testapp.pro b/tests/auto/windeployqt/testapp/testapp.pro
new file mode 100644
index 000000000..7bd2fba0e
--- /dev/null
+++ b/tests/auto/windeployqt/testapp/testapp.pro
@@ -0,0 +1,2 @@
+SOURCES = main.cpp
+DESTDIR = ./
diff --git a/tests/auto/windeployqt/tst_windeployqt.cpp b/tests/auto/windeployqt/tst_windeployqt.cpp
new file mode 100644
index 000000000..4acea454f
--- /dev/null
+++ b/tests/auto/windeployqt/tst_windeployqt.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QProcess>
+#include <QtCore/QProcessEnvironment>
+#include <QtCore/QStandardPaths>
+#include <QtCore/QTextStream>
+#include <QtTest/QtTest>
+
+#ifndef QT_NO_PROCESS
+static const QString msgProcessError(const QProcess &process, const QString &what)
+{
+ QString result;
+ QTextStream(&result) << what << ": \"" << process.program() << ' '
+ << process.arguments().join(QLatin1Char(' ')) << "\": " << process.errorString();
+ return result;
+}
+
+static bool runProcess(const QString &binary,
+ const QStringList &arguments,
+ QString *errorMessage,
+ const QString &workingDir = QString(),
+ const QProcessEnvironment &env = QProcessEnvironment(),
+ int timeOut = 5000,
+ QByteArray *stdOut = Q_NULLPTR, QByteArray *stdErr = Q_NULLPTR)
+{
+ QProcess process;
+ if (!env.isEmpty())
+ process.setProcessEnvironment(env);
+ if (!workingDir.isEmpty())
+ process.setWorkingDirectory(workingDir);
+ qDebug().noquote().nospace() << "Running: " << QDir::toNativeSeparators(binary)
+ << ' ' << arguments.join(QLatin1Char(' '));
+ process.start(binary, arguments, QIODevice::ReadOnly);
+ if (!process.waitForStarted()) {
+ *errorMessage = msgProcessError(process, "Failed to start");
+ return false;
+ }
+ if (!process.waitForFinished(timeOut)) {
+ *errorMessage = msgProcessError(process, "Timed out");
+ process.terminate();
+ if (!process.waitForFinished(300))
+ process.kill();
+ return false;
+ }
+ if (stdOut)
+ *stdOut = process.readAllStandardOutput();
+ if (stdErr)
+ *stdErr= process.readAllStandardError();
+ if (process.exitStatus() != QProcess::NormalExit) {
+ *errorMessage = msgProcessError(process, "Crashed");
+ return false;
+ }
+ if (process.exitCode() != QProcess::NormalExit) {
+ *errorMessage = msgProcessError(process, "Exit code " + QString::number(process.exitCode()));
+ return false;
+ }
+ return true;
+}
+
+#endif // !QT_NO_PROCESS
+
+class tst_windeployqt : public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase();
+ void help();
+ void deploy();
+
+private:
+ QString m_windeployqtBinary;
+ QString m_testApp;
+ QString m_testAppBinary;
+};
+
+void tst_windeployqt::initTestCase()
+{
+#ifdef QT_NO_PROCESS
+ QSKIP("This test requires QProcess support");
+#else
+ m_windeployqtBinary = QStandardPaths::findExecutable("windeployqt");
+ QVERIFY(!m_windeployqtBinary.isEmpty());
+ m_testApp = QFINDTESTDATA("testapp");
+ QVERIFY(!m_testApp.isEmpty());
+ const QFileInfo testAppBinary(m_testApp + QLatin1String("/testapp.exe"));
+ QVERIFY2(testAppBinary.isFile(), qPrintable(testAppBinary.absoluteFilePath()));
+ m_testAppBinary = testAppBinary.absoluteFilePath();
+#endif // QT_NO_PROCESS
+}
+
+void tst_windeployqt::help()
+{
+#ifdef QT_NO_PROCESS
+ QSKIP("This test requires QProcess support");
+#else
+ QString errorMessage;
+ QByteArray stdOut;
+ QByteArray stdErr;
+ QVERIFY2(runProcess(m_windeployqtBinary, QStringList("--help"), &errorMessage,
+ QString(), QProcessEnvironment(), 5000, &stdOut, &stdErr),
+ qPrintable(errorMessage));
+ QVERIFY2(!stdOut.isEmpty(), stdErr);
+#endif // QT_NO_PROCESS
+}
+
+// deploy(): Deploys the test application and launches it with Qt removed from the environment
+// to verify it runs stand-alone.
+
+void tst_windeployqt::deploy()
+{
+#ifdef QT_NO_PROCESS
+ QSKIP("This test requires QProcess support");
+#else
+ QString errorMessage;
+ // Deploy application
+ QStringList deployArguments;
+ deployArguments << QLatin1String("--no-translations") << QDir::toNativeSeparators(m_testAppBinary);
+ QVERIFY2(runProcess(m_windeployqtBinary, deployArguments, &errorMessage, QString(), QProcessEnvironment(), 20000),
+ qPrintable(errorMessage));
+
+ // Create environment with Qt and all "lib" paths removed.
+ const QString qtBinDir = QDir::toNativeSeparators(QLibraryInfo::location(QLibraryInfo::BinariesPath));
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ const QString pathKey = QLatin1String("PATH");
+ const QChar pathSeparator(QLatin1Char(';')); // ### fixme: Qt 5.6: QDir::listSeparator()
+ const QString origPath = env.value(pathKey);
+ QString newPath;
+ foreach (const QString &pathElement, origPath.split(pathSeparator, QString::SkipEmptyParts)) {
+ if (pathElement.compare(qtBinDir, Qt::CaseInsensitive)
+ && !pathElement.contains(QLatin1String("\\lib"), Qt::CaseInsensitive)) {
+ if (!newPath.isEmpty())
+ newPath.append(pathSeparator);
+ newPath.append(pathElement);
+ }
+ }
+ if (newPath == origPath)
+ qWarning() << "Unable to remove Qt from PATH";
+ env.insert(pathKey, newPath);
+
+ // Create qt.conf to enforce usage of local plugins
+ QFile qtConf(QFileInfo(m_testAppBinary).absolutePath() + QLatin1String("/qt.conf"));
+ QVERIFY2(qtConf.open(QIODevice::WriteOnly | QIODevice::Text),
+ qPrintable(qtConf.fileName() + QLatin1String(": ") + qtConf.errorString()));
+ QVERIFY(qtConf.write("[Paths]\nPrefix = .\n"));
+ qtConf.close();
+
+ // Verify that application still runs
+ QVERIFY2(runProcess(m_testAppBinary, QStringList(), &errorMessage, QString(), env, 10000),
+ qPrintable(errorMessage));
+#endif // QT_NO_PROCESS
+}
+
+QTEST_MAIN(tst_windeployqt)
+#include "tst_windeployqt.moc"
diff --git a/tests/auto/windeployqt/windeployqt.pro b/tests/auto/windeployqt/windeployqt.pro
new file mode 100644
index 000000000..0ae9b2bab
--- /dev/null
+++ b/tests/auto/windeployqt/windeployqt.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS = testapp test
+CONFIG += ordered