blob: 4efc2c62f20a218145ee9a9b3ebe76ded1275e4d [file] [log] [blame]
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmQtAutoGeneratorMocUic_h
#define cmQtAutoGeneratorMocUic_h
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmQtAutoGen.h"
#include "cmQtAutoGenerator.h"
#include "cmWorkerPool.h"
#include "cmsys/RegularExpression.hxx"
#include <array>
#include <atomic>
#include <map>
#include <memory> // IWYU pragma: keep
#include <mutex>
#include <set>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
class cmMakefile;
// @brief AUTOMOC and AUTOUIC generator
class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator
{
public:
cmQtAutoGeneratorMocUic();
~cmQtAutoGeneratorMocUic() override;
cmQtAutoGeneratorMocUic(cmQtAutoGeneratorMocUic const&) = delete;
cmQtAutoGeneratorMocUic& operator=(cmQtAutoGeneratorMocUic const&) = delete;
public:
// -- Types
typedef std::multimap<std::string, std::array<std::string, 2>> IncludesMap;
/// @brief Search key plus regular expression pair
///
struct KeyExpT
{
KeyExpT() = default;
KeyExpT(const char* key, const char* exp)
: Key(key)
, Exp(exp)
{
}
KeyExpT(std::string key, std::string const& exp)
: Key(std::move(key))
, Exp(exp)
{
}
std::string Key;
cmsys::RegularExpression Exp;
};
/// @brief Common settings
///
class BaseSettingsT
{
public:
// -- Volatile methods
BaseSettingsT(FileSystem* fileSystem)
: MultiConfig(false)
, IncludeProjectDirsBefore(false)
, QtVersionMajor(4)
, NumThreads(1)
, FileSys(fileSystem)
{
}
BaseSettingsT(BaseSettingsT const&) = delete;
BaseSettingsT& operator=(BaseSettingsT const&) = delete;
// -- Const methods
std::string AbsoluteBuildPath(std::string const& relativePath) const;
bool FindHeader(std::string& header,
std::string const& testBasePath) const;
// -- Attributes
// - Config
bool MultiConfig;
bool IncludeProjectDirsBefore;
unsigned int QtVersionMajor;
unsigned int NumThreads;
// - Directories
std::string ProjectSourceDir;
std::string ProjectBinaryDir;
std::string CurrentSourceDir;
std::string CurrentBinaryDir;
std::string AutogenBuildDir;
std::string AutogenIncludeDir;
// - Files
std::vector<std::string> HeaderExtensions;
// - File system
FileSystem* FileSys;
};
/// @brief Moc settings
///
class MocSettingsT
{
public:
MocSettingsT(FileSystem* fileSys)
: FileSys(fileSys)
{
}
MocSettingsT(MocSettingsT const&) = delete;
MocSettingsT& operator=(MocSettingsT const&) = delete;
// -- Const methods
bool skipped(std::string const& fileName) const;
std::string FindMacro(std::string const& content) const;
std::string MacrosString() const;
std::string FindIncludedFile(std::string const& sourcePath,
std::string const& includeString) const;
void FindDependencies(std::string const& content,
std::set<std::string>& depends) const;
// -- Attributes
bool Enabled = false;
bool SettingsChanged = false;
bool RelaxedMode = false;
std::string Executable;
std::string CompFileAbs;
std::string PredefsFileRel;
std::string PredefsFileAbs;
std::unordered_set<std::string> SkipList;
std::vector<std::string> IncludePaths;
std::vector<std::string> Includes;
std::vector<std::string> Definitions;
std::vector<std::string> Options;
std::vector<std::string> AllOptions;
std::vector<std::string> PredefsCmd;
std::vector<KeyExpT> DependFilters;
std::vector<KeyExpT> MacroFilters;
cmsys::RegularExpression RegExpInclude;
// - File system
FileSystem* FileSys;
};
/// @brief Uic settings
///
class UicSettingsT
{
public:
UicSettingsT() = default;
UicSettingsT(UicSettingsT const&) = delete;
UicSettingsT& operator=(UicSettingsT const&) = delete;
// -- Const methods
bool skipped(std::string const& fileName) const;
// -- Attributes
bool Enabled = false;
bool SettingsChanged = false;
std::string Executable;
std::unordered_set<std::string> SkipList;
std::vector<std::string> TargetOptions;
std::map<std::string, std::vector<std::string>> Options;
std::vector<std::string> SearchPaths;
cmsys::RegularExpression RegExpInclude;
};
/// @brief Abstract job class for concurrent job processing
///
class JobT : public cmWorkerPool::JobT
{
protected:
/**
* @brief Protected default constructor
*/
JobT(bool fence = false)
: cmWorkerPool::JobT(fence)
{
}
//! Get the generator. Only valid during Process() call!
cmQtAutoGeneratorMocUic* Gen() const
{
return static_cast<cmQtAutoGeneratorMocUic*>(UserData());
};
//! Get the file system interface. Only valid during Process() call!
FileSystem& FileSys() { return Gen()->FileSys(); }
//! Get the logger. Only valid during Process() call!
Logger& Log() { return Gen()->Log(); }
// -- Error logging with automatic abort
void LogError(GenT genType, std::string const& message) const;
void LogFileError(GenT genType, std::string const& filename,
std::string const& message) const;
void LogCommandError(GenT genType, std::string const& message,
std::vector<std::string> const& command,
std::string const& output) const;
/**
* @brief Run an external process. Use only during Process() call!
*/
bool RunProcess(GenT genType, cmWorkerPool::ProcessResultT& result,
std::vector<std::string> const& command);
};
/// @brief Fence job utility class
///
class JobFenceT : public JobT
{
public:
JobFenceT()
: JobT(true)
{
}
void Process() override{};
};
/// @brief Generate moc_predefs.h
///
class JobMocPredefsT : public JobT
{
private:
void Process() override;
};
/// @brief Parses a source file
///
class JobParseT : public JobT
{
public:
JobParseT(std::string fileName, bool moc, bool uic, bool header = false)
: FileName(std::move(fileName))
, AutoMoc(moc)
, AutoUic(uic)
, Header(header)
{
}
private:
struct MetaT
{
std::string Content;
std::string FileDir;
std::string FileBase;
};
void Process() override;
bool ParseMocSource(MetaT const& meta);
bool ParseMocHeader(MetaT const& meta);
std::string MocStringHeaders(std::string const& fileBase) const;
std::string MocFindIncludedHeader(std::string const& includerDir,
std::string const& includeBase);
bool ParseUic(MetaT const& meta);
bool ParseUicInclude(MetaT const& meta, std::string&& includeString);
std::string UicFindIncludedFile(MetaT const& meta,
std::string const& includeString);
private:
std::string FileName;
bool AutoMoc = false;
bool AutoUic = false;
bool Header = false;
};
/// @brief Generates additional jobs after all files have been parsed
///
class JobPostParseT : public JobFenceT
{
private:
void Process() override;
};
/// @brief Generate mocs_compilation.cpp
///
class JobMocsCompilationT : public JobFenceT
{
private:
void Process() override;
};
/// @brief Moc a file job
///
class JobMocT : public JobT
{
public:
JobMocT(std::string sourceFile, std::string includerFile,
std::string includeString)
: SourceFile(std::move(sourceFile))
, IncluderFile(std::move(includerFile))
, IncludeString(std::move(includeString))
{
}
void FindDependencies(std::string const& content);
private:
void Process() override;
bool UpdateRequired();
void GenerateMoc();
public:
std::string SourceFile;
std::string IncluderFile;
std::string IncludeString;
std::string BuildFile;
bool DependsValid = false;
std::set<std::string> Depends;
};
/// @brief Uic a file job
///
class JobUicT : public JobT
{
public:
JobUicT(std::string sourceFile, std::string includerFile,
std::string includeString)
: SourceFile(std::move(sourceFile))
, IncluderFile(std::move(includerFile))
, IncludeString(std::move(includeString))
{
}
private:
void Process() override;
bool UpdateRequired();
void GenerateUic();
public:
std::string SourceFile;
std::string IncluderFile;
std::string IncludeString;
std::string BuildFile;
};
/// @brief The last job
///
class JobFinishT : public JobFenceT
{
private:
void Process() override;
};
// -- Const settings interface
const BaseSettingsT& Base() const { return this->Base_; }
const MocSettingsT& Moc() const { return this->Moc_; }
const UicSettingsT& Uic() const { return this->Uic_; }
// -- Parallel job processing interface
cmWorkerPool& WorkerPool() { return WorkerPool_; }
void AbortError() { Abort(true); }
void AbortSuccess() { Abort(false); }
bool ParallelJobPushMoc(cmWorkerPool::JobHandleT&& jobHandle);
bool ParallelJobPushUic(cmWorkerPool::JobHandleT&& jobHandle);
// -- Mocs compilation include file updated flag
void ParallelMocAutoUpdated() { MocAutoFileUpdated_.store(true); }
bool MocAutoFileUpdated() const { return MocAutoFileUpdated_.load(); }
// -- Mocs compilation file register
std::string ParallelMocAutoRegister(std::string const& baseName);
bool ParallelMocIncluded(std::string const& sourceFile);
std::set<std::string> const& MocAutoFiles() const
{
return this->MocAutoFiles_;
}
private:
// -- Utility accessors
Logger& Log() { return Logger_; }
FileSystem& FileSys() { return FileSys_; }
// -- Abstract processing interface
bool Init(cmMakefile* makefile) override;
bool Process() override;
// -- Settings file
void SettingsFileRead();
bool SettingsFileWrite();
// -- Thread processing
void Abort(bool error);
// -- Generation
bool CreateDirectories();
private:
// -- Utility
Logger Logger_;
FileSystem FileSys_;
// -- Settings
BaseSettingsT Base_;
MocSettingsT Moc_;
UicSettingsT Uic_;
// -- Moc meta
std::mutex MocMetaMutex_;
std::set<std::string> MocIncludedFiles_;
IncludesMap MocIncludes_;
std::set<std::string> MocAutoFiles_;
std::atomic<bool> MocAutoFileUpdated_ = ATOMIC_VAR_INIT(false);
// -- Uic meta
std::mutex UicMetaMutex_;
IncludesMap UicIncludes_;
// -- Settings file
std::string SettingsFile_;
std::string SettingsStringMoc_;
std::string SettingsStringUic_;
// -- Thread pool and job queue
std::atomic<bool> JobError_ = ATOMIC_VAR_INIT(false);
cmWorkerPool WorkerPool_;
};
#endif