7#include <QtCore/QString>
8#include <QtCore/QDebug>
10#include <QtCore/QFile>
11#include <QtCore/QFileInfo>
12#include <QtCore/QTemporaryFile>
13#include <QtCore/QScopedPointer>
14#include <QtCore/QScopedArrayPointer>
15#include <QtCore/QStandardPaths>
17# include <QtCore/qt_windows.h>
18# include <QtCore/private/qsystemerror_p.h>
23# include <sys/types.h>
41 && (dirName ==
"debug"_L1 || dirName ==
"release"_L1);
103 const QString dllPath = dllFi.absoluteFilePath();
116 result += dllFi.fileName();
128 if (!GetShortPathNameW(
reinterpret_cast<LPCWSTR
>(nativeFileName.
utf16()), shortBuffer,
MAX_PATH))
147static HANDLE createInheritableTemporaryFile()
151 return INVALID_HANDLE_VALUE;
153 if (!GetTempFileName(
path, L
"temp", 0,
name))
154 return INVALID_HANDLE_VALUE;
155 SECURITY_ATTRIBUTES securityAttributes;
156 ZeroMemory(&securityAttributes,
sizeof(securityAttributes));
157 securityAttributes.nLength =
sizeof(securityAttributes);
158 securityAttributes.bInheritHandle = TRUE;
159 return CreateFile(
name, GENERIC_READ | GENERIC_WRITE,
160 FILE_SHARE_READ | FILE_SHARE_WRITE, &securityAttributes,
162 FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL);
168 if (SetFilePointer(
handle, 0, 0, FILE_BEGIN) == 0xFFFFFFFF)
172 while (ReadFile(
handle,
buf,
sizeof(
buf), &bytesRead, NULL) && bytesRead)
179 const bool needsQuote =
argument.contains(u
' ');
181 commandLine->
append(u
' ');
183 commandLine->
append(u
'"');
186 commandLine->
append(u
'"');
192 const QString &workingDirectory,
200 ZeroMemory(&si,
sizeof(si));
204 GetStartupInfo(&myInfo);
205 si.hStdInput = myInfo.hStdInput;
206 si.hStdOutput = myInfo.hStdOutput;
207 si.hStdError = myInfo.hStdError;
209 PROCESS_INFORMATION
pi;
210 ZeroMemory(&
pi,
sizeof(PROCESS_INFORMATION));
211 const QChar backSlash = u
'\\';
213 if (!nativeWorkingDir.
endsWith(backSlash))
214 nativeWorkingDir += backSlash;
217 si.hStdOutput = createInheritableTemporaryFile();
218 if (si.hStdOutput == INVALID_HANDLE_VALUE) {
223 si.dwFlags |= STARTF_USESTDHANDLES;
227 si.hStdError = createInheritableTemporaryFile();
228 if (si.hStdError == INVALID_HANDLE_VALUE) {
233 si.dwFlags |= STARTF_USESTDHANDLES;
238 appendToCommandLine(
binary, &commandLine);
240 appendToCommandLine(
a, &commandLine);
242 std::wcout <<
"Running: " << commandLine <<
'\n';
245 commandLine.toWCharArray(commandLineW.data());
246 commandLineW[commandLine.size()] = 0;
247 if (!CreateProcessW(0, commandLineW.data(), 0, 0, TRUE, 0, 0,
248 reinterpret_cast<LPCWSTR
>(nativeWorkingDir.
utf16()), &si, &
pi)) {
250 CloseHandle(si.hStdOutput);
252 CloseHandle(si.hStdError);
255 + QSystemError::windowsString();
260 WaitForSingleObject(
pi.hProcess, INFINITE);
261 CloseHandle(
pi.hThread);
263 GetExitCodeProcess(
pi.hProcess, exitCode);
264 CloseHandle(
pi.hProcess);
267 readTemporaryProcessFile(si.hStdOutput, stdOut);
269 readTemporaryProcessFile(si.hStdError, stdErr);
286 if (!
path.endsWith(u
'/'))
297 if (!lseek(
fd, 0, 0)) {
313 const QString &workingDirectory,
323 stdOutFile = mkstemp(stdOutFileName.
data());
324 if (stdOutFile < 0) {
333 stdErrFile = mkstemp(stdErrFileName.
data());
334 if (stdErrFile < 0) {
340 const pid_t pID = fork();
349 dup2(stdOutFile, STDOUT_FILENO);
353 dup2(stdErrFile, STDERR_FILENO);
358 std::wcerr <<
"Failed to change working directory to " << workingDirectory <<
".\n";
362 char **argv =
new char *[
args.
size() + 2];
369 execvp(argv[0], argv);
377 waitResult = waitpid(pID, &status, 0);
378 }
while (waitResult == -1 && errno == EINTR);
382 unlink(stdOutFileName.
data());
386 unlink(stdErrFileName.
data());
389 if (waitResult < 0) {
393 if (!WIFEXITED(status)) {
398 *exitCode = WEXITSTATUS(status);
413 if (PathFindOnPath(
buffer, NULL))
429 unsigned long exitCode = 0;
479 const QFileInfo sourceFileInfo(sourceFileName);
480 const QString targetFileName = targetDirectory + u
'/' + sourceFileInfo.
fileName();
482 std::wcout <<
"Checking " << sourceFileName <<
", " << targetFileName<<
'\n';
484 if (!sourceFileInfo.
exists()) {
495 const QFileInfo targetFileInfo(targetFileName);
497 if (sourceFileInfo.
isDir()) {
498 if (targetFileInfo.
exists()) {
499 if (!targetFileInfo.
isDir()) {
505 QDir d(targetDirectory);
518 for (
const QFileInfo &entryFi : allEntries) {
525 if (targetFileInfo.
exists()) {
529 std::wcout << sourceFileInfo.
fileName() <<
" is up to date.\n";
531 json->
addFile(sourceFileName, targetDirectory);
534 QFile targetFile(targetFileName);
543 std::wcout <<
"Updating " << sourceFileInfo.
fileName() <<
".\n";
552 json->
addFile(sourceFileName, targetDirectory);
557 QStringList *dependentLibraries,
unsigned *wordSize,
560 ElfReader elfReader(elfExecutableFileName);
562 if (
data.sectionHeaders.isEmpty()) {
570 if (dependentLibraries) {
571 dependentLibraries->clear();
589static inline QString stringFromRvaPtr(
const void *rvaPtr)
596template <
class ImageNtHeader>
597const IMAGE_SECTION_HEADER *findSectionHeader(DWORD rva,
const ImageNtHeader *nTHeader)
599 const IMAGE_SECTION_HEADER *section = IMAGE_FIRST_SECTION(nTHeader);
600 const IMAGE_SECTION_HEADER *sectionEnd = section + nTHeader->FileHeader.NumberOfSections;
601 for ( ; section < sectionEnd; ++section)
602 if (rva >= section->VirtualAddress && rva < (section->VirtualAddress + section->Misc.VirtualSize))
608template <
class ImageNtHeader>
609inline const void *rvaToPtr(DWORD rva,
const ImageNtHeader *nTHeader,
const void *imageBase)
611 const IMAGE_SECTION_HEADER *sectionHdr = findSectionHeader(rva, nTHeader);
614 const DWORD delta = sectionHdr->VirtualAddress - sectionHdr->PointerToRawData;
615 return static_cast<const char *
>(imageBase) + rva - delta;
619template <
class ImageNtHeader>
620inline unsigned ntHeaderWordSize(
const ImageNtHeader *
header)
623 enum { imageNtOptionlHeader32Magic = 0x10b, imageNtOptionlHeader64Magic = 0x20b };
624 if (
header->OptionalHeader.Magic == imageNtOptionlHeader32Magic)
626 if (
header->OptionalHeader.Magic == imageNtOptionlHeader64Magic)
635 IMAGE_DOS_HEADER *dosHeader =
static_cast<PIMAGE_DOS_HEADER
>(fileMemory);
637 if (IsBadReadPtr(dosHeader,
sizeof(IMAGE_DOS_HEADER))
638 || dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
643 char *ntHeaderC =
static_cast<char *
>(fileMemory) + dosHeader->e_lfanew;
644 IMAGE_NT_HEADERS *ntHeaders =
reinterpret_cast<IMAGE_NT_HEADERS *
>(ntHeaderC);
646 if (IsBadReadPtr(ntHeaders,
sizeof(ntHeaders->Signature))
647 || ntHeaders->Signature != IMAGE_NT_SIGNATURE
648 || IsBadReadPtr(&ntHeaders->FileHeader,
sizeof(IMAGE_FILE_HEADER))) {
653 if (!ntHeaderWordSize(ntHeaders)) {
655 arg(ntHeaders->OptionalHeader.Magic);
659 IMAGE_SECTION_HEADER *sectionHeaders = IMAGE_FIRST_SECTION(ntHeaders);
660 if (IsBadReadPtr(sectionHeaders, ntHeaders->FileHeader.NumberOfSections *
sizeof(IMAGE_SECTION_HEADER))) {
669template <
class ImageNtHeader>
673 const DWORD importsStartRVA = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
674 if (!importsStartRVA) {
678 const IMAGE_IMPORT_DESCRIPTOR *importDesc =
static_cast<const IMAGE_IMPORT_DESCRIPTOR *
>(rvaToPtr(importsStartRVA, ntHeaders,
base));
684 for ( ; importDesc->Name; ++importDesc)
685 result.push_back(stringFromRvaPtr(rvaToPtr(importDesc->Name, ntHeaders,
base)));
689 if (
const DWORD delayedImportsStartRVA = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress) {
690 const ImgDelayDescr *delayedImportDesc =
static_cast<const ImgDelayDescr *
>(rvaToPtr(delayedImportsStartRVA, ntHeaders,
base));
691 for ( ; delayedImportDesc->rvaDLLName && (delayedImportDesc->grAttrs & 1); ++delayedImportDesc)
692 result.push_back(stringFromRvaPtr(rvaToPtr(delayedImportDesc->rvaDLLName, ntHeaders,
base)));
700enum MsvcDebugRuntimeResult { MsvcDebugRuntime, MsvcReleaseRuntime, NoMsvcRuntime };
702static inline MsvcDebugRuntimeResult checkMsvcDebugRuntime(
const QStringList &dependentLibraries)
704 for (
const QString &lib : dependentLibraries) {
709 qsizetype lastDotPos = lib.lastIndexOf(u
'.');
710 pos = -1 == lastDotPos ? 0 : lastDotPos - 1;
717 return lib.at(
pos).toLower() == u
'd' ? MsvcDebugRuntime : MsvcReleaseRuntime;
719 return NoMsvcRuntime;
722template <
class ImageNtHeader>
723inline QStringList determineDependentLibs(
const ImageNtHeader *nth,
const void *fileMemory,
726 return readImportSections(nth, fileMemory,
errorMessage);
729template <
class ImageNtHeader>
730inline bool determineDebug(
const ImageNtHeader *nth,
const void *fileMemory,
733 if (nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
736 const QStringList dependentLibraries = dependentLibrariesIn !=
nullptr ?
737 *dependentLibrariesIn :
740 const bool hasDebugEntry = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
743 const MsvcDebugRuntimeResult msvcrt = checkMsvcDebugRuntime(dependentLibraries);
744 if (msvcrt == NoMsvcRuntime)
745 return hasDebugEntry;
747 return hasDebugEntry && msvcrt == MsvcDebugRuntime;
750template <
class ImageNtHeader>
751inline void determineDebugAndDependentLibs(
const ImageNtHeader *nth,
const void *fileMemory,
755 if (dependentLibrariesIn)
756 *dependentLibrariesIn = determineDependentLibs(nth, fileMemory,
errorMessage);
759 *isDebugIn = determineDebug(nth, fileMemory, dependentLibrariesIn,
errorMessage);
765 QStringList *dependentLibrariesIn,
unsigned *wordSizeIn,
766 bool *isDebugIn,
bool isMinGW,
unsigned short *machineArchIn)
771 void *fileMemory = 0;
773 if (dependentLibrariesIn)
774 dependentLibrariesIn->clear();
782 hFile = CreateFile(
reinterpret_cast<const WCHAR*
>(peExecutableFileName.
utf16()), GENERIC_READ, FILE_SHARE_READ, NULL,
783 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
784 if (hFile == INVALID_HANDLE_VALUE || hFile == NULL) {
786 .
arg(peExecutableFileName, QSystemError::windowsString());
790 hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
791 if (hFileMap == NULL) {
793 .
arg(peExecutableFileName, QSystemError::windowsString());
797 fileMemory = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
800 .
arg(peExecutableFileName, QSystemError::windowsString());
804 const IMAGE_NT_HEADERS *ntHeaders = getNtHeader(fileMemory,
errorMessage);
808 const unsigned wordSize = ntHeaderWordSize(ntHeaders);
810 *wordSizeIn = wordSize;
811 if (wordSize == 32) {
812 determineDebugAndDependentLibs(
reinterpret_cast<const IMAGE_NT_HEADERS32 *
>(ntHeaders),
813 fileMemory, dependentLibrariesIn, isDebugIn,
errorMessage);
815 determineDebugAndDependentLibs(
reinterpret_cast<const IMAGE_NT_HEADERS64 *
>(ntHeaders),
816 fileMemory, dependentLibrariesIn, isDebugIn,
errorMessage);
820 *machineArchIn = ntHeaders->FileHeader.Machine;
825 <<
' ' << wordSize <<
" bit";
827 std::wcout <<
", MinGW";
828 if (dependentLibrariesIn) {
829 std::wcout <<
", dependent libraries: ";
831 std::wcout << dependentLibrariesIn->join(u
' ');
833 std::wcout << dependentLibrariesIn->size();
836 std::wcout << (*isDebugIn ?
", debug" :
", release");
842 UnmapViewOfFile(fileMemory);
844 if (hFileMap != NULL)
845 CloseHandle(hFileMap);
847 if (hFile != NULL && hFile != INVALID_HANDLE_VALUE)
866 QDir redistDir(redistDirPath);
867 if (redistDir.exists()) {
869 if (!
files.isEmpty())
870 return files.front().absoluteFilePath();
874 for (
int i = 47 ;
i >= 40 ; --
i)
878 for (
const QString &candidate :
std::as_const(candidateVersions)) {
886 unsigned detectedWordSize;
887 for (
const QString &candidate :
std::as_const(candidateVersions)) {
891 && detectedWordSize == wordSize) {
913 QDir redistDir(redistDirPath);
914 if (redistDir.exists()) {
916 if (!
files.isEmpty()) {
932 unsigned detectedWordSize;
936 && detectedWordSize == wordSize)
949 QStringList *,
unsigned *,
bool *,
bool,
unsigned short *)
991 int startPos = content.
indexOf(prfxpath);
992 if (startPos == -1) {
994 "Unable to patch %1: Could not locate pattern \"qt_prfxpath=\"").
arg(
998 startPos += prfxpath.
length();
999 int endPos = content.
indexOf(
char(0), startPos);
1007 replacement[0] =
'.';
1008 content.
replace(startPos, endPos - startPos, replacement);
1009 if (content == oldContent)
1022QString getArchString(
unsigned short machineArch)
1024 switch (machineArch) {
1025 case IMAGE_FILE_MACHINE_I386:
1027 case IMAGE_FILE_MACHINE_ARM:
1029 case IMAGE_FILE_MACHINE_AMD64:
QList< QByteArray > dependencies()
QString errorString() const
void addFile(const QString &source, const QString &target)
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
qsizetype indexOf(char c, qsizetype from=0) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
qsizetype length() const noexcept
Same as size().
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
QByteArray & replace(qsizetype index, qsizetype len, const char *s, qsizetype alen)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString fromNativeSeparators(const QString &pathName)
static bool setCurrent(const QString &path)
Sets the application's current working directory to path.
static QString tempPath()
Returns the absolute canonical path of the system's temporary directory.
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
static QString toNativeSeparators(const QString &pathName)
static QString currentPath()
Returns the absolute path of the application's current directory.
void close() override
Calls QFileDevice::flush() and closes the file.
\inmodule QtCore \reentrant
QDateTime lastModified() const
Returns the date and time when the file was last modified.
bool isSymLink() const
Returns true if this object points to a symbolic link, shortcut, or alias; otherwise returns false.
QString fileName() const
Returns the name of the file, excluding the path.
QString absoluteFilePath() const
Returns an absolute path including the file name.
bool isFile() const
Returns true if this object points to a file or to a symbolic link to a file.
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory.
bool exists() const
Returns true if the file exists; otherwise returns false.
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
bool link(const QString &newName)
Creates a link named linkName that points to the file currently specified by fileName().
bool copy(const QString &newName)
Copies the file named fileName() to newName.
bool remove()
Removes the file specified by fileName().
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
QString fileName() const override
Returns the name set by setFileName() or to the QFile constructors.
qint64 size() const override
\reimp
qint64 readLine(char *data, qint64 maxlen)
This function reads a line of ASCII characters from the device, up to a maximum of maxSize - 1 bytes,...
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
QString errorString() const
Returns a human-readable description of the last device error that occurred.
qsizetype size() const noexcept
bool isEmpty() const noexcept
void append(parameter_type t)
T * data() const noexcept
Returns the value of the pointer referenced by this object.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
static QString findExecutable(const QString &executableName, const QStringList &paths=QStringList())
\macro QT_RESTRICTED_CAST_FROM_ASCII
QString right(qsizetype n) const
Returns a substring that contains the n rightmost characters of the string.
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
qsizetype size() const
Returns the number of characters in this string.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString & append(QChar c)
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
QString trimmed() const &
QString & remove(qsizetype i, qsizetype len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Combined button and popup list for selecting options.
static QString header(const QString &name)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static bool matches(const QJsonObject &object, const QString &osName, const QVersionNumber &kernelVersion, const QString &osRelease, const QOpenGLConfig::Gpu &gpu)
GLsizei GLsizei GLenum void * binary
GLuint64 GLenum void * handle
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei const GLuint * paths
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei GLsizei GLchar * source
GLsizei const GLchar *const * path
#define QStringLiteral(str)
#define IMAGE_FILE_MACHINE_ARM64
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, qsizetype errorPosition)
ReturnedValue read(const char *data)
QT_BEGIN_NAMESPACE typedef uchar * output
QFileInfo fi("c:/temp/foo")
[newstuff]
static QByteArray readOutRedirectFile(int fd)
QStringList findDxc(Platform, const QString &, unsigned)
bool readPeExecutable(const QString &, QString *errorMessage, QStringList *, unsigned *, bool *, bool, unsigned short *)
QString findInPath(const QString &file)
static char * encodeFileName(const QString &f)
QMap< QString, QString > queryQtPaths(const QString &qtpathsBinary, QString *errorMessage)
bool createSymbolicLink(const QFileInfo &source, const QString &target, QString *errorMessage)
static char * tempFilePattern()
QString findD3dCompiler(Platform, const QString &, unsigned)
bool createDirectory(const QString &directory, QString *errorMessage, bool dryRun)
QStringList findSharedLibraries(const QDir &directory, Platform platform, DebugMatchMode debugMatchMode, const QString &prefix)
bool updateFile(const QString &sourceFileName, const QStringList &nameFilters, const QString &targetDirectory, unsigned flags, JsonOutput *json, QString *errorMessage)
bool runProcess(const QString &binary, const QStringList &args, const QString &workingDirectory, unsigned long *exitCode, QByteArray *stdOut, QByteArray *stdErr, QString *errorMessage)
bool isBuildDirectory(Platform platform, const QString &dirName)
bool patchQtCore(const QString &path, QString *errorMessage)
bool readElfExecutable(const QString &elfExecutableFileName, QString *errorMessage, QStringList *dependentLibraries, unsigned *wordSize, bool *isDebug)
const char * qmakeInfixKey
bool platformHasDebugSuffix(Platform p)
static const char windowsSharedLibrarySuffix[]
QString normalizeFileName(const QString &name)
QString sharedLibrarySuffix(Platform platform)