qmake: Use utimensat on macOS when propagating mtime during install

macOS only claims to conform to POSIX.1-2001, but has had utimensat
since macOS 10.13.

By enabling the utimensat code path, using stat.st_mtimespec as input,
we get nanosecond precision when qmake installs files.

Without this the tst_qmake::install_files tests fails due to the source
file having a sub second timestamp -- 2023-07-31 15:58:12.468 -- while the
installed does not: 2023-07-31 15:58:12.000.

The reason this test passes in the CI right now is probably because
the source file archive we use to pass test sources to the test
machines does not support the same level of precision.

Pick-to: 6.8
Change-Id: I6ca7a2a2f9e71981814cbf496aa55717b3a3f74f
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Tor Arne Vestbø 2024-07-07 23:53:54 +02:00
parent 60550f8acc
commit a2779192ee

View File

@ -221,15 +221,21 @@ bool IoUtils::touchFile(const QString &targetFileName, const QString &referenceF
*errorString = fL1S("Cannot stat() reference file %1: %2.").arg(referenceFileName, fL1S(strerror(errno))); *errorString = fL1S("Cannot stat() reference file %1: %2.").arg(referenceFileName, fL1S(strerror(errno)));
return false; return false;
} }
# if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) || defined(Q_OS_DARWIN)
const struct timespec times[2] = { { 0, UTIME_NOW },
# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L # if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L
const struct timespec times[2] = { { 0, UTIME_NOW }, st.st_mtim }; st.st_mtim // POSIX.1-2008
# else
st.st_mtimespec // Darwin
# endif
};
const bool utimeError = utimensat(AT_FDCWD, targetFileName.toLocal8Bit().constData(), times, 0) < 0; const bool utimeError = utimensat(AT_FDCWD, targetFileName.toLocal8Bit().constData(), times, 0) < 0;
# else # else
struct utimbuf utb; struct utimbuf utb;
utb.actime = time(0); utb.actime = time(0);
utb.modtime = st.st_mtime; utb.modtime = st.st_mtime;
const bool utimeError= utime(targetFileName.toLocal8Bit().constData(), &utb) < 0; const bool utimeError= utime(targetFileName.toLocal8Bit().constData(), &utb) < 0;
# endif # endif // (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) || defined(Q_OS_DARWIN)
if (utimeError) { if (utimeError) {
*errorString = fL1S("Cannot touch %1: %2.").arg(targetFileName, fL1S(strerror(errno))); *errorString = fL1S("Cannot touch %1: %2.").arg(targetFileName, fL1S(strerror(errno)));
return false; return false;
@ -256,7 +262,7 @@ bool IoUtils::touchFile(const QString &targetFileName, const QString &referenceF
} }
SetFileTime(wHand, NULL, NULL, &ft); SetFileTime(wHand, NULL, NULL, &ft);
CloseHandle(wHand); CloseHandle(wHand);
# endif # endif // Q_OS_UNIX
return true; return true;
} }