ClangPchManager: Don't update system PCH if no system include file changed

If a project or user file is touched the system PCH should not be
regenerated.

Change-Id: Id5989735bab4441fc1eebfb5d31e01ba9714428b
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2019-07-03 16:41:59 +02:00
parent cc87615fcd
commit f864c7a0d8
9 changed files with 180 additions and 41 deletions

View File

@@ -221,7 +221,8 @@ struct Data // because we have a cycle dependency
database};
ClangBackEnd::PchTaskGenerator pchTaskGenerator{buildDependencyProvider,
pchTaskMerger,
dependencyCreationProgressCounter};
dependencyCreationProgressCounter,
pchTaskQueue};
PchManagerServer clangPchManagerServer{includeWatcher,
pchTaskGenerator,
projectParts,

View File

@@ -143,46 +143,67 @@ struct FilterResults
ProjectPartIds userIds;
};
std::pair<ProjectPartIds, ProjectPartIds> pchProjectPartIds(const std::vector<IdPaths> &idPaths)
ProjectPartIds removeIds(const ProjectPartIds &subtrahend, const ProjectPartIds &minuend)
{
ProjectPartIds changedProjectPartIds;
changedProjectPartIds.reserve(idPaths.size());
ProjectPartIds difference;
difference.reserve(subtrahend.size());
ProjectPartIds changedPchProjectPartIds;
changedPchProjectPartIds.reserve(idPaths.size());
std::set_difference(subtrahend.begin(),
subtrahend.end(),
minuend.begin(),
minuend.end(),
std::back_inserter(difference));
return difference;
}
FilterResults pchProjectPartIds(const std::vector<IdPaths> &idPaths)
{
ProjectPartIds changedUserProjectPartIds;
changedUserProjectPartIds.reserve(idPaths.size());
ProjectPartIds changedSystemPchProjectPartIds;
changedSystemPchProjectPartIds.reserve(idPaths.size());
ProjectPartIds changedProjectPchProjectPartIds;
changedProjectPchProjectPartIds.reserve(idPaths.size());
for (const IdPaths &idPath : idPaths) {
switch (idPath.id.sourceType) {
case SourceType::TopSystemInclude:
case SourceType::SystemInclude:
changedSystemPchProjectPartIds.push_back(idPath.id.id);
break;
case SourceType::TopProjectInclude:
case SourceType::ProjectInclude:
changedPchProjectPartIds.push_back(idPath.id.id);
changedProjectPchProjectPartIds.push_back(idPath.id.id);
break;
case SourceType::UserInclude:
case SourceType::Source:
changedProjectPartIds.push_back(idPath.id.id);
changedUserProjectPartIds.push_back(idPath.id.id);
break;
}
}
changedPchProjectPartIds.erase(std::unique(changedPchProjectPartIds.begin(),
changedPchProjectPartIds.end()),
changedPchProjectPartIds.end());
changedPchProjectPartIds.erase(std::unique(changedPchProjectPartIds.begin(),
changedPchProjectPartIds.end()),
changedPchProjectPartIds.end());
changedSystemPchProjectPartIds.erase(std::unique(changedSystemPchProjectPartIds.begin(),
changedSystemPchProjectPartIds.end()),
changedSystemPchProjectPartIds.end());
changedProjectPchProjectPartIds.erase(std::unique(changedProjectPchProjectPartIds.begin(),
changedProjectPchProjectPartIds.end()),
changedProjectPchProjectPartIds.end());
changedUserProjectPartIds.erase(std::unique(changedUserProjectPartIds.begin(),
changedUserProjectPartIds.end()),
changedUserProjectPartIds.end());
ProjectPartIds changedUserProjectPartIds;
changedProjectPartIds.reserve(changedProjectPartIds.size());
changedProjectPchProjectPartIds = removeIds(changedProjectPchProjectPartIds,
changedSystemPchProjectPartIds);
std::set_difference(changedProjectPartIds.begin(),
changedProjectPartIds.end(),
changedPchProjectPartIds.begin(),
changedPchProjectPartIds.end(),
std::back_inserter(changedUserProjectPartIds));
changedUserProjectPartIds = removeIds(changedUserProjectPartIds, changedSystemPchProjectPartIds);
changedUserProjectPartIds = removeIds(changedUserProjectPartIds, changedProjectPchProjectPartIds);
return {changedPchProjectPartIds, changedUserProjectPartIds};
return {std::move(changedSystemPchProjectPartIds),
std::move(changedProjectPchProjectPartIds),
std::move(changedUserProjectPartIds)};
}
} // namespace
@@ -190,14 +211,11 @@ void PchManagerServer::pathsWithIdsChanged(const std::vector<IdPaths> &idPaths)
{
auto changedProjectPartIds = pchProjectPartIds(idPaths);
ArgumentsEntries entries = m_toolChainsArgumentsCache.arguments(changedProjectPartIds.first);
addCompleteProjectParts(changedProjectPartIds.systemIds);
for (ArgumentsEntry &entry : entries) {
m_pchTaskGenerator.addProjectParts(m_projectPartsManager.projects(entry.ids),
std::move(entry.arguments));
}
addNonSystemProjectParts(changedProjectPartIds.projectIds);
client()->precompiledHeadersUpdated(std::move(changedProjectPartIds.second));
client()->precompiledHeadersUpdated(std::move(changedProjectPartIds.userIds));
}
void PchManagerServer::pathsChanged(const FilePathIds &filePathIds)
@@ -215,4 +233,24 @@ void PchManagerServer::setDependencyCreationProgress(int progress, int total)
client()->progress({ProgressType::DependencyCreation, progress, total});
}
void PchManagerServer::addCompleteProjectParts(const ProjectPartIds &projectPartIds)
{
ArgumentsEntries entries = m_toolChainsArgumentsCache.arguments(projectPartIds);
for (ArgumentsEntry &entry : entries) {
m_pchTaskGenerator.addProjectParts(m_projectPartsManager.projects(entry.ids),
std::move(entry.arguments));
}
}
void PchManagerServer::addNonSystemProjectParts(const ProjectPartIds &projectPartIds)
{
ArgumentsEntries entries = m_toolChainsArgumentsCache.arguments(projectPartIds);
for (ArgumentsEntry &entry : entries) {
m_pchTaskGenerator.addNonSystemProjectParts(m_projectPartsManager.projects(entry.ids),
std::move(entry.arguments));
}
}
} // namespace ClangBackEnd

View File

@@ -65,6 +65,10 @@ public:
void setPchCreationProgress(int progress, int total);
void setDependencyCreationProgress(int progress, int total);
private:
void addCompleteProjectParts(const ProjectPartIds &projectPartIds);
void addNonSystemProjectParts(const ProjectPartIds &projectPartIds);
private:
ClangPathWatcherInterface &m_fileSystemWatcher;
PchTaskGeneratorInterface &m_pchTaskGenerator;

View File

@@ -26,6 +26,7 @@
#include "pchtaskgenerator.h"
#include "builddependenciesproviderinterface.h"
#include "pchtaskqueueinterface.h"
#include "pchtasksmergerinterface.h"
#include "usedmacrofilter.h"
@@ -88,4 +89,38 @@ void PchTaskGenerator::removeProjectParts(const ProjectPartIds &projectsPartIds)
m_pchTasksMergerInterface.removePchTasks(projectsPartIds);
}
void PchTaskGenerator::addNonSystemProjectParts(ProjectPartContainers &&projectParts,
Utils::SmallStringVector &&)
{
PchTasks pchTasks;
pchTasks.reserve(projectParts.size());
m_progressCounter.addTotal(static_cast<int>(projectParts.size()));
for (auto &projectPart : projectParts) {
BuildDependency buildDependency = m_buildDependenciesProvider.create(projectPart);
UsedMacroFilter filter{buildDependency.sources,
buildDependency.usedMacros,
projectPart.compilerMacros};
pchTasks.emplace_back(projectPart.projectPartId,
std::move(filter.topProjectIncludes),
std::move(filter.systemIncludes),
std::move(filter.projectIncludes),
std::move(filter.userIncludes),
std::move(filter.sources),
std::move(filter.projectCompilerMacros),
std::move(filter.projectUsedMacros),
projectPart.toolChainArguments,
projectPart.systemIncludeSearchPaths,
projectPart.projectIncludeSearchPaths,
projectPart.language,
projectPart.languageVersion,
projectPart.languageExtension);
m_progressCounter.addProgress(1);
}
m_pchTaskQueue.addProjectPchTasks(std::move(pchTasks));
}
} // namespace ClangBackEnd

View File

@@ -35,6 +35,7 @@ namespace ClangBackEnd {
class PchTasksMergerInterface;
class BuildDependenciesProviderInterface;
class PchTaskQueueInterface;
class ProgressCounter;
class PchTaskGenerator : public PchTaskGeneratorInterface
@@ -42,21 +43,26 @@ class PchTaskGenerator : public PchTaskGeneratorInterface
public:
PchTaskGenerator(BuildDependenciesProviderInterface &buildDependenciesProvider,
PchTasksMergerInterface &pchTasksMergerInterface,
ProgressCounter &progressCounter)
ProgressCounter &progressCounter,
PchTaskQueueInterface &pchTaskQueue)
: m_buildDependenciesProvider(buildDependenciesProvider)
, m_pchTasksMergerInterface(pchTasksMergerInterface)
, m_progressCounter(progressCounter)
, m_pchTaskQueue(pchTaskQueue)
{}
void addProjectParts(ProjectPartContainers &&projectParts,
Utils::SmallStringVector &&toolChainArguments) override;
void removeProjectParts(const ProjectPartIds &projectsPartIds) override;
void addNonSystemProjectParts(ProjectPartContainers &&projectParts,
Utils::SmallStringVector &&toolChainArguments) override;
private:
BuildDependenciesProviderInterface &m_buildDependenciesProvider;
PchTasksMergerInterface &m_pchTasksMergerInterface;
ProgressCounter &m_progressCounter;
PchTaskQueueInterface &m_pchTaskQueue;
};
} // namespace ClangBackEnd

View File

@@ -35,6 +35,9 @@ public:
virtual void addProjectParts(ProjectPartContainers &&projectParts,
Utils::SmallStringVector &&toolChainArguments)
= 0;
virtual void addNonSystemProjectParts(ProjectPartContainers &&projectParts,
Utils::SmallStringVector &&toolChainArguments)
= 0;
virtual void removeProjectParts(const ProjectPartIds &projectsPartIds) = 0;
protected:

View File

@@ -35,6 +35,9 @@ public:
MOCK_METHOD2(addProjectParts,
void(const ClangBackEnd::ProjectPartContainers &projectParts,
const Utils::SmallStringVector &toolChainArguments));
MOCK_METHOD2(addNonSystemProjectParts,
void(const ClangBackEnd::ProjectPartContainers &projectParts,
const Utils::SmallStringVector &toolChainArguments));
MOCK_METHOD1(removeProjectParts, void(const ClangBackEnd::ProjectPartIds &projectsPartIds));
void addProjectParts(ClangBackEnd::ProjectPartContainers &&projectParts,
@@ -42,4 +45,10 @@ public:
{
addProjectParts(projectParts, toolChainArguments);
}
void addNonSystemProjectParts(ClangBackEnd::ProjectPartContainers &&projectParts,
Utils::SmallStringVector &&toolChainArguments) override
{
addNonSystemProjectParts(projectParts, toolChainArguments);
}
};

View File

@@ -227,26 +227,36 @@ TEST_F(PchManagerServer, SetPathWatcherNotifier)
TEST_F(PchManagerServer, UpdateProjectPartQueueByPathIds)
{
InSequence s;
server.updateProjectParts(ClangBackEnd::UpdateProjectPartsMessage{
{projectPart1, projectPart2, projectPart3, projectPart4, projectPart5, projectPart6},
{"toolChainArgument"}});
EXPECT_CALL(mockProjectPartsManager,
projects(ElementsAre(projectPart1.projectPartId,
projectPart2.projectPartId,
projectPart4.projectPartId,
projectPart5.projectPartId)))
.WillOnce(Return(std::vector<ClangBackEnd::ProjectPartContainer>{
{projectPart1, projectPart2, projectPart4, projectPart5}}));
projects(ElementsAre(projectPart1.projectPartId, projectPart2.projectPartId)))
.WillOnce(
Return(std::vector<ClangBackEnd::ProjectPartContainer>{{projectPart1, projectPart2}}));
EXPECT_CALL(mockPchTaskGenerator,
addProjectParts(ElementsAre(projectPart1, projectPart2, projectPart4, projectPart5),
addProjectParts(ElementsAre(projectPart1, projectPart2),
ElementsAre("toolChainArgument")));
EXPECT_CALL(mockProjectPartsManager,
projects(ElementsAre(projectPart4.projectPartId, projectPart5.projectPartId)))
.WillOnce(
Return(std::vector<ClangBackEnd::ProjectPartContainer>{{projectPart4, projectPart5}}));
EXPECT_CALL(mockPchTaskGenerator,
addNonSystemProjectParts(ElementsAre(projectPart4, projectPart5),
ElementsAre("toolChainArgument")));
server.pathsWithIdsChanged({{{projectPartId1, ClangBackEnd::SourceType::TopProjectInclude}, {}},
{{projectPartId2, ClangBackEnd::SourceType::TopSystemInclude}, {}},
server.pathsWithIdsChanged({{{projectPartId1, ClangBackEnd::SourceType::TopSystemInclude}, {}},
{{projectPartId1, ClangBackEnd::SourceType::ProjectInclude}, {}},
{{projectPartId1, ClangBackEnd::SourceType::UserInclude}, {}},
{{projectPartId2, ClangBackEnd::SourceType::SystemInclude}, {}},
{{projectPartId2, ClangBackEnd::SourceType::ProjectInclude}, {}},
{{projectPartId3, ClangBackEnd::SourceType::UserInclude}, {}},
{{projectPartId4, ClangBackEnd::SourceType::ProjectInclude}, {}},
{{projectPartId5, ClangBackEnd::SourceType::SystemInclude}, {}},
{{projectPartId4, ClangBackEnd::SourceType::TopProjectInclude}, {}},
{{projectPartId4, ClangBackEnd::SourceType::Source}, {}},
{{projectPartId4, ClangBackEnd::SourceType::UserInclude}, {}},
{{projectPartId5, ClangBackEnd::SourceType::ProjectInclude}, {}},
{{projectPartId6, ClangBackEnd::SourceType::Source}, {}}});
}

View File

@@ -26,6 +26,7 @@
#include "googletest.h"
#include "mockbuilddependenciesprovider.h"
#include "mockpchtaskqueue.h"
#include "mockpchtasksmerger.h"
#include <pchtaskgenerator.h>
@@ -52,11 +53,13 @@ class PchTaskGenerator : public testing::Test
protected:
NiceMock<MockBuildDependenciesProvider> mockBuildDependenciesProvider;
NiceMock<MockPchTasksMerger> mockPchTaskMerger;
NiceMock<MockPchTaskQueue> mockPchTaskQueue;
NiceMock<MockFunction<void(int, int)>> mockProgressCounterCallback;
ClangBackEnd::ProgressCounter progressCounter{mockProgressCounterCallback.AsStdFunction()};
ClangBackEnd::PchTaskGenerator generator{mockBuildDependenciesProvider,
mockPchTaskMerger,
progressCounter};
progressCounter,
mockPchTaskQueue};
ClangBackEnd::ProjectPartContainer projectPart1{
1,
{"--yi"},
@@ -145,6 +148,36 @@ TEST_F(PchTaskGenerator, AddProjectParts)
generator.addProjectParts({projectPart1}, {"ToolChainArgument"});
}
TEST_F(PchTaskGenerator, AddNonSystemProjectParts)
{
ON_CALL(mockBuildDependenciesProvider, create(_)).WillByDefault(Return(buildDependency));
EXPECT_CALL(
mockPchTaskQueue,
addProjectPchTasks(ElementsAre(AllOf(
Field(&PchTask::projectPartIds, ElementsAre(ProjectPartId{1})),
Field(&PchTask::includes, ElementsAre(3)),
Field(&PchTask::watchedSystemIncludes, ElementsAre(4, 5)),
Field(&PchTask::watchedProjectIncludes, ElementsAre(1, 3)),
Field(&PchTask::watchedUserIncludes, ElementsAre(2)),
Field(&PchTask::watchedUserSources, ElementsAre(6)),
Field(&PchTask::compilerMacros,
ElementsAre(CompilerMacro{"YI", "1", 1}, CompilerMacro{"SAN", "3", 3})),
Field(&PchTask::systemIncludeSearchPaths,
ElementsAre(IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
IncludeSearchPath{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
IncludeSearchPath{"/framework/path", 1, IncludeSearchPathType::System})),
Field(&PchTask::projectIncludeSearchPaths,
ElementsAre(IncludeSearchPath{"/to/path1", 1, IncludeSearchPathType::User},
IncludeSearchPath{"/to/path2", 2, IncludeSearchPathType::User})),
Field(&PchTask::toolChainArguments, ElementsAre("--yi")),
Field(&PchTask::language, Eq(Utils::Language::Cxx)),
Field(&PchTask::languageVersion, Eq(Utils::LanguageVersion::CXX11)),
Field(&PchTask::languageExtension, Eq(Utils::LanguageExtension::All))))));
generator.addNonSystemProjectParts({projectPart1}, {"ToolChainArgument"});
}
TEST_F(PchTaskGenerator, ProgressCounter)
{
ON_CALL(mockBuildDependenciesProvider, create(_)).WillByDefault(Return(buildDependency));