summaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2017-01-30 11:24:46 +0100
committerMarco Bubke <marco.bubke@qt.io>2017-01-30 13:55:58 +0000
commitc072cdfb8876df773da11222a35b7062dee2ad29 (patch)
tree954c931d5fed150fe4cb14d92a8aeb7285a27794 /src/tools
parentd4b1cb4a65510477d0bc4a888e66c67da6e28237 (diff)
downloadqt-creator-c072cdfb8876df773da11222a35b7062dee2ad29.tar.gz
Clang: Add ClangPchManager
Compiling every header file again and again is quite time comsuming. There are technics to improve this like preambles(a kind of automated precompiled header) but they don't share their data between translation units. This approach provides an automatically generated precompiled header for every project and subproject to improve the loading time. Change-Id: I34f5bd4db21951175920e2a9bbf6b97b1d705969 Reviewed-by: Eike Ziller <eike.ziller@qt.io> Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/clangpchmanagerbackend/clangpchmanagerbackend.pro34
-rw-r--r--src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp108
-rw-r--r--src/tools/clangpchmanagerbackend/source/clangpathwatcher.cpp42
-rw-r--r--src/tools/clangpchmanagerbackend/source/clangpathwatcher.h392
-rw-r--r--src/tools/clangpchmanagerbackend/source/clangpathwatcherinterface.cpp35
-rw-r--r--src/tools/clangpchmanagerbackend/source/clangpathwatcherinterface.h47
-rw-r--r--src/tools/clangpchmanagerbackend/source/clangpathwatchernotifier.cpp35
-rw-r--r--src/tools/clangpchmanagerbackend/source/clangpathwatchernotifier.h40
-rw-r--r--src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri32
-rw-r--r--src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend_global.h52
-rw-r--r--src/tools/clangpchmanagerbackend/source/collectincludesaction.h85
-rw-r--r--src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h114
-rw-r--r--src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h62
-rw-r--r--src/tools/clangpchmanagerbackend/source/environment.h39
-rw-r--r--src/tools/clangpchmanagerbackend/source/idpaths.cpp41
-rw-r--r--src/tools/clangpchmanagerbackend/source/idpaths.h48
-rw-r--r--src/tools/clangpchmanagerbackend/source/includecollector.cpp82
-rw-r--r--src/tools/clangpchmanagerbackend/source/includecollector.h55
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchcreator.cpp518
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchcreator.h121
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchcreatorinterface.cpp35
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchcreatorinterface.h45
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp82
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchmanagerserver.h61
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchnotcreatederror.h36
-rw-r--r--src/tools/clangpchmanagerbackend/source/projectparts.cpp121
-rw-r--r--src/tools/clangpchmanagerbackend/source/projectparts.h57
-rw-r--r--src/tools/clangpchmanagerbackend/source/projectpartsinterface.cpp34
-rw-r--r--src/tools/clangpchmanagerbackend/source/projectpartsinterface.h42
-rw-r--r--src/tools/clangpchmanagerbackend/source/stringcache.h160
-rw-r--r--src/tools/tools.pro3
31 files changed, 2657 insertions, 1 deletions
diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackend.pro b/src/tools/clangpchmanagerbackend/clangpchmanagerbackend.pro
new file mode 100644
index 0000000000..d3563c029e
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackend.pro
@@ -0,0 +1,34 @@
+QTC_LIB_DEPENDS += \
+ clangbackendipc
+
+include(../../qtcreatortool.pri)
+include(../../shared/clang/clang_installation.pri)
+include(source/clangpchmanagerbackend-source.pri)
+
+win32 {
+ LLVM_BUILDMODE = $$system($$llvm_config --build-mode, lines)
+ CONFIG(debug, debug|release):requires(equals(LLVM_BUILDMODE, "Debug"))
+}
+
+QT += core network
+QT -= gui
+
+LIBS += $$LIBTOOLING_LIBS
+INCLUDEPATH += $$LLVM_INCLUDEPATH
+
+QMAKE_CXXFLAGS += $$LLVM_CXXFLAGS
+
+INCLUDEPATH += ../clangrefactoringbackend/source
+
+SOURCES += \
+ clangpchmanagerbackendmain.cpp \
+ ../clangrefactoringbackend/source/clangtool.cpp \
+ ../clangrefactoringbackend/source/refactoringcompilationdatabase.cpp
+
+
+unix {
+ !macos: QMAKE_LFLAGS += -Wl,-z,origin
+ !disable_external_rpath: QMAKE_LFLAGS += -Wl,-rpath,$$shell_quote($${LLVM_LIBDIR})
+}
+
+DEFINES += CLANG_COMPILER_PATH=\"R\\\"xxx($$LLVM_INSTALL_DIR/bin/clang)xxx\\\"\"
diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp
new file mode 100644
index 0000000000..929393116e
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include <clangpathwatcher.h>
+#include <connectionserver.h>
+#include <environment.h>
+#include <pchcreator.h>
+#include <pchmanagerserver.h>
+#include <pchmanagerclientproxy.h>
+#include <projectparts.h>
+#include <stringcache.h>
+
+#include <QCommandLineParser>
+#include <QCoreApplication>
+#include <QFileSystemWatcher>
+#include <QLoggingCategory>
+#include <QTemporaryDir>
+
+using ClangBackEnd::ClangPathWatcher;
+using ClangBackEnd::ConnectionServer;
+using ClangBackEnd::PchCreator;
+using ClangBackEnd::PchManagerClientProxy;
+using ClangBackEnd::PchManagerServer;
+using ClangBackEnd::ProjectParts;
+using ClangBackEnd::StringCache;
+
+class ApplicationEnvironment : public ClangBackEnd::Environment
+{
+public:
+ QString pchBuildDirectory() const override
+ {
+ return temporaryDirectory.path();
+ }
+
+ QString clangCompilerPath() const override
+ {
+ return QString(CLANG_COMPILER_PATH);
+ }
+
+private:
+ QTemporaryDir temporaryDirectory;
+};
+
+QString processArguments(QCoreApplication &application)
+{
+ QCommandLineParser parser;
+ parser.setApplicationDescription(QStringLiteral("Qt Creator Clang PchManager Backend"));
+ parser.addHelpOption();
+ parser.addVersionOption();
+ parser.addPositionalArgument(QStringLiteral("connection"), QStringLiteral("Connection"));
+
+ parser.process(application);
+
+ if (parser.positionalArguments().isEmpty())
+ parser.showHelp(1);
+
+ return parser.positionalArguments().first();
+}
+
+int main(int argc, char *argv[])
+{
+ //QLoggingCategory::setFilterRules(QStringLiteral("*.debug=false"));
+
+ QCoreApplication::setOrganizationName(QStringLiteral("QtProject"));
+ QCoreApplication::setOrganizationDomain(QStringLiteral("qt-project.org"));
+ QCoreApplication::setApplicationName(QStringLiteral("ClangPchManagerBackend"));
+ QCoreApplication::setApplicationVersion(QStringLiteral("0.1.0"));
+
+ QCoreApplication application(argc, argv);
+
+ const QString connection = processArguments(application);
+
+ StringCache<Utils::SmallString> filePathCache;
+ ClangPathWatcher<QFileSystemWatcher> includeWatcher(filePathCache);
+ ApplicationEnvironment environment;
+ PchCreator pchCreator(environment, filePathCache);
+ ProjectParts projectParts;
+ PchManagerServer clangPchManagerServer(filePathCache, includeWatcher, pchCreator, projectParts);
+ ConnectionServer<PchManagerServer, PchManagerClientProxy> connectionServer(connection);
+ connectionServer.start();
+ connectionServer.setServer(&clangPchManagerServer);
+
+ return application.exec();
+}
+
+
diff --git a/src/tools/clangpchmanagerbackend/source/clangpathwatcher.cpp b/src/tools/clangpchmanagerbackend/source/clangpathwatcher.cpp
new file mode 100644
index 0000000000..1647fa7943
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/clangpathwatcher.cpp
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangpathwatcher.h"
+
+#include <utils/smallstringio.h>
+
+namespace ClangBackEnd {
+
+std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry)
+{
+ out << "("
+ << entry.id << ", "
+ << entry.path
+ << ")";
+
+ return out;
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h b/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h
new file mode 100644
index 0000000000..b3756ed2e5
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h
@@ -0,0 +1,392 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "clangpathwatcherinterface.h"
+#include "clangpathwatchernotifier.h"
+#include "stringcache.h"
+
+#include <QObject>
+
+namespace ClangBackEnd {
+
+class WatcherEntry
+{
+public:
+ uint id;
+ uint path;
+
+ friend bool operator==(const WatcherEntry &first, const WatcherEntry &second)
+ {
+ return first.id == second.id && first.path == second.path;
+ }
+
+ friend bool operator<(const WatcherEntry &first, const WatcherEntry &second)
+ {
+ return std::tie(first.path, first.id) < std::tie(second.path, second.id);
+ }
+
+ friend bool operator<(const WatcherEntry &entry, uint path)
+ {
+ return entry.path < path;
+ }
+
+ friend bool operator<(uint path, const WatcherEntry &entry)
+ {
+ return path < entry.path;
+ }
+};
+
+template <typename FileSystemWatcher>
+class ClangPathWatcher : public ClangPathWatcherInterface
+{
+public:
+ ClangPathWatcher(StringCache<Utils::SmallString> &pathCache,
+ ClangPathWatcherNotifier *notifier=nullptr)
+ : m_pathCache(pathCache),
+ m_notifier(notifier)
+ {
+ QObject::connect(&m_fileSystemWatcher,
+ &FileSystemWatcher::fileChanged,
+ [&] (const QString &filePath) { addChangedPathForFilePath(filePath); });
+ }
+
+ void updateIdPaths(const std::vector<IdPaths> &idPaths) override
+ {
+ auto entriesAndIds = convertIdPathsToWatcherEntriesAndIds(idPaths);
+
+ addEntries(entriesAndIds.first);
+ removeUnusedEntries(entriesAndIds.first, entriesAndIds.second);
+ }
+
+ void removeIds(const Utils::SmallStringVector &ids) override
+ {
+ auto removedEntries = removeIdsFromWatchedEntries(convertToIdNumbers(ids));
+
+ auto filteredPaths = filterNotWatchedPaths(removedEntries);
+
+ if (!filteredPaths.empty())
+ m_fileSystemWatcher.removePaths(convertWatcherEntriesToQStringList(filteredPaths));
+ }
+
+ void setNotifier(ClangPathWatcherNotifier *notifier) override
+ {
+ m_notifier = notifier;
+ }
+
+unitttest_public:
+ static std::vector<uint> idsFromIdPaths(const std::vector<IdPaths> &idPaths)
+ {
+ std::vector<uint> ids;
+ ids.reserve(idPaths.size());
+
+ auto extractId = [] (const IdPaths &idPath) {
+ return idPath.id;
+ };
+
+ std::transform(idPaths.begin(),
+ idPaths.end(),
+ std::back_inserter(ids),
+ extractId);
+
+ std::sort(ids.begin(), ids.end());
+
+ return ids;
+ }
+
+ std::vector<uint> convertToIdNumbers(const Utils::SmallStringVector &ids)
+ {
+ std::vector<uint> idNumbers = m_idCache.stringIds(ids);
+
+ std::sort(idNumbers.begin(), idNumbers.end());
+
+ return idNumbers;
+ }
+
+ std::size_t sizeOfIdPaths(const std::vector<IdPaths> &idPaths)
+ {
+ auto sumSize = [] (std::size_t size, const IdPaths &idPath) {
+ return size + idPath.paths.size();
+ };
+
+ return std::accumulate(idPaths.begin(), idPaths.end(), 0u, sumSize);
+ }
+
+
+ std::pair<std::vector<WatcherEntry>,std::vector<uint>>
+ convertIdPathsToWatcherEntriesAndIds(const std::vector<IdPaths> &idPaths)
+ {
+ std::vector<WatcherEntry> entries;
+ entries.reserve(sizeOfIdPaths(idPaths));
+ std::vector<uint> ids;
+ ids.reserve(ids.size());
+
+ auto outputIterator = std::back_inserter(entries);
+
+ for (const IdPaths &idPath : idPaths)
+ {
+ uint id = m_idCache.stringId(idPath.id);
+
+ ids.push_back(id);
+
+ outputIterator = std::transform(idPath.paths.begin(),
+ idPath.paths.end(),
+ outputIterator,
+ [&] (uint path) { return WatcherEntry{id, path}; });
+ }
+
+ std::sort(entries.begin(), entries.end());
+ std::sort(ids.begin(), ids.end());
+
+ return {entries, ids};
+ }
+
+ void addEntries(const std::vector<WatcherEntry> &entries)
+ {
+ auto newEntries = notWatchedEntries(entries);
+
+ auto filteredPaths = filterNotWatchedPaths(newEntries);
+
+ mergeToWatchedEntries(newEntries);
+
+ if (!filteredPaths.empty())
+ m_fileSystemWatcher.addPaths(convertWatcherEntriesToQStringList(filteredPaths));
+ }
+
+ void removeUnusedEntries(const std::vector<WatcherEntry> &entries,
+ const std::vector<uint> &ids)
+ {
+ auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids);
+
+ removeFromWatchedEntries(oldEntries);
+
+ auto filteredPaths = filterNotWatchedPaths(oldEntries);
+
+ if (!filteredPaths.empty())
+ m_fileSystemWatcher.removePaths(convertWatcherEntriesToQStringList(filteredPaths));
+ }
+
+ FileSystemWatcher &fileSystemWatcher()
+ {
+ return m_fileSystemWatcher;
+ }
+
+ QStringList convertWatcherEntriesToQStringList(
+ const std::vector<WatcherEntry> &watcherEntries)
+ {
+ QStringList paths;
+ paths.reserve(int(watcherEntries.size()));
+
+ std::transform(watcherEntries.begin(),
+ watcherEntries.end(),
+ std::back_inserter(paths),
+ [&] (const WatcherEntry &entry) { return m_pathCache.string(entry.path); });
+
+ return paths;
+ }
+
+ template <typename Compare>
+ std::vector<WatcherEntry> notWatchedEntries(const std::vector<WatcherEntry> &entries,
+ Compare compare) const
+ {
+ std::vector<WatcherEntry> notWatchedEntries;
+ notWatchedEntries.reserve(entries.size());
+
+ std::set_difference(entries.begin(),
+ entries.end(),
+ m_watchedEntries.cbegin(),
+ m_watchedEntries.cend(),
+ std::back_inserter(notWatchedEntries),
+ compare);
+
+ return notWatchedEntries;
+ }
+
+ std::vector<WatcherEntry> notWatchedEntries(const std::vector<WatcherEntry> &entries) const
+ {
+ return notWatchedEntries(entries, std::less<WatcherEntry>());
+ }
+
+ std::vector<WatcherEntry> notWatchedPaths(const std::vector<WatcherEntry> &entries) const
+ {
+ auto compare = [] (const WatcherEntry &first, const WatcherEntry &second) {
+ return first.path < second.path;
+ };
+
+ return notWatchedEntries(entries, compare);
+ }
+
+ template <typename Compare>
+ std::vector<WatcherEntry> notAnymoreWatchedEntries(
+ const std::vector<WatcherEntry> &newEntries,
+ Compare compare) const
+ {
+ std::vector<WatcherEntry> notAnymoreWatchedEntries;
+ notAnymoreWatchedEntries.reserve(m_watchedEntries.size());
+
+ std::set_difference(m_watchedEntries.cbegin(),
+ m_watchedEntries.cend(),
+ newEntries.begin(),
+ newEntries.end(),
+ std::back_inserter(notAnymoreWatchedEntries),
+ compare);
+
+ return notAnymoreWatchedEntries;
+ }
+
+ std::vector<WatcherEntry> notAnymoreWatchedEntriesWithIds(
+ const std::vector<WatcherEntry> &newEntries,
+ const std::vector<uint> &ids) const
+ {
+ auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>());
+
+ auto newEnd = std::remove_if(oldEntries.begin(),
+ oldEntries.end(),
+ [&] (WatcherEntry entry) {
+ return !std::binary_search(ids.begin(), ids.end(), entry.id);
+ });
+
+ oldEntries.erase(newEnd, oldEntries.end());
+
+ return oldEntries;
+ }
+
+ void mergeToWatchedEntries(const std::vector<WatcherEntry> &newEntries)
+ {
+ std::vector<WatcherEntry> newWatchedEntries;
+ newWatchedEntries.reserve(m_watchedEntries.size() + newEntries.size());
+
+ std::merge(m_watchedEntries.cbegin(),
+ m_watchedEntries.cend(),
+ newEntries.begin(),
+ newEntries.end(),
+ std::back_inserter(newWatchedEntries));
+
+ m_watchedEntries = std::move(newWatchedEntries);
+ }
+
+ static
+ std::vector<WatcherEntry> uniquePaths(const std::vector<WatcherEntry> &pathEntries)
+ {
+ std::vector<WatcherEntry> uniqueEntries;
+
+ auto compare = [] (const WatcherEntry &first, const WatcherEntry &second) {
+ return first.path == second.path;
+ };
+
+ std::unique_copy(pathEntries.begin(),
+ pathEntries.end(),
+ std::back_inserter(uniqueEntries),
+ compare);
+
+ return uniqueEntries;
+ }
+
+ std::vector<WatcherEntry> filterNotWatchedPaths(const std::vector<WatcherEntry> &entries)
+ {
+ return notWatchedPaths(uniquePaths(entries));
+ }
+
+ const std::vector<WatcherEntry> &watchedEntries() const
+ {
+ return m_watchedEntries;
+ }
+
+ std::vector<WatcherEntry> removeIdsFromWatchedEntries(const std::vector<uint> &ids)
+ {
+
+ auto keep = [&] (const WatcherEntry &entry) {
+ return !std::binary_search(ids.begin(), ids.end(), entry.id);
+ };
+
+ auto found = std::stable_partition(m_watchedEntries.begin(),
+ m_watchedEntries.end(),
+ keep);
+
+ std::vector<WatcherEntry> removedEntries(found, m_watchedEntries.end());
+
+ m_watchedEntries.erase(found, m_watchedEntries.end());
+
+ return removedEntries;
+ }
+
+ void removeFromWatchedEntries(const std::vector<WatcherEntry> &oldEntries)
+ {
+ std::vector<WatcherEntry> newWatchedEntries;
+ newWatchedEntries.reserve(m_watchedEntries.size() - oldEntries.size());
+
+ std::set_difference(m_watchedEntries.cbegin(),
+ m_watchedEntries.cend(),
+ oldEntries.begin(),
+ oldEntries.end(),
+ std::back_inserter(newWatchedEntries));
+
+
+ m_watchedEntries = newWatchedEntries;
+ }
+
+ void addChangedPathForFilePath(const QString &filePath)
+ {
+ uint pathId = m_pathCache.stringId(Utils::SmallString(filePath));
+
+ auto range = std::equal_range(m_watchedEntries.begin(), m_watchedEntries.end(), pathId);
+
+ Utils::SmallStringVector changedIds;
+
+ std::transform(range.first,
+ range.second,
+ std::back_inserter(changedIds),
+ [&] (const WatcherEntry &entry) {
+ return m_idCache.string(entry.id);
+ });
+
+ std::sort(changedIds.begin(), changedIds.end());
+
+ if (m_notifier)
+ m_notifier->pathsWithIdsChanged(changedIds);
+ }
+
+ StringCache<Utils::SmallString> &pathCache()
+ {
+ return m_pathCache;
+ }
+
+ StringCache<Utils::SmallString> &idCache()
+ {
+ return m_idCache;
+ }
+
+private:
+ StringCache<Utils::SmallString> m_idCache;
+ std::vector<WatcherEntry> m_watchedEntries;
+ FileSystemWatcher m_fileSystemWatcher;
+ StringCache<Utils::SmallString> &m_pathCache;
+ ClangPathWatcherNotifier *m_notifier;
+};
+
+std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry);
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/clangpathwatcherinterface.cpp b/src/tools/clangpchmanagerbackend/source/clangpathwatcherinterface.cpp
new file mode 100644
index 0000000000..7862f4d0fd
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/clangpathwatcherinterface.cpp
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangpathwatcherinterface.h"
+
+namespace ClangBackEnd {
+
+ClangPathWatcherInterface::~ClangPathWatcherInterface()
+{
+
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/clangpathwatcherinterface.h b/src/tools/clangpchmanagerbackend/source/clangpathwatcherinterface.h
new file mode 100644
index 0000000000..fbd1776e5c
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/clangpathwatcherinterface.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "idpaths.h"
+
+#include <utils/smallstringvector.h>
+
+namespace ClangBackEnd {
+
+class ClangPathWatcherNotifier;
+
+class ClangPathWatcherInterface
+{
+public:
+ virtual ~ClangPathWatcherInterface();
+
+ virtual void updateIdPaths(const std::vector<IdPaths> &idPaths) = 0;
+ virtual void removeIds(const Utils::SmallStringVector &ids) = 0;
+
+ virtual void setNotifier(ClangPathWatcherNotifier *notifier) = 0;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/clangpathwatchernotifier.cpp b/src/tools/clangpchmanagerbackend/source/clangpathwatchernotifier.cpp
new file mode 100644
index 0000000000..66f6b3534f
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/clangpathwatchernotifier.cpp
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangpathwatchernotifier.h"
+
+namespace ClangBackEnd {
+
+ClangPathWatcherNotifier::~ClangPathWatcherNotifier()
+{
+
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/clangpathwatchernotifier.h b/src/tools/clangpchmanagerbackend/source/clangpathwatchernotifier.h
new file mode 100644
index 0000000000..c95ab56e51
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/clangpathwatchernotifier.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utils/smallstringvector.h>
+
+namespace ClangBackEnd {
+
+class ClangPathWatcherNotifier
+{
+public:
+ virtual ~ClangPathWatcherNotifier();
+
+ virtual void pathsWithIdsChanged(const Utils::SmallStringVector &ids) = 0;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri
new file mode 100644
index 0000000000..696159245b
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri
@@ -0,0 +1,32 @@
+INCLUDEPATH += $$PWD
+
+SOURCES += \
+ $$PWD/includecollector.cpp \
+ $$PWD/pchmanagerserver.cpp \
+ $$PWD/pchcreator.cpp \
+ $$PWD/clangpathwatcher.cpp \
+ $$PWD/projectparts.cpp \
+ $$PWD/idpaths.cpp \
+ $$PWD/pchcreatorinterface.cpp \
+ $$PWD/clangpathwatcherinterface.cpp \
+ $$PWD/projectpartsinterface.cpp \
+ $$PWD/clangpathwatchernotifier.cpp
+
+HEADERS += \
+ $$PWD/clangpchmanagerbackend_global.h \
+ $$PWD/includecollector.h \
+ $$PWD/collectincludestoolaction.h \
+ $$PWD/collectincludesaction.h \
+ $$PWD/collectincludespreprocessorcallbacks.h \
+ $$PWD/pchmanagerserver.h \
+ $$PWD/pchcreator.h \
+ $$PWD/pchnotcreatederror.h \
+ $$PWD/environment.h \
+ $$PWD/clangpathwatcher.h \
+ $$PWD/projectparts.h \
+ $$PWD/stringcache.h \
+ $$PWD/idpaths.h \
+ $$PWD/pchcreatorinterface.h \
+ $$PWD/clangpathwatcherinterface.h \
+ $$PWD/projectpartsinterface.h \
+ $$PWD/clangpathwatchernotifier.h
diff --git a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend_global.h b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend_global.h
new file mode 100644
index 0000000000..57fa8c64f8
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend_global.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#ifdef UNIT_TESTS
+#define unitttest_public public
+#else
+#define unitttest_public private
+#endif
+
+namespace llvm {
+template <typename T, unsigned N>
+class SmallVector;
+}
+
+using uint = unsigned int;
+
+namespace Utils {
+template <uint Size>
+class BasicSmallString;
+using SmallString = BasicSmallString<31>;
+using PathString = BasicSmallString<191>;
+}
+
+namespace ClangBackEnd {
+
+using USRName = llvm::SmallVector<char, 128>;
+
+}
diff --git a/src/tools/clangpchmanagerbackend/source/collectincludesaction.h b/src/tools/clangpchmanagerbackend/source/collectincludesaction.h
new file mode 100644
index 0000000000..3f98b307e1
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/collectincludesaction.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "stringcache.h"
+
+#include <collectincludespreprocessorcallbacks.h>
+
+#include <clang/Frontend/FrontendActions.h>
+#include <clang/Frontend/CompilerInstance.h>
+#include <clang/Lex/Preprocessor.h>
+
+namespace ClangBackEnd {
+
+class CollectIncludesAction final : public clang::PreprocessOnlyAction
+{
+public:
+ CollectIncludesAction(std::vector<uint> &includeIds,
+ StringCache<Utils::SmallString> &filePathCache,
+ const std::vector<uint> &excludedIncludeUID,
+ std::vector<uint> &alreadyIncludedFileUIDs)
+ : m_includeIds(includeIds),
+ m_filePathCache(filePathCache),
+ m_excludedIncludeUID(excludedIncludeUID),
+ m_alreadyIncludedFileUIDs(alreadyIncludedFileUIDs)
+ {
+ }
+
+ bool BeginSourceFileAction(clang::CompilerInstance &compilerInstance,
+ llvm::StringRef filename) override
+ {
+ if (clang::PreprocessOnlyAction::BeginSourceFileAction(compilerInstance, filename)) {
+ auto &preprocessor = compilerInstance.getPreprocessor();
+ auto &headerSearch = preprocessor.getHeaderSearchInfo();
+
+ auto macroPreprocessorCallbacks = new CollectIncludesPreprocessorCallbacks(headerSearch,
+ m_includeIds,
+ m_filePathCache,
+ m_excludedIncludeUID,
+ m_alreadyIncludedFileUIDs);
+
+ preprocessor.addPPCallbacks(std::unique_ptr<clang::PPCallbacks>(macroPreprocessorCallbacks));
+
+ return true;
+ }
+
+ return false;
+ }
+
+ void EndSourceFileAction() override
+ {
+ clang::PreprocessOnlyAction::EndSourceFileAction();
+ }
+
+private:
+ std::vector<uint> &m_includeIds;
+ StringCache<Utils::SmallString> &m_filePathCache;
+ const std::vector<uint> &m_excludedIncludeUID;
+ std::vector<uint> &m_alreadyIncludedFileUIDs;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h b/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h
new file mode 100644
index 0000000000..4dbf0d9758
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "stringcache.h"
+
+#include <clang/Basic/SourceManager.h>
+#include <clang/Lex/MacroInfo.h>
+#include <clang/Lex/HeaderSearch.h>
+#include <clang/Lex/PPCallbacks.h>
+#include <clang/Lex/Preprocessor.h>
+
+#include <utils/smallstringvector.h>
+
+#include <algorithm>
+
+namespace ClangBackEnd {
+
+class CollectIncludesPreprocessorCallbacks final : public clang::PPCallbacks
+{
+public:
+ CollectIncludesPreprocessorCallbacks(clang::HeaderSearch &headerSearch,
+ std::vector<uint> &includeIds,
+ StringCache<Utils::SmallString> &filePathCache,
+ const std::vector<uint> &excludedIncludeUID,
+ std::vector<uint> &alreadyIncludedFileUIDs)
+ : m_headerSearch(headerSearch),
+ m_includeIds(includeIds),
+ m_filePathCache(filePathCache),
+ m_excludedIncludeUID(excludedIncludeUID),
+ m_alreadyIncludedFileUIDs(alreadyIncludedFileUIDs)
+ {}
+
+ void InclusionDirective(clang::SourceLocation /*hashLocation*/,
+ const clang::Token &/*includeToken*/,
+ llvm::StringRef fileName,
+ bool /*isAngled*/,
+ clang::CharSourceRange /*fileNameRange*/,
+ const clang::FileEntry *file,
+ llvm::StringRef /*searchPath*/,
+ llvm::StringRef /*relativePath*/,
+ const clang::Module */*imported*/) override
+ {
+ auto fileUID = file->getUID();
+
+ flagIncludeAlreadyRead(file);
+
+ if (isNotInExcludedIncludeUID(fileUID)) {
+ auto notAlreadyIncluded = isNotAlreadyIncluded(fileUID);
+ if (notAlreadyIncluded.first) {
+ m_alreadyIncludedFileUIDs.insert(notAlreadyIncluded.second, fileUID);
+ uint includeId = m_filePathCache.stringId({fileName.data(), fileName.size()});
+ m_includeIds.emplace_back(includeId);
+ }
+ }
+ }
+
+ bool isNotInExcludedIncludeUID(uint uid) const
+ {
+ return !std::binary_search(m_excludedIncludeUID.begin(),
+ m_excludedIncludeUID.end(),
+ uid);
+ }
+
+ std::pair<bool, std::vector<uint>::iterator> isNotAlreadyIncluded(uint uid) const
+ {
+ auto range = std::equal_range(m_alreadyIncludedFileUIDs.begin(),
+ m_alreadyIncludedFileUIDs.end(),
+ uid);
+
+ return {range.first == range.second, range.first};
+ }
+
+ void flagIncludeAlreadyRead(const clang::FileEntry *file)
+ {
+ auto &headerFileInfo = m_headerSearch.getFileInfo(file);
+
+ headerFileInfo.isImport = true;
+ ++headerFileInfo.NumIncludes;
+
+ }
+
+private:
+ clang::HeaderSearch &m_headerSearch;
+ std::vector<uint> &m_includeIds;
+ StringCache<Utils::SmallString> &m_filePathCache;
+ const std::vector<uint> &m_excludedIncludeUID;
+ std::vector<uint> &m_alreadyIncludedFileUIDs;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h b/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h
new file mode 100644
index 0000000000..f8b9f28a83
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "stringcache.h"
+
+#include "collectincludesaction.h"
+
+#include <clang/Tooling/Tooling.h>
+
+namespace ClangBackEnd {
+
+class CollectIncludesToolAction final : public clang::tooling::FrontendActionFactory
+{
+public:
+ CollectIncludesToolAction(std::vector<uint> &includeIds,
+ StringCache<Utils::SmallString> &filePathCache,
+ const std::vector<uint> &excludedIncludeUIDs)
+ : m_includeIds(includeIds),
+ m_filePathCache(filePathCache),
+ m_excludedIncludeUIDs(excludedIncludeUIDs)
+ {}
+
+ clang::FrontendAction *create()
+ {
+ return new CollectIncludesAction(m_includeIds,
+ m_filePathCache,
+ m_excludedIncludeUIDs,
+ m_alreadyIncludedFileUIDs);
+ }
+
+private:
+ std::vector<uint> m_alreadyIncludedFileUIDs;
+ std::vector<uint> &m_includeIds;
+ StringCache<Utils::SmallString> &m_filePathCache;
+ const std::vector<uint> &m_excludedIncludeUIDs;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/environment.h b/src/tools/clangpchmanagerbackend/source/environment.h
new file mode 100644
index 0000000000..4fe7442c17
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/environment.h
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QString>
+
+namespace ClangBackEnd {
+
+class Environment
+{
+public:
+ virtual QString pchBuildDirectory() const = 0;
+ virtual QString clangCompilerPath() const = 0;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/idpaths.cpp b/src/tools/clangpchmanagerbackend/source/idpaths.cpp
new file mode 100644
index 0000000000..f1dba02e4e
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/idpaths.cpp
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "idpaths.h"
+
+#include <utils/smallstringio.h>
+
+namespace ClangBackEnd {
+
+std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths)
+{
+ out << "("
+ << idPaths.id << ", "
+ << idPaths.paths << ")";
+
+ return out;
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/idpaths.h b/src/tools/clangpchmanagerbackend/source/idpaths.h
new file mode 100644
index 0000000000..f6f312f05f
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/idpaths.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utils/smallstring.h>
+
+#include <iosfwd>
+
+namespace ClangBackEnd {
+
+class IdPaths
+{
+public:
+ Utils::SmallString id;
+ std::vector<uint> paths;
+
+ friend bool operator==(const IdPaths &first, const IdPaths &second)
+ {
+ return first.id == second.id && first.paths == second.paths;
+ }
+};
+
+std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths);
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/includecollector.cpp b/src/tools/clangpchmanagerbackend/source/includecollector.cpp
new file mode 100644
index 0000000000..f383af9609
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/includecollector.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "includecollector.h"
+
+#include "collectincludestoolaction.h"
+
+#include <utils/smallstring.h>
+
+namespace ClangBackEnd {
+
+IncludeCollector::IncludeCollector(StringCache<Utils::SmallString> &filePathCache)
+ : m_filePathCache(filePathCache)
+{
+}
+
+void IncludeCollector::collectIncludes()
+{
+ clang::tooling::ClangTool tool = createTool();
+
+ auto excludedIncludeFileUIDs = generateExcludedIncludeFileUIDs(tool.getFiles());
+
+ auto action = std::unique_ptr<CollectIncludesToolAction>(
+ new CollectIncludesToolAction(m_includeIds, m_filePathCache, excludedIncludeFileUIDs));
+
+ tool.run(action.get());
+}
+
+void IncludeCollector::setExcludedIncludes(Utils::SmallStringVector &&excludedIncludes)
+{
+ this->m_excludedIncludes = std::move(excludedIncludes);
+}
+
+std::vector<uint> IncludeCollector::takeIncludeIds()
+{
+ std::sort(m_includeIds.begin(), m_includeIds.end());
+
+ return std::move(m_includeIds);
+}
+
+std::vector<uint> IncludeCollector::generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const
+{
+ std::vector<uint> fileUIDs;
+ fileUIDs.reserve(m_excludedIncludes.size());
+
+ auto generateUID = [&] (const Utils::SmallString &filePath) {
+ return fileManager.getFile({filePath.data(), filePath.size()})->getUID();
+ };
+
+ std::transform(m_excludedIncludes.begin(),
+ m_excludedIncludes.end(),
+ std::back_inserter(fileUIDs),
+ generateUID);
+
+ std::sort(fileUIDs.begin(), fileUIDs.end());
+
+ return fileUIDs;
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/includecollector.h b/src/tools/clangpchmanagerbackend/source/includecollector.h
new file mode 100644
index 0000000000..15914c22a2
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/includecollector.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "stringcache.h"
+
+#include <clangtool.h>
+
+namespace ClangBackEnd {
+
+class IncludeCollector : public ClangTool
+{
+public:
+ IncludeCollector(StringCache<Utils::SmallString> &filePathCache);
+
+ void collectIncludes();
+
+ void setExcludedIncludes(Utils::SmallStringVector &&excludedIncludes);
+
+ std::vector<uint> takeIncludeIds();
+
+private:
+ std::vector<uint> generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const;
+
+private:
+ Utils::SmallStringVector m_excludedIncludes;
+ std::vector<uint> m_includeIds;
+ Utils::SmallStringVector m_directories;
+ StringCache<Utils::SmallString> &m_filePathCache;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
new file mode 100644
index 0000000000..560e6a2bb5
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
@@ -0,0 +1,518 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "pchcreator.h"
+
+#include "environment.h"
+#include "includecollector.h"
+#include "pchnotcreatederror.h"
+
+#include <projectpartpch.h>
+
+#include <QCryptographicHash>
+#include <QFile>
+#include <QProcess>
+
+namespace ClangBackEnd {
+
+PchCreator::PchCreator(Environment &environment, StringCache<Utils::SmallString> &filePathCache)
+ : m_environment(environment),
+ m_filePathCache(filePathCache)
+{
+}
+
+PchCreator::PchCreator(V2::ProjectPartContainers &&projectsParts,
+ Environment &environment,
+ StringCache<Utils::SmallString> &filePathCache)
+ : m_projectParts(std::move(projectsParts)),
+ m_environment(environment),
+ m_filePathCache(filePathCache)
+{
+}
+
+namespace {
+template <typename Source,
+ typename Target>
+void append(Target &target, const Source &source)
+{
+ Source clonedSource = source.clone();
+
+ target.reserve(target.size() + source.size());
+
+ std::move(clonedSource.begin(),
+ clonedSource.end(),
+ std::back_inserter(target));
+}
+
+template <typename Source,
+ typename Target>
+void append(Target &target, Source &source)
+{
+ target.reserve(target.size() + source.size());
+
+ std::move(source.begin(),
+ source.end(),
+ std::back_inserter(target));
+}
+
+template <typename GetterFunction>
+std::size_t globalCount(const V2::ProjectPartContainers &projectsParts,
+ GetterFunction getterFunction)
+{
+ auto sizeFunction = [&] (std::size_t size, const V2::ProjectPartContainer &projectContainer) {
+ return size + getterFunction(projectContainer).size();
+ };
+
+ return std::accumulate(projectsParts.begin(),
+ projectsParts.end(),
+ std::size_t(0),
+ sizeFunction);
+}
+
+template <typename GetterFunction>
+void generateGlobal(Utils::SmallStringVector &entries,
+ const V2::ProjectPartContainers &projectsParts,
+ GetterFunction getterFunction)
+{
+ entries.reserve(entries.size() + globalCount(projectsParts, getterFunction));
+
+ for (const V2::ProjectPartContainer &projectPart : projectsParts) {
+ const auto &projectPartPaths = getterFunction(projectPart);
+
+ append(entries, projectPartPaths);
+ };
+}
+
+template <typename GetterFunction>
+Utils::SmallStringVector generateGlobal(
+ const V2::ProjectPartContainers &projectsParts,
+ GetterFunction getterFunction)
+{
+ Utils::SmallStringVector entries;
+
+ generateGlobal(entries, projectsParts, getterFunction);
+
+ return entries;
+}
+
+}
+
+Utils::SmallStringVector PchCreator::generateGlobalHeaderPaths() const
+{
+ auto includeFunction = [] (const V2::ProjectPartContainer &projectPart)
+ -> const Utils::SmallStringVector & {
+ return projectPart.headerPaths();
+ };
+
+ return generateGlobal(m_projectParts, includeFunction);
+}
+
+Utils::SmallStringVector PchCreator::generateGlobalSourcePaths() const
+{
+ auto sourceFunction = [] (const V2::ProjectPartContainer &projectPart)
+ -> const Utils::SmallStringVector & {
+ return projectPart.sourcePaths();
+ };
+
+ return generateGlobal(m_projectParts, sourceFunction);
+}
+
+Utils::SmallStringVector PchCreator::generateGlobalHeaderAndSourcePaths() const
+{
+ const auto &sourcePaths = generateGlobalSourcePaths();
+ auto includePaths = generateGlobalHeaderPaths();
+
+ append(includePaths, sourcePaths);
+
+ return includePaths;
+}
+
+Utils::SmallStringVector PchCreator::generateGlobalArguments() const
+{
+ Utils::SmallStringVector arguments;
+
+ auto argumentFunction = [] (const V2::ProjectPartContainer &projectPart)
+ -> const Utils::SmallStringVector & {
+ return projectPart.arguments();
+ };
+
+ generateGlobal(arguments, m_projectParts, argumentFunction);
+
+ return arguments;
+}
+
+Utils::SmallStringVector PchCreator::generateGlobalCommandLine() const
+{
+ Utils::SmallStringVector commandLine;
+ commandLine.emplace_back(m_environment.clangCompilerPath());
+
+ auto argumentFunction = [] (const V2::ProjectPartContainer &projectPart)
+ -> const Utils::SmallStringVector & {
+ return projectPart.arguments();
+ };
+
+ generateGlobal(commandLine, m_projectParts, argumentFunction);
+
+ return commandLine;
+}
+
+Utils::SmallStringVector PchCreator::generateGlobalPchCompilerArguments() const
+{
+ Utils::SmallStringVector arguments;
+ arguments.reserve(5);
+
+ arguments.emplace_back("-x");
+ arguments.emplace_back("c++-header");
+ arguments.emplace_back("-Xclang");
+ arguments.emplace_back("-emit-pch");
+ arguments.emplace_back("-o");
+ arguments.emplace_back(generateGlobalPchFilePath());
+ arguments.emplace_back(generateGlobalPchHeaderFilePath());
+
+ return arguments;
+}
+
+Utils::SmallStringVector PchCreator::generateGlobalClangCompilerArguments() const
+{
+ auto compilerArguments = generateGlobalArguments();
+ const auto pchArguments = generateGlobalPchCompilerArguments();
+
+ append(compilerArguments, pchArguments);
+
+ return compilerArguments;
+}
+
+std::vector<uint> PchCreator::generateGlobalPchIncludeIds() const
+{
+ IncludeCollector collector(m_filePathCache);
+
+ collector.setExcludedIncludes(generateGlobalHeaderPaths());
+
+ collector.addFiles(generateGlobalHeaderAndSourcePaths(), generateGlobalCommandLine());
+
+ collector.collectIncludes();
+
+ return collector.takeIncludeIds();
+}
+
+namespace {
+
+std::size_t contentSize(const std::vector<Utils::SmallString> &includes)
+{
+ auto countIncludeSize = [] (std::size_t size, const Utils::SmallString &include) {
+ return size + include.size();
+ };
+
+ return std::accumulate(includes.begin(), includes.end(), std::size_t(0), countIncludeSize);
+}
+}
+
+Utils::SmallString PchCreator::generatePchIncludeFileContent(
+ const std::vector<uint> &includeIds) const
+{
+ Utils::SmallString fileContent;
+ const std::size_t lineTemplateSize = 12;
+ auto includes = m_filePathCache.strings(includeIds);
+
+ fileContent.reserve(includes.size() * lineTemplateSize + contentSize(includes));
+
+ for (const Utils::SmallString &include : includes) {
+ fileContent += "#include <";
+ fileContent += include;
+ fileContent += ">\n";
+ }
+
+ return fileContent;
+}
+
+Utils::SmallString PchCreator::generateGlobalPchHeaderFileContent() const
+{
+ return generatePchIncludeFileContent(generateGlobalPchIncludeIds());
+}
+
+std::unique_ptr<QFile> PchCreator::generateGlobalPchHeaderFile()
+{
+ return generatePchHeaderFile(generateGlobalPchHeaderFilePath(),
+ generateGlobalPchHeaderFileContent());
+}
+
+void PchCreator::generatePch(const Utils::SmallStringVector &clangCompilerArguments)
+{
+ QProcess process;
+ process.setProcessChannelMode(QProcess::ForwardedChannels);
+
+ process.start(m_environment.clangCompilerPath(),
+ convertToQStringList(clangCompilerArguments));
+ process.waitForFinished(100000);
+
+ checkIfProcessHasError(process);
+}
+
+void PchCreator::generateGlobalPch()
+{
+ generateGlobalPchHeaderFile();
+
+ generatePch(generateGlobalClangCompilerArguments());
+}
+
+QStringList PchCreator::convertToQStringList(const Utils::SmallStringVector &compilerArguments)
+{
+ QStringList qStringList;
+
+ append(qStringList, compilerArguments);
+
+ return qStringList;
+}
+
+namespace {
+
+void hashProjectPart(QCryptographicHash &hash, const V2::ProjectPartContainer &projectPart)
+{
+ const auto &projectPartId = projectPart.projectPartId();
+ hash.addData(projectPartId.data(), projectPartId.size());
+
+ for (const auto &argument : projectPart.arguments())
+ hash.addData(argument.data(), argument.size());
+}
+}
+
+QByteArray PchCreator::globalProjectHash() const
+{
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+
+ for (const auto &projectPart : m_projectParts)
+ hashProjectPart(hash, projectPart);
+
+ auto result = hash.result();
+
+ return result.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
+}
+
+void PchCreator::checkIfProcessHasError(const QProcess &process)
+{
+ if (process.exitCode()) {
+ const std::string errorString = process.errorString().toStdString();
+ throw PchNotCreatedError(errorString);
+ }
+}
+
+Utils::SmallString PchCreator::generateGlobalPchFilePathWithoutExtension() const
+{
+ QByteArray fileName = m_environment.pchBuildDirectory().toUtf8();
+ fileName += '/';
+ fileName += globalProjectHash();
+
+ return Utils::SmallString::fromQByteArray(fileName);
+}
+
+Utils::SmallString PchCreator::generateGlobalPchHeaderFilePath() const
+{
+ Utils::SmallString filePath = generateGlobalPchFilePathWithoutExtension();
+
+ filePath += ".h";
+
+ return filePath;
+}
+
+Utils::SmallString PchCreator::generateGlobalPchFilePath() const
+{
+ Utils::SmallString filePath = generateGlobalPchFilePathWithoutExtension();
+
+ filePath += ".pch";
+
+ return filePath;
+}
+
+Utils::SmallStringVector PchCreator::generateProjectPartCommandLine(
+ const V2::ProjectPartContainer &projectPart) const
+{
+ const Utils::SmallStringVector &arguments = projectPart.arguments();
+
+ Utils::SmallStringVector commandLine;
+ commandLine.reserve(arguments.size() + 1);
+
+ commandLine.emplace_back(m_environment.clangCompilerPath());
+
+ append(commandLine , arguments);
+
+ return commandLine;
+}
+
+Utils::SmallString PchCreator::generateProjectPartPchFilePathWithoutExtension(
+ const V2::ProjectPartContainer &projectPart) const
+{
+ QByteArray fileName = m_environment.pchBuildDirectory().toUtf8();
+ fileName += '/';
+ fileName += projectPartHash(projectPart);
+
+ return Utils::SmallString::fromQByteArray(fileName);
+}
+
+Utils::SmallStringVector PchCreator::generateProjectPartHeaderAndSourcePaths(
+ const V2::ProjectPartContainer &projectPart)
+{
+ Utils::SmallStringVector includeAndSources;
+ includeAndSources.reserve(projectPart.headerPaths().size() + projectPart.sourcePaths().size());
+
+ append(includeAndSources, projectPart.headerPaths());
+ append(includeAndSources, projectPart.sourcePaths());
+
+ return includeAndSources;
+}
+
+std::vector<uint> PchCreator::generateProjectPartPchIncludes(
+ const V2::ProjectPartContainer &projectPart) const
+{
+ IncludeCollector collector(m_filePathCache);
+
+ collector.setExcludedIncludes(projectPart.headerPaths().clone());
+
+ collector.addFiles(generateProjectPartHeaderAndSourcePaths(projectPart),
+ generateProjectPartCommandLine(projectPart));
+
+ collector.collectIncludes();
+
+ return collector.takeIncludeIds();
+}
+
+Utils::SmallString PchCreator::generateProjectPathPchHeaderFilePath(
+ const V2::ProjectPartContainer &projectPart) const
+{
+ Utils::SmallString filePath = generateProjectPartPchFilePathWithoutExtension(projectPart);
+
+ filePath += ".h";
+
+ return filePath;
+}
+
+Utils::SmallString PchCreator::generateProjectPartPchFilePath(
+ const V2::ProjectPartContainer &projectPart) const
+{
+ Utils::SmallString filePath = generateProjectPartPchFilePathWithoutExtension(projectPart);
+
+ filePath += ".pch";
+
+ return filePath;
+}
+
+Utils::SmallStringVector PchCreator::generateProjectPartPchCompilerArguments(
+ const V2::ProjectPartContainer &projectPart) const
+{
+ Utils::SmallStringVector arguments;
+ arguments.reserve(5);
+
+ arguments.emplace_back("-x");
+ arguments.emplace_back("c++-header");
+// arguments.emplace_back("-Xclang");
+// arguments.emplace_back("-include-pch");
+// arguments.emplace_back("-Xclang");
+// arguments.emplace_back(generateGlobalPchFilePath());
+ arguments.emplace_back("-Xclang");
+ arguments.emplace_back("-emit-pch");
+ arguments.emplace_back("-o");
+ arguments.emplace_back(generateProjectPartPchFilePath(projectPart));
+ arguments.emplace_back(generateProjectPathPchHeaderFilePath(projectPart));
+
+ return arguments;
+}
+
+Utils::SmallStringVector PchCreator::generateProjectPartClangCompilerArguments(
+ const V2::ProjectPartContainer &projectPart) const
+{
+ Utils::SmallStringVector compilerArguments = projectPart.arguments().clone();
+ const auto pchArguments = generateProjectPartPchCompilerArguments(projectPart);
+
+ append(compilerArguments, pchArguments);
+
+ return compilerArguments;
+}
+
+std::pair<ProjectPartPch, IdPaths> PchCreator::generateProjectPartPch(
+ const V2::ProjectPartContainer &projectPart)
+{
+ auto includes = generateProjectPartPchIncludes(projectPart);
+ auto content = generatePchIncludeFileContent(includes);
+ auto pchIncludeFilePath = generateProjectPathPchHeaderFilePath(projectPart);
+ auto pchFilePath = generateProjectPartPchFilePath(projectPart);
+ auto file = generatePchHeaderFile(pchIncludeFilePath, content);
+
+ generatePch(generateProjectPartClangCompilerArguments(projectPart));
+
+ return {{projectPart.projectPartId().clone(), std::move(pchFilePath)},
+ {projectPart.projectPartId().clone(), includes}};
+}
+
+void PchCreator::generatePchs()
+{
+ for (const V2::ProjectPartContainer &projectPart : m_projectParts) {
+ auto projectInfos = generateProjectPartPch(projectPart);
+ m_projectPartPchs.push_back(projectInfos.first);
+ m_projectsIncludeIds.push_back(projectInfos.second);
+ }
+}
+
+void PchCreator::generatePchs(V2::ProjectPartContainers &&projectsParts)
+{
+ m_projectParts = std::move(projectsParts);
+
+ generatePchs();
+}
+
+std::vector<ProjectPartPch> PchCreator::takeProjectPartPchs()
+{
+ return std::move(m_projectPartPchs);
+}
+
+std::vector<IdPaths> PchCreator::takeProjectsIncludes()
+{
+ return std::move(m_projectsIncludeIds);
+}
+
+std::unique_ptr<QFile> PchCreator::generatePchHeaderFile(
+ const Utils::SmallString &filePath,
+ const Utils::SmallString &content)
+{
+ std::unique_ptr<QFile> precompiledIncludeFile(new QFile(filePath));
+
+ precompiledIncludeFile->open(QIODevice::WriteOnly);
+
+ precompiledIncludeFile->write(content.data(), content.size());
+ precompiledIncludeFile->close();
+
+ return precompiledIncludeFile;
+}
+
+QByteArray PchCreator::projectPartHash(const V2::ProjectPartContainer &projectPart)
+{
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+
+ hashProjectPart(hash, projectPart);
+
+ auto result = hash.result();
+
+ return result.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.h b/src/tools/clangpchmanagerbackend/source/pchcreator.h
new file mode 100644
index 0000000000..5bc38cb58b
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/pchcreator.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "pchcreatorinterface.h"
+
+#include "stringcache.h"
+#include "idpaths.h"
+
+#include <projectpartpch.h>
+#include <projectpartcontainerv2.h>
+
+#include <vector>
+
+QT_FORWARD_DECLARE_CLASS(QFile)
+QT_FORWARD_DECLARE_CLASS(QCryptographicHash)
+QT_FORWARD_DECLARE_CLASS(QProcess)
+
+namespace ClangBackEnd {
+
+class Environment;
+
+class PchCreator final : public PchCreatorInterface
+{
+public:
+ PchCreator(Environment &environment,
+ StringCache<Utils::SmallString> &filePathCache);
+ PchCreator(V2::ProjectPartContainers &&projectsParts,
+ Environment &environment,
+ StringCache<Utils::SmallString> &filePathCache);
+
+ void generatePchs(V2::ProjectPartContainers &&projectsParts) override;
+ std::vector<ProjectPartPch> takeProjectPartPchs() override;
+ std::vector<IdPaths> takeProjectsIncludes() override;
+
+unitttest_public:
+ Utils::SmallStringVector generateGlobalHeaderPaths() const;
+ Utils::SmallStringVector generateGlobalSourcePaths() const;
+ Utils::SmallStringVector generateGlobalHeaderAndSourcePaths() const;
+ Utils::SmallStringVector generateGlobalArguments() const;
+ Utils::SmallStringVector generateGlobalCommandLine() const;
+ Utils::SmallStringVector generateGlobalPchCompilerArguments() const;
+ Utils::SmallStringVector generateGlobalClangCompilerArguments() const;
+
+ std::vector<uint> generateGlobalPchIncludeIds() const;
+
+ Utils::SmallString generatePchIncludeFileContent(const std::vector<uint> &includeIds) const;
+ Utils::SmallString generateGlobalPchHeaderFileContent() const;
+ std::unique_ptr<QFile> generateGlobalPchHeaderFile();
+ void generatePch(const Utils::SmallStringVector &commandLineArguments);
+ void generateGlobalPch();
+
+ Utils::SmallString globalPchContent() const;
+
+ static QStringList convertToQStringList(const Utils::SmallStringVector &convertToQStringList);
+
+ Utils::SmallString generateGlobalPchFilePathWithoutExtension() const;
+ Utils::SmallString generateGlobalPchHeaderFilePath() const;
+ Utils::SmallString generateGlobalPchFilePath() const;
+
+ Utils::SmallStringVector generateProjectPartCommandLine(
+ const V2::ProjectPartContainer &projectPart) const;
+ Utils::SmallString generateProjectPartPchFilePathWithoutExtension(
+ const V2::ProjectPartContainer &projectPart) const;
+ static Utils::SmallStringVector generateProjectPartHeaderAndSourcePaths(
+ const V2::ProjectPartContainer &projectPart);
+ std::vector<uint> generateProjectPartPchIncludes(
+ const V2::ProjectPartContainer &projectPart) const;
+ Utils::SmallString generateProjectPathPchHeaderFilePath(
+ const V2::ProjectPartContainer &projectPart) const;
+ Utils::SmallString generateProjectPartPchFilePath(
+ const V2::ProjectPartContainer &projectPart) const;
+ Utils::SmallStringVector generateProjectPartPchCompilerArguments(
+ const V2::ProjectPartContainer &projectPart) const;
+ Utils::SmallStringVector generateProjectPartClangCompilerArguments(
+ const V2::ProjectPartContainer &projectPart) const;
+ std::pair<ProjectPartPch, IdPaths> generateProjectPartPch(
+ const V2::ProjectPartContainer &projectPart);
+ static std::unique_ptr<QFile> generatePchHeaderFile(
+ const Utils::SmallString &filePath,
+ const Utils::SmallString &content);
+
+ void generatePchs();
+
+private:
+ static QByteArray projectPartHash(const V2::ProjectPartContainer &projectPart);
+ QByteArray globalProjectHash() const;
+ static void checkIfProcessHasError(const QProcess &process);
+
+private:
+ V2::ProjectPartContainers m_projectParts;
+ std::vector<ProjectPartPch> m_projectPartPchs;
+ std::vector<IdPaths> m_projectsIncludeIds;
+ Environment &m_environment;
+ StringCache<Utils::SmallString> &m_filePathCache;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/pchcreatorinterface.cpp b/src/tools/clangpchmanagerbackend/source/pchcreatorinterface.cpp
new file mode 100644
index 0000000000..44d28dee01
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/pchcreatorinterface.cpp
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "pchcreatorinterface.h"
+
+namespace ClangBackEnd {
+
+PchCreatorInterface::~PchCreatorInterface()
+{
+
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/pchcreatorinterface.h b/src/tools/clangpchmanagerbackend/source/pchcreatorinterface.h
new file mode 100644
index 0000000000..89aac39bd5
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/pchcreatorinterface.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "idpaths.h"
+#include "projectpartpch.h"
+
+#include <projectpartcontainerv2.h>
+
+namespace ClangBackEnd {
+
+class PchCreatorInterface
+{
+public:
+ virtual ~PchCreatorInterface();
+
+ virtual void generatePchs(V2::ProjectPartContainers &&projectsParts) = 0;
+ virtual std::vector<ProjectPartPch> takeProjectPartPchs() = 0;
+ virtual std::vector<IdPaths> takeProjectsIncludes() = 0;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp
new file mode 100644
index 0000000000..71ec82e45c
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "pchmanagerserver.h"
+
+#include <pchmanagerclientinterface.h>
+#include <precompiledheadersupdatedmessage.h>
+#include <removepchprojectpartsmessage.h>
+#include <updatepchprojectpartsmessage.h>
+
+#include <utils/smallstring.h>
+
+#include <QApplication>
+
+namespace ClangBackEnd {
+
+PchManagerServer::PchManagerServer(StringCache<Utils::SmallString> &filePathCache,
+ ClangPathWatcherInterface &fileSystemWatcher,
+ PchCreatorInterface &pchCreator,
+ ProjectPartsInterface &projectParts)
+ : m_filePathCache(filePathCache),
+ m_fileSystemWatcher(fileSystemWatcher),
+ m_pchCreator(pchCreator),
+ m_projectParts(projectParts)
+{
+ m_fileSystemWatcher.setNotifier(this);
+}
+
+void PchManagerServer::end()
+{
+ QCoreApplication::exit();
+
+}
+
+void PchManagerServer::updatePchProjectParts(UpdatePchProjectPartsMessage &&message)
+{
+ m_pchCreator.generatePchs(m_projectParts.update(message.takeProjectsParts()));
+
+ client()->precompiledHeadersUpdated(PrecompiledHeadersUpdatedMessage(m_pchCreator.takeProjectPartPchs()));
+
+ m_fileSystemWatcher.updateIdPaths(m_pchCreator.takeProjectsIncludes());
+}
+
+void PchManagerServer::removePchProjectParts(RemovePchProjectPartsMessage &&message)
+{
+ m_fileSystemWatcher.removeIds(message.projectsPartIds());
+
+ m_projectParts.remove(message.projectsPartIds());
+}
+
+void PchManagerServer::pathsWithIdsChanged(const Utils::SmallStringVector &ids)
+{
+ m_pchCreator.generatePchs(m_projectParts.projects(ids));
+
+ client()->precompiledHeadersUpdated(PrecompiledHeadersUpdatedMessage(m_pchCreator.takeProjectPartPchs()));
+
+ m_fileSystemWatcher.updateIdPaths(m_pchCreator.takeProjectsIncludes());
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h
new file mode 100644
index 0000000000..b12ffeca7f
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "clangpathwatcherinterface.h"
+#include "clangpathwatchernotifier.h"
+#include "pchcreatorinterface.h"
+#include "pchmanagerserverinterface.h"
+#include "projectpartsinterface.h"
+#include "stringcache.h"
+
+namespace ClangBackEnd {
+
+class SourceRangesAndDiagnosticsForQueryMessage;
+
+class PchManagerServer : public PchManagerServerInterface, public ClangPathWatcherNotifier
+{
+public:
+ PchManagerServer(StringCache<Utils::SmallString> &filePathCache,
+ ClangPathWatcherInterface &fileSystemWatcher,
+ PchCreatorInterface &pchCreator,
+ ProjectPartsInterface &projectParts);
+
+
+ void end() override;
+ void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override;
+ void removePchProjectParts(RemovePchProjectPartsMessage &&message) override;
+
+ void pathsWithIdsChanged(const Utils::SmallStringVector &ids) override;
+
+private:
+ StringCache<Utils::SmallString> &m_filePathCache;
+ ClangPathWatcherInterface &m_fileSystemWatcher;
+ PchCreatorInterface &m_pchCreator;
+ ProjectPartsInterface &m_projectParts;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/pchnotcreatederror.h b/src/tools/clangpchmanagerbackend/source/pchnotcreatederror.h
new file mode 100644
index 0000000000..6be51c0baa
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/pchnotcreatederror.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+
+#include <stdexcept>
+
+namespace ClangBackEnd {
+
+class PchNotCreatedError : public std::runtime_error
+{
+ using std::runtime_error::runtime_error;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/projectparts.cpp b/src/tools/clangpchmanagerbackend/source/projectparts.cpp
new file mode 100644
index 0000000000..c79882766d
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/projectparts.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "projectparts.h"
+
+#include <projectpartcontainerv2.h>
+
+#include <algorithm>
+
+namespace ClangBackEnd {
+
+inline namespace Pch {
+
+V2::ProjectPartContainers ProjectParts::update(V2::ProjectPartContainers &&projectsParts)
+{
+ auto uniqueProjectParts = ProjectParts::uniqueProjectParts(std::move(projectsParts));
+
+ auto updatedProjectPartContainers = newProjectParts(std::move(uniqueProjectParts));
+
+ mergeProjectParts(updatedProjectPartContainers);
+
+ return updatedProjectPartContainers;
+}
+
+void ProjectParts::remove(const Utils::SmallStringVector &ids)
+{
+ auto shouldRemove = [&] (const V2::ProjectPartContainer &projectPart) {
+ return std::find(ids.begin(), ids.end(), projectPart.projectPartId()) != ids.end();
+ };
+
+ auto newEnd = std::remove_if(m_projectParts.begin(), m_projectParts.end(), shouldRemove);
+ m_projectParts.erase(newEnd, m_projectParts.end());
+}
+
+V2::ProjectPartContainers ProjectParts::projects(const Utils::SmallStringVector &projectPartIds) const
+{
+ V2::ProjectPartContainers projectPartsWithIds;
+
+ std::copy_if(m_projectParts.begin(),
+ m_projectParts.end(),
+ std::back_inserter(projectPartsWithIds),
+ [&] (const V2::ProjectPartContainer &projectPart) {
+ return std::binary_search(projectPartIds.begin(), projectPartIds.end(), projectPart.projectPartId());
+ });
+
+ return projectPartsWithIds;
+}
+
+V2::ProjectPartContainers ProjectParts::uniqueProjectParts(V2::ProjectPartContainers &&projectsParts)
+{
+ std::sort(projectsParts.begin(), projectsParts.end());
+ auto newEnd = std::unique(projectsParts.begin(), projectsParts.end());
+
+ projectsParts.erase(newEnd, projectsParts.end());
+
+ return std::move(projectsParts);
+}
+
+V2::ProjectPartContainers ProjectParts::newProjectParts(V2::ProjectPartContainers &&projectsParts) const
+{
+ V2::ProjectPartContainers updatedProjectPartContainers;
+ updatedProjectPartContainers.reserve(projectsParts.size());
+
+ std::set_difference(std::make_move_iterator(projectsParts.begin()),
+ std::make_move_iterator(projectsParts.end()),
+ m_projectParts.begin(),
+ m_projectParts.end(),
+ std::back_inserter(updatedProjectPartContainers));
+
+ return updatedProjectPartContainers;
+}
+
+void ProjectParts::mergeProjectParts(const V2::ProjectPartContainers &projectsParts)
+{
+ V2::ProjectPartContainers newProjectParts;
+ newProjectParts.reserve(m_projectParts.size() + projectsParts.size());
+
+ auto compare = [] (const V2::ProjectPartContainer &first, const V2::ProjectPartContainer &second) {
+ return first.projectPartId() < second.projectPartId();
+ };
+
+ std::set_union(projectsParts.begin(),
+ projectsParts.end(),
+ m_projectParts.begin(),
+ m_projectParts.end(),
+ std::back_inserter(newProjectParts),
+ compare);
+
+ m_projectParts = newProjectParts;
+}
+
+const V2::ProjectPartContainers &ProjectParts::projectParts() const
+{
+ return m_projectParts;
+}
+
+} // namespace Pch
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/projectparts.h b/src/tools/clangpchmanagerbackend/source/projectparts.h
new file mode 100644
index 0000000000..2651e22ce6
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/projectparts.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "clangpchmanagerbackend_global.h"
+
+#include <projectpartsinterface.h>
+
+#include <utils/smallstringvector.h>
+
+namespace ClangBackEnd {
+
+inline namespace Pch {
+
+class ProjectParts final : public ProjectPartsInterface
+{
+public:
+ V2::ProjectPartContainers update(V2::ProjectPartContainers &&projectsParts) override;
+ void remove(const Utils::SmallStringVector &projectPartIds) override;
+ V2::ProjectPartContainers projects(const Utils::SmallStringVector &projectPartIds) const override;
+
+unitttest_public:
+ static V2::ProjectPartContainers uniqueProjectParts(V2::ProjectPartContainers &&projectsParts);
+ V2::ProjectPartContainers newProjectParts(V2::ProjectPartContainers &&projectsParts) const;
+ void mergeProjectParts(const V2::ProjectPartContainers &projectsParts);
+ const V2::ProjectPartContainers &projectParts() const;
+
+private:
+ V2::ProjectPartContainers m_projectParts;
+};
+
+} // namespace Pch
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/projectpartsinterface.cpp b/src/tools/clangpchmanagerbackend/source/projectpartsinterface.cpp
new file mode 100644
index 0000000000..fe7a0e6bd1
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/projectpartsinterface.cpp
@@ -0,0 +1,34 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "projectpartsinterface.h"
+
+namespace ClangBackEnd {
+
+ProjectPartsInterface::~ProjectPartsInterface()
+{
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/projectpartsinterface.h b/src/tools/clangpchmanagerbackend/source/projectpartsinterface.h
new file mode 100644
index 0000000000..1c3ec785b3
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/projectpartsinterface.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <projectpartcontainerv2.h>
+
+namespace ClangBackEnd {
+
+class ProjectPartsInterface
+{
+public:
+ virtual ~ProjectPartsInterface();
+
+ virtual V2::ProjectPartContainers update(V2::ProjectPartContainers &&projectsParts) = 0;
+ virtual void remove(const Utils::SmallStringVector &projectPartIds) = 0;
+ virtual V2::ProjectPartContainers projects(const Utils::SmallStringVector &projectPartIds) const = 0;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/stringcache.h b/src/tools/clangpchmanagerbackend/source/stringcache.h
new file mode 100644
index 0000000000..a85c314700
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/stringcache.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "clangpchmanagerbackend_global.h"
+
+#include <utils/smallstringview.h>
+
+#include <algorithm>
+#include <vector>
+
+namespace ClangBackEnd {
+
+template <typename StringType>
+class StringCache
+{
+ class StringCacheEntry
+ {
+ public:
+ StringCacheEntry(StringType &&string, uint id)
+ : string(std::move(string)),
+ id(id)
+ {}
+
+ friend bool operator<(const StringCacheEntry &entry, Utils::SmallStringView stringView)
+ {
+ return entry.string < stringView;
+ }
+
+ friend bool operator<(Utils::SmallStringView stringView, const StringCacheEntry &entry)
+ {
+ return stringView < entry.string;
+ }
+
+ StringType string;
+ uint id;
+ };
+
+ using StringCacheEntries = std::vector<StringCacheEntry>;
+ using const_iterator = typename StringCacheEntries::const_iterator;
+
+ class Found
+ {
+ public:
+ typename StringCacheEntries::const_iterator iterator;
+ bool wasFound;
+ };
+
+
+public:
+ StringCache()
+ {
+ m_strings.reserve(1024);
+ m_indices.reserve(1024);
+ }
+
+ uint stringId(Utils::SmallStringView stringView)
+ {
+ Found found = find(stringView);
+
+ if (!found.wasFound)
+ return insertString(found.iterator, stringView);
+
+ return found.iterator->id;
+ }
+
+ std::vector<uint> stringIds(const std::vector<StringType> &strings)
+ {
+ std::vector<uint> ids;
+ ids.reserve(strings.size());
+
+ std::transform(strings.begin(),
+ strings.end(),
+ std::back_inserter(ids),
+ [&] (const StringType &string) { return stringId(string); });
+
+ return ids;
+ }
+
+ const StringType &string(uint id) const
+ {
+ return m_strings.at(m_indices.at(id)).string;
+ }
+
+ std::vector<StringType> strings(const std::vector<uint> &ids) const
+ {
+ std::vector<StringType> strings;
+ strings.reserve(ids.size());
+
+ std::transform(ids.begin(),
+ ids.end(),
+ std::back_inserter(strings),
+ [&] (uint id) { return m_strings.at(m_indices.at(id)).string; });
+
+ return strings;
+ }
+
+private:
+ Found find(Utils::SmallStringView stringView)
+ {
+ auto range = std::equal_range(m_strings.cbegin(), m_strings.cend(), stringView);
+
+ return {range.first, range.first != range.second};
+ }
+
+ void incrementLargerOrEqualIndicesByOne(uint newIndex)
+ {
+ std::transform(m_indices.begin(),
+ m_indices.end(),
+ m_indices.begin(),
+ [&] (uint index) {
+ return index >= newIndex ? ++index : index;
+ });
+ }
+
+ uint insertString(const_iterator beforeIterator,
+ Utils::SmallStringView stringView)
+ {
+ auto id = uint(m_strings.size());
+
+ auto inserted = m_strings.emplace(beforeIterator, StringType(stringView), id);
+
+ auto newIndex = uint(std::distance(m_strings.begin(), inserted));
+
+ incrementLargerOrEqualIndicesByOne(newIndex);
+
+ m_indices.push_back(newIndex);
+
+ return id;
+ }
+
+private:
+ StringCacheEntries m_strings;
+ std::vector<uint> m_indices;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/tools.pro b/src/tools/tools.pro
index 25506b7282..dc42b053bd 100644
--- a/src/tools/tools.pro
+++ b/src/tools/tools.pro
@@ -26,8 +26,9 @@ exists($$LLVM_INSTALL_DIR) {
win32-msvc2015:lessThan(QT_CL_PATCH_VERSION, 24210): QTC_NO_CLANG_LIBTOOLING = 1
isEmpty(QTC_NO_CLANG_LIBTOOLING) {
SUBDIRS += clangrefactoringbackend
+ SUBDIRS += clangpchmanagerbackend
} else {
- warning("Building the Clang refactoring back end is disabled.")
+ warning("Building the Clang refactoring back end and the pch manager plugins are disabled.")
}
}