mirror of
https://github.com/reactos/CMake.git
synced 2024-12-02 08:37:09 +00:00
ccc38fa509
Closes #17861 Closes #17862
437 lines
11 KiB
C++
437 lines
11 KiB
C++
/* 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 "cmUVHandlePtr.h"
|
|
#include "cm_uv.h"
|
|
#include "cmsys/RegularExpression.hxx"
|
|
|
|
#include <algorithm>
|
|
#include <condition_variable>
|
|
#include <cstddef>
|
|
#include <deque>
|
|
#include <map>
|
|
#include <memory> // IWYU pragma: keep
|
|
#include <mutex>
|
|
#include <set>
|
|
#include <string>
|
|
#include <thread>
|
|
#include <vector>
|
|
|
|
class cmMakefile;
|
|
|
|
// @brief AUTOMOC and AUTOUIC generator
|
|
class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator
|
|
{
|
|
CM_DISABLE_COPY(cmQtAutoGeneratorMocUic)
|
|
public:
|
|
cmQtAutoGeneratorMocUic();
|
|
~cmQtAutoGeneratorMocUic() override;
|
|
|
|
public:
|
|
// -- Types
|
|
class WorkerT;
|
|
|
|
/// @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 const& key, std::string const& exp)
|
|
: Key(key)
|
|
, Exp(exp)
|
|
{
|
|
}
|
|
|
|
std::string Key;
|
|
cmsys::RegularExpression Exp;
|
|
};
|
|
|
|
/// @brief Common settings
|
|
///
|
|
class BaseSettingsT
|
|
{
|
|
CM_DISABLE_COPY(BaseSettingsT)
|
|
public:
|
|
// -- Volatile methods
|
|
BaseSettingsT(FileSystem* fileSystem)
|
|
: MultiConfig(false)
|
|
, IncludeProjectDirsBefore(false)
|
|
, QtVersionMajor(4)
|
|
, NumThreads(1)
|
|
, FileSys(fileSystem)
|
|
{
|
|
}
|
|
|
|
// -- 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
|
|
{
|
|
CM_DISABLE_COPY(MocSettingsT)
|
|
public:
|
|
MocSettingsT(FileSystem* fileSys)
|
|
: FileSys(fileSys)
|
|
{
|
|
}
|
|
|
|
// -- 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::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
|
|
{
|
|
CM_DISABLE_COPY(UicSettingsT)
|
|
public:
|
|
UicSettingsT() = default;
|
|
// -- Const methods
|
|
bool skipped(std::string const& fileName) const;
|
|
|
|
// -- Attributes
|
|
bool Enabled = false;
|
|
bool SettingsChanged = false;
|
|
std::string Executable;
|
|
std::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 threaded processing
|
|
///
|
|
class JobT
|
|
{
|
|
CM_DISABLE_COPY(JobT)
|
|
public:
|
|
JobT() = default;
|
|
virtual ~JobT() = default;
|
|
// -- Abstract processing interface
|
|
virtual void Process(WorkerT& wrk) = 0;
|
|
};
|
|
|
|
/// @brief Deleter for classes derived from Job
|
|
///
|
|
struct JobDeleterT
|
|
{
|
|
void operator()(JobT* job);
|
|
};
|
|
|
|
// Job management types
|
|
typedef std::unique_ptr<JobT, JobDeleterT> JobHandleT;
|
|
typedef std::deque<JobHandleT> JobQueueT;
|
|
|
|
/// @brief Parse source job
|
|
///
|
|
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(WorkerT& wrk) override;
|
|
bool ParseMocSource(WorkerT& wrk, MetaT const& meta);
|
|
bool ParseMocHeader(WorkerT& wrk, MetaT const& meta);
|
|
std::string MocStringHeaders(WorkerT& wrk,
|
|
std::string const& fileBase) const;
|
|
std::string MocFindIncludedHeader(WorkerT& wrk,
|
|
std::string const& includerDir,
|
|
std::string const& includeBase);
|
|
bool ParseUic(WorkerT& wrk, MetaT const& meta);
|
|
bool ParseUicInclude(WorkerT& wrk, MetaT const& meta,
|
|
std::string&& includeString);
|
|
std::string UicFindIncludedFile(WorkerT& wrk, MetaT const& meta,
|
|
std::string const& includeString);
|
|
|
|
private:
|
|
std::string FileName;
|
|
bool AutoMoc = false;
|
|
bool AutoUic = false;
|
|
bool Header = false;
|
|
};
|
|
|
|
/// @brief Generate moc_predefs
|
|
///
|
|
class JobMocPredefsT : public JobT
|
|
{
|
|
private:
|
|
void Process(WorkerT& wrk) override;
|
|
};
|
|
|
|
/// @brief Moc a file job
|
|
///
|
|
class JobMocT : public JobT
|
|
{
|
|
public:
|
|
JobMocT(std::string&& sourceFile, std::string const& includerFile,
|
|
std::string&& includeString)
|
|
: SourceFile(std::move(sourceFile))
|
|
, IncluderFile(includerFile)
|
|
, IncludeString(std::move(includeString))
|
|
{
|
|
}
|
|
|
|
void FindDependencies(WorkerT& wrk, std::string const& content);
|
|
|
|
private:
|
|
void Process(WorkerT& wrk) override;
|
|
bool UpdateRequired(WorkerT& wrk);
|
|
void GenerateMoc(WorkerT& wrk);
|
|
|
|
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 const& includerFile,
|
|
std::string&& includeString)
|
|
: SourceFile(std::move(sourceFile))
|
|
, IncluderFile(includerFile)
|
|
, IncludeString(std::move(includeString))
|
|
{
|
|
}
|
|
|
|
private:
|
|
void Process(WorkerT& wrk) override;
|
|
bool UpdateRequired(WorkerT& wrk);
|
|
void GenerateUic(WorkerT& wrk);
|
|
|
|
public:
|
|
std::string SourceFile;
|
|
std::string IncluderFile;
|
|
std::string IncludeString;
|
|
std::string BuildFile;
|
|
};
|
|
|
|
/// @brief Worker Thread
|
|
///
|
|
class WorkerT
|
|
{
|
|
CM_DISABLE_COPY(WorkerT)
|
|
public:
|
|
WorkerT(cmQtAutoGeneratorMocUic* gen, uv_loop_t* uvLoop);
|
|
~WorkerT();
|
|
|
|
// -- Const accessors
|
|
cmQtAutoGeneratorMocUic& Gen() const { return *Gen_; }
|
|
Logger& Log() const { return Gen_->Log(); }
|
|
FileSystem& FileSys() const { return Gen_->FileSys(); }
|
|
const BaseSettingsT& Base() const { return Gen_->Base(); }
|
|
const MocSettingsT& Moc() const { return Gen_->Moc(); }
|
|
const UicSettingsT& Uic() const { return Gen_->Uic(); }
|
|
|
|
// -- Log info
|
|
void LogInfo(GeneratorT genType, std::string const& message) const;
|
|
// -- Log warning
|
|
void LogWarning(GeneratorT genType, std::string const& message) const;
|
|
void LogFileWarning(GeneratorT genType, std::string const& filename,
|
|
std::string const& message) const;
|
|
// -- Log error
|
|
void LogError(GeneratorT genType, std::string const& message) const;
|
|
void LogFileError(GeneratorT genType, std::string const& filename,
|
|
std::string const& message) const;
|
|
void LogCommandError(GeneratorT genType, std::string const& message,
|
|
std::vector<std::string> const& command,
|
|
std::string const& output) const;
|
|
|
|
// -- External processes
|
|
/// @brief Verbose logging version
|
|
bool RunProcess(GeneratorT genType, ProcessResultT& result,
|
|
std::vector<std::string> const& command);
|
|
|
|
private:
|
|
/// @brief Thread main loop
|
|
void Loop();
|
|
|
|
// -- Libuv callbacks
|
|
static void UVProcessStart(uv_async_t* handle);
|
|
void UVProcessFinished();
|
|
|
|
private:
|
|
// -- Generator
|
|
cmQtAutoGeneratorMocUic* Gen_;
|
|
// -- Job handle
|
|
JobHandleT JobHandle_;
|
|
// -- Process management
|
|
std::mutex ProcessMutex_;
|
|
cm::uv_async_ptr ProcessRequest_;
|
|
std::condition_variable ProcessCondition_;
|
|
std::unique_ptr<ReadOnlyProcessT> Process_;
|
|
// -- System thread
|
|
std::thread Thread_;
|
|
};
|
|
|
|
/// @brief Processing stage
|
|
enum class StageT
|
|
{
|
|
SETTINGS_READ,
|
|
CREATE_DIRECTORIES,
|
|
PARSE_SOURCES,
|
|
PARSE_HEADERS,
|
|
MOC_PREDEFS,
|
|
MOC_PROCESS,
|
|
MOCS_COMPILATION,
|
|
UIC_PROCESS,
|
|
SETTINGS_WRITE,
|
|
FINISH,
|
|
END
|
|
};
|
|
|
|
// -- Const settings interface
|
|
const BaseSettingsT& Base() const { return this->Base_; }
|
|
const MocSettingsT& Moc() const { return this->Moc_; }
|
|
const UicSettingsT& Uic() const { return this->Uic_; }
|
|
|
|
// -- Worker thread interface
|
|
void WorkerSwapJob(JobHandleT& jobHandle);
|
|
// -- Parallel job processing interface
|
|
void ParallelRegisterJobError();
|
|
bool ParallelJobPushMoc(JobHandleT& jobHandle);
|
|
bool ParallelJobPushUic(JobHandleT& jobHandle);
|
|
bool ParallelMocIncluded(std::string const& sourceFile);
|
|
void ParallelMocAutoRegister(std::string const& mocFile);
|
|
void ParallelMocAutoUpdated();
|
|
|
|
private:
|
|
// -- Abstract processing interface
|
|
bool Init(cmMakefile* makefile) override;
|
|
bool Process() override;
|
|
// -- Process stage
|
|
static void UVPollStage(uv_async_t* handle);
|
|
void PollStage();
|
|
void SetStage(StageT stage);
|
|
// -- Settings file
|
|
void SettingsFileRead();
|
|
void SettingsFileWrite();
|
|
// -- Thread processing
|
|
bool ThreadsStartJobs(JobQueueT& queue);
|
|
bool ThreadsJobsDone();
|
|
void ThreadsStop();
|
|
void RegisterJobError();
|
|
// -- Generation
|
|
void CreateDirectories();
|
|
void MocGenerateCompilation();
|
|
|
|
private:
|
|
// -- Settings
|
|
BaseSettingsT Base_;
|
|
MocSettingsT Moc_;
|
|
UicSettingsT Uic_;
|
|
// -- Progress
|
|
StageT Stage_;
|
|
// -- Job queues
|
|
std::mutex JobsMutex_;
|
|
struct
|
|
{
|
|
JobQueueT Sources;
|
|
JobQueueT Headers;
|
|
JobQueueT MocPredefs;
|
|
JobQueueT Moc;
|
|
JobQueueT Uic;
|
|
} JobQueues_;
|
|
JobQueueT JobQueue_;
|
|
std::size_t volatile JobsRemain_;
|
|
bool volatile JobError_;
|
|
bool volatile JobThreadsAbort_;
|
|
std::condition_variable JobsConditionRead_;
|
|
// -- Moc meta
|
|
std::set<std::string> MocIncludedStrings_;
|
|
std::set<std::string> MocIncludedFiles_;
|
|
std::set<std::string> MocAutoFiles_;
|
|
bool volatile MocAutoFileUpdated_;
|
|
// -- Settings file
|
|
std::string SettingsFile_;
|
|
std::string SettingsStringMoc_;
|
|
std::string SettingsStringUic_;
|
|
// -- Threads and loops
|
|
std::vector<std::unique_ptr<WorkerT>> Workers_;
|
|
};
|
|
|
|
#endif
|