summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--qmake/generators/makefile.cpp7
-rw-r--r--qmake/generators/unix/unixmake.cpp4
-rw-r--r--qmake/generators/win32/winmakefile.cpp1
-rw-r--r--qmake/library/ioutils.cpp70
-rw-r--r--qmake/library/ioutils.h3
-rw-r--r--qmake/library/qmakebuiltins.cpp60
-rw-r--r--qmake/main.cpp57
-rw-r--r--tests/auto/tools/qmake/tst_qmake.cpp1
8 files changed, 140 insertions, 63 deletions
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index 2845888dde..5f3b8c9047 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -1294,7 +1294,7 @@ MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild)
else if (is_target || fi.isExecutable())
cmd = "-$(INSTALL_PROGRAM)";
else
- cmd = "-$(INSTALL_FILE)";
+ cmd = "-$(QINSTALL_FILE)";
cmd += " " + escapeFilePath(wild) + " " + escapeFilePath(dst_file);
inst << cmd;
if (!project->isActiveConfig("debug_info") && !project->isActiveConfig("nostrip") &&
@@ -1320,7 +1320,7 @@ MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild)
} else if (installConfigValues.contains("executable")) {
cmd = QLatin1String("-$(INSTALL_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,7 @@ 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 << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl;
t << "SYMLINK = " << var("QMAKE_SYMBOLIC_LINK") << endl;
t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl;
diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp
index 794d04a6e9..0f5e6dc8c0 100644
--- a/qmake/generators/unix/unixmake.cpp
+++ b/qmake/generators/unix/unixmake.cpp
@@ -584,7 +584,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,7 +622,7 @@ 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())
diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp
index 3c029c8004..b6dd734bc2 100644
--- a/qmake/generators/win32/winmakefile.cpp
+++ b/qmake/generators/win32/winmakefile.cpp
@@ -530,6 +530,7 @@ 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 << 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 461f46e705..2bb6f2e12d 100644
--- a/qmake/library/qmakebuiltins.cpp
+++ b/qmake/library/qmakebuiltins.cpp
@@ -56,9 +56,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>
@@ -256,23 +254,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)
{
@@ -1813,46 +1794,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..0b0b5ff128 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,73 @@ static int doLink(int argc, char **argv)
return 0;
}
+#endif
+
+static int installFile(const QString &source, const QString &targetFileOrDirectory)
+{
+ 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;
+ }
+ // 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);
+
+ 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 +355,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/tests/auto/tools/qmake/tst_qmake.cpp b/tests/auto/tools/qmake/tst_qmake.cpp
index eed1fe1a56..10aabcf196 100644
--- a/tests/auto/tools/qmake/tst_qmake.cpp
+++ b/tests/auto/tools/qmake/tst_qmake.cpp
@@ -286,6 +286,7 @@ void tst_qmake::install_files()
QVERIFY( test_compiler.make( workDir, "install" ));
QVERIFY( test_compiler.exists( workDir + "/dist", "foo", Exe, "1.0.0" ));
QVERIFY( test_compiler.exists( workDir + "/dist", "test.txt", Plain, "1.0.0" ));
+ QCOMPARE(QFileInfo(workDir + "/test.txt").lastModified(), QFileInfo(workDir + "/dist/test.txt").lastModified());
QVERIFY( test_compiler.make( workDir, "uninstall" ));
QVERIFY( test_compiler.makeDistClean( workDir ));