123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
- #ifndef cmQtAutoGenerator_h
- #define cmQtAutoGenerator_h
- #include "cmConfigure.h" // IWYU pragma: keep
- #include "cmQtAutoGen.h"
- #include "cmUVHandlePtr.h"
- #include "cmUVSignalHackRAII.h" // IWYU pragma: keep
- #include "cm_uv.h"
- #include <array>
- #include <functional>
- #include <mutex>
- #include <stddef.h>
- #include <stdint.h>
- #include <string>
- #include <vector>
- class cmMakefile;
- /// @brief Base class for QtAutoGen gernerators
- class cmQtAutoGenerator : public cmQtAutoGen
- {
- CM_DISABLE_COPY(cmQtAutoGenerator)
- public:
- // -- Types
- /// @brief Thread safe logging
- class Logger
- {
- public:
- // -- Verbosity
- bool Verbose() const { return this->Verbose_; }
- void SetVerbose(bool value);
- bool ColorOutput() const { return this->ColorOutput_; }
- void SetColorOutput(bool value);
- // -- Log info
- void Info(GeneratorT genType, std::string const& message);
- // -- Log warning
- void Warning(GeneratorT genType, std::string const& message);
- void WarningFile(GeneratorT genType, std::string const& filename,
- std::string const& message);
- // -- Log error
- void Error(GeneratorT genType, std::string const& message);
- void ErrorFile(GeneratorT genType, std::string const& filename,
- std::string const& message);
- void ErrorCommand(GeneratorT genType, std::string const& message,
- std::vector<std::string> const& command,
- std::string const& output);
- private:
- static std::string HeadLine(std::string const& title);
- private:
- std::mutex Mutex_;
- bool volatile Verbose_ = false;
- bool volatile ColorOutput_ = false;
- };
- /// @brief Thread safe file system interface
- class FileSystem
- {
- public:
- FileSystem(Logger* log)
- : Log_(log)
- {
- }
- Logger* Log() const { return Log_; }
- std::string RealPath(std::string const& filename);
- bool FileExists(std::string const& filename);
- bool FileIsOlderThan(std::string const& buildFile,
- std::string const& sourceFile,
- std::string* error = nullptr);
- bool FileRead(std::string& content, std::string const& filename,
- std::string* error = nullptr);
- /// @brief Error logging version
- bool FileRead(GeneratorT genType, std::string& content,
- std::string const& filename);
- bool FileWrite(std::string const& filename, std::string const& content,
- std::string* error = nullptr);
- /// @brief Error logging version
- bool FileWrite(GeneratorT genType, std::string const& filename,
- std::string const& content);
- bool FileDiffers(std::string const& filename, std::string const& content);
- bool FileRemove(std::string const& filename);
- bool Touch(std::string const& filename);
- bool MakeDirectory(std::string const& dirname);
- /// @brief Error logging version
- bool MakeDirectory(GeneratorT genType, std::string const& dirname);
- bool MakeParentDirectory(std::string const& filename);
- /// @brief Error logging version
- bool MakeParentDirectory(GeneratorT genType, std::string const& filename);
- private:
- std::mutex Mutex_;
- Logger* Log_;
- };
- /// @brief Return value and output of an external process
- struct ProcessResultT
- {
- void reset();
- bool error() const
- {
- return (ExitStatus != 0) || (TermSignal != 0) || !ErrorMessage.empty();
- }
- std::int64_t ExitStatus = 0;
- int TermSignal = 0;
- std::string StdOut;
- std::string StdErr;
- std::string ErrorMessage;
- };
- /// @brief External process management class
- struct ReadOnlyProcessT
- {
- // -- Types
- /// @brief libuv pipe buffer class
- class PipeT
- {
- public:
- int init(uv_loop_t* uv_loop, ReadOnlyProcessT* process);
- int startRead(std::string* target);
- void reset();
- // -- Libuv casts
- uv_pipe_t* uv_pipe() { return UVPipe_.get(); }
- uv_stream_t* uv_stream()
- {
- return reinterpret_cast<uv_stream_t*>(uv_pipe());
- }
- uv_handle_t* uv_handle()
- {
- return reinterpret_cast<uv_handle_t*>(uv_pipe());
- }
- // -- Libuv callbacks
- static void UVAlloc(uv_handle_t* handle, size_t suggestedSize,
- uv_buf_t* buf);
- static void UVData(uv_stream_t* stream, ssize_t nread,
- const uv_buf_t* buf);
- private:
- ReadOnlyProcessT* Process_ = nullptr;
- std::string* Target_ = nullptr;
- std::vector<char> Buffer_;
- cm::uv_pipe_ptr UVPipe_;
- };
- /// @brief Process settings
- struct SetupT
- {
- std::string WorkingDirectory;
- std::vector<std::string> Command;
- ProcessResultT* Result = nullptr;
- bool MergedOutput = false;
- };
- // -- Constructor
- ReadOnlyProcessT() = default;
- // -- Const accessors
- const SetupT& Setup() const { return Setup_; }
- ProcessResultT* Result() const { return Setup_.Result; }
- bool IsStarted() const { return IsStarted_; }
- bool IsFinished() const { return IsFinished_; }
- // -- Runtime
- void setup(ProcessResultT* result, bool mergedOutput,
- std::vector<std::string> const& command,
- std::string const& workingDirectory = std::string());
- bool start(uv_loop_t* uv_loop, std::function<void()>&& finishedCallback);
- private:
- // -- Friends
- friend class PipeT;
- // -- Libuv callbacks
- static void UVExit(uv_process_t* handle, int64_t exitStatus,
- int termSignal);
- void UVTryFinish();
- // -- Setup
- SetupT Setup_;
- // -- Runtime
- bool IsStarted_ = false;
- bool IsFinished_ = false;
- std::function<void()> FinishedCallback_;
- std::vector<const char*> CommandPtr_;
- std::array<uv_stdio_container_t, 3> UVOptionsStdIO_;
- uv_process_options_t UVOptions_;
- cm::uv_process_ptr UVProcess_;
- PipeT UVPipeOut_;
- PipeT UVPipeErr_;
- };
- public:
- // -- Constructors
- cmQtAutoGenerator();
- virtual ~cmQtAutoGenerator();
- // -- Run
- bool Run(std::string const& infoFile, std::string const& config);
- // -- Accessors
- // Logging
- Logger& Log() { return Logger_; }
- // File System
- FileSystem& FileSys() { return FileSys_; }
- // InfoFile
- std::string const& InfoFile() const { return InfoFile_; }
- std::string const& InfoDir() const { return InfoDir_; }
- std::string const& InfoConfig() const { return InfoConfig_; }
- // libuv loop
- uv_loop_t* UVLoop() { return UVLoop_.get(); }
- cm::uv_async_ptr& UVRequest() { return UVRequest_; }
- // -- Utility
- static std::string SettingsFind(std::string const& content, const char* key);
- protected:
- // -- Abstract processing interface
- virtual bool Init(cmMakefile* makefile) = 0;
- virtual bool Process() = 0;
- private:
- // -- Logging
- Logger Logger_;
- FileSystem FileSys_;
- // -- Info settings
- std::string InfoFile_;
- std::string InfoDir_;
- std::string InfoConfig_;
- // -- libuv loop
- #ifdef CMAKE_UV_SIGNAL_HACK
- std::unique_ptr<cmUVSignalHackRAII> UVHackRAII_;
- #endif
- std::unique_ptr<uv_loop_t> UVLoop_;
- cm::uv_async_ptr UVRequest_;
- };
- #endif
|