You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
684 lines
18 KiB
684 lines
18 KiB
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
|
#include "cmQtAutoGeneratorRcc.h"
|
|
#include "cmQtAutoGen.h"
|
|
|
|
#include "cmAlgorithms.h"
|
|
#include "cmCryptoHash.h"
|
|
#include "cmFileLockResult.h"
|
|
#include "cmMakefile.h"
|
|
#include "cmSystemTools.h"
|
|
#include "cmUVHandlePtr.h"
|
|
|
|
#include <functional>
|
|
|
|
// -- Class methods
|
|
|
|
cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc()
|
|
: MultiConfig_(false)
|
|
, SettingsChanged_(false)
|
|
, Stage_(StageT::SETTINGS_READ)
|
|
, Error_(false)
|
|
, Generate_(false)
|
|
, BuildFileChanged_(false)
|
|
{
|
|
// Initialize libuv asynchronous iteration request
|
|
UVRequest().init(*UVLoop(), &cmQtAutoGeneratorRcc::UVPollStage, this);
|
|
}
|
|
|
|
cmQtAutoGeneratorRcc::~cmQtAutoGeneratorRcc()
|
|
{
|
|
}
|
|
|
|
bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
|
|
{
|
|
// -- Utility lambdas
|
|
auto InfoGet = [makefile](std::string const& key) {
|
|
return makefile->GetSafeDefinition(key);
|
|
};
|
|
auto InfoGetList =
|
|
[makefile](std::string const& key) -> std::vector<std::string> {
|
|
std::vector<std::string> list;
|
|
cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
|
|
return list;
|
|
};
|
|
auto InfoGetConfig = [makefile,
|
|
this](std::string const& key) -> std::string {
|
|
const char* valueConf = nullptr;
|
|
{
|
|
std::string keyConf = key;
|
|
keyConf += '_';
|
|
keyConf += InfoConfig();
|
|
valueConf = makefile->GetDefinition(keyConf);
|
|
}
|
|
if (valueConf == nullptr) {
|
|
return makefile->GetSafeDefinition(key);
|
|
}
|
|
return std::string(valueConf);
|
|
};
|
|
auto InfoGetConfigList =
|
|
[&InfoGetConfig](std::string const& key) -> std::vector<std::string> {
|
|
std::vector<std::string> list;
|
|
cmSystemTools::ExpandListArgument(InfoGetConfig(key), list);
|
|
return list;
|
|
};
|
|
|
|
// -- Read info file
|
|
if (!makefile->ReadListFile(InfoFile().c_str())) {
|
|
Log().ErrorFile(GeneratorT::RCC, InfoFile(), "File processing failed");
|
|
return false;
|
|
}
|
|
|
|
// - Configurations
|
|
Log().RaiseVerbosity(InfoGet("ARCC_VERBOSITY"));
|
|
MultiConfig_ = makefile->IsOn("ARCC_MULTI_CONFIG");
|
|
|
|
// - Directories
|
|
AutogenBuildDir_ = InfoGet("ARCC_BUILD_DIR");
|
|
if (AutogenBuildDir_.empty()) {
|
|
Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Build directory empty");
|
|
return false;
|
|
}
|
|
|
|
IncludeDir_ = InfoGetConfig("ARCC_INCLUDE_DIR");
|
|
if (IncludeDir_.empty()) {
|
|
Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Include directory empty");
|
|
return false;
|
|
}
|
|
|
|
// - Rcc executable
|
|
RccExecutable_ = InfoGet("ARCC_RCC_EXECUTABLE");
|
|
RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS");
|
|
|
|
// - Job
|
|
LockFile_ = InfoGet("ARCC_LOCK_FILE");
|
|
QrcFile_ = InfoGet("ARCC_SOURCE");
|
|
QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_);
|
|
QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_);
|
|
RccPathChecksum_ = InfoGet("ARCC_OUTPUT_CHECKSUM");
|
|
RccFileName_ = InfoGet("ARCC_OUTPUT_NAME");
|
|
Options_ = InfoGetConfigList("ARCC_OPTIONS");
|
|
Inputs_ = InfoGetList("ARCC_INPUTS");
|
|
|
|
// - Settings file
|
|
SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE");
|
|
|
|
// - Validity checks
|
|
if (LockFile_.empty()) {
|
|
Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Lock file name missing");
|
|
return false;
|
|
}
|
|
if (SettingsFile_.empty()) {
|
|
Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Settings file name missing");
|
|
return false;
|
|
}
|
|
if (AutogenBuildDir_.empty()) {
|
|
Log().ErrorFile(GeneratorT::RCC, InfoFile(),
|
|
"Autogen build directory missing");
|
|
return false;
|
|
}
|
|
if (RccExecutable_.empty()) {
|
|
Log().ErrorFile(GeneratorT::RCC, InfoFile(), "rcc executable missing");
|
|
return false;
|
|
}
|
|
if (QrcFile_.empty()) {
|
|
Log().ErrorFile(GeneratorT::RCC, InfoFile(), "rcc input file missing");
|
|
return false;
|
|
}
|
|
if (RccFileName_.empty()) {
|
|
Log().ErrorFile(GeneratorT::RCC, InfoFile(), "rcc output file missing");
|
|
return false;
|
|
}
|
|
|
|
// Init derived information
|
|
// ------------------------
|
|
|
|
RccFilePublic_ = AutogenBuildDir_;
|
|
RccFilePublic_ += '/';
|
|
RccFilePublic_ += RccPathChecksum_;
|
|
RccFilePublic_ += '/';
|
|
RccFilePublic_ += RccFileName_;
|
|
|
|
// Compute rcc output file name
|
|
if (IsMultiConfig()) {
|
|
RccFileOutput_ = IncludeDir_;
|
|
RccFileOutput_ += '/';
|
|
RccFileOutput_ += MultiConfigOutput();
|
|
} else {
|
|
RccFileOutput_ = RccFilePublic_;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool cmQtAutoGeneratorRcc::Process()
|
|
{
|
|
// Run libuv event loop
|
|
UVRequest().send();
|
|
if (uv_run(UVLoop(), UV_RUN_DEFAULT) == 0) {
|
|
if (Error_) {
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void cmQtAutoGeneratorRcc::UVPollStage(uv_async_t* handle)
|
|
{
|
|
reinterpret_cast<cmQtAutoGeneratorRcc*>(handle->data)->PollStage();
|
|
}
|
|
|
|
void cmQtAutoGeneratorRcc::PollStage()
|
|
{
|
|
switch (Stage_) {
|
|
// -- Initialize
|
|
case StageT::SETTINGS_READ:
|
|
if (SettingsFileRead()) {
|
|
SetStage(StageT::TEST_QRC_RCC_FILES);
|
|
} else {
|
|
SetStage(StageT::FINISH);
|
|
}
|
|
break;
|
|
|
|
// -- Change detection
|
|
case StageT::TEST_QRC_RCC_FILES:
|
|
if (TestQrcRccFiles()) {
|
|
SetStage(StageT::GENERATE);
|
|
} else {
|
|
SetStage(StageT::TEST_RESOURCES_READ);
|
|
}
|
|
break;
|
|
case StageT::TEST_RESOURCES_READ:
|
|
if (TestResourcesRead()) {
|
|
SetStage(StageT::TEST_RESOURCES);
|
|
}
|
|
break;
|
|
case StageT::TEST_RESOURCES:
|
|
if (TestResources()) {
|
|
SetStage(StageT::GENERATE);
|
|
} else {
|
|
SetStage(StageT::TEST_INFO_FILE);
|
|
}
|
|
break;
|
|
case StageT::TEST_INFO_FILE:
|
|
TestInfoFile();
|
|
SetStage(StageT::GENERATE_WRAPPER);
|
|
break;
|
|
|
|
// -- Generation
|
|
case StageT::GENERATE:
|
|
GenerateParentDir();
|
|
SetStage(StageT::GENERATE_RCC);
|
|
break;
|
|
case StageT::GENERATE_RCC:
|
|
if (GenerateRcc()) {
|
|
SetStage(StageT::GENERATE_WRAPPER);
|
|
}
|
|
break;
|
|
case StageT::GENERATE_WRAPPER:
|
|
GenerateWrapper();
|
|
SetStage(StageT::SETTINGS_WRITE);
|
|
break;
|
|
|
|
// -- Finalize
|
|
case StageT::SETTINGS_WRITE:
|
|
SettingsFileWrite();
|
|
SetStage(StageT::FINISH);
|
|
break;
|
|
case StageT::FINISH:
|
|
// Clear all libuv handles
|
|
UVRequest().reset();
|
|
// Set highest END stage manually
|
|
Stage_ = StageT::END;
|
|
break;
|
|
case StageT::END:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void cmQtAutoGeneratorRcc::SetStage(StageT stage)
|
|
{
|
|
if (Error_) {
|
|
stage = StageT::FINISH;
|
|
}
|
|
// Only allow to increase the stage
|
|
if (Stage_ < stage) {
|
|
Stage_ = stage;
|
|
UVRequest().send();
|
|
}
|
|
}
|
|
|
|
std::string cmQtAutoGeneratorRcc::MultiConfigOutput() const
|
|
{
|
|
static std::string const suffix = "_CMAKE_";
|
|
std::string res;
|
|
res += RccPathChecksum_;
|
|
res += '/';
|
|
res += AppendFilenameSuffix(RccFileName_, suffix);
|
|
return res;
|
|
}
|
|
|
|
bool cmQtAutoGeneratorRcc::SettingsFileRead()
|
|
{
|
|
// Compose current settings strings
|
|
{
|
|
cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
|
|
std::string const sep(" ~~~ ");
|
|
{
|
|
std::string str;
|
|
str += RccExecutable_;
|
|
str += sep;
|
|
str += cmJoin(RccListOptions_, ";");
|
|
str += sep;
|
|
str += QrcFile_;
|
|
str += sep;
|
|
str += RccPathChecksum_;
|
|
str += sep;
|
|
str += RccFileName_;
|
|
str += sep;
|
|
str += cmJoin(Options_, ";");
|
|
str += sep;
|
|
str += cmJoin(Inputs_, ";");
|
|
str += sep;
|
|
SettingsString_ = crypt.HashString(str);
|
|
}
|
|
}
|
|
|
|
// Make sure the settings file exists
|
|
if (!FileSys().FileExists(SettingsFile_, true)) {
|
|
// Touch the settings file to make sure it exists
|
|
FileSys().Touch(SettingsFile_, true);
|
|
}
|
|
|
|
// Lock the lock file
|
|
{
|
|
// Make sure the lock file exists
|
|
if (!FileSys().FileExists(LockFile_, true)) {
|
|
if (!FileSys().Touch(LockFile_, true)) {
|
|
Log().ErrorFile(GeneratorT::RCC, LockFile_,
|
|
"Lock file creation failed");
|
|
Error_ = true;
|
|
return false;
|
|
}
|
|
}
|
|
// Lock the lock file
|
|
cmFileLockResult lockResult =
|
|
LockFileLock_.Lock(LockFile_, static_cast<unsigned long>(-1));
|
|
if (!lockResult.IsOk()) {
|
|
Log().ErrorFile(GeneratorT::RCC, LockFile_,
|
|
"File lock failed: " + lockResult.GetOutputMessage());
|
|
Error_ = true;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Read old settings
|
|
{
|
|
std::string content;
|
|
if (FileSys().FileRead(content, SettingsFile_)) {
|
|
SettingsChanged_ = (SettingsString_ != SettingsFind(content, "rcc"));
|
|
// In case any setting changed clear the old settings file.
|
|
// This triggers a full rebuild on the next run if the current
|
|
// build is aborted before writing the current settings in the end.
|
|
if (SettingsChanged_) {
|
|
FileSys().FileWrite(GeneratorT::RCC, SettingsFile_, "");
|
|
}
|
|
} else {
|
|
SettingsChanged_ = true;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void cmQtAutoGeneratorRcc::SettingsFileWrite()
|
|
{
|
|
// Only write if any setting changed
|
|
if (SettingsChanged_) {
|
|
if (Log().Verbose()) {
|
|
Log().Info(GeneratorT::RCC,
|
|
"Writing settings file " + Quoted(SettingsFile_));
|
|
}
|
|
// Write settings file
|
|
std::string content = "rcc:";
|
|
content += SettingsString_;
|
|
content += '\n';
|
|
if (!FileSys().FileWrite(GeneratorT::RCC, SettingsFile_, content)) {
|
|
Log().ErrorFile(GeneratorT::RCC, SettingsFile_,
|
|
"Settings file writing failed");
|
|
// Remove old settings file to trigger a full rebuild on the next run
|
|
FileSys().FileRemove(SettingsFile_);
|
|
Error_ = true;
|
|
}
|
|
}
|
|
|
|
// Unlock the lock file
|
|
LockFileLock_.Release();
|
|
}
|
|
|
|
bool cmQtAutoGeneratorRcc::TestQrcRccFiles()
|
|
{
|
|
// Do basic checks if rcc generation is required
|
|
|
|
// Test if the rcc output file exists
|
|
if (!FileSys().FileExists(RccFileOutput_)) {
|
|
if (Log().Verbose()) {
|
|
std::string reason = "Generating ";
|
|
reason += Quoted(RccFileOutput_);
|
|
reason += " from its source file ";
|
|
reason += Quoted(QrcFile_);
|
|
reason += " because it doesn't exist";
|
|
Log().Info(GeneratorT::RCC, reason);
|
|
}
|
|
Generate_ = true;
|
|
return Generate_;
|
|
}
|
|
|
|
// Test if the settings changed
|
|
if (SettingsChanged_) {
|
|
if (Log().Verbose()) {
|
|
std::string reason = "Generating ";
|
|
reason += Quoted(RccFileOutput_);
|
|
reason += " from ";
|
|
reason += Quoted(QrcFile_);
|
|
reason += " because the RCC settings changed";
|
|
Log().Info(GeneratorT::RCC, reason);
|
|
}
|
|
Generate_ = true;
|
|
return Generate_;
|
|
}
|
|
|
|
// Test if the rcc output file is older than the .qrc file
|
|
{
|
|
bool isOlder = false;
|
|
{
|
|
std::string error;
|
|
isOlder = FileSys().FileIsOlderThan(RccFileOutput_, QrcFile_, &error);
|
|
if (!error.empty()) {
|
|
Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
|
|
Error_ = true;
|
|
}
|
|
}
|
|
if (isOlder) {
|
|
if (Log().Verbose()) {
|
|
std::string reason = "Generating ";
|
|
reason += Quoted(RccFileOutput_);
|
|
reason += " because it is older than ";
|
|
reason += Quoted(QrcFile_);
|
|
Log().Info(GeneratorT::RCC, reason);
|
|
}
|
|
Generate_ = true;
|
|
}
|
|
}
|
|
|
|
return Generate_;
|
|
}
|
|
|
|
bool cmQtAutoGeneratorRcc::TestResourcesRead()
|
|
{
|
|
if (!Inputs_.empty()) {
|
|
// Inputs are known already
|
|
return true;
|
|
}
|
|
|
|
if (!RccListOptions_.empty()) {
|
|
// Start a rcc list process and parse the output
|
|
if (Process_) {
|
|
// Process is running already
|
|
if (Process_->IsFinished()) {
|
|
// Process is finished
|
|
if (!ProcessResult_.error()) {
|
|
// Process success
|
|
std::string parseError;
|
|
if (!RccListParseOutput(ProcessResult_.StdOut, ProcessResult_.StdErr,
|
|
Inputs_, parseError)) {
|
|
Log().ErrorFile(GeneratorT::RCC, QrcFile_, parseError);
|
|
Error_ = true;
|
|
}
|
|
} else {
|
|
Log().ErrorFile(GeneratorT::RCC, QrcFile_,
|
|
ProcessResult_.ErrorMessage);
|
|
Error_ = true;
|
|
}
|
|
// Clean up
|
|
Process_.reset();
|
|
ProcessResult_.reset();
|
|
} else {
|
|
// Process is not finished, yet.
|
|
return false;
|
|
}
|
|
} else {
|
|
// Start a new process
|
|
// rcc prints relative entry paths when started in the directory of the
|
|
// qrc file with a pathless qrc file name argument.
|
|
// This is important because on Windows absolute paths returned by rcc
|
|
// might contain bad multibyte characters when the qrc file path
|
|
// contains non-ASCII pcharacters.
|
|
std::vector<std::string> cmd;
|
|
cmd.push_back(RccExecutable_);
|
|
cmd.insert(cmd.end(), RccListOptions_.begin(), RccListOptions_.end());
|
|
cmd.push_back(QrcFileName_);
|
|
// We're done here if the process fails to start
|
|
return !StartProcess(QrcFileDir_, cmd, false);
|
|
}
|
|
} else {
|
|
// rcc does not support the --list command.
|
|
// Read the qrc file content and parse it.
|
|
std::string qrcContent;
|
|
if (FileSys().FileRead(GeneratorT::RCC, qrcContent, QrcFile_)) {
|
|
RccListParseContent(qrcContent, Inputs_);
|
|
}
|
|
}
|
|
|
|
if (!Inputs_.empty()) {
|
|
// Convert relative paths to absolute paths
|
|
RccListConvertFullPath(QrcFileDir_, Inputs_);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool cmQtAutoGeneratorRcc::TestResources()
|
|
{
|
|
if (Inputs_.empty()) {
|
|
return true;
|
|
}
|
|
{
|
|
std::string error;
|
|
for (std::string const& resFile : Inputs_) {
|
|
// Check if the resource file exists
|
|
if (!FileSys().FileExists(resFile)) {
|
|
error = "Could not find the resource file\n ";
|
|
error += Quoted(resFile);
|
|
error += '\n';
|
|
Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
|
|
Error_ = true;
|
|
break;
|
|
}
|
|
// Check if the resource file is newer than the build file
|
|
if (FileSys().FileIsOlderThan(RccFileOutput_, resFile, &error)) {
|
|
if (Log().Verbose()) {
|
|
std::string reason = "Generating ";
|
|
reason += Quoted(RccFileOutput_);
|
|
reason += " from ";
|
|
reason += Quoted(QrcFile_);
|
|
reason += " because it is older than ";
|
|
reason += Quoted(resFile);
|
|
Log().Info(GeneratorT::RCC, reason);
|
|
}
|
|
Generate_ = true;
|
|
break;
|
|
}
|
|
// Print error and break on demand
|
|
if (!error.empty()) {
|
|
Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
|
|
Error_ = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return Generate_;
|
|
}
|
|
|
|
void cmQtAutoGeneratorRcc::TestInfoFile()
|
|
{
|
|
// Test if the rcc output file is older than the info file
|
|
{
|
|
bool isOlder = false;
|
|
{
|
|
std::string error;
|
|
isOlder = FileSys().FileIsOlderThan(RccFileOutput_, InfoFile(), &error);
|
|
if (!error.empty()) {
|
|
Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
|
|
Error_ = true;
|
|
}
|
|
}
|
|
if (isOlder) {
|
|
if (Log().Verbose()) {
|
|
std::string reason = "Touching ";
|
|
reason += Quoted(RccFileOutput_);
|
|
reason += " because it is older than ";
|
|
reason += Quoted(InfoFile());
|
|
Log().Info(GeneratorT::RCC, reason);
|
|
}
|
|
// Touch build file
|
|
FileSys().Touch(RccFileOutput_);
|
|
BuildFileChanged_ = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void cmQtAutoGeneratorRcc::GenerateParentDir()
|
|
{
|
|
// Make sure the parent directory exists
|
|
if (!FileSys().MakeParentDirectory(GeneratorT::RCC, RccFileOutput_)) {
|
|
Error_ = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return True when finished
|
|
*/
|
|
bool cmQtAutoGeneratorRcc::GenerateRcc()
|
|
{
|
|
if (!Generate_) {
|
|
// Nothing to do
|
|
return true;
|
|
}
|
|
|
|
if (Process_) {
|
|
// Process is running already
|
|
if (Process_->IsFinished()) {
|
|
// Process is finished
|
|
if (!ProcessResult_.error()) {
|
|
// Rcc process success
|
|
// Print rcc output
|
|
if (!ProcessResult_.StdOut.empty()) {
|
|
Log().Info(GeneratorT::RCC, ProcessResult_.StdOut);
|
|
}
|
|
BuildFileChanged_ = true;
|
|
} else {
|
|
// Rcc process failed
|
|
{
|
|
std::string emsg = "The rcc process failed to compile\n ";
|
|
emsg += Quoted(QrcFile_);
|
|
emsg += "\ninto\n ";
|
|
emsg += Quoted(RccFileOutput_);
|
|
if (ProcessResult_.error()) {
|
|
emsg += "\n";
|
|
emsg += ProcessResult_.ErrorMessage;
|
|
}
|
|
Log().ErrorCommand(GeneratorT::RCC, emsg, Process_->Setup().Command,
|
|
ProcessResult_.StdOut);
|
|
}
|
|
FileSys().FileRemove(RccFileOutput_);
|
|
Error_ = true;
|
|
}
|
|
// Clean up
|
|
Process_.reset();
|
|
ProcessResult_.reset();
|
|
} else {
|
|
// Process is not finished, yet.
|
|
return false;
|
|
}
|
|
} else {
|
|
// Start a rcc process
|
|
std::vector<std::string> cmd;
|
|
cmd.push_back(RccExecutable_);
|
|
cmd.insert(cmd.end(), Options_.begin(), Options_.end());
|
|
cmd.push_back("-o");
|
|
cmd.push_back(RccFileOutput_);
|
|
cmd.push_back(QrcFile_);
|
|
// We're done here if the process fails to start
|
|
return !StartProcess(AutogenBuildDir_, cmd, true);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void cmQtAutoGeneratorRcc::GenerateWrapper()
|
|
{
|
|
// Generate a wrapper source file on demand
|
|
if (IsMultiConfig()) {
|
|
// Wrapper file content
|
|
std::string content;
|
|
content += "// This is an autogenerated configuration wrapper file.\n";
|
|
content += "// Changes will be overwritten.\n";
|
|
content += "#include <";
|
|
content += MultiConfigOutput();
|
|
content += ">\n";
|
|
|
|
// Write content to file
|
|
if (FileSys().FileDiffers(RccFilePublic_, content)) {
|
|
// Write new wrapper file
|
|
if (Log().Verbose()) {
|
|
Log().Info(GeneratorT::RCC,
|
|
"Generating RCC wrapper file " + RccFilePublic_);
|
|
}
|
|
if (!FileSys().FileWrite(GeneratorT::RCC, RccFilePublic_, content)) {
|
|
Log().ErrorFile(GeneratorT::RCC, RccFilePublic_,
|
|
"RCC wrapper file writing failed");
|
|
Error_ = true;
|
|
}
|
|
} else if (BuildFileChanged_) {
|
|
// Just touch the wrapper file
|
|
if (Log().Verbose()) {
|
|
Log().Info(GeneratorT::RCC,
|
|
"Touching RCC wrapper file " + RccFilePublic_);
|
|
}
|
|
FileSys().Touch(RccFilePublic_);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool cmQtAutoGeneratorRcc::StartProcess(
|
|
std::string const& workingDirectory, std::vector<std::string> const& command,
|
|
bool mergedOutput)
|
|
{
|
|
// Log command
|
|
if (Log().Verbose()) {
|
|
std::string msg = "Running command:\n";
|
|
msg += QuotedCommand(command);
|
|
msg += '\n';
|
|
Log().Info(GeneratorT::RCC, msg);
|
|
}
|
|
|
|
// Create process handler
|
|
Process_ = cm::make_unique<ReadOnlyProcessT>();
|
|
Process_->setup(&ProcessResult_, mergedOutput, command, workingDirectory);
|
|
// Start process
|
|
if (!Process_->start(UVLoop(),
|
|
std::bind(&cm::uv_async_ptr::send, &UVRequest()))) {
|
|
Log().ErrorFile(GeneratorT::RCC, QrcFile_, ProcessResult_.ErrorMessage);
|
|
Error_ = true;
|
|
// Clean up
|
|
Process_.reset();
|
|
ProcessResult_.reset();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|