- Remove duplicated code locateFile/locateFileInPaths.
- Move basic path search functionality to Environment.
- Add functions for headerPaths/libraryPaths to Environment.
- Use QStandardPaths::findExecutable().
- Replace Environment::detectExecutable by
QStandardPaths::findExecutable().
- Introduce static path lists in findFile() to avoid
repeated directory scans
Change-Id: I9b93066a3de65f40527780d6ddf7989bca35cd04
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
qtextstream.o \
qlogging.o \
qtemporaryfile.o \
+ qstandardpaths.o \
+ qstandardpaths_win.o \
qsystemlibrary.o \
qbitarray.o \
qdatetime.o \
qtextstream.obj \
qlogging.obj \
qtemporaryfile.obj \
+ qstandardpaths.obj \
+ qstandardpaths_win.obj \
qsystemlibrary.obj \
qbitarray.obj \
qdatetime.obj \
qiodevice.obj: $(CORESRC)\io\qiodevice.cpp $(PCH)
qtextstream.obj: $(CORESRC)\io\qtextstream.cpp $(PCH)
qtemporaryfile.obj: $(CORESRC)\io\qtemporaryfile.cpp $(PCH)
+qstandardpaths.obj: $(CORESRC)\io\qstandardpaths.cpp $(PCH)
+qstandardpaths_win.obj: $(CORESRC)\io\qstandardpaths_win.cpp $(PCH)
qsystemlibrary.obj: $(CORESRC)\plugin\qsystemlibrary.cpp $(PCH)
qbitarray.obj: $(CORESRC)\tools\qbitarray.cpp $(PCH)
qdatetime.obj: $(CORESRC)\tools\qdatetime.cpp $(PCH)
$$QT_SOURCE_TREE/src/corelib/io/qiodevice.h \
$$QT_SOURCE_TREE/src/corelib/io/qtextstream.h \
$$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.h \
+ $$QT_SOURCE_TREE/src/corelib/io/qstandardpaths.h \
$$QT_SOURCE_TREE/src/corelib/tools/qbitarray.h \
$$QT_SOURCE_TREE/src/corelib/tools/qdatetime.h \
$$QT_SOURCE_TREE/src/corelib/tools/qmap.h \
$$QT_SOURCE_TREE/src/corelib/io/qiodevice.cpp \
$$QT_SOURCE_TREE/src/corelib/io/qtextstream.cpp \
$$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qstandardpaths.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qstandardpaths_win.cpp \
$$QT_SOURCE_TREE/src/corelib/plugin/qsystemlibrary.cpp \
$$QT_SOURCE_TREE/src/corelib/tools/qbitarray.cpp \
$$QT_SOURCE_TREE/src/corelib/tools/qdatetime.cpp \
#include <qdir.h>
#include <qdiriterator.h>
#include <qtemporaryfile.h>
+#include <qstandardpaths.h>
#include <qstack.h>
#include <qdebug.h>
#include <qfileinfo.h>
const QString installPath = buildPath;
#endif
if (sourceDir != buildDir) { //shadow builds!
- if (!findFile("perl") && !findFile("perl.exe")) {
+ if (QStandardPaths::findExecutable(QStringLiteral("perl.exe")).isEmpty()) {
cout << "Error: Creating a shadow build of Qt requires" << endl
<< "perl to be in the PATH environment";
exit(0); // Exit cleanly for Ctrl+C
}
}
-QString Configure::locateFileInPaths(const QString &fileName, const QStringList &paths)
-{
- QDir d;
- for (QStringList::ConstIterator it = paths.begin(); it != paths.end(); ++it) {
- // Remove any leading or trailing ", this is commonly used in the environment
- // variables
- QString path = (*it);
- if (path.startsWith("\""))
- path = path.right(path.length() - 1);
- if (path.endsWith("\""))
- path = path.left(path.length() - 1);
- if (d.exists(path + QDir::separator() + fileName)) {
- return (path);
- }
- }
- return QString();
-}
-
-QString Configure::locateFile(const QString &fileName)
-{
- QString file = fileName.toLower();
- QStringList paths;
-#if defined(Q_OS_WIN32)
- QRegExp splitReg("[;,]");
-#else
- QRegExp splitReg("[:]");
-#endif
- if (file.endsWith(".h"))
- paths = QString::fromLocal8Bit(getenv("INCLUDE")).split(splitReg, QString::SkipEmptyParts);
- else if (file.endsWith(".lib"))
- paths = QString::fromLocal8Bit(getenv("LIB")).split(splitReg, QString::SkipEmptyParts);
- else
- paths = QString::fromLocal8Bit(getenv("PATH")).split(splitReg, QString::SkipEmptyParts);
- return locateFileInPaths(file, paths);
-}
-
// Output helper functions ---------------------------------[ Stop ]-
return false;
}
-QString Configure::findFileInPaths(const QString &fileName, const QString &paths)
-{
-#if defined(Q_OS_WIN32)
- QRegExp splitReg("[;,]");
-#else
- QRegExp splitReg("[:]");
-#endif
- QStringList pathList = paths.split(splitReg, QString::SkipEmptyParts);
- QDir d;
- for (QStringList::ConstIterator it = pathList.begin(); it != pathList.end(); ++it) {
- // Remove any leading or trailing ", this is commonly used in the environment
- // variables
- QString path = (*it);
- if (path.startsWith('\"'))
- path = path.right(path.length() - 1);
- if (path.endsWith('\"'))
- path = path.left(path.length() - 1);
- if (d.exists(path + QDir::separator() + fileName))
- return path;
- }
- return QString();
-}
-
-static QString mingwPaths(const QString &mingwPath, const QString &pathName)
-{
- QString ret;
- QDir mingwDir = QFileInfo(mingwPath).dir();
- const QFileInfoList subdirs = mingwDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
- for (int i = 0 ;i < subdirs.length(); ++i) {
- const QFileInfo &fi = subdirs.at(i);
- const QString name = fi.fileName();
- if (name == pathName)
- ret += fi.absoluteFilePath() + ';';
- else if (name.contains("mingw"))
- ret += fi.absoluteFilePath() + QDir::separator() + pathName + ';';
- }
- return ret;
-}
-
-bool Configure::findFile(const QString &fileName)
+// Locate a file and return its containing directory.
+QString Configure::locateFile(const QString &fileName) const
{
const QString file = fileName.toLower();
- const QString pathEnvVar = QString::fromLocal8Bit(getenv("PATH"));
- const QString mingwPath = dictionary["QMAKESPEC"].endsWith("-g++") ?
- findFileInPaths("g++.exe", pathEnvVar) : QString();
-
- QString paths;
+ QStringList pathList;
if (file.endsWith(".h")) {
- if (!mingwPath.isNull()) {
- if (!findFileInPaths(file, mingwPaths(mingwPath, "include")).isNull())
- return true;
- //now let's try the additional compiler path
-
- const QFileInfoList mingwConfigs = QDir(mingwPath + QLatin1String("/../lib/gcc")).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
- for (int i = 0; i < mingwConfigs.length(); ++i) {
- const QDir mingwLibDir = mingwConfigs.at(i).absoluteFilePath();
- foreach(const QFileInfo &version, mingwLibDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) {
- if (!findFileInPaths(file, version.absoluteFilePath() + QLatin1String("/include")).isNull())
- return true;
- }
- }
- }
- paths = QString::fromLocal8Bit(getenv("INCLUDE"));
- const QByteArray directXSdk = qgetenv("DXSDK_DIR");
- if (!directXSdk.isEmpty()) // Add Direct X SDK for ANGLE
- paths += QLatin1Char(';') + QString::fromLocal8Bit(directXSdk) + QLatin1String("/include");
+ static const QStringList headerPaths =
+ Environment::headerPaths(Environment::compilerFromQMakeSpec(dictionary[QStringLiteral("QMAKESPEC")]));
+ pathList = headerPaths;
} else if (file.endsWith(".lib") || file.endsWith(".a")) {
- if (!mingwPath.isNull() && !findFileInPaths(file, mingwPaths(mingwPath, "lib")).isNull())
- return true;
- paths = QString::fromLocal8Bit(getenv("LIB"));
+ static const QStringList libPaths =
+ Environment::libraryPaths(Environment::compilerFromQMakeSpec(dictionary[QStringLiteral("QMAKESPEC")]));
+ pathList = libPaths;
} else {
- paths = pathEnvVar;
+ // Fallback for .exe and .dll (latter are not covered by QStandardPaths).
+ static const QStringList exePaths = Environment::path();
+ pathList = exePaths;
}
- return !findFileInPaths(file, paths).isNull();
+ return Environment::findFileInPaths(file, pathList);
}
/*!
dictionary[ "DONE" ] = "error";
}
} else if (part == "INCREDIBUILD_XGE") {
- available = findFile("BuildConsole.exe") && findFile("xgConsole.exe");
+ available = !QStandardPaths::findExecutable(QStringLiteral("BuildConsole.exe")).isEmpty()
+ && !QStandardPaths::findExecutable(QStringLiteral("xgConsole.exe")).isEmpty();
} else if (part == "WMSDK") {
available = findFile("wmsdk.h");
} else if (part == "V8SNAPSHOT") {
if (dictionary["QMAKESPEC"].endsWith("-g++")) {
QString includepath = qgetenv("INCLUDE");
- bool hasSh = Environment::detectExecutable("sh.exe");
+ const bool hasSh = !QStandardPaths::findExecutable(QStringLiteral("sh.exe")).isEmpty();
QChar separator = (!includepath.contains(":\\") && hasSh ? QChar(':') : QChar(';'));
qmakeVars += QString("TMPPATH = $$quote($$(INCLUDE))");
qmakeVars += QString("QMAKE_INCDIR_POST += $$split(TMPPATH,\"%1\")").arg(separator);
dictionary["SYNCQT"] = defaultTo("SYNCQT");
if (dictionary["SYNCQT"] == "yes") {
- if (findFile("perl.exe")) {
+ if (!QStandardPaths::findExecutable(QStringLiteral("perl.exe")).isEmpty()) {
cout << "Running syncqt..." << endl;
QStringList args;
args += buildPath + "/bin/syncqt.bat";
QString formatPaths(const QStringList &paths);
bool filesDiffer(const QString &file1, const QString &file2);
- bool findFile(const QString &fileName);
- static QString findFileInPaths(const QString &fileName, const QString &paths);
+ QString locateFile(const QString &fileName) const;
+ bool findFile(const QString &fileName) const { return !locateFile(fileName).isEmpty(); }
+ static QString findFileInPaths(const QString &fileName, const QStringList &paths);
#if !defined(EVAL)
void reloadCmdLine();
void saveCmdLine();
void desc(const char *option, const char *description, bool skipIndent = false, char fillChar = '.');
void desc(const char *mark_option, const char *mark, const char *option, const char *description, char fillChar = '.');
void applySpecSpecifics();
- static QString locateFile(const QString &fileName);
- static QString locateFileInPaths(const QString &fileName, const QStringList &paths);
};
class MakeItem
#include <qdir.h>
#include <qfile.h>
#include <qfileinfo.h>
+#include <qstandardpaths.h>
#include <process.h>
#include <errno.h>
return spec;
}
+Compiler Environment::compilerFromQMakeSpec(const QString &qmakeSpec)
+{
+ if (qmakeSpec == QLatin1String("win32-msvc2012"))
+ return CC_NET2012;
+ if (qmakeSpec == QLatin1String("win32-msvc2012"))
+ return CC_NET2010;
+ if (qmakeSpec == QLatin1String("win32-msvc2008"))
+ return CC_NET2008;
+ if (qmakeSpec == QLatin1String("win32-msvc2005"))
+ return CC_NET2005;
+ if (qmakeSpec == QLatin1String("win32-msvc2003"))
+ return CC_NET2003;
+ if (qmakeSpec == QLatin1String("win32-icc"))
+ return CC_INTEL;
+ if (qmakeSpec == QLatin1String("win32-g++"))
+ return CC_MINGW;
+ if (qmakeSpec == QLatin1String("win32-borland"))
+ return CC_BORLAND;
+ return CC_UNKNOWN;
+}
+
/*!
Returns the enum of the compiler which was detected on the system.
The compilers are detected in the order as entered into the
if (!installed) {
for(int i = 0; compiler_info[i].compiler; ++i) {
QString executable = QString(compiler_info[i].executable).toLower();
- if (executable.length() && Environment::detectExecutable(executable)) {
+ if (executable.length() && !QStandardPaths::findExecutable(executable).isEmpty()) {
if (detectedCompiler != compiler_info[i].compiler) {
++installed;
detectedCompiler = compiler_info[i].compiler;
};
/*!
- Returns true if the \a executable could be loaded, else false.
- This means that the executable either is in the current directory
- or in the PATH.
-*/
-bool Environment::detectExecutable(const QString &executable)
-{
- PROCESS_INFORMATION procInfo;
- memset(&procInfo, 0, sizeof(procInfo));
-
- STARTUPINFO startInfo;
- memset(&startInfo, 0, sizeof(startInfo));
- startInfo.cb = sizeof(startInfo);
-
- bool couldExecute = CreateProcess(0, (wchar_t*)executable.utf16(),
- 0, 0, false,
- CREATE_NO_WINDOW | CREATE_SUSPENDED,
- 0, 0, &startInfo, &procInfo);
-
- if (couldExecute) {
- CloseHandle(procInfo.hThread);
- TerminateProcess(procInfo.hProcess, 0);
- CloseHandle(procInfo.hProcess);
- }
- return couldExecute;
-}
-
-/*!
Creates a commandling from \a program and it \a arguments,
escaping characters that needs it.
*/
return result;
}
+static QStringList splitPathList(const QString &path)
+{
+#if defined(Q_OS_WIN)
+ QRegExp splitReg(QStringLiteral("[;,]"));
+#else
+ QRegExp splitReg(QStringLiteral("[:]"));
+#endif
+ QStringList result = path.split(splitReg, QString::SkipEmptyParts);
+ const QChar separator = QDir::separator();
+ const QStringList::iterator end = result.end();
+ for (QStringList::iterator it = result.begin(); it != end; ++it) {
+ // Remove any leading or trailing ", this is commonly used in the environment
+ // variables
+ if (it->startsWith('"'))
+ it->remove(0, 1);
+ if (it->endsWith('"'))
+ it->chop(1);
+ if (it->endsWith(separator))
+ it->chop(1);
+ }
+ return result;
+}
+
+QString Environment::findFileInPaths(const QString &fileName, const QStringList &paths)
+{
+ if (!paths.isEmpty()) {
+ QDir d;
+ const QChar separator = QDir::separator();
+ foreach (const QString &path, paths)
+ if (d.exists(path + separator + fileName))
+ return path;
+ }
+ return QString();
+}
+
+QStringList Environment::path()
+{
+ return splitPathList(QString::fromLocal8Bit(qgetenv("PATH")));
+}
+
+static QStringList mingwPaths(const QString &mingwPath, const QString &pathName)
+{
+ QStringList ret;
+ QDir mingwDir(mingwPath);
+ const QFileInfoList subdirs = mingwDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
+ for (int i = 0 ;i < subdirs.length(); ++i) {
+ const QFileInfo &fi = subdirs.at(i);
+ const QString name = fi.fileName();
+ if (name == pathName)
+ ret += fi.absoluteFilePath();
+ else if (name.contains(QLatin1String("mingw"))) {
+ ret += fi.absoluteFilePath() + QLatin1Char('/') + pathName;
+ }
+ }
+ return ret;
+}
+
+// Return MinGW location from "c:\mingw\bin" -> "c:\mingw"
+static inline QString detectMinGW()
+{
+ const QString gcc = QStandardPaths::findExecutable(QLatin1String("g++.exe"));
+ return gcc.isEmpty() ?
+ gcc : QFileInfo(QFileInfo(gcc).absolutePath()).absolutePath();
+}
+
+// Detect Direct X SDK up tp June 2010. Included in Windows Kit 8.
+QString Environment::detectDirectXSdk()
+{
+ const QByteArray directXSdkEnv = qgetenv("DXSDK_DIR");
+ if (directXSdkEnv.isEmpty())
+ return QString();
+ QString directXSdk = QDir::cleanPath(QString::fromLocal8Bit(directXSdkEnv));
+ if (directXSdk.endsWith(QLatin1Char('/')))
+ directXSdk.truncate(directXSdk.size() - 1);
+ return directXSdk;
+}
+
+QStringList Environment::headerPaths(Compiler compiler)
+{
+ QStringList headerPaths;
+ if (compiler == CC_MINGW) {
+ const QString mingwPath = detectMinGW();
+ headerPaths = mingwPaths(mingwPath, QLatin1String("include"));
+ // Additional compiler paths
+ const QFileInfoList mingwConfigs = QDir(mingwPath + QLatin1String("/lib/gcc")).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
+ for (int i = 0; i < mingwConfigs.length(); ++i) {
+ const QDir mingwLibDir = mingwConfigs.at(i).absoluteFilePath();
+ foreach (const QFileInfo &version, mingwLibDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot))
+ headerPaths += version.absoluteFilePath() + QLatin1String("/include");
+ }
+ } else {
+ headerPaths = splitPathList(QString::fromLocal8Bit(getenv("INCLUDE")));
+ }
+ // Add Direct X SDK for ANGLE
+ const QString directXSdk = detectDirectXSdk();
+ if (!directXSdk.isEmpty()) // Add Direct X SDK for ANGLE
+ headerPaths += directXSdk + QLatin1String("/include");
+ return headerPaths;
+}
+
+QStringList Environment::libraryPaths(Compiler compiler)
+{
+ QStringList libraryPaths;
+ if (compiler == CC_MINGW) {
+ libraryPaths = mingwPaths(detectMinGW(), "lib");
+ } else {
+ libraryPaths = splitPathList(QString::fromLocal8Bit(qgetenv("LIB")));
+ }
+ // Add Direct X SDK for ANGLE
+ const QString directXSdk = detectDirectXSdk();
+ if (!directXSdk.isEmpty()) {
+#ifdef Q_OS_WIN64
+ libraryPaths += directXSdk + QLatin1String("/lib/x64");
+#else
+ libraryPaths += directXSdk + QLatin1String("/lib/x86");
+#endif
+ }
+ return libraryPaths;
+}
+
QT_END_NAMESPACE
**
****************************************************************************/
-#include <qstring.h>
-#include <qt_windows.h>
+#include <qstringlist.h>
QT_BEGIN_NAMESPACE
public:
static Compiler detectCompiler();
static QString detectQMakeSpec();
- static bool detectExecutable(const QString &executable);
+ static Compiler compilerFromQMakeSpec(const QString &qmakeSpec);
static int execute(QStringList arguments, const QStringList &additionalEnv, const QStringList &removeEnv);
static QString execute(const QString &command, int *returnCode = 0);
static bool cpdir(const QString &srcDir, const QString &destDir);
static bool rmdir(const QString &name);
+ static QString findFileInPaths(const QString &fileName, const QStringList &paths);
+ static QStringList path();
+
+ static QString detectDirectXSdk();
+ static QStringList headerPaths(Compiler compiler);
+ static QStringList libraryPaths(Compiler compiler);
+
private:
static Compiler detectedCompiler;