示例#1
0
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));
}
示例#2
0
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);
    }
}
示例#3
0
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) {