Source

Target

Commits (7)
Showing with 106 additions and 29 deletions
...@@ -1697,25 +1697,53 @@ bool copyQtFiles(Options *options) ...@@ -1697,25 +1697,53 @@ bool copyQtFiles(Options *options)
return true; return true;
} }
QStringList getLibraryProjectsInOutputFolder(const Options &options)
{
QStringList ret;
QFile file(options.outputDirectory + QLatin1String("/project.properties"));
if (file.open(QIODevice::ReadOnly)) {
while (!file.atEnd()) {
QByteArray line = file.readLine().trimmed();
if (line.startsWith("android.library.reference")) {
int equalSignIndex = line.indexOf('=');
if (equalSignIndex >= 0) {
QString path = QString::fromLocal8Bit(line.mid(equalSignIndex + 1));
QFileInfo info(options.outputDirectory + QLatin1Char('/') + path);
if (QDir::isRelativePath(path)
&& info.exists()
&& info.isDir()
&& info.canonicalFilePath().startsWith(options.outputDirectory)) {
ret += info.canonicalFilePath();
}
}
}
}
}
return ret;
}
bool createAndroidProject(const Options &options) bool createAndroidProject(const Options &options)
{ {
if (options.verbose) if (options.verbose)
fprintf(stdout, "Running Android tool to create package definition.\n"); fprintf(stdout, "Running Android tool to create package definition.\n");
QString androidTool = options.sdkPath + QLatin1String("/tools/android"); QString androidToolExecutable = options.sdkPath + QLatin1String("/tools/android");
#if defined(Q_OS_WIN32) #if defined(Q_OS_WIN32)
androidTool += QLatin1String(".bat"); androidToolExecutable += QLatin1String(".bat");
#endif #endif
if (!QFile::exists(androidTool)) { if (!QFile::exists(androidToolExecutable)) {
fprintf(stderr, "Cannot find Android tool: %s\n", qPrintable(androidTool)); fprintf(stderr, "Cannot find Android tool: %s\n", qPrintable(androidToolExecutable));
return false; return false;
} }
androidTool = QString::fromLatin1("%1 update project --path %2 --target %3 --name QtApp") QString androidTool = QString::fromLatin1("%1 update project --path %2 --target %3 --name QtApp")
.arg(shellQuote(androidTool)) .arg(shellQuote(androidToolExecutable))
.arg(shellQuote(options.outputDirectory)) .arg(shellQuote(options.outputDirectory))
.arg(shellQuote(options.androidPlatform)); .arg(shellQuote(options.androidPlatform));
if (options.verbose) if (options.verbose)
fprintf(stdout, " -- Command: %s\n", qPrintable(androidTool)); fprintf(stdout, " -- Command: %s\n", qPrintable(androidTool));
...@@ -1728,6 +1756,29 @@ bool createAndroidProject(const Options &options) ...@@ -1728,6 +1756,29 @@ bool createAndroidProject(const Options &options)
pclose(androidToolCommand); pclose(androidToolCommand);
// If the project has subprojects inside the current folder, we need to also run android update on these.
QStringList libraryProjects = getLibraryProjectsInOutputFolder(options);
foreach (QString libraryProject, libraryProjects) {
if (options.verbose)
fprintf(stdout, "Updating subproject %s\n", qPrintable(libraryProject));
androidTool = QString::fromLatin1("%1 update lib-project --path %2 --target %3")
.arg(shellQuote(androidToolExecutable))
.arg(shellQuote(libraryProject))
.arg(shellQuote(options.androidPlatform));
if (options.verbose)
fprintf(stdout, " -- Command: %s\n", qPrintable(androidTool));
FILE *androidToolCommand = popen(androidTool.toLocal8Bit().constData(), "r");
if (androidToolCommand == 0) {
fprintf(stderr, "Cannot run command '%s'\n", qPrintable(androidTool));
return false;
}
pclose(androidToolCommand);
}
return true; return true;
} }
......
...@@ -172,13 +172,6 @@ void dumpGlInfo(QTextStream &str, bool listExtensions) ...@@ -172,13 +172,6 @@ void dumpGlInfo(QTextStream &str, bool listExtensions)
#endif // !QT_NO_OPENGL #endif // !QT_NO_OPENGL
static QStringList toNativeSeparators(QStringList in)
{
for (int i = 0; i < in.size(); ++i)
in[i] = QDir::toNativeSeparators(in.at(i));
return in;
}
#define DUMP_CAPABILITY(str, integration, capability) \ #define DUMP_CAPABILITY(str, integration, capability) \
if (platformIntegration->hasCapability(QPlatformIntegration::capability)) \ if (platformIntegration->hasCapability(QPlatformIntegration::capability)) \
str << ' ' << #capability; str << ' ' << #capability;
...@@ -243,7 +236,7 @@ QString qtDiag(unsigned flags) ...@@ -243,7 +236,7 @@ QString qtDiag(unsigned flags)
DUMP_LIBRARYPATH(str, ExamplesPath) DUMP_LIBRARYPATH(str, ExamplesPath)
DUMP_LIBRARYPATH(str, TestsPath) DUMP_LIBRARYPATH(str, TestsPath)
str << "\nStandard paths:\n"; str << "\nStandard paths [*...* denote writable entry]:\n";
DUMP_STANDARDPATH(str, DesktopLocation) DUMP_STANDARDPATH(str, DesktopLocation)
DUMP_STANDARDPATH(str, DocumentsLocation) DUMP_STANDARDPATH(str, DocumentsLocation)
DUMP_STANDARDPATH(str, FontsLocation) DUMP_STANDARDPATH(str, FontsLocation)
...@@ -312,7 +305,7 @@ QString qtDiag(unsigned flags) ...@@ -312,7 +305,7 @@ QString qtDiag(unsigned flags)
if (passwordMaskCharacter.unicode() >= 32 && passwordMaskCharacter.unicode() < 128) if (passwordMaskCharacter.unicode() >= 32 && passwordMaskCharacter.unicode() < 128)
str << '\'' << passwordMaskCharacter << '\''; str << '\'' << passwordMaskCharacter << '\'';
else else
str << hex << showbase << passwordMaskCharacter.unicode() << noshowbase << dec; str << "U+" << qSetFieldWidth(4) << qSetPadChar('0') << uppercasedigits << hex << passwordMaskCharacter.unicode() << dec << qSetFieldWidth(0);
str << '\n' str << '\n'
<< " fontSmoothingGamma: " << styleHints->fontSmoothingGamma() << '\n' << " fontSmoothingGamma: " << styleHints->fontSmoothingGamma() << '\n'
<< " useRtlExtensions: " << styleHints->useRtlExtensions() << '\n' << " useRtlExtensions: " << styleHints->useRtlExtensions() << '\n'
...@@ -331,7 +324,7 @@ QString qtDiag(unsigned flags) ...@@ -331,7 +324,7 @@ QString qtDiag(unsigned flags)
str << " General font : " << QFontDatabase::systemFont(QFontDatabase::GeneralFont) << '\n' str << " General font : " << QFontDatabase::systemFont(QFontDatabase::GeneralFont) << '\n'
<< " Fixed font : " << QFontDatabase::systemFont(QFontDatabase::FixedFont) << '\n' << " Fixed font : " << QFontDatabase::systemFont(QFontDatabase::FixedFont) << '\n'
<< " Title font : " << QFontDatabase::systemFont(QFontDatabase::TitleFont) << '\n' << " Title font : " << QFontDatabase::systemFont(QFontDatabase::TitleFont) << '\n'
<< " Smallest font: " << QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont) << "\n\n"; << " Smallest font: " << QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont) << '\n';
if (platformTheme->usePlatformNativeDialog(QPlatformTheme::FileDialog)) if (platformTheme->usePlatformNativeDialog(QPlatformTheme::FileDialog))
str << " Native file dialog\n"; str << " Native file dialog\n";
...@@ -345,9 +338,9 @@ QString qtDiag(unsigned flags) ...@@ -345,9 +338,9 @@ QString qtDiag(unsigned flags)
str << "\nScreens: " << screenCount << '\n'; str << "\nScreens: " << screenCount << '\n';
for (int s = 0; s < screenCount; ++s) { for (int s = 0; s < screenCount; ++s) {
const QScreen *screen = screens.at(s); const QScreen *screen = screens.at(s);
str << (screen == QGuiApplication::primaryScreen() ? '*' : ' ') str << '#' << ' ' << s << " \"" << screen->name() << '"'
<< '#' << ' ' << s << " \"" << screen->name() << '"'
<< " Depth: " << screen->depth() << " Depth: " << screen->depth()
<< " Primary: " << (screen == QGuiApplication::primaryScreen() ? "yes" : "no")
<< "\n Geometry: " << screen->geometry() << " Available: " << screen->availableGeometry(); << "\n Geometry: " << screen->geometry() << " Available: " << screen->availableGeometry();
if (screen->geometry() != screen->virtualGeometry()) if (screen->geometry() != screen->virtualGeometry())
str << "\n Virtual geometry: " << screen->virtualGeometry() << " Available: " << screen->availableVirtualGeometry(); str << "\n Virtual geometry: " << screen->virtualGeometry() << " Available: " << screen->availableVirtualGeometry();
......
...@@ -571,14 +571,23 @@ private: ...@@ -571,14 +571,23 @@ private:
// QML import trees: DLLs (matching debgug) and .qml/,js, etc. // QML import trees: DLLs (matching debgug) and .qml/,js, etc.
class QmlDirectoryFileEntryFunction { class QmlDirectoryFileEntryFunction {
public: public:
explicit QmlDirectoryFileEntryFunction(Platform platform, bool debug) explicit QmlDirectoryFileEntryFunction(Platform platform, bool debug, bool skipQmlSources = false)
: m_qmlNameFilter(QStringList() << QStringLiteral("*.js") << QStringLiteral("qmldir") << QStringLiteral("*.qml") << QStringLiteral("*.qmltypes") << QStringLiteral("*.png")) : m_qmlNameFilter(QmlDirectoryFileEntryFunction::qmlNameFilters(skipQmlSources))
, m_dllFilter(platform, debug) , m_dllFilter(platform, debug)
{} {}
QStringList operator()(const QDir &dir) const { return m_dllFilter(dir) + m_qmlNameFilter(dir); } QStringList operator()(const QDir &dir) const { return m_dllFilter(dir) + m_qmlNameFilter(dir); }
private: private:
static inline QStringList qmlNameFilters(bool skipQmlSources)
{
QStringList result;
result << QStringLiteral("qmldir") << QStringLiteral("*.qmltypes");
if (!skipQmlSources)
result << QStringLiteral("*.js") << QStringLiteral("*.qml") << QStringLiteral("*.png");
return result;
}
NameFilterFileEntryFunction m_qmlNameFilter; NameFilterFileEntryFunction m_qmlNameFilter;
DllDirectoryFileEntryFunction m_dllFilter; DllDirectoryFileEntryFunction m_dllFilter;
}; };
...@@ -1048,7 +1057,14 @@ static DeployResult deploy(const Options &options, ...@@ -1048,7 +1057,14 @@ static DeployResult deploy(const Options &options,
<< QDir::toNativeSeparators(installPath) << '\n'; << QDir::toNativeSeparators(installPath) << '\n';
if (installPath != options.directory && !createDirectory(installPath, errorMessage)) if (installPath != options.directory && !createDirectory(installPath, errorMessage))
return result; return result;
if (!updateFile(module.sourcePath, qmlFileEntryFunction, installPath, options.updateFileFlags, options.json, errorMessage)) const bool updateResult = module.sourcePath.contains(QLatin1String("QtQuick/Controls"))
|| module.sourcePath.contains(QLatin1String("QtQuick/Dialogs")) ?
updateFile(module.sourcePath, QmlDirectoryFileEntryFunction(options.platform, isDebug, true),
installPath, options.updateFileFlags | RemoveEmptyQmlDirectories,
options.json, errorMessage) :
updateFile(module.sourcePath, qmlFileEntryFunction, installPath, options.updateFileFlags,
options.json, errorMessage);
if (!updateResult)
return result; return result;
} }
} // Quick 2 } // Quick 2
......
...@@ -872,7 +872,7 @@ QString findD3dCompiler(Platform platform, const QString &qtBinDir, unsigned wor ...@@ -872,7 +872,7 @@ QString findD3dCompiler(Platform platform, const QString &qtBinDir, unsigned wor
#else // Q_OS_WIN #else // Q_OS_WIN
bool readPeExecutable(const QString &, QString *errorMessage, bool readPeExecutable(const QString &, QString *errorMessage,
QStringList *, unsigned *, bool *) QStringList *, unsigned *, bool *, bool)
{ {
*errorMessage = QStringLiteral("Not implemented."); *errorMessage = QStringLiteral("Not implemented.");
return false; return false;
......
...@@ -201,7 +201,8 @@ extern int optVerboseLevel; ...@@ -201,7 +201,8 @@ extern int optVerboseLevel;
// to obtain the files. // to obtain the files.
enum UpdateFileFlag { enum UpdateFileFlag {
ForceUpdateFile = 0x1, ForceUpdateFile = 0x1,
SkipUpdateFile = 0x2 SkipUpdateFile = 0x2,
RemoveEmptyQmlDirectories = 0x4
}; };
template <class DirectoryFileEntryFunction> template <class DirectoryFileEntryFunction>
...@@ -257,6 +258,7 @@ bool updateFile(const QString &sourceFileName, ...@@ -257,6 +258,7 @@ bool updateFile(const QString &sourceFileName,
} // Source is symbolic link } // Source is symbolic link
if (sourceFileInfo.isDir()) { if (sourceFileInfo.isDir()) {
bool created = false;
if (targetFileInfo.exists()) { if (targetFileInfo.exists()) {
if (!targetFileInfo.isDir()) { if (!targetFileInfo.isDir()) {
*errorMessage = QString::fromLatin1("%1 already exists and is not a directory.") *errorMessage = QString::fromLatin1("%1 already exists and is not a directory.")
...@@ -267,10 +269,13 @@ bool updateFile(const QString &sourceFileName, ...@@ -267,10 +269,13 @@ bool updateFile(const QString &sourceFileName,
QDir d(targetDirectory); QDir d(targetDirectory);
if (optVerboseLevel) if (optVerboseLevel)
std::wcout << "Creating " << targetFileName << ".\n"; std::wcout << "Creating " << targetFileName << ".\n";
if (!(flags & SkipUpdateFile) && !d.mkdir(sourceFileInfo.fileName())) { if (!(flags & SkipUpdateFile)) {
*errorMessage = QString::fromLatin1("Cannot create directory %1 under %2.") created = d.mkdir(sourceFileInfo.fileName());
.arg(sourceFileInfo.fileName(), QDir::toNativeSeparators(targetDirectory)); if (!created) {
return false; *errorMessage = QString::fromLatin1("Cannot create directory %1 under %2.")
.arg(sourceFileInfo.fileName(), QDir::toNativeSeparators(targetDirectory));
return false;
}
} }
} }
// Recurse into directory // Recurse into directory
...@@ -280,6 +285,18 @@ bool updateFile(const QString &sourceFileName, ...@@ -280,6 +285,18 @@ bool updateFile(const QString &sourceFileName,
foreach (const QString &entry, allEntries) foreach (const QString &entry, allEntries)
if (!updateFile(sourceFileName + QLatin1Char('/') + entry, directoryFileEntryFunction, targetFileName, flags, json, errorMessage)) if (!updateFile(sourceFileName + QLatin1Char('/') + entry, directoryFileEntryFunction, targetFileName, flags, json, errorMessage))
return false; return false;
// Remove empty directories, for example QML import folders for which the filter did not match.
if (created && (flags & RemoveEmptyQmlDirectories)) {
QDir d(targetFileName);
const QStringList entries = d.entryList(QStringList(), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
if (entries.isEmpty() || (entries.size() == 1 && entries.first() == QLatin1String("qmldir"))) {
if (!d.removeRecursively()) {
*errorMessage = QString::fromLatin1("Cannot remove empty directory %1.")
.arg(QDir::toNativeSeparators(targetFileName));
return false;
}
}
}
return true; return true;
} // Source is directory. } // Source is directory.
......