diff options
author | Liang Qi <liang.qi@qt.io> | 2017-04-20 11:19:14 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2017-04-20 12:31:27 +0200 |
commit | 7950b6b283549c98f1e0f981c84b68071a13b616 (patch) | |
tree | cf7281872045ebd57c68e10064ff0f400084aa13 /qmake | |
parent | 58d2927861d3e57cac4f6db599e209d2bfb17a2c (diff) | |
parent | 0794d61c822585530243f638687b8a75f0a15d0c (diff) |
Merge remote-tracking branch 'origin/5.9' into dev
Conflicts:
src/corelib/tools/qbytearray.h
src/corelib/tools/qdatetime.h
src/corelib/tools/qstring.h
src/corelib/tools/qversionnumber.h
src/plugins/platforms/android/qandroidplatformintegration.cpp
tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
Change-Id: Iefd92a435e687a76cd593099e40d9a9620a1454d
Diffstat (limited to 'qmake')
-rw-r--r-- | qmake/generators/makefile.cpp | 36 | ||||
-rw-r--r-- | qmake/generators/unix/unixmake.cpp | 30 | ||||
-rw-r--r-- | qmake/generators/unix/unixmake2.cpp | 70 | ||||
-rw-r--r-- | qmake/generators/win32/winmakefile.cpp | 2 | ||||
-rw-r--r-- | qmake/library/ioutils.cpp | 70 | ||||
-rw-r--r-- | qmake/library/ioutils.h | 3 | ||||
-rw-r--r-- | qmake/library/qmakebuiltins.cpp | 60 | ||||
-rw-r--r-- | qmake/main.cpp | 70 | ||||
-rw-r--r-- | qmake/option.cpp | 4 |
9 files changed, 230 insertions, 115 deletions
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 2845888dde..4568f1d4f2 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -1292,9 +1292,9 @@ MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild) if (fi.isDir()) cmd = "-$(INSTALL_DIR)"; else if (is_target || fi.isExecutable()) - cmd = "-$(INSTALL_PROGRAM)"; + cmd = "-$(QINSTALL_PROGRAM)"; else - cmd = "-$(INSTALL_FILE)"; + cmd = "-$(QINSTALL_FILE)"; cmd += " " + escapeFilePath(wild) + " " + escapeFilePath(dst_file); inst << cmd; if (!project->isActiveConfig("debug_info") && !project->isActiveConfig("nostrip") && @@ -1318,9 +1318,9 @@ MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild) dst_file += filestr; } } else if (installConfigValues.contains("executable")) { - cmd = QLatin1String("-$(INSTALL_PROGRAM)"); + cmd = QLatin1String("-$(QINSTALL_PROGRAM)"); } else { - cmd = QLatin1String("-$(INSTALL_FILE)"); + cmd = QLatin1String("-$(QINSTALL_FILE)"); } cmd += " " + escapeFilePath(wild) + " " + escapeFilePath(dst_file); inst << cmd; @@ -1336,7 +1336,7 @@ MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild) dst_file += Option::dir_sep; dst_file += fi.fileName(); } - QString cmd = QString(fi.isDir() ? "-$(INSTALL_DIR)" : "-$(INSTALL_FILE)") + " " + + QString cmd = QString(fi.isDir() ? "-$(INSTALL_DIR)" : "-$(QINSTALL_FILE)") + " " + escapeFilePath(dirstr + file) + " " + escapeFilePath(dst_file); inst << cmd; if (!project->isActiveConfig("debug_info") && !project->isActiveConfig("nostrip") && @@ -2248,6 +2248,8 @@ MakefileGenerator::writeDefaultVariables(QTextStream &t) t << "INSTALL_FILE = " << var("QMAKE_INSTALL_FILE") << endl; t << "INSTALL_PROGRAM = " << var("QMAKE_INSTALL_PROGRAM") << endl; t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << endl; + t << "QINSTALL_FILE = " << var("QMAKE_QMAKE") << " -install qinstall file" << endl; + t << "QINSTALL_PROGRAM = " << var("QMAKE_QMAKE") << " -install qinstall program" << endl; t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; t << "SYMLINK = " << var("QMAKE_SYMBOLIC_LINK") << endl; t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; @@ -3310,19 +3312,19 @@ MakefileGenerator::writePkgConfigFile() } t << shellQuote(pkgConfiglibName) << " \n"; - ProStringList libs; - if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS")) { - libs = project->values("QMAKE_INTERNAL_PRL_LIBS"); - } else { - libs << "QMAKE_LIBS"; //obvious one - } - libs << "QMAKE_LIBS_PRIVATE"; - libs << "QMAKE_LFLAGS_THREAD"; //not sure about this one, but what about things like -pthread? - t << "Libs.private: "; - for (ProStringList::ConstIterator it = libs.begin(); it != libs.end(); ++it) { - t << fixLibFlags((*it).toKey()).join(' ') << ' '; + if (project->isActiveConfig("staticlib")) { + ProStringList libs; + if (!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS")) + libs = project->values("QMAKE_INTERNAL_PRL_LIBS"); + else + libs << "QMAKE_LIBS"; //obvious one + libs << "QMAKE_LIBS_PRIVATE"; + libs << "QMAKE_LFLAGS_THREAD"; //not sure about this one, but what about things like -pthread? + t << "Libs.private:"; + for (ProStringList::ConstIterator it = libs.begin(); it != libs.end(); ++it) + t << ' ' << fixLibFlags((*it).toKey()).join(' '); + t << endl; } - t << endl; // flags // ### too many diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 794d04a6e9..1073386a82 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -180,6 +180,13 @@ UnixMakefileGenerator::init() // icc style pchFlags.replace(QLatin1String("${QMAKE_PCH_OUTPUT}"), escapeFilePath(pchBaseName + project->first("QMAKE_PCH_OUTPUT_EXT"))); + const ProStringList pchArchs = project->values("QMAKE_PCH_ARCHS"); + for (const ProString &arch : pchArchs) { + QString suffix = project->first("QMAKE_PCH_OUTPUT_EXT").toQString(); + suffix.replace(QLatin1String("${QMAKE_PCH_ARCH}"), arch.toQString()); + pchFlags.replace(QLatin1String("${QMAKE_PCH_OUTPUT_") + arch + QLatin1Char('}'), + escapeFilePath(pchBaseName + suffix)); + } } else { // gcc style (including clang_pch_style) QString headerSuffix; @@ -334,10 +341,19 @@ QStringList header_prefix += project->first("QMAKE_PCH_OUTPUT_EXT").toQString(); if (project->isActiveConfig("icc_pch_style")) { // icc style - for(QStringList::Iterator it = Option::cpp_ext.begin(); it != Option::cpp_ext.end(); ++it) { - if(file.endsWith(*it)) { - ret += header_prefix; - break; + ProStringList pchArchs = project->values("QMAKE_PCH_ARCHS"); + if (pchArchs.isEmpty()) + pchArchs << ProString(); // normal single-arch PCH + for (const ProString &arch : qAsConst(pchArchs)) { + auto pfx = header_prefix; + if (!arch.isEmpty()) + pfx.replace(QLatin1String("${QMAKE_PCH_ARCH}"), arch.toQString()); + for (QStringList::Iterator it = Option::cpp_ext.begin(); + it != Option::cpp_ext.end(); ++it) { + if (file.endsWith(*it)) { + ret += pfx; + break; + } } } } else { @@ -584,7 +600,7 @@ UnixMakefileGenerator::defaultInstall(const QString &t) dst = escapeFilePath(filePrefixRoot(root, targetdir + src.section('/', -1))); if(!ret.isEmpty()) ret += "\n\t"; - ret += "-$(INSTALL_FILE) " + escapeFilePath(Option::fixPathToTargetOS(src, false)) + ' ' + dst; + ret += "-$(QINSTALL_FILE) " + escapeFilePath(Option::fixPathToTargetOS(src, false)) + ' ' + dst; if(!uninst.isEmpty()) uninst.append("\n\t"); uninst.append("-$(DEL_FILE) " + dst); @@ -622,14 +638,14 @@ UnixMakefileGenerator::defaultInstall(const QString &t) if (bundle == SolidBundle) { copy_cmd += "-$(INSTALL_DIR) " + src_targ + ' ' + plain_targ; } else if (project->first("TEMPLATE") == "lib" && project->isActiveConfig("staticlib")) { - copy_cmd += "-$(INSTALL_FILE) " + src_targ + ' ' + dst_targ; + copy_cmd += "-$(QINSTALL_FILE) " + src_targ + ' ' + dst_targ; } else if (!isAux) { if (bundle == SlicedBundle) { if (!ret.isEmpty()) ret += "\n\t"; ret += mkdir_p_asstring("\"`dirname " + dst_targ + "`\"", false); } - copy_cmd += "-$(INSTALL_PROGRAM) " + src_targ + ' ' + dst_targ; + copy_cmd += "-$(QINSTALL_PROGRAM) " + src_targ + ' ' + dst_targ; } if(project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib") && project->values(ProKey(t + ".CONFIG")).indexOf("fix_rpath") != -1) { diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 5b56cac784..f7097e58dc 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -1006,14 +1006,22 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if (project->isActiveConfig("icc_pch_style")) { // icc style ProString pchBaseName = project->first("QMAKE_ORIG_TARGET"); - ProString pchOutput; - if(!project->isEmpty("PRECOMPILED_DIR")) - pchOutput = project->first("PRECOMPILED_DIR"); - pchOutput += pchBaseName + project->first("QMAKE_PCH_OUTPUT_EXT"); - ProString sourceFile = pchOutput + Option::cpp_ext.first(); - ProString objectFile = createObjectList(ProStringList(sourceFile)).first(); + ProStringList pchArchs = project->values("QMAKE_PCH_ARCHS"); + if (pchArchs.isEmpty()) + pchArchs << ProString(); // normal single-arch PCH + for (const ProString &arch : qAsConst(pchArchs)) { + ProString pchOutput; + if (!project->isEmpty("PRECOMPILED_DIR")) + pchOutput = project->first("PRECOMPILED_DIR"); + pchOutput += pchBaseName + project->first("QMAKE_PCH_OUTPUT_EXT"); + if (!arch.isEmpty()) + pchOutput = ProString(pchOutput.toQString().replace( + QStringLiteral("${QMAKE_PCH_ARCH}"), arch.toQString())); - precomp_files << precomph_out_dir << sourceFile << objectFile; + ProString sourceFile = pchOutput + Option::cpp_ext.first(); + ProString objectFile = createObjectList(ProStringList(sourceFile)).first(); + precomp_files << precomph_out_dir << sourceFile << objectFile; + } } else { // gcc style (including clang_pch_style) precomph_out_dir += Option::dir_sep; @@ -1115,19 +1123,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if (!project->isActiveConfig("clang_pch_style")) pchOutput += project->first("QMAKE_PCH_OUTPUT_EXT"); - if (project->isActiveConfig("icc_pch_style")) { - // icc style - QString sourceFile = pchOutput + Option::cpp_ext.first(); - QString sourceFile_f = escapeFilePath(sourceFile); - QString objectFile = createObjectList(ProStringList(sourceFile)).first().toQString(); - t << escapeDependencyPath(pchOutput) << ": " << escapeDependencyPath(pchInput) << ' ' - << escapeDependencyPaths(findDependencies(pchInput)).join(" \\\n\t\t") - << "\n\techo \"// Automatically generated, do not modify\" > " << sourceFile_f - << "\n\trm -f " << escapeFilePath(pchOutput); - - pchFlags.replace(QLatin1String("${QMAKE_PCH_TEMP_SOURCE}"), sourceFile_f) - .replace(QLatin1String("${QMAKE_PCH_TEMP_OBJECT}"), escapeFilePath(objectFile)); - } else { + if (!project->isActiveConfig("icc_pch_style")) { // gcc style (including clang_pch_style) ProString header_prefix = project->first("QMAKE_PRECOMP_PREFIX"); ProString header_suffix = project->isActiveConfig("clang_pch_style") @@ -1148,18 +1144,28 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if (!arch.isEmpty()) pchArchOutput.replace(QStringLiteral("${QMAKE_PCH_ARCH}"), arch.toQString()); - if (!project->isActiveConfig("icc_pch_style")) { - const auto pchFilePath_d = escapeDependencyPath(pchArchOutput); - if (!arch.isEmpty()) { - t << pchFilePath_d << ": " << "EXPORT_ARCH_ARGS = -arch " << arch << "\n\n"; - t << pchFilePath_d << ": " - << "EXPORT_QMAKE_XARCH_CFLAGS = $(EXPORT_QMAKE_XARCH_CFLAGS_" << arch << ")" << "\n\n"; - t << pchFilePath_d << ": " - << "EXPORT_QMAKE_XARCH_LFLAGS = $(EXPORT_QMAKE_XARCH_LFLAGS_" << arch << ")" << "\n\n"; - } - t << pchFilePath_d << ": " << escapeDependencyPath(pchInput) << ' ' - << escapeDependencyPaths(findDependencies(pchInput)).join(" \\\n\t\t") - << "\n\t" << mkdir_p_asstring(pchOutputDir); + const auto pchFilePath_d = escapeDependencyPath(pchArchOutput); + if (!arch.isEmpty()) { + t << pchFilePath_d << ": " << "EXPORT_ARCH_ARGS = -arch " << arch << "\n\n"; + t << pchFilePath_d << ": " + << "EXPORT_QMAKE_XARCH_CFLAGS = $(EXPORT_QMAKE_XARCH_CFLAGS_" << arch << ")" << "\n\n"; + t << pchFilePath_d << ": " + << "EXPORT_QMAKE_XARCH_LFLAGS = $(EXPORT_QMAKE_XARCH_LFLAGS_" << arch << ")" << "\n\n"; + } + t << pchFilePath_d << ": " << escapeDependencyPath(pchInput) << ' ' + << escapeDependencyPaths(findDependencies(pchInput)).join(" \\\n\t\t"); + if (project->isActiveConfig("icc_pch_style")) { + QString sourceFile = pchArchOutput + Option::cpp_ext.first(); + QString sourceFile_f = escapeFilePath(sourceFile); + QString objectFile = createObjectList(ProStringList(sourceFile)).first().toQString(); + + pchFlags.replace(QLatin1String("${QMAKE_PCH_TEMP_SOURCE}"), sourceFile_f) + .replace(QLatin1String("${QMAKE_PCH_TEMP_OBJECT}"), escapeFilePath(objectFile)); + + t << "\n\techo \"// Automatically generated, do not modify\" > " << sourceFile_f + << "\n\trm -f " << escapeFilePath(pchArchOutput); + } else { + t << "\n\t" << mkdir_p_asstring(pchOutputDir); } auto pchArchFlags = pchFlags; diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 3c029c8004..86d388354a 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -530,6 +530,8 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t) t << "INSTALL_FILE = " << var("QMAKE_INSTALL_FILE") << endl; t << "INSTALL_PROGRAM = " << var("QMAKE_INSTALL_PROGRAM") << endl; t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << endl; + t << "QINSTALL_FILE = " << var("QMAKE_QMAKE") << " -install qinstall file" << endl; + t << "QINSTALL_PROGRAM = " << var("QMAKE_QMAKE") << " -install qinstall program" << endl; t << endl; t << "####### Output directory\n\n"; diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp index 67d2f541a1..39264952c6 100644 --- a/qmake/library/ioutils.cpp +++ b/qmake/library/ioutils.cpp @@ -37,8 +37,13 @@ # include <sys/types.h> # include <sys/stat.h> # include <unistd.h> +# include <utime.h> +# include <fcntl.h> +# include <errno.h> #endif +#define fL1S(s) QString::fromLatin1(s) + QT_BEGIN_NAMESPACE using namespace QMakeInternal; @@ -183,4 +188,69 @@ QString IoUtils::shellQuoteWin(const QString &arg) return ret; } +#if defined(PROEVALUATOR_FULL) + +# if defined(Q_OS_WIN) +static QString windowsErrorCode() +{ + wchar_t *string = 0; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPWSTR)&string, + 0, + NULL); + QString ret = QString::fromWCharArray(string); + LocalFree((HLOCAL)string); + return ret.trimmed(); +} +# endif + +bool IoUtils::touchFile(const QString &targetFileName, const QString &referenceFileName, QString *errorString) +{ +# ifdef Q_OS_UNIX + struct stat st; + if (stat(referenceFileName.toLocal8Bit().constData(), &st)) { + *errorString = fL1S("Cannot stat() reference file %1: %2.").arg(referenceFileName, fL1S(strerror(errno))); + return false; + } +# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L + const struct timespec times[2] = { { 0, UTIME_NOW }, st.st_mtim }; + const bool utimeError = utimensat(AT_FDCWD, targetFileName.toLocal8Bit().constData(), times, 0) < 0; +# else + struct utimbuf utb; + utb.actime = time(0); + utb.modtime = st.st_mtime; + const bool utimeError= utime(targetFileName.toLocal8Bit().constData(), &utb) < 0; +# endif + if (utimeError) { + *errorString = fL1S("Cannot touch %1: %2.").arg(targetFileName, fL1S(strerror(errno))); + return false; + } +# else + HANDLE rHand = CreateFile((wchar_t*)referenceFileName.utf16(), + GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (rHand == INVALID_HANDLE_VALUE) { + *errorString = fL1S("Cannot open reference file %1: %2").arg(referenceFileName, windowsErrorCode()); + return false; + } + FILETIME ft; + GetFileTime(rHand, 0, 0, &ft); + CloseHandle(rHand); + HANDLE wHand = CreateFile((wchar_t*)targetFileName.utf16(), + GENERIC_WRITE, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (wHand == INVALID_HANDLE_VALUE) { + *errorString = fL1S("Cannot open %1: %2").arg(targetFileName, windowsErrorCode()); + return false; + } + SetFileTime(wHand, 0, 0, &ft); + CloseHandle(wHand); +# endif + return true; +} +#endif + QT_END_NAMESPACE diff --git a/qmake/library/ioutils.h b/qmake/library/ioutils.h index a806f3d2eb..905974b7cb 100644 --- a/qmake/library/ioutils.h +++ b/qmake/library/ioutils.h @@ -62,6 +62,9 @@ public: #else { return shellQuoteWin(arg); } #endif +#if defined(PROEVALUATOR_FULL) + static bool touchFile(const QString &targetFileName, const QString &referenceFileName, QString *errorString); +#endif }; } // namespace ProFileEvaluatorInternal diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index b86efa33b4..85de50ef0c 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -57,9 +57,7 @@ #ifdef Q_OS_UNIX #include <time.h> -#include <utime.h> #include <errno.h> -#include <fcntl.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> @@ -260,23 +258,6 @@ QMakeEvaluator::getMemberArgs(const ProKey &func, int srclen, const ProStringLis return true; } -#if defined(Q_OS_WIN) && defined(PROEVALUATOR_FULL) -static QString windowsErrorCode() -{ - wchar_t *string = 0; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPWSTR)&string, - 0, - NULL); - QString ret = QString::fromWCharArray(string); - LocalFree((HLOCAL)string); - return ret.trimmed(); -} -#endif - QString QMakeEvaluator::quoteValue(const ProString &val) { @@ -1830,46 +1811,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( #ifdef PROEVALUATOR_FULL const QString &tfn = resolvePath(args.at(0).toQString(m_tmp1)); const QString &rfn = resolvePath(args.at(1).toQString(m_tmp2)); -#ifdef Q_OS_UNIX - struct stat st; - if (stat(rfn.toLocal8Bit().constData(), &st)) { - evalError(fL1S("Cannot stat() reference file %1: %2.").arg(rfn, fL1S(strerror(errno)))); + QString error; + if (!IoUtils::touchFile(tfn, rfn, &error)) { + evalError(error); return ReturnFalse; } -#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L - const struct timespec times[2] = { { 0, UTIME_NOW }, st.st_mtim }; - const bool utimeError = utimensat(AT_FDCWD, tfn.toLocal8Bit().constData(), times, 0) < 0; -#else - struct utimbuf utb; - utb.actime = time(0); - utb.modtime = st.st_mtime; - const bool utimeError = utime(tfn.toLocal8Bit().constData(), &utb) < 0; -#endif - if (utimeError) { - evalError(fL1S("Cannot touch %1: %2.").arg(tfn, fL1S(strerror(errno)))); - return ReturnFalse; - } -#else - HANDLE rHand = CreateFile((wchar_t*)rfn.utf16(), - GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (rHand == INVALID_HANDLE_VALUE) { - evalError(fL1S("Cannot open reference file %1: %2").arg(rfn, windowsErrorCode())); - return ReturnFalse; - } - FILETIME ft; - GetFileTime(rHand, 0, 0, &ft); - CloseHandle(rHand); - HANDLE wHand = CreateFile((wchar_t*)tfn.utf16(), - GENERIC_WRITE, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (wHand == INVALID_HANDLE_VALUE) { - evalError(fL1S("Cannot open %1: %2").arg(tfn, windowsErrorCode())); - return ReturnFalse; - } - SetFileTime(wHand, 0, 0, &ft); - CloseHandle(wHand); -#endif #endif return ReturnTrue; } diff --git a/qmake/main.cpp b/qmake/main.cpp index 6d7e023b41..2bdb5370df 100644 --- a/qmake/main.cpp +++ b/qmake/main.cpp @@ -47,6 +47,8 @@ # include <qt_windows.h> #endif +using namespace QMakeInternal; + QT_BEGIN_NAMESPACE #ifdef Q_OS_WIN @@ -232,20 +234,86 @@ static int doLink(int argc, char **argv) return 0; } +#endif + +static int installFile(const QString &source, const QString &targetFileOrDirectory, bool exe = false) +{ + QFile sourceFile(source); + + QString target(targetFileOrDirectory); + if (QFileInfo(target).isDir()) + target += QDir::separator() + QFileInfo(sourceFile.fileName()).fileName(); + + if (QFile::exists(target)) + QFile::remove(target); + + QDir::root().mkpath(QFileInfo(target).absolutePath()); + + if (!sourceFile.copy(target)) { + fprintf(stderr, "Error copying %s to %s: %s\n", source.toLatin1().constData(), qPrintable(target), qPrintable(sourceFile.errorString())); + return 3; + } + + if (exe) { + QFile targetFile(target); + if (!targetFile.setPermissions(sourceFile.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeUser | + QFileDevice::ExeGroup | QFileDevice::ExeOther)) { + fprintf(stderr, "Error setting execute permissions on %s: %s\n", + qPrintable(target), qPrintable(targetFile.errorString())); + return 3; + } + } + + // Copy file times + QString error; + if (!IoUtils::touchFile(target, sourceFile.fileName(), &error)) { + fprintf(stderr, "%s", qPrintable(error)); + return 3; + } + return 0; +} + +static int doQInstall(int argc, char **argv) +{ + if (argc != 3) { + fprintf(stderr, "Error: this qinstall command requires exactly three arguments (type, source, destination)\n"); + return 3; + } + + const QString source = QString::fromLocal8Bit(argv[1]); + const QString target = QString::fromLocal8Bit(argv[2]); + + if (!strcmp(argv[0], "file")) + return installFile(source, target); + if (!strcmp(argv[0], "program")) + return installFile(source, target, /*exe=*/true); + + fprintf(stderr, "Error: Unsupported qinstall command type %s\n", argv[0]); + return 3; +} + + static int doInstall(int argc, char **argv) { if (!argc) { fprintf(stderr, "Error: -install requires further arguments\n"); return 3; } +#ifdef Q_OS_WIN if (!strcmp(argv[0], "sed")) return doSed(argc - 1, argv + 1); if (!strcmp(argv[0], "ln")) return doLink(argc - 1, argv + 1); +#endif + if (!strcmp(argv[0], "qinstall")) + return doQInstall(argc - 1, argv + 1); fprintf(stderr, "Error: unrecognized -install subcommand '%s'\n", argv[0]); return 3; } + +#ifdef Q_OS_WIN + static int dumpMacros(const wchar_t *cmdline) { // from http://stackoverflow.com/questions/3665537/how-to-find-out-cl-exes-built-in-macros @@ -300,11 +368,11 @@ int runQMake(int argc, char **argv) // This is particularly important for things like QtCreator and scripted builds. setvbuf(stdout, (char *)NULL, _IONBF, 0); -#ifdef Q_OS_WIN // Workaround for inferior/missing command line tools on Windows: make our own! if (argc >= 2 && !strcmp(argv[1], "-install")) return doInstall(argc - 2, argv + 2); +#ifdef Q_OS_WIN { // Support running as Visual C++'s compiler const wchar_t *cmdline = _wgetenv(L"MSC_CMD_FLAGS"); diff --git a/qmake/option.cpp b/qmake/option.cpp index 52f9cb8a0e..4da2a1ae2c 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -462,7 +462,9 @@ Option::init(int argc, char **argv) void Option::prepareProject(const QString &pfile) { - QString srcpath = QDir::cleanPath(QFileInfo(pfile).absolutePath()); + // Canonicalize only the directory, otherwise things will go haywire + // if the file itself is a symbolic link. + const QString srcpath = QFileInfo(QFileInfo(pfile).absolutePath()).canonicalFilePath(); globals->setDirectories(srcpath, output_dir); } |