|
@@ -1,666 +0,0 @@
|
|
|
-/* 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"
|
|
|
|
|
-
|
|
|
|
|
-// -- Class methods
|
|
|
|
|
-
|
|
|
|
|
-cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc()
|
|
|
|
|
-{
|
|
|
|
|
- // Initialize libuv asynchronous iteration request
|
|
|
|
|
- UVRequest().init(*UVLoop(), &cmQtAutoGeneratorRcc::UVPollStage, this);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-cmQtAutoGeneratorRcc::~cmQtAutoGeneratorRcc() = default;
|
|
|
|
|
-
|
|
|
|
|
-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())) {
|
|
|
|
|
- Log().ErrorFile(GenT::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(GenT::RCC, InfoFile(), "Build directory empty");
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- IncludeDir_ = InfoGetConfig("ARCC_INCLUDE_DIR");
|
|
|
|
|
- if (IncludeDir_.empty()) {
|
|
|
|
|
- Log().ErrorFile(GenT::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(GenT::RCC, InfoFile(), "Lock file name missing");
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- if (SettingsFile_.empty()) {
|
|
|
|
|
- Log().ErrorFile(GenT::RCC, InfoFile(), "Settings file name missing");
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- if (AutogenBuildDir_.empty()) {
|
|
|
|
|
- Log().ErrorFile(GenT::RCC, InfoFile(), "Autogen build directory missing");
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- if (RccExecutable_.empty()) {
|
|
|
|
|
- Log().ErrorFile(GenT::RCC, InfoFile(), "rcc executable missing");
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- if (QrcFile_.empty()) {
|
|
|
|
|
- Log().ErrorFile(GenT::RCC, InfoFile(), "rcc input file missing");
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- if (RccFileName_.empty()) {
|
|
|
|
|
- Log().ErrorFile(GenT::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(GenT::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(GenT::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(GenT::RCC, SettingsFile_, "");
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- SettingsChanged_ = true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void cmQtAutoGeneratorRcc::SettingsFileWrite()
|
|
|
|
|
-{
|
|
|
|
|
- // Only write if any setting changed
|
|
|
|
|
- if (SettingsChanged_) {
|
|
|
|
|
- if (Log().Verbose()) {
|
|
|
|
|
- Log().Info(GenT::RCC, "Writing settings file " + Quoted(SettingsFile_));
|
|
|
|
|
- }
|
|
|
|
|
- // Write settings file
|
|
|
|
|
- std::string content = "rcc:";
|
|
|
|
|
- content += SettingsString_;
|
|
|
|
|
- content += '\n';
|
|
|
|
|
- if (!FileSys().FileWrite(GenT::RCC, SettingsFile_, content)) {
|
|
|
|
|
- Log().ErrorFile(GenT::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(GenT::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(GenT::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(GenT::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(GenT::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(GenT::RCC, QrcFile_, parseError);
|
|
|
|
|
- Error_ = true;
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- Log().ErrorFile(GenT::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(GenT::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(GenT::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(GenT::RCC, reason);
|
|
|
|
|
- }
|
|
|
|
|
- Generate_ = true;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- // Print error and break on demand
|
|
|
|
|
- if (!error.empty()) {
|
|
|
|
|
- Log().ErrorFile(GenT::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(GenT::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(GenT::RCC, reason);
|
|
|
|
|
- }
|
|
|
|
|
- // Touch build file
|
|
|
|
|
- FileSys().Touch(RccFileOutput_);
|
|
|
|
|
- BuildFileChanged_ = true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void cmQtAutoGeneratorRcc::GenerateParentDir()
|
|
|
|
|
-{
|
|
|
|
|
- // Make sure the parent directory exists
|
|
|
|
|
- if (!FileSys().MakeParentDirectory(GenT::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(GenT::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(GenT::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.emplace_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(GenT::RCC, "Generating RCC wrapper file " + RccFilePublic_);
|
|
|
|
|
- }
|
|
|
|
|
- if (!FileSys().FileWrite(GenT::RCC, RccFilePublic_, content)) {
|
|
|
|
|
- Log().ErrorFile(GenT::RCC, RccFilePublic_,
|
|
|
|
|
- "RCC wrapper file writing failed");
|
|
|
|
|
- Error_ = true;
|
|
|
|
|
- }
|
|
|
|
|
- } else if (BuildFileChanged_) {
|
|
|
|
|
- // Just touch the wrapper file
|
|
|
|
|
- if (Log().Verbose()) {
|
|
|
|
|
- Log().Info(GenT::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(GenT::RCC, msg);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Create process handler
|
|
|
|
|
- Process_ = cm::make_unique<ReadOnlyProcessT>();
|
|
|
|
|
- Process_->setup(&ProcessResult_, mergedOutput, command, workingDirectory);
|
|
|
|
|
- // Start process
|
|
|
|
|
- if (!Process_->start(UVLoop(), [this] { UVRequest().send(); })) {
|
|
|
|
|
- Log().ErrorFile(GenT::RCC, QrcFile_, ProcessResult_.ErrorMessage);
|
|
|
|
|
- Error_ = true;
|
|
|
|
|
- // Clean up
|
|
|
|
|
- Process_.reset();
|
|
|
|
|
- ProcessResult_.reset();
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|