diff options
author | Marco Bubke <marco.bubke@qt.io> | 2019-07-31 16:54:39 +0200 |
---|---|---|
committer | Marco Bubke <marco.bubke@qt.io> | 2019-08-27 11:50:39 +0000 |
commit | 56d611e0a3847dc477ec940edcf48cb821eee7b5 (patch) | |
tree | 50fcffcb367e650724c53b2536ff81eddf7e9742 /src/tools | |
parent | f1be7793c43074d67d47429dd6ec2e4681667820 (diff) | |
download | qt-creator-56d611e0a3847dc477ec940edcf48cb821eee7b5.tar.gz |
ClangPchManager: Update PCHs if time stamps of dependencies changed
If there is a newer file than the last indexing or if a file is added or
removed from the project or system PCH we have to reindex the project and
maybe the system PCH.
Change-Id: Ibce2a244190a79b5c422c469c065ddc11e44b2cb
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Diffstat (limited to 'src/tools')
7 files changed, 264 insertions, 64 deletions
diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp index 5a634f8fe1..8c2023834d 100644 --- a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp +++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp @@ -185,8 +185,12 @@ struct Data // because we have a cycle dependency ApplicationEnvironment environment; ProjectPartsStorage<> projectPartsStorage{database}; PrecompiledHeaderStorage<> preCompiledHeaderStorage{database}; - ProjectPartsManager projectParts{projectPartsStorage, preCompiledHeaderStorage}; GeneratedFiles generatedFiles; + ProjectPartsManager projectParts{projectPartsStorage, + preCompiledHeaderStorage, + buildDependencyProvider, + filePathCache, + generatedFiles}; PchCreatorManager pchCreatorManager{generatedFiles, environment, database, @@ -227,7 +231,9 @@ struct Data // because we have a cycle dependency pchTaskGenerator, projectParts, generatedFiles, - buildDependencyStorage}; + buildDependencyStorage/*, + buildDependencyProvider, + filePathCache*/}; TaskScheduler systemTaskScheduler{pchCreatorManager, pchTaskQueue, pchCreationProgressCounter, diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp index b393a8e465..47ac358765 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp @@ -26,6 +26,7 @@ #include "pchmanagerserver.h" #include <builddependenciesstorage.h> +#include <filepathcachinginterface.h> #include <pchmanagerclientinterface.h> #include <pchtaskgeneratorinterface.h> #include <precompiledheadersupdatedmessage.h> @@ -54,6 +55,7 @@ PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher, , m_projectPartsManager(projectParts) , m_generatedFiles(generatedFiles) , m_buildDependenciesStorage(buildDependenciesStorage) + { m_fileSystemWatcher.setNotifier(this); } @@ -79,10 +81,13 @@ void PchManagerServer::updateProjectParts(UpdateProjectPartsMessage &&message) auto upToDateProjectParts = m_projectPartsManager.update(message.takeProjectsParts()); if (m_generatedFiles.isValid()) { - m_pchTaskGenerator.addProjectParts(std::move(upToDateProjectParts.notUpToDate), - std::move(message.toolChainArguments)); + m_pchTaskGenerator.addProjectParts(std::move(upToDateProjectParts.updateSystem), + message.toolChainArguments.clone()); + m_pchTaskGenerator.addNonSystemProjectParts(std::move(upToDateProjectParts.updateProject), + std::move(message.toolChainArguments)); } else { - m_projectPartsManager.updateDeferred(upToDateProjectParts.notUpToDate); + m_projectPartsManager.updateDeferred(std::move(upToDateProjectParts.updateSystem), + std::move(upToDateProjectParts.updateProject)); } client()->precompiledHeadersUpdated(toProjectPartIds(upToDateProjectParts.upToDate)); @@ -119,13 +124,21 @@ void PchManagerServer::updateGeneratedFiles(UpdateGeneratedFilesMessage &&messag m_generatedFiles.update(message.takeGeneratedFiles()); if (m_generatedFiles.isValid()) { - ProjectPartContainers deferredProjectParts = m_projectPartsManager.deferredUpdates(); - ArgumentsEntries entries = m_toolChainsArgumentsCache.arguments( - projectPartIds(deferredProjectParts)); + ProjectPartContainers deferredSystems = m_projectPartsManager.deferredSystemUpdates(); + ArgumentsEntries systemEntries = m_toolChainsArgumentsCache.arguments( + projectPartIds(deferredSystems)); + + for (ArgumentsEntry &entry : systemEntries) { + m_pchTaskGenerator.addProjectParts(std::move(deferredSystems), std::move(entry.arguments)); + } + + ProjectPartContainers deferredProjects = m_projectPartsManager.deferredProjectUpdates(); + ArgumentsEntries projectEntries = m_toolChainsArgumentsCache.arguments( + projectPartIds(deferredProjects)); - for (ArgumentsEntry &entry : entries) { - m_pchTaskGenerator.addProjectParts(std::move(deferredProjectParts), - std::move(entry.arguments)); + for (ArgumentsEntry &entry : projectEntries) { + m_pchTaskGenerator.addNonSystemProjectParts(std::move(deferredProjects), + std::move(entry.arguments)); } } } diff --git a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h index a65ab803df..d781c96e52 100644 --- a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h +++ b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h @@ -125,6 +125,20 @@ public: } } + void deleteSystemAndProjectPrecompiledHeaders(const ProjectPartIds &projectPartIds) override + { + try { + Sqlite::ImmediateTransaction transaction{database}; + + for (ProjectPartId projectPartId : projectPartIds) + deleteSystemAndProjectPrecompiledHeaderStatement.write(projectPartId.projectPathId); + + transaction.commit(); + } catch (const Sqlite::StatementIsBusy) { + deleteSystemAndProjectPrecompiledHeaders(projectPartIds); + } + } + FilePath fetchSystemPrecompiledHeaderPath(ProjectPartId projectPartId) override { try { @@ -230,6 +244,11 @@ public: "UPDATE OR IGNORE precompiledHeaders SET systemPchPath=NULL,systemPchBuildTime=NULL " "WHERE projectPartId = ?", database}; + WriteStatement deleteSystemAndProjectPrecompiledHeaderStatement{ + "UPDATE OR IGNORE precompiledHeaders SET " + "systemPchPath=NULL,systemPchBuildTime=NULL,projectPchPath=NULL,projectPchBuildTime=NULL " + "WHERE projectPartId = ?", + database}; ReadStatement fetchSystemPrecompiledHeaderPathStatement{ "SELECT systemPchPath FROM precompiledHeaders WHERE projectPartId = ?", database}; mutable ReadStatement fetchPrecompiledHeaderStatement{ diff --git a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h index dacdbe9e17..92b3604cdc 100644 --- a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h +++ b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h @@ -55,6 +55,7 @@ public: TimeStamp pchBuildTime) = 0; virtual void deleteSystemPrecompiledHeaders(const ProjectPartIds &projectPartIds) = 0; + virtual void deleteSystemAndProjectPrecompiledHeaders(const ProjectPartIds &projectPartIds) = 0; virtual FilePath fetchSystemPrecompiledHeaderPath(ProjectPartId projectPartId) = 0; virtual FilePath fetchPrecompiledHeader(ProjectPartId projectPartId) const = 0; virtual PchPaths fetchPrecompiledHeaders(ProjectPartId projectPartId) const = 0; diff --git a/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp b/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp index 191a13e16b..f618559e40 100644 --- a/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp +++ b/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp @@ -25,7 +25,11 @@ #include "projectpartsmanager.h" +#include <builddependenciesproviderinterface.h> +#include <filecontainerv2.h> +#include <filepathcachinginterface.h> #include <projectpartcontainer.h> +#include <set_algorithm.h> #include <algorithm> @@ -44,38 +48,171 @@ ProjectPartIds toProjectPartIds(const ProjectPartContainers &projectsParts) return ids; } +namespace { + +enum class Change { System, Project, No }; + +Change changedSourceType(const SourceEntries &sources) +{ + Change change = Change::No; + for (SourceEntry sourceEntry : sources) { + switch (sourceEntry.sourceType) { + case SourceType::SystemInclude: + case SourceType::TopSystemInclude: + return Change::System; + case SourceType::ProjectInclude: + case SourceType::TopProjectInclude: + change = Change::Project; + break; + case SourceType::Source: + case SourceType::UserInclude: + break; + } + } + + return change; +} + +} // namespace + ProjectPartsManager::UpToDataProjectParts ProjectPartsManager::update(ProjectPartContainers &&projectsParts) { - auto notUpToDateProjectParts = filterProjectParts(projectsParts, m_projectParts); + auto updateSystemProjectParts = filterProjectParts(projectsParts, m_projectParts); - if (notUpToDateProjectParts.empty()) - return {std::move(projectsParts), {}}; + if (!updateSystemProjectParts.empty()) { + auto persistentProjectParts = m_projectPartsStorage.fetchProjectParts( + toProjectPartIds(updateSystemProjectParts)); - auto persistentProjectParts = m_projectPartsStorage.fetchProjectParts( - toProjectPartIds(notUpToDateProjectParts)); + if (persistentProjectParts.size() > 0) { + mergeProjectParts(persistentProjectParts); - if (persistentProjectParts.size() > 0) { - mergeProjectParts(persistentProjectParts); + updateSystemProjectParts = filterProjectParts(updateSystemProjectParts, + persistentProjectParts); + } - notUpToDateProjectParts = filterProjectParts(notUpToDateProjectParts, persistentProjectParts); + if (updateSystemProjectParts.size()) { + m_projectPartsStorage.updateProjectParts(updateSystemProjectParts); - if (notUpToDateProjectParts.empty()) - return {}; + mergeProjectParts(updateSystemProjectParts); + } } - m_projectPartsStorage.updateProjectParts(notUpToDateProjectParts); - m_projectPartsStorage.resetIndexingTimeStamps(notUpToDateProjectParts); - m_precompiledHeaderStorage.deleteProjectPrecompiledHeaders( - toProjectPartIds(notUpToDateProjectParts)); + auto upToDateProjectParts = filterProjectParts(projectsParts, updateSystemProjectParts); - mergeProjectParts(notUpToDateProjectParts); + auto updates = checkDependeciesAndTime(std::move(upToDateProjectParts), + std::move(updateSystemProjectParts)); - auto upToDateProjectParts = filterProjectParts(projectsParts, notUpToDateProjectParts); + if (updates.updateSystem.size()) { + m_projectPartsStorage.resetIndexingTimeStamps(updates.updateSystem); + m_precompiledHeaderStorage.deleteSystemAndProjectPrecompiledHeaders( + toProjectPartIds(updates.updateSystem)); + } + if (updates.updateProject.size()) { + m_projectPartsStorage.resetIndexingTimeStamps(updates.updateProject); + m_precompiledHeaderStorage.deleteProjectPrecompiledHeaders( + toProjectPartIds(updates.updateProject)); + } - return {upToDateProjectParts, notUpToDateProjectParts}; + return updates; } -void ProjectPartsManager::remove(const ProjectPartIds &projectPartIds) +ProjectPartsManagerInterface::UpToDataProjectParts ProjectPartsManager::checkDependeciesAndTime( + ProjectPartContainers &&upToDateProjectParts, ProjectPartContainers &&updateSystemProjectParts) +{ + ProjectPartContainerReferences changeProjectParts; + changeProjectParts.reserve(upToDateProjectParts.size()); + + ProjectPartContainers updateProjectProjectParts; + updateProjectProjectParts.reserve(upToDateProjectParts.size()); + + updateSystemProjectParts.reserve(updateProjectProjectParts.size() + upToDateProjectParts.size()); + + auto systemSplit = updateSystemProjectParts.end(); + + for (ProjectPartContainer &projectPart : upToDateProjectParts) { + auto oldSources = m_buildDependenciesProvider.createSourceEntriesFromStorage( + projectPart.sourcePathIds, projectPart.projectPartId); + + BuildDependency buildDependency = m_buildDependenciesProvider.create(projectPart, + Utils::clone(oldSources)); + + auto newSources = buildDependency.sources; + + SourceEntries updatedSourceTyes; + updatedSourceTyes.reserve(newSources.size()); + + std::set_symmetric_difference(newSources.begin(), + newSources.end(), + oldSources.begin(), + oldSources.end(), + std::back_inserter(updatedSourceTyes), + [](SourceEntry first, SourceEntry second) { + return std::tie(first.sourceId, first.sourceType) + < std::tie(second.sourceId, second.sourceType); + }); + + auto change = changedSourceType(updatedSourceTyes); + + switch (change) { + case Change::Project: + updateProjectProjectParts.emplace_back(std::move(projectPart)); + projectPart.projectPartId = -1; + break; + case Change::System: + updateSystemProjectParts.emplace_back(std::move(projectPart)); + projectPart.projectPartId = -1; + break; + case Change::No: + break; + } + + if (change == Change::No) { + SourceEntries updatedTimeStamps; + updatedTimeStamps.reserve(newSources.size()); + + std::set_difference(newSources.begin(), + newSources.end(), + oldSources.begin(), + oldSources.end(), + std::back_inserter(updatedTimeStamps), + [](SourceEntry first, SourceEntry second) { + return std::tie(first.sourceId, first.timeStamp) + < std::tie(second.sourceId, second.timeStamp); + }); + + auto change = changedSourceType(updatedTimeStamps); + + switch (change) { + case Change::Project: + updateProjectProjectParts.emplace_back(std::move(projectPart)); + projectPart.projectPartId = -1; + break; + case Change::System: + updateSystemProjectParts.emplace_back(std::move(projectPart)); + projectPart.projectPartId = -1; + break; + case Change::No: + break; + } + } + } + + std::inplace_merge(updateSystemProjectParts.begin(), systemSplit, updateSystemProjectParts.end()); + upToDateProjectParts.erase(std::remove_if(upToDateProjectParts.begin(), + upToDateProjectParts.end(), + [](const ProjectPartContainer &projectPart) { + return !projectPart.projectPartId.isValid(); + }), + upToDateProjectParts.end()); + + return {std::move(upToDateProjectParts), + std::move(updateSystemProjectParts), + updateProjectProjectParts}; +} + +namespace { +ProjectPartContainers removed(ProjectPartContainers &&projectParts, + const ProjectPartIds &projectPartIds) { ProjectPartContainers projectPartsWithoutIds; @@ -99,14 +236,22 @@ void ProjectPartsManager::remove(const ProjectPartIds &projectPartIds) } }; - std::set_difference(std::make_move_iterator(m_projectParts.begin()), - std::make_move_iterator(m_projectParts.end()), + std::set_difference(std::make_move_iterator(projectParts.begin()), + std::make_move_iterator(projectParts.end()), projectPartIds.begin(), projectPartIds.end(), std::back_inserter(projectPartsWithoutIds), Compare{}); - m_projectParts = std::move(projectPartsWithoutIds); + return projectPartsWithoutIds; +} +} // namespace + +void ProjectPartsManager::remove(const ProjectPartIds &projectPartIds) +{ + m_projectParts = removed(std::move(m_projectParts), projectPartIds); + m_systemDeferredProjectParts = removed(std::move(m_systemDeferredProjectParts), projectPartIds); + m_projectDeferredProjectParts = removed(std::move(m_projectDeferredProjectParts), projectPartIds); } ProjectPartContainers ProjectPartsManager::projects(const ProjectPartIds &projectPartIds) const @@ -143,38 +288,42 @@ ProjectPartContainers ProjectPartsManager::projects(const ProjectPartIds &projec return projectPartsWithIds; } -void ProjectPartsManager::updateDeferred(const ProjectPartContainers &deferredProjectsParts) +namespace { +ProjectPartContainers merge(ProjectPartContainers &&newProjectParts, + ProjectPartContainers &&oldProjectParts) { - ProjectPartContainerReferences deferredProjectPartPointers; - deferredProjectPartPointers.reserve(deferredProjectsParts.size()); - - std::set_intersection(m_projectParts.begin(), - m_projectParts.end(), - deferredProjectsParts.begin(), - deferredProjectsParts.end(), - std::back_inserter(deferredProjectPartPointers), - [](const ProjectPartContainer &first, const ProjectPartContainer &second) { - return first.projectPartId < second.projectPartId; - }); - - for (ProjectPartContainer &projectPart : deferredProjectPartPointers) - projectPart.updateIsDeferred = true; + ProjectPartContainers mergedProjectParts; + mergedProjectParts.reserve(newProjectParts.size() + oldProjectParts.size()); + + std::set_union(std::make_move_iterator(newProjectParts.begin()), + std::make_move_iterator(newProjectParts.end()), + std::make_move_iterator(oldProjectParts.begin()), + std::make_move_iterator(oldProjectParts.end()), + std::back_inserter(mergedProjectParts), + [](const ProjectPartContainer &first, const ProjectPartContainer &second) { + return first.projectPartId < second.projectPartId; + }); + + return mergedProjectParts; } +} // namespace -ProjectPartContainers ProjectPartsManager::deferredUpdates() +void ProjectPartsManager::updateDeferred(ProjectPartContainers &&system, + ProjectPartContainers &&project) { - ProjectPartContainers deferredProjectParts; - deferredProjectParts.reserve(m_projectParts.size()); - - std::copy_if(m_projectParts.cbegin(), - m_projectParts.cend(), - std::back_inserter(deferredProjectParts), - [](const ProjectPartContainer &projectPart) { return projectPart.updateIsDeferred; }); + m_systemDeferredProjectParts = merge(std::move(system), std::move(m_systemDeferredProjectParts)); + m_projectDeferredProjectParts = merge(std::move(project), + std::move(m_projectDeferredProjectParts)); +} - for (ProjectPartContainer &projectPart : m_projectParts) - projectPart.updateIsDeferred = false; +ProjectPartContainers ProjectPartsManager::deferredSystemUpdates() +{ + return std::move(m_systemDeferredProjectParts); +} - return deferredProjectParts; +ProjectPartContainers ProjectPartsManager::deferredProjectUpdates() +{ + return std::move(m_projectDeferredProjectParts); } ProjectPartContainers ProjectPartsManager::filterProjectParts( diff --git a/src/tools/clangpchmanagerbackend/source/projectpartsmanager.h b/src/tools/clangpchmanagerbackend/source/projectpartsmanager.h index 35d9e41c1c..e32c41fde1 100644 --- a/src/tools/clangpchmanagerbackend/source/projectpartsmanager.h +++ b/src/tools/clangpchmanagerbackend/source/projectpartsmanager.h @@ -35,32 +35,42 @@ namespace ClangBackEnd { +class BuildDependenciesProviderInterface; + inline namespace Pch { class ProjectPartsManager final : public ProjectPartsManagerInterface { public: ProjectPartsManager(ProjectPartsStorageInterface &projectPartsStorage, - PrecompiledHeaderStorageInterface &precompiledHeaderStorage) + PrecompiledHeaderStorageInterface &precompiledHeaderStorage, + BuildDependenciesProviderInterface &buildDependenciesProvider) : m_projectPartsStorage(projectPartsStorage) , m_precompiledHeaderStorage(precompiledHeaderStorage) + , m_buildDependenciesProvider(buildDependenciesProvider) {} UpToDataProjectParts update(ProjectPartContainers &&projectsParts) override; void remove(const ProjectPartIds &projectPartIds) override; ProjectPartContainers projects(const ProjectPartIds &projectPartIds) const override; - void updateDeferred(const ProjectPartContainers &projectsParts) override; - ProjectPartContainers deferredUpdates() override; + void updateDeferred(ProjectPartContainers &&system, ProjectPartContainers &&project) override; + ProjectPartContainers deferredSystemUpdates() override; + ProjectPartContainers deferredProjectUpdates() override; static ProjectPartContainers filterProjectParts(const ProjectPartContainers &newProjectsParts, const ProjectPartContainers &oldProjectParts); void mergeProjectParts(const ProjectPartContainers &projectsParts); const ProjectPartContainers &projectParts() const; + UpToDataProjectParts checkDependeciesAndTime(ProjectPartContainers &&upToDateProjectParts, + ProjectPartContainers &&updateSystemProjectParts); private: ProjectPartContainers m_projectParts; + ProjectPartContainers m_systemDeferredProjectParts; + ProjectPartContainers m_projectDeferredProjectParts; ProjectPartsStorageInterface &m_projectPartsStorage; PrecompiledHeaderStorageInterface &m_precompiledHeaderStorage; + BuildDependenciesProviderInterface &m_buildDependenciesProvider; }; } // namespace Pch diff --git a/src/tools/clangpchmanagerbackend/source/projectpartsmanagerinterface.h b/src/tools/clangpchmanagerbackend/source/projectpartsmanagerinterface.h index 54bae58c1a..696839c4b8 100644 --- a/src/tools/clangpchmanagerbackend/source/projectpartsmanagerinterface.h +++ b/src/tools/clangpchmanagerbackend/source/projectpartsmanagerinterface.h @@ -36,7 +36,8 @@ public: { public: ProjectPartContainers upToDate; - ProjectPartContainers notUpToDate; + ProjectPartContainers updateSystem; + ProjectPartContainers updateProject; }; ProjectPartsManagerInterface() = default; @@ -46,8 +47,9 @@ public: virtual UpToDataProjectParts update(ProjectPartContainers &&projectsParts) = 0; virtual void remove(const ProjectPartIds &projectPartIds) = 0; virtual ProjectPartContainers projects(const ProjectPartIds &projectPartIds) const = 0; - virtual void updateDeferred(const ProjectPartContainers &projectsParts) = 0; - virtual ProjectPartContainers deferredUpdates() = 0; + virtual void updateDeferred(ProjectPartContainers &&system, ProjectPartContainers &&project) = 0; + virtual ProjectPartContainers deferredSystemUpdates() = 0; + virtual ProjectPartContainers deferredProjectUpdates() = 0; protected: ~ProjectPartsManagerInterface() = default; |