cmQtAutoGenerator.h 9.17 KB
Newer Older
1 2 3 4 5 6 7
/* 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

8
#include "cmFilePathChecksum.h"
9
#include "cmQtAutoGen.h"
10
#include "cmUVHandlePtr.h"
Brad King's avatar
Brad King committed
11
#include "cmUVSignalHackRAII.h" // IWYU pragma: keep
12
#include "cm_uv.h"
13

14 15 16 17 18
#include <array>
#include <functional>
#include <mutex>
#include <stddef.h>
#include <stdint.h>
19 20 21 22 23
#include <string>
#include <vector>

class cmMakefile;

24 25
/// @brief Base class for QtAutoGen gernerators
class cmQtAutoGenerator : public cmQtAutoGen
26 27
{
public:
28 29 30 31 32 33 34
  // -- Types

  /// @brief Thread safe logging
  class Logger
  {
  public:
    // -- Verbosity
35 36 37 38 39
    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; }
40 41 42
    bool ColorOutput() const { return this->ColorOutput_; }
    void SetColorOutput(bool value);
    // -- Log info
43
    void Info(GenT genType, std::string const& message);
44
    // -- Log warning
45 46
    void Warning(GenT genType, std::string const& message);
    void WarningFile(GenT genType, std::string const& filename,
47 48
                     std::string const& message);
    // -- Log error
49 50
    void Error(GenT genType, std::string const& message);
    void ErrorFile(GenT genType, std::string const& filename,
51
                   std::string const& message);
52
    void ErrorCommand(GenT genType, std::string const& message,
53 54 55 56 57 58 59 60
                      std::vector<std::string> const& command,
                      std::string const& output);

  private:
    static std::string HeadLine(std::string const& title);

  private:
    std::mutex Mutex_;
61 62
    unsigned int Verbosity_ = 0;
    bool ColorOutput_ = false;
63 64 65 66 67 68 69 70 71 72 73
  };

  /// @brief Thread safe file system interface
  class FileSystem
  {
  public:
    FileSystem(Logger* log)
      : Log_(log)
    {
    }

74
    /// @brief Logger
75
    Logger* Log() const { return Log_; }
76 77 78 79

    // -- Paths
    /// @brief Wrapper for cmSystemTools::GetRealPath
    std::string GetRealPath(std::string const& filename);
80 81 82
    /// @brief Wrapper for cmSystemTools::CollapseFullPath
    std::string CollapseFullPath(std::string const& file,
                                 std::string const& dir);
83 84 85 86 87 88 89 90
    /// @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);
91 92
    /// @brief Wrapper for cmSystemTools::GetFilenameWithoutLastExtension
    std::string GetFilenameWithoutLastExtension(const std::string& filename);
93 94
    /// @brief Wrapper for cmQtAutoGen::SubDirPrefix
    std::string SubDirPrefix(std::string const& filename);
95 96 97 98 99 100 101
    /// @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);
102 103

    // -- File access
104
    /// @brief Wrapper for cmSystemTools::FileExists
105
    bool FileExists(std::string const& filename);
106 107 108 109
    /// @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);
110 111 112 113 114 115 116
    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
117
    bool FileRead(GenT genType, std::string& content,
118 119 120 121 122
                  std::string const& filename);

    bool FileWrite(std::string const& filename, std::string const& content,
                   std::string* error = nullptr);
    /// @brief Error logging version
123
    bool FileWrite(GenT genType, std::string const& filename,
124 125 126 127 128
                   std::string const& content);

    bool FileDiffers(std::string const& filename, std::string const& content);

    bool FileRemove(std::string const& filename);
129
    bool Touch(std::string const& filename, bool create = false);
130

131
    // -- Directory access
132 133
    bool MakeDirectory(std::string const& dirname);
    /// @brief Error logging version
134
    bool MakeDirectory(GenT genType, std::string const& dirname);
135 136 137

    bool MakeParentDirectory(std::string const& filename);
    /// @brief Error logging version
138
    bool MakeParentDirectory(GenT genType, std::string const& filename);
139 140 141

  private:
    std::mutex Mutex_;
142
    cmFilePathChecksum FilePathChecksum_;
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
    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;
    };

    // -- 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
244
  cmQtAutoGenerator();
245 246
  virtual ~cmQtAutoGenerator();

wahikihiki's avatar
wahikihiki committed
247 248 249
  cmQtAutoGenerator(cmQtAutoGenerator const&) = delete;
  cmQtAutoGenerator& operator=(cmQtAutoGenerator const&) = delete;

250
  // -- Run
251 252
  bool Run(std::string const& infoFile, std::string const& config);

253 254 255 256 257 258 259 260 261 262 263 264
  // -- 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_; }
265 266

  // -- Utility
267 268 269 270 271 272
  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;
273 274

private:
275 276 277
  // -- Logging
  Logger Logger_;
  FileSystem FileSys_;
278
  // -- Info settings
279 280 281 282 283 284 285 286 287
  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_;
288 289 290
};

#endif