| |   |
| 35 | 35 | #include "msvcparser.h" |
| 36 | 36 | #include "linuxiccparser.h" |
| 37 | 37 | |
|
| #include <utils/synchronousprocess.h> |
|
| 38 | 41 | #include <QtCore/QDebug> |
| 39 | 42 | #include <QtCore/QFileInfo> |
| 40 | 43 | #include <QtCore/QProcess> |
| … | … | |
| 178 | 178 | return ToolChain::GCC; |
| 179 | 179 | } |
| 180 | 180 | |
| QByteArray GccToolChain::predefinedMacros() |
| static QByteArray gccPredefinedMacros(const QString &gcc, const QStringList &env) |
| 182 | 182 | { |
| if (m_predefinedMacros.isEmpty()) { |
| QStringList arguments; |
| arguments << QLatin1String("-xc++") |
| << QLatin1String("-E") |
| << QLatin1String("-dM") |
| << QLatin1String("-"); |
| QStringList arguments; |
| arguments << QLatin1String("-xc++") |
| << QLatin1String("-E") |
| << QLatin1String("-dM") |
| << QLatin1String("-"); |
| 189 | 188 | |
| QProcess cpp; |
| ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment(); |
| addToEnvironment(env); |
| cpp.setEnvironment(env.toStringList()); |
| cpp.start(m_gcc, arguments); |
| cpp.closeWriteChannel(); |
| cpp.waitForFinished(); |
| m_predefinedMacros = cpp.readAllStandardOutput(); |
| QProcess cpp; |
| cpp.setEnvironment(env); |
| cpp.start(gcc, arguments); |
| if (!cpp.waitForStarted()) { |
| qWarning("Cannot start '%s': %s", qPrintable(gcc), qPrintable(cpp.errorString())); |
| return QByteArray(); |
| } |
| cpp.closeWriteChannel(); |
| if (!cpp.waitForFinished()) { |
| Utils::SynchronousProcess::stopProcess(cpp); |
| qWarning("Timeout running '%s'.", qPrintable(gcc)); |
| return QByteArray(); |
| } |
| 198 | 202 | |
| QByteArray predefinedMacros = cpp.readAllStandardOutput(); |
| 199 | 204 | #ifdef Q_OS_MAC |
| // Turn off flag indicating Apple's blocks support |
| const QByteArray blocksDefine("#define __BLOCKS__ 1"); |
| const QByteArray blocksUndefine("#undef __BLOCKS__"); |
| int idx = m_predefinedMacros.indexOf(blocksDefine); |
| if (idx != -1) { |
| m_predefinedMacros.replace(idx, blocksDefine.length(), blocksUndefine); |
| } |
| // Turn off flag indicating Apple's blocks support |
| const QByteArray blocksDefine("#define __BLOCKS__ 1"); |
| const QByteArray blocksUndefine("#undef __BLOCKS__"); |
| const int idx = predefinedMacros.indexOf(blocksDefine); |
| if (idx != -1) { |
| predefinedMacros.replace(idx, blocksDefine.length(), blocksUndefine); |
| } |
| 207 | 212 | |
| // Define __strong and __weak (used for Apple's GC extension of C) to be empty |
| m_predefinedMacros.append("#define __strong\n"); |
| m_predefinedMacros.append("#define __weak\n"); |
| // Define __strong and __weak (used for Apple's GC extension of C) to be empty |
| predefinedMacros.append("#define __strong\n"); |
| predefinedMacros.append("#define __weak\n"); |
| 211 | 216 | #endif // Q_OS_MAC |
| return predefinedMacros; |
| } |
|
| QByteArray GccToolChain::predefinedMacros() |
| { |
| if (m_predefinedMacros.isEmpty()) { |
| ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment(); |
| addToEnvironment(env); |
| m_predefinedMacros = gccPredefinedMacros(m_gcc, env.toStringList()); |
| 212 | 226 | } |
| 213 | 227 | return m_predefinedMacros; |
| 214 | 228 | } |
| 215 | 229 | |
| QList<HeaderPath> GccToolChain::systemHeaderPaths() |
| static QList<HeaderPath> gccSystemHeaderPaths(const QString &gcc, ProjectExplorer::Environment env) |
| 217 | 231 | { |
| if (m_systemHeaderPaths.isEmpty()) { |
| QStringList arguments; |
| arguments << QLatin1String("-xc++") |
| << QLatin1String("-E") |
| << QLatin1String("-v") |
| << QLatin1String("-"); |
| QList<HeaderPath> systemHeaderPaths; |
| QStringList arguments; |
| arguments << QLatin1String("-xc++") |
| << QLatin1String("-E") |
| << QLatin1String("-v") |
| << QLatin1String("-"); |
| 224 | 238 | |
| QProcess cpp; |
| ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment(); |
| addToEnvironment(env); |
| env.set(QLatin1String("LC_ALL"), QLatin1String("C")); //override current locale settings |
| cpp.setEnvironment(env.toStringList()); |
| cpp.setReadChannelMode(QProcess::MergedChannels); |
| cpp.start(m_gcc, arguments); |
| cpp.closeWriteChannel(); |
| cpp.waitForFinished(); |
| QProcess cpp; |
| env.set(QLatin1String("LC_ALL"), QLatin1String("C")); //override current locale settings |
| cpp.setEnvironment(env.toStringList()); |
| cpp.setReadChannelMode(QProcess::MergedChannels); |
| cpp.start(gcc, arguments); |
| if (!cpp.waitForStarted()) { |
| qWarning("Cannot start '%s': %s", qPrintable(gcc), qPrintable(cpp.errorString())); |
| return systemHeaderPaths; |
| } |
| cpp.closeWriteChannel(); |
| if (!cpp.waitForFinished()) { |
| Utils::SynchronousProcess::stopProcess(cpp); |
| qWarning("Timeout running '%s'.", qPrintable(gcc)); |
| return systemHeaderPaths; |
| } |
| 234 | 254 | |
| QByteArray line; |
| QByteArray line; |
| while (cpp.canReadLine()) { |
| line = cpp.readLine(); |
| if (line.startsWith("#include")) |
| break; |
| } |
|
| if (! line.isEmpty() && line.startsWith("#include")) { |
| HeaderPath::Kind kind = HeaderPath::UserHeaderPath; |
| 236 | 264 | while (cpp.canReadLine()) { |
| 237 | 265 | line = cpp.readLine(); |
| if (line.startsWith("#include")) |
| break; |
| } |
| if (line.startsWith("#include")) { |
| kind = HeaderPath::GlobalHeaderPath; |
| } else if (! line.isEmpty() && QChar(line.at(0)).isSpace()) { |
| HeaderPath::Kind thisHeaderKind = kind; |
| 241 | 270 | |
| if (! line.isEmpty() && line.startsWith("#include")) { |
| HeaderPath::Kind kind = HeaderPath::UserHeaderPath; |
| while (cpp.canReadLine()) { |
| line = cpp.readLine(); |
| if (line.startsWith("#include")) { |
| kind = HeaderPath::GlobalHeaderPath; |
| } else if (! line.isEmpty() && QChar(line.at(0)).isSpace()) { |
| HeaderPath::Kind thisHeaderKind = kind; |
| line = line.trimmed(); |
| if (line.endsWith('\n')) |
| line.chop(1); |
| 250 | 274 | |
| line = line.trimmed(); |
| if (line.endsWith('\n')) |
| line.chop(1); |
|
| int index = line.indexOf(" (framework directory)"); |
| if (index != -1) { |
| line = line.left(index); |
| thisHeaderKind = HeaderPath::FrameworkHeaderPath; |
| } |
|
| m_systemHeaderPaths.append(HeaderPath(QFile::decodeName(line), thisHeaderKind)); |
| } else if (line.startsWith("End of search list.")) { |
| break; |
| } else { |
| qWarning() << "ignore line:" << line; |
| const int index = line.indexOf(" (framework directory)"); |
| if (index != -1) { |
| line.truncate(index); |
| thisHeaderKind = HeaderPath::FrameworkHeaderPath; |
| 266 | 279 | } |
|
| systemHeaderPaths.append(HeaderPath(QFile::decodeName(line), thisHeaderKind)); |
| } else if (line.startsWith("End of search list.")) { |
| break; |
| } else { |
| qWarning() << "ignore line:" << line; |
| 267 | 286 | } |
| 268 | 287 | } |
| 269 | 288 | } |
| return systemHeaderPaths; |
| } |
|
| QList<HeaderPath> GccToolChain::systemHeaderPaths() |
| { |
| if (m_systemHeaderPaths.isEmpty()) { |
| ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment(); |
| addToEnvironment(env); |
| m_systemHeaderPaths = gccSystemHeaderPaths(m_gcc, env); |
| } |
| 270 | 299 | return m_systemHeaderPaths; |
| 271 | 300 | } |
| 272 | 301 | |
| … | … | |
| 619 | 619 | return file; |
| 620 | 620 | } |
| 621 | 621 | |
| QByteArray MSVCToolChain::predefinedMacros() |
| // Run MSVC 'cl' compiler to obtain #defines. |
| static QByteArray msvcPredefinedMacros(const QStringList &env) |
| 623 | 624 | { |
| if (m_predefinedMacros.isEmpty()) { |
| m_predefinedMacros += "#define __MSVCRT__\n" |
| "#define __w64\n" |
| "#define __int64 long long\n" |
| "#define __int32 long\n" |
| "#define __int16 short\n" |
| "#define __int8 char\n" |
| "#define __ptr32\n" |
| "#define __ptr64\n"; |
| QByteArray predefinedMacros = "#define __MSVCRT__\n" |
| "#define __w64\n" |
| "#define __int64 long long\n" |
| "#define __int32 long\n" |
| "#define __int16 short\n" |
| "#define __int8 char\n" |
| "#define __ptr32\n" |
| "#define __ptr64\n"; |
| 633 | 633 | |
| QString tmpFilePath; |
| { |
| // QTemporaryFile is buggy and will not unlock the file for cl.exe |
| QTemporaryFile tmpFile(QDir::tempPath()+"/envtestXXXXXX.cpp"); |
| tmpFile.setAutoRemove(false); |
| if (!tmpFile.open()) |
| return m_predefinedMacros; |
| tmpFilePath = QFileInfo(tmpFile).canonicalFilePath(); |
| tmpFile.write(msvcCompilationFile()); |
| tmpFile.close(); |
| QString tmpFilePath; |
| { |
| // QTemporaryFile is buggy and will not unlock the file for cl.exe |
| QTemporaryFile tmpFile(QDir::tempPath()+"/envtestXXXXXX.cpp"); |
| tmpFile.setAutoRemove(false); |
| if (!tmpFile.open()) |
| return predefinedMacros; |
| tmpFilePath = QFileInfo(tmpFile).canonicalFilePath(); |
| tmpFile.write(msvcCompilationFile()); |
| tmpFile.close(); |
| } |
| QProcess cpp; |
| cpp.setEnvironment(env); |
| cpp.setWorkingDirectory(QDir::tempPath()); |
| QStringList arguments; |
| const QString binary = QLatin1String("cl.exe"); |
| arguments << QLatin1String("/EP") << QDir::toNativeSeparators(tmpFilePath); |
| cpp.start(QLatin1String("cl.exe"), arguments); |
| if (!cpp.waitForStarted()) { |
| qWarning("Cannot start '%s': %s", qPrintable(binary), qPrintable(cpp.errorString())); |
| return predefinedMacros; |
| } |
| cpp.closeWriteChannel(); |
| if (!cpp.waitForFinished()) { |
| Utils::SynchronousProcess::stopProcess(cpp); |
| qWarning("Timeout running '%s'.", qPrintable(binary)); |
| return predefinedMacros; |
| } |
| const QList<QByteArray> output = cpp.readAllStandardOutput().split('\n'); |
| foreach (const QByteArray& line, output) { |
| if (line.startsWith('V')) { |
| QList<QByteArray> split = line.split('='); |
| const QByteArray key = split.at(0).mid(1); |
| QByteArray value = split.at(1); |
| if (!value.isEmpty()) { |
| value.chop(1); //remove '\n' |
| } |
| predefinedMacros += "#define "; |
| predefinedMacros += key; |
| predefinedMacros += ' '; |
| predefinedMacros += value; |
| predefinedMacros += '\n'; |
| 644 | 676 | } |
| } |
| QFile::remove(tmpFilePath); |
| return predefinedMacros; |
| } |
|
| QByteArray MSVCToolChain::predefinedMacros() |
| { |
| if (m_predefinedMacros.isEmpty()) { |
| 645 | 685 | ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment(); |
| 646 | 686 | addToEnvironment(env); |
| QProcess cpp; |
| cpp.setEnvironment(env.toStringList()); |
| cpp.setWorkingDirectory(QDir::tempPath()); |
| QStringList arguments; |
| arguments << "/EP" << QDir::toNativeSeparators(tmpFilePath); |
| cpp.start(QLatin1String("cl.exe"), arguments); |
| cpp.closeWriteChannel(); |
| cpp.waitForFinished(); |
| QList<QByteArray> output = cpp.readAllStandardOutput().split('\n'); |
| foreach (const QByteArray& line, output) { |
| if (line.startsWith('V')) { |
| QList<QByteArray> split = line.split('='); |
| QByteArray key = split.at(0).mid(1); |
| QByteArray value = split.at(1); |
| if (!value.isEmpty()) { |
| value.chop(1); //remove '\n' |
| } |
| QByteArray newDefine = "#define " + key + ' ' + value + '\n'; |
| m_predefinedMacros.append(newDefine); |
| } |
| } |
| QFile::remove(tmpFilePath); |
| m_predefinedMacros = msvcPredefinedMacros(env.toStringList()); |
| 669 | 688 | } |
| 670 | 689 | return m_predefinedMacros; |
| 671 | 690 | } |
| … | … | |
| 763 | 763 | } |
| 764 | 764 | call += "\r\n"; |
| 765 | 765 | tf.write(call); |
| QString redirect = "set > \"" + tempOutputFileName + "\"\r\n"; |
| tf.write(redirect.toLocal8Bit()); |
| const QByteArray redirect = "set > \"" + QDir::toNativeSeparators(tempOutputFileName).toLocal8Bit() + "\"\r\n"; |
| tf.write(redirect); |
| 768 | 768 | tf.flush(); |
| 769 | 769 | tf.waitForBytesWritten(30000); |
| 770 | 770 | |
| 771 | 771 | QProcess run; |
| 772 | 772 | run.setEnvironment(env.toStringList()); |
| 773 | 773 | const QString cmdPath = QString::fromLocal8Bit(qgetenv("COMSPEC")); |
| run.start(cmdPath, QStringList()<< QLatin1String("/c")<<filename); |
| if (!run.waitForStarted() || !run.waitForFinished()) |
| run.start(cmdPath, QStringList()<< QLatin1String("/c")<<QDir::toNativeSeparators(filename)); |
| if (!run.waitForStarted()) { |
| qWarning("Unable to run '%s': %s", qPrintable(varsBat), qPrintable(run.errorString())); |
| 776 | 777 | return StringStringPairList(); |
| } |
| if (!run.waitForFinished()) { |
| qWarning("Timeout running '%s'", qPrintable(varsBat)); |
| Utils::SynchronousProcess::stopProcess(run); |
| return StringStringPairList(); |
| } |
| 777 | 784 | tf.close(); |
| 778 | 785 | |
| 779 | 786 | QFile varsFile(tempOutputFileName); |