QPair<bool, QStringList> precompile(const PchInfo::Ptr &pchInfo) { // qDebug() << "*** Precompiling" << pchInfo->inputFileName() // << "into" << pchInfo->fileName() // << "with options" << pchInfo->options(); bool ok = false; Internal::Unit unit(pchInfo->inputFileName()); unit.setCompilationOptions(pchInfo->options()); unsigned parseOpts = CXTranslationUnit_ForSerialization | CXTranslationUnit_Incomplete; unit.setManagementOptions(parseOpts); unit.parse(); if (unit.isLoaded()) ok = CXSaveError_None == unit.save(pchInfo->fileName()); return qMakePair(ok, Internal::formattedDiagnostics(unit)); }
void PchManager::setPCHInfo(const QList<ProjectPart::Ptr> &projectParts, const PchInfo::Ptr &pchInfo, const QPair<bool, QStringList> &msgs) { QMutexLocker locker(&m_mutex); foreach (ProjectPart::Ptr pPart, projectParts) m_activePchFiles[pPart] = pchInfo; if (pchInfo) { if (msgs.first) { if (!pchInfo->fileName().isEmpty()) emit pchMessage(tr("Successfully generated PCH file \"%1\".").arg( pchInfo->fileName()), Core::MessageManager::Silent); } else { emit pchMessage(tr("Failed to generate PCH file \"%1\".").arg( pchInfo->fileName()), Core::MessageManager::Silent); } if (!msgs.second.isEmpty()) emit pchMessage(msgs.second.join(QLatin1String("\n")), Core::MessageManager::Flash); } }
void PchManager::doPchInfoUpdate(QFutureInterface<void> &future, ClangProjectSettings::PchUsage pchUsage, const QString customPchFile, const QList<ProjectPart::Ptr> projectParts) { PchManager *pchManager = PchManager::instance(); // qDebug() << "switching to" << pchUsage; if (pchUsage == ClangProjectSettings::PchUse_None || (pchUsage == ClangProjectSettings::PchUse_Custom && customPchFile.isEmpty())) { future.setProgressRange(0, 2); Core::MessageManager::write(QLatin1String("updatePchInfo: switching to none"), Core::MessageManager::Silent); PchInfo::Ptr emptyPch = PchInfo::createEmpty(); pchManager->setPCHInfo(projectParts, emptyPch, qMakePair(true, QStringList())); future.setProgressValue(1); } else if (pchUsage == ClangProjectSettings::PchUse_BuildSystem_Fuzzy) { Core::MessageManager::write( QLatin1String("updatePchInfo: switching to build system (fuzzy)"), Core::MessageManager::Silent); QHash<QString, QSet<QString> > includes, frameworks; QHash<QString, QSet<QByteArray> > definesPerPCH; QHash<QString, bool> objc; QHash<QString, bool> cplusplus; QHash<QString, ProjectPart::QtVersion> qtVersions; QHash<QString, ProjectPart::CVersion> cVersions; QHash<QString, ProjectPart::CXXVersion> cxxVersions; QHash<QString, ProjectPart::CXXExtensions> cxxExtensionsMap; QHash<QString, QList<ProjectPart::Ptr> > inputToParts; foreach (const ProjectPart::Ptr &projectPart, projectParts) { if (projectPart->precompiledHeaders.isEmpty()) continue; const QString &pch = projectPart->precompiledHeaders.first(); // TODO: support more than 1 PCH file. if (!QFile(pch).exists()) continue; inputToParts[pch].append(projectPart); includes[pch].unite(QSet<QString>::fromList(projectPart->includePaths)); frameworks[pch].unite(QSet<QString>::fromList(projectPart->frameworkPaths)); cVersions[pch] = std::max(cVersions.value(pch, ProjectPart::C89), projectPart->cVersion); cxxVersions[pch] = std::max(cxxVersions.value(pch, ProjectPart::CXX98), projectPart->cxxVersion); cxxExtensionsMap[pch] = cxxExtensionsMap[pch] | projectPart->cxxExtensions; if (hasObjCFiles(projectPart)) objc[pch] = true; if (hasCppFiles(projectPart)) cplusplus[pch] = true; QSet<QByteArray> projectDefines = QSet<QByteArray>::fromList(projectPart->toolchainDefines.split('\n')); QMutableSetIterator<QByteArray> iter(projectDefines); while (iter.hasNext()){ QByteArray v = iter.next(); if (v.startsWith("#define _") || v.isEmpty()) // TODO: see ProjectPart::createClangOptions iter.remove(); } projectDefines.unite(QSet<QByteArray>::fromList(projectPart->projectDefines.split('\n'))); if (definesPerPCH.contains(pch)) { definesPerPCH[pch].intersect(projectDefines); } else { definesPerPCH[pch] = projectDefines; } qtVersions[pch] = projectPart->qtVersion; } future.setProgressRange(0, definesPerPCH.size() + 1); future.setProgressValue(0); foreach (const QString &pch, inputToParts.keys()) { if (future.isCanceled()) return; ProjectPart::Ptr projectPart(new ProjectPart); projectPart->qtVersion = qtVersions[pch]; projectPart->cVersion = cVersions[pch]; projectPart->cxxVersion = cxxVersions[pch]; projectPart->cxxExtensions = cxxExtensionsMap[pch]; projectPart->includePaths = includes[pch].toList(); projectPart->frameworkPaths = frameworks[pch].toList(); QList<QByteArray> defines = definesPerPCH[pch].toList(); if (!defines.isEmpty()) { projectPart->projectDefines = defines[0]; for (int i = 1; i < defines.size(); ++i) { projectPart->projectDefines += '\n'; projectPart->projectDefines += defines[i]; } } CppTools::ProjectFile::Kind prefixFileKind = getPrefixFileKind(objc.value(pch, false), cplusplus.value(pch, false)); QStringList options = Utils::createClangOptions(projectPart, prefixFileKind); projectPart.reset(); PchInfo::Ptr pchInfo = pchManager->findMatchingPCH(pch, options, true); QPair<bool, QStringList> msgs = qMakePair(true, QStringList()); if (pchInfo.isNull()) { pchInfo = PchInfo::createWithFileName(pch, options, objc[pch]); msgs = precompile(pchInfo); } pchManager->setPCHInfo(inputToParts[pch], pchInfo, msgs); future.setProgressValue(future.progressValue() + 1); } } else if (pchUsage == ClangProjectSettings::PchUse_BuildSystem_Exact) {