Improve path search in configure.

- 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>
This commit is contained in:
Friedemann Kleint 2012-11-01 14:31:16 +01:00 committed by The Qt Project
parent 227accf0a3
commit 9c2ec72b95
7 changed files with 183 additions and 143 deletions

View File

@ -52,6 +52,8 @@ OBJECTS = \
qtextstream.o \ qtextstream.o \
qlogging.o \ qlogging.o \
qtemporaryfile.o \ qtemporaryfile.o \
qstandardpaths.o \
qstandardpaths_win.o \
qsystemlibrary.o \ qsystemlibrary.o \
qbitarray.o \ qbitarray.o \
qdatetime.o \ qdatetime.o \

View File

@ -50,6 +50,8 @@ OBJECTS = \
qtextstream.obj \ qtextstream.obj \
qlogging.obj \ qlogging.obj \
qtemporaryfile.obj \ qtemporaryfile.obj \
qstandardpaths.obj \
qstandardpaths_win.obj \
qsystemlibrary.obj \ qsystemlibrary.obj \
qbitarray.obj \ qbitarray.obj \
qdatetime.obj \ qdatetime.obj \
@ -119,6 +121,8 @@ qfsfileengine_iterator.obj: $(CORESRC)\io\qfsfileengine_iterator.cpp $(PCH)
qiodevice.obj: $(CORESRC)\io\qiodevice.cpp $(PCH) qiodevice.obj: $(CORESRC)\io\qiodevice.cpp $(PCH)
qtextstream.obj: $(CORESRC)\io\qtextstream.cpp $(PCH) qtextstream.obj: $(CORESRC)\io\qtextstream.cpp $(PCH)
qtemporaryfile.obj: $(CORESRC)\io\qtemporaryfile.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) qsystemlibrary.obj: $(CORESRC)\plugin\qsystemlibrary.cpp $(PCH)
qbitarray.obj: $(CORESRC)\tools\qbitarray.cpp $(PCH) qbitarray.obj: $(CORESRC)\tools\qbitarray.cpp $(PCH)
qdatetime.obj: $(CORESRC)\tools\qdatetime.cpp $(PCH) qdatetime.obj: $(CORESRC)\tools\qdatetime.cpp $(PCH)

View File

@ -63,6 +63,7 @@ HEADERS = configureapp.h environment.h tools.h\
$$QT_SOURCE_TREE/src/corelib/io/qiodevice.h \ $$QT_SOURCE_TREE/src/corelib/io/qiodevice.h \
$$QT_SOURCE_TREE/src/corelib/io/qtextstream.h \ $$QT_SOURCE_TREE/src/corelib/io/qtextstream.h \
$$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.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/qbitarray.h \
$$QT_SOURCE_TREE/src/corelib/tools/qdatetime.h \ $$QT_SOURCE_TREE/src/corelib/tools/qdatetime.h \
$$QT_SOURCE_TREE/src/corelib/tools/qmap.h \ $$QT_SOURCE_TREE/src/corelib/tools/qmap.h \
@ -110,6 +111,8 @@ SOURCES = main.cpp configureapp.cpp environment.cpp tools.cpp \
$$QT_SOURCE_TREE/src/corelib/io/qiodevice.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qiodevice.cpp \
$$QT_SOURCE_TREE/src/corelib/io/qtextstream.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qtextstream.cpp \
$$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.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/plugin/qsystemlibrary.cpp \
$$QT_SOURCE_TREE/src/corelib/tools/qbitarray.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qbitarray.cpp \
$$QT_SOURCE_TREE/src/corelib/tools/qdatetime.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qdatetime.cpp \

View File

@ -49,6 +49,7 @@
#include <qdir.h> #include <qdir.h>
#include <qdiriterator.h> #include <qdiriterator.h>
#include <qtemporaryfile.h> #include <qtemporaryfile.h>
#include <qstandardpaths.h>
#include <qstack.h> #include <qstack.h>
#include <qdebug.h> #include <qdebug.h>
#include <qfileinfo.h> #include <qfileinfo.h>
@ -142,7 +143,7 @@ Configure::Configure(int& argc, char** argv)
const QString installPath = buildPath; const QString installPath = buildPath;
#endif #endif
if (sourceDir != buildDir) { //shadow builds! 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 cout << "Error: Creating a shadow build of Qt requires" << endl
<< "perl to be in the PATH environment"; << "perl to be in the PATH environment";
exit(0); // Exit cleanly for Ctrl+C exit(0); // Exit cleanly for Ctrl+C
@ -1521,42 +1522,6 @@ void Configure::applySpecSpecifics()
} }
} }
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 ]- // Output helper functions ---------------------------------[ Stop ]-
@ -1830,80 +1795,25 @@ bool Configure::displayHelp()
return false; return false;
} }
QString Configure::findFileInPaths(const QString &fileName, const QString &paths) // Locate a file and return its containing directory.
{ QString Configure::locateFile(const QString &fileName) const
#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)
{ {
const QString file = fileName.toLower(); const QString file = fileName.toLower();
const QString pathEnvVar = QString::fromLocal8Bit(getenv("PATH")); QStringList pathList;
const QString mingwPath = dictionary["QMAKESPEC"].endsWith("-g++") ?
findFileInPaths("g++.exe", pathEnvVar) : QString();
QString paths;
if (file.endsWith(".h")) { if (file.endsWith(".h")) {
if (!mingwPath.isNull()) { static const QStringList headerPaths =
if (!findFileInPaths(file, mingwPaths(mingwPath, "include")).isNull()) Environment::headerPaths(Environment::compilerFromQMakeSpec(dictionary[QStringLiteral("QMAKESPEC")]));
return true; pathList = headerPaths;
//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");
} else if (file.endsWith(".lib") || file.endsWith(".a")) { } else if (file.endsWith(".lib") || file.endsWith(".a")) {
if (!mingwPath.isNull() && !findFileInPaths(file, mingwPaths(mingwPath, "lib")).isNull()) static const QStringList libPaths =
return true; Environment::libraryPaths(Environment::compilerFromQMakeSpec(dictionary[QStringLiteral("QMAKESPEC")]));
paths = QString::fromLocal8Bit(getenv("LIB")); pathList = libPaths;
} else { } 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);
} }
/*! /*!
@ -2058,7 +1968,8 @@ bool Configure::checkAvailability(const QString &part)
dictionary[ "DONE" ] = "error"; dictionary[ "DONE" ] = "error";
} }
} else if (part == "INCREDIBUILD_XGE") { } 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") { } else if (part == "WMSDK") {
available = findFile("wmsdk.h"); available = findFile("wmsdk.h");
} else if (part == "V8SNAPSHOT") { } else if (part == "V8SNAPSHOT") {
@ -2673,7 +2584,7 @@ void Configure::generateOutputVars()
if (dictionary["QMAKESPEC"].endsWith("-g++")) { if (dictionary["QMAKESPEC"].endsWith("-g++")) {
QString includepath = qgetenv("INCLUDE"); 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(';')); QChar separator = (!includepath.contains(":\\") && hasSh ? QChar(':') : QChar(';'));
qmakeVars += QString("TMPPATH = $$quote($$(INCLUDE))"); qmakeVars += QString("TMPPATH = $$quote($$(INCLUDE))");
qmakeVars += QString("QMAKE_INCDIR_POST += $$split(TMPPATH,\"%1\")").arg(separator); qmakeVars += QString("QMAKE_INCDIR_POST += $$split(TMPPATH,\"%1\")").arg(separator);
@ -3461,7 +3372,7 @@ void Configure::generateHeaders()
dictionary["SYNCQT"] = defaultTo("SYNCQT"); dictionary["SYNCQT"] = defaultTo("SYNCQT");
if (dictionary["SYNCQT"] == "yes") { if (dictionary["SYNCQT"] == "yes") {
if (findFile("perl.exe")) { if (!QStandardPaths::findExecutable(QStringLiteral("perl.exe")).isEmpty()) {
cout << "Running syncqt..." << endl; cout << "Running syncqt..." << endl;
QStringList args; QStringList args;
args += buildPath + "/bin/syncqt.bat"; args += buildPath + "/bin/syncqt.bat";

View File

@ -167,8 +167,9 @@ private:
QString formatPaths(const QStringList &paths); QString formatPaths(const QStringList &paths);
bool filesDiffer(const QString &file1, const QString &file2); bool filesDiffer(const QString &file1, const QString &file2);
bool findFile(const QString &fileName); QString locateFile(const QString &fileName) const;
static QString findFileInPaths(const QString &fileName, const QString &paths); bool findFile(const QString &fileName) const { return !locateFile(fileName).isEmpty(); }
static QString findFileInPaths(const QString &fileName, const QStringList &paths);
#if !defined(EVAL) #if !defined(EVAL)
void reloadCmdLine(); void reloadCmdLine();
void saveCmdLine(); void saveCmdLine();
@ -181,8 +182,6 @@ private:
void desc(const char *option, const char *description, bool skipIndent = false, char fillChar = '.'); 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 desc(const char *mark_option, const char *mark, const char *option, const char *description, char fillChar = '.');
void applySpecSpecifics(); void applySpecSpecifics();
static QString locateFile(const QString &fileName);
static QString locateFileInPaths(const QString &fileName, const QStringList &paths);
}; };
class MakeItem class MakeItem

View File

@ -47,6 +47,7 @@
#include <qdir.h> #include <qdir.h>
#include <qfile.h> #include <qfile.h>
#include <qfileinfo.h> #include <qfileinfo.h>
#include <qstandardpaths.h>
#include <process.h> #include <process.h>
#include <errno.h> #include <errno.h>
@ -141,6 +142,27 @@ QString Environment::detectQMakeSpec()
return spec; 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. Returns the enum of the compiler which was detected on the system.
The compilers are detected in the order as entered into the The compilers are detected in the order as entered into the
@ -189,7 +211,7 @@ Compiler Environment::detectCompiler()
if (!installed) { if (!installed) {
for(int i = 0; compiler_info[i].compiler; ++i) { for(int i = 0; compiler_info[i].compiler; ++i) {
QString executable = QString(compiler_info[i].executable).toLower(); 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) { if (detectedCompiler != compiler_info[i].compiler) {
++installed; ++installed;
detectedCompiler = compiler_info[i].compiler; detectedCompiler = compiler_info[i].compiler;
@ -215,33 +237,6 @@ Compiler Environment::detectCompiler()
#endif #endif
}; };
/*!
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, Creates a commandling from \a program and it \a arguments,
escaping characters that needs it. escaping characters that needs it.
@ -514,4 +509,124 @@ bool Environment::rmdir(const QString &name)
return result; 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 QT_END_NAMESPACE

View File

@ -39,8 +39,7 @@
** **
****************************************************************************/ ****************************************************************************/
#include <qstring.h> #include <qstringlist.h>
#include <qt_windows.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -63,13 +62,20 @@ class Environment
public: public:
static Compiler detectCompiler(); static Compiler detectCompiler();
static QString detectQMakeSpec(); 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 int execute(QStringList arguments, const QStringList &additionalEnv, const QStringList &removeEnv);
static QString execute(const QString &command, int *returnCode = 0); static QString execute(const QString &command, int *returnCode = 0);
static bool cpdir(const QString &srcDir, const QString &destDir); static bool cpdir(const QString &srcDir, const QString &destDir);
static bool rmdir(const QString &name); 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: private:
static Compiler detectedCompiler; static Compiler detectedCompiler;