summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Holtermann <sebholt@xwmw.org>2019-09-12 10:14:12 (GMT)
committerSebastian Holtermann <sebholt@xwmw.org>2019-09-16 16:18:48 (GMT)
commit1a3f185c1a1f5f67e6c7d8d821f17619208e6311 (patch)
tree513f47dbc41cf98a06a948bdfcb58982d9690994
parent726ea1d15134591c352468b64b3e92f04f2449bb (diff)
downloadCMake-1a3f185c1a1f5f67e6c7d8d821f17619208e6311.zip
CMake-1a3f185c1a1f5f67e6c7d8d821f17619208e6311.tar.gz
CMake-1a3f185c1a1f5f67e6c7d8d821f17619208e6311.tar.bz2
Autogen: Split JobProbeDepsT job into separate moc and uic jobs
By splitting `JobProbeDepsT` into two independent `JobProbeDepsMocT`, `JobProbeDepsUicT`, the moc and uic job generation will happen concurrently. This should improve the execution speed, when both AUTOMOC and AUTOUIC are enabled. Parent directory names for moc and uic output files are are collected in a `std::unordered_set<std::string>` and get created in a batch. Beforehand we tried to create the parent directory for each output file. This led to duplications of `MakeDirectory` calls when there were multiple output files in the same directory (which is the case usually).
-rw-r--r--Source/cmQtAutoGen.cxx9
-rw-r--r--Source/cmQtAutoGen.h3
-rw-r--r--Source/cmQtAutoMocUic.cxx140
-rw-r--r--Source/cmQtAutoMocUic.h38
4 files changed, 124 insertions, 66 deletions
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index f3c78d3..57c8825 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -162,6 +162,15 @@ std::string cmQtAutoGen::QuotedCommand(std::vector<std::string> const& command)
return res;
}
+std::string cmQtAutoGen::ParentDir(cm::string_view filename)
+{
+ auto slashPos = filename.rfind('/');
+ if (slashPos == cm::string_view::npos) {
+ return std::string();
+ }
+ return std::string(filename.substr(0, slashPos));
+}
+
std::string cmQtAutoGen::SubDirPrefix(cm::string_view filename)
{
auto slashPos = filename.rfind('/');
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index fb15586..71969ee 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -80,6 +80,9 @@ public:
static std::string QuotedCommand(std::vector<std::string> const& command);
+ /// @brief Returns the parent directory of the file (thread safe)
+ static std::string ParentDir(cm::string_view filename);
+
/// @brief Returns the parent directory of the file with a "/" suffix
static std::string SubDirPrefix(cm::string_view filename);
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index fe63dec..6265777 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -577,8 +577,20 @@ void cmQtAutoMocUic::JobEvalCacheT::Process()
// Add discovered header parse jobs
Gen()->CreateParseJobs<JobParseHeaderT>(MocEval().HeadersDiscovered);
- // Add generate job after
- Gen()->WorkerPool().EmplaceJob<JobProbeDepsT>();
+
+ // Add dependency probing jobs
+ {
+ // Add fence job to ensure all parsing has finished
+ Gen()->WorkerPool().EmplaceJob<JobFenceT>();
+ if (MocConst().Enabled) {
+ Gen()->WorkerPool().EmplaceJob<JobProbeDepsMocT>();
+ }
+ if (UicConst().Enabled) {
+ Gen()->WorkerPool().EmplaceJob<JobProbeDepsUicT>();
+ }
+ // Add probe finish job
+ Gen()->WorkerPool().EmplaceJob<JobProbeDepsFinishT>();
+ }
}
bool cmQtAutoMocUic::JobEvalCacheT::MocEvalHeader(SourceFileHandleT source)
@@ -1083,57 +1095,38 @@ cmQtAutoMocUic::JobEvalCacheT::UicFindIncludedUi(
return SourceFileHandleT();
}
-void cmQtAutoMocUic::JobProbeDepsT::Process()
+void cmQtAutoMocUic::JobProbeDepsMocT::Process()
{
- // Add moc compile jobs
- if (MocConst().Enabled) {
- for (auto const& pair : MocEval().HeaderMappings) {
- // Register if this mapping is a candidate for mocs_compilation.cpp
- bool const compFile = pair.second->IncludeString.empty();
- if (compFile) {
- MocEval().CompFiles.emplace_back(pair.second->SourceFile->BuildPath);
- }
- if (!MocGenerate(pair.second, compFile)) {
- return;
- }
+ // Create moc header jobs
+ for (auto const& pair : MocEval().HeaderMappings) {
+ // Register if this mapping is a candidate for mocs_compilation.cpp
+ bool const compFile = pair.second->IncludeString.empty();
+ if (compFile) {
+ MocEval().CompFiles.emplace_back(pair.second->SourceFile->BuildPath);
}
- for (auto const& pair : MocEval().SourceMappings) {
- if (!MocGenerate(pair.second, false)) {
- return;
- }
+ if (!Generate(pair.second, compFile)) {
+ return;
}
-
- // Add mocs compilations job on demand
- Gen()->WorkerPool().EmplaceJob<JobMocsCompilationT>();
}
- // Add uic compile jobs
- if (UicConst().Enabled) {
- for (auto const& pair : Gen()->UicEval().Includes) {
- if (!UicGenerate(pair.second)) {
- return;
- }
+ // Create moc source jobs
+ for (auto const& pair : MocEval().SourceMappings) {
+ if (!Generate(pair.second, false)) {
+ return;
}
}
-
- // Add finish job
- Gen()->WorkerPool().EmplaceJob<JobFinishT>();
}
-bool cmQtAutoMocUic::JobProbeDepsT::MocGenerate(MappingHandleT const& mapping,
+bool cmQtAutoMocUic::JobProbeDepsMocT::Generate(MappingHandleT const& mapping,
bool compFile) const
{
std::unique_ptr<std::string> reason;
if (Log().Verbose()) {
reason = cm::make_unique<std::string>();
}
- if (MocUpdate(*mapping, reason.get())) {
- // Create the parent directory
- if (!MakeParentDirectory(mapping->OutputFile)) {
- LogFileError(GenT::MOC, mapping->OutputFile,
- "Could not create parent directory.");
- return false;
- }
+ if (Probe(*mapping, reason.get())) {
+ // Register the parent directory for creation
+ MocEval().OutputDirs.emplace(cmQtAutoGen::ParentDir(mapping->OutputFile));
// Add moc job
Gen()->WorkerPool().EmplaceJob<JobCompileMocT>(mapping, std::move(reason));
// Check if a moc job for a mocs_compilation.cpp entry was generated
@@ -1144,8 +1137,8 @@ bool cmQtAutoMocUic::JobProbeDepsT::MocGenerate(MappingHandleT const& mapping,
return true;
}
-bool cmQtAutoMocUic::JobProbeDepsT::MocUpdate(MappingT const& mapping,
- std::string* reason) const
+bool cmQtAutoMocUic::JobProbeDepsMocT::Probe(MappingT const& mapping,
+ std::string* reason) const
{
std::string const& sourceFile = mapping.SourceFile->FileName;
std::string const& outputFile = mapping.OutputFile;
@@ -1209,7 +1202,7 @@ bool cmQtAutoMocUic::JobProbeDepsT::MocUpdate(MappingT const& mapping,
std::string const sourceDir = SubDirPrefix(sourceFile);
for (std::string const& dep : mapping.SourceFile->ParseData->Moc.Depends) {
// Find dependency file
- auto const depMatch = MocFindDependency(sourceDir, dep);
+ auto const depMatch = FindDependency(sourceDir, dep);
if (depMatch.first.empty()) {
Log().WarningFile(GenT::MOC, sourceFile,
"Could not find dependency file " + Quoted(dep));
@@ -1232,7 +1225,7 @@ bool cmQtAutoMocUic::JobProbeDepsT::MocUpdate(MappingT const& mapping,
}
std::pair<std::string, cmFileTime>
-cmQtAutoMocUic::JobProbeDepsT::MocFindDependency(
+cmQtAutoMocUic::JobProbeDepsMocT::FindDependency(
std::string const& sourceDir, std::string const& includeString) const
{
using ResPair = std::pair<std::string, cmFileTime>;
@@ -1254,28 +1247,27 @@ cmQtAutoMocUic::JobProbeDepsT::MocFindDependency(
return ResPair();
}
-bool cmQtAutoMocUic::JobProbeDepsT::UicGenerate(
- MappingHandleT const& mapping) const
+void cmQtAutoMocUic::JobProbeDepsUicT::Process()
{
- std::unique_ptr<std::string> reason;
- if (Log().Verbose()) {
- reason = cm::make_unique<std::string>();
- }
- if (UicUpdate(*mapping, reason.get())) {
- // Create the parent directory
- if (!MakeParentDirectory(mapping->OutputFile)) {
- LogFileError(GenT::UIC, mapping->OutputFile,
- "Could not create parent directory.");
- return false;
+ for (auto const& pair : Gen()->UicEval().Includes) {
+ MappingHandleT const& mapping = pair.second;
+ std::unique_ptr<std::string> reason;
+ if (Log().Verbose()) {
+ reason = cm::make_unique<std::string>();
+ }
+ if (!Probe(*mapping, reason.get())) {
+ continue;
}
+
+ // Register the parent directory for creation
+ UicEval().OutputDirs.emplace(cmQtAutoGen::ParentDir(mapping->OutputFile));
// Add uic job
Gen()->WorkerPool().EmplaceJob<JobCompileUicT>(mapping, std::move(reason));
}
- return true;
}
-bool cmQtAutoMocUic::JobProbeDepsT::UicUpdate(MappingT const& mapping,
- std::string* reason) const
+bool cmQtAutoMocUic::JobProbeDepsUicT::Probe(MappingT const& mapping,
+ std::string* reason) const
{
std::string const& sourceFile = mapping.SourceFile->FileName;
std::string const& outputFile = mapping.OutputFile;
@@ -1324,6 +1316,40 @@ bool cmQtAutoMocUic::JobProbeDepsT::UicUpdate(MappingT const& mapping,
return false;
}
+void cmQtAutoMocUic::JobProbeDepsFinishT::Process()
+{
+ // Create output directories
+ {
+ using StringSet = std::unordered_set<std::string>;
+ auto createDirs = [this](GenT genType, StringSet const& dirSet) {
+ for (std::string const& dirName : dirSet) {
+ if (!cmSystemTools::MakeDirectory(dirName)) {
+ this->LogFileError(genType, dirName, "Could not create directory.");
+ return;
+ }
+ }
+ };
+ if (MocConst().Enabled && UicConst().Enabled) {
+ StringSet outputDirs = MocEval().OutputDirs;
+ outputDirs.insert(UicEval().OutputDirs.begin(),
+ UicEval().OutputDirs.end());
+ createDirs(GenT::GEN, outputDirs);
+ } else if (MocConst().Enabled) {
+ createDirs(GenT::MOC, MocEval().OutputDirs);
+ } else if (UicConst().Enabled) {
+ createDirs(GenT::UIC, UicEval().OutputDirs);
+ }
+ }
+
+ if (MocConst().Enabled) {
+ // Add mocs compilations job
+ Gen()->WorkerPool().EmplaceJob<JobMocsCompilationT>();
+ }
+
+ // Add finish job
+ Gen()->WorkerPool().EmplaceJob<JobFinishT>();
+}
+
void cmQtAutoMocUic::JobCompileMocT::Process()
{
std::string const& sourceFile = Mapping->SourceFile->FileName;
diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h
index 3e815cd..3af1846 100644
--- a/Source/cmQtAutoMocUic.h
+++ b/Source/cmQtAutoMocUic.h
@@ -243,6 +243,8 @@ public:
MappingMapT Includes;
// -- Discovered files
SourceFileMapT HeadersDiscovered;
+ // -- Output directories
+ std::unordered_set<std::string> OutputDirs;
// -- Mocs compilation
bool CompUpdated = false;
std::vector<std::string> CompFiles;
@@ -277,8 +279,12 @@ public:
class UicEvalT
{
public:
+ // -- Discovered files
SourceFileMapT UiFiles;
+ // -- Mappings
MappingMapT Includes;
+ // -- Output directories
+ std::unordered_set<std::string> OutputDirs;
};
/** Abstract job class for concurrent job processing. */
@@ -408,18 +414,32 @@ public:
SourceFileHandleT includerFileHandle);
};
- /** Probes file dependencies and generates moc and uic compile jobs. */
- class JobProbeDepsT : public JobFenceT
+ /** Dependency probing base job. */
+ class JobProbeDepsT : public JobT
+ {
+ };
+
+ /** Probes file dependencies and generates moc compile jobs. */
+ class JobProbeDepsMocT : public JobProbeDepsT
{
void Process() override;
- // -- Moc
- bool MocGenerate(MappingHandleT const& mapping, bool compFile) const;
- bool MocUpdate(MappingT const& mapping, std::string* reason) const;
- std::pair<std::string, cmFileTime> MocFindDependency(
+ bool Generate(MappingHandleT const& mapping, bool compFile) const;
+ bool Probe(MappingT const& mapping, std::string* reason) const;
+ std::pair<std::string, cmFileTime> FindDependency(
std::string const& sourceDir, std::string const& includeString) const;
- // -- Uic
- bool UicGenerate(MappingHandleT const& mapping) const;
- bool UicUpdate(MappingT const& mapping, std::string* reason) const;
+ };
+
+ /** Probes file dependencies and generates uic compile jobs. */
+ class JobProbeDepsUicT : public JobProbeDepsT
+ {
+ void Process() override;
+ bool Probe(MappingT const& mapping, std::string* reason) const;
+ };
+
+ /** Dependency probing finish job. */
+ class JobProbeDepsFinishT : public JobFenceT
+ {
+ void Process() override;
};
/** Meta compiler base job. */