1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
|
/* 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 "cmFilePathChecksum.h"
#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
unsigned int Verbosity() const { return this->Verbosity_; }
void SetVerbosity(unsigned int value) { this->Verbosity_ = value; }
void RaiseVerbosity(std::string const& value);
bool Verbose() const { return (this->Verbosity_ != 0); }
void SetVerbose(bool value) { this->Verbosity_ = value ? 1 : 0; }
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_;
unsigned int Verbosity_ = 0;
bool ColorOutput_ = false;
};
/// @brief Thread safe file system interface
class FileSystem
{
public:
FileSystem(Logger* log)
: Log_(log)
{
}
/// @brief Logger
Logger* Log() const { return Log_; }
// -- Paths
/// @brief Wrapper for cmSystemTools::GetRealPath
std::string GetRealPath(std::string const& filename);
/// @brief Wrapper for cmSystemTools::CollapseCombinedPath
std::string CollapseCombinedPath(std::string const& dir,
std::string const& file);
/// @brief Wrapper for cmSystemTools::SplitPath
void SplitPath(const std::string& p, std::vector<std::string>& components,
bool expand_home_dir = true);
/// @brief Wrapper for cmSystemTools::JoinPath
std::string JoinPath(const std::vector<std::string>& components);
/// @brief Wrapper for cmSystemTools::JoinPath
std::string JoinPath(std::vector<std::string>::const_iterator first,
std::vector<std::string>::const_iterator last);
/// @brief Wrapper for cmSystemTools::GetFilenameWithoutLastExtension
std::string GetFilenameWithoutLastExtension(const std::string& filename);
/// @brief Wrapper for cmQtAutoGen::SubDirPrefix
std::string SubDirPrefix(std::string const& filename);
/// @brief Wrapper for cmFilePathChecksum::setupParentDirs
void setupFilePathChecksum(std::string const& currentSrcDir,
std::string const& currentBinDir,
std::string const& projectSrcDir,
std::string const& projectBinDir);
/// @brief Wrapper for cmFilePathChecksum::getPart
std::string GetFilePathChecksum(std::string const& filename);
// -- File access
/// @brief Wrapper for cmSystemTools::FileExists
bool FileExists(std::string const& filename);
/// @brief Wrapper for cmSystemTools::FileExists
bool FileExists(std::string const& filename, bool isFile);
/// @brief Wrapper for cmSystemTools::FileLength
unsigned long FileLength(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 create = false);
// -- Directory access
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_;
cmFilePathChecksum FilePathChecksum_;
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
|