diff options
author | Stephen Kelly <steveire@gmail.com> | 2013-09-15 14:41:07 +0200 |
---|---|---|
committer | Stephen Kelly <steveire@gmail.com> | 2013-10-24 12:30:41 +0200 |
commit | 9c87d9cc3e7a046f79ff62eda81203ef424e4a14 (patch) | |
tree | da7af3604feb5e81e122aaabbc8a84345ba90440 /Source/cmQtAutoGenerators.cxx | |
parent | 84218e1870ab075c9e2be1f2947358702c849fed (diff) | |
download | cmake-9c87d9cc3e7a046f79ff62eda81203ef424e4a14.tar.gz |
Add automatic rcc invocation for Qt.
This replaces the need to invoke qt4_add_resources by allowing
adding the source .qrc file directly to the target sources.
Diffstat (limited to 'Source/cmQtAutoGenerators.cxx')
-rw-r--r-- | Source/cmQtAutoGenerators.cxx | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 30211f22fc..5f7a26f68a 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -119,6 +119,7 @@ cmQtAutoGenerators::cmQtAutoGenerators() ,ColorOutput(true) ,RunMocFailed(false) ,RunUicFailed(false) +,RunRccFailed(false) ,GenerateAll(false) { @@ -266,9 +267,18 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget* target) { toolNames.push_back("uic"); } + if (target->GetPropertyAsBool("AUTORCC")) + { + toolNames.push_back("rcc"); + } std::string tools = toolNames[0]; toolNames.erase(toolNames.begin()); + while (toolNames.size() > 1) + { + tools += ", " + toolNames[0]; + toolNames.erase(toolNames.begin()); + } if (toolNames.size() == 1) { tools += " and " + toolNames[0]; @@ -343,6 +353,10 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget* target) { this->SetupAutoUicTarget(target); } + if (target->GetPropertyAsBool("AUTORCC")) + { + this->SetupAutoRccTarget(target); + } const char* cmakeRoot = makefile->GetSafeDefinition("CMAKE_ROOT"); std::string inputFile = cmakeRoot; @@ -670,6 +684,168 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget* target) } } +void cmQtAutoGenerators::MergeRccOptions(std::vector<std::string> &opts, + const std::vector<std::string> &fileOpts, + bool isQt5) +{ + static const char* valueOptions[] = { + "name", + "root", + "compress", + "threshold" + }; + std::vector<std::string> extraOpts; + for(std::vector<std::string>::const_iterator it = fileOpts.begin(); + it != fileOpts.end(); ++it) + { + std::vector<std::string>::iterator existingIt + = std::find(opts.begin(), opts.end(), *it); + if (existingIt != opts.end()) + { + const char *o = it->c_str(); + if (*o == '-') + { + ++o; + } + if (isQt5 && *o == '-') + { + ++o; + } + if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), + cmStrCmp(o)) != cmArrayEnd(valueOptions)) + { + assert(existingIt + 1 != opts.end()); + *(existingIt + 1) = *(it + 1); + ++it; + } + } + else + { + extraOpts.push_back(*it); + } + } + opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); +} + +void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget* target) +{ + std::string _rcc_files; + const char* sepRccFiles = ""; + cmMakefile *makefile = target->GetMakefile(); + + std::vector<cmSourceFile*> newFiles; + + const std::vector<cmSourceFile*>& srcFiles = target->GetSourceFiles(); + + std::string rccFileFiles; + std::string rccFileOptions; + const char *sep = ""; + + const char *qtVersion = makefile->GetDefinition("_target_qt_version"); + + std::vector<std::string> rccOptions; + if (const char* opts = target->GetProperty("AUTORCC_OPTIONS")) + { + cmSystemTools::ExpandListArgument(opts, rccOptions); + } + + for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin(); + fileIt != srcFiles.end(); + ++fileIt) + { + cmSourceFile* sf = *fileIt; + std::string ext = sf->GetExtension(); + if (ext == "qrc") + { + std::string absFile = cmsys::SystemTools::GetRealPath( + sf->GetFullPath().c_str()); + bool skip = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")); + + if (!skip) + { + _rcc_files += sepRccFiles; + _rcc_files += absFile; + sepRccFiles = ";"; + + std::string basename = cmsys::SystemTools:: + GetFilenameWithoutLastExtension(absFile); + + std::string rcc_output_file = makefile->GetCurrentOutputDirectory(); + rcc_output_file += "/qrc_" + basename + ".cpp"; + makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", + rcc_output_file.c_str(), false); + cmSourceFile* rccCppSource + = makefile->GetOrCreateSource(rcc_output_file.c_str(), true); + newFiles.push_back(rccCppSource); + + if (const char *prop = sf->GetProperty("AUTORCC_OPTIONS")) + { + std::vector<std::string> optsVec; + cmSystemTools::ExpandListArgument(prop, optsVec); + this->MergeRccOptions(rccOptions, optsVec, + strcmp(qtVersion, "5") == 0); + } + + if (!rccOptions.empty()) + { + rccFileFiles += sep; + rccFileFiles += absFile; + rccFileOptions += sep; + } + const char *listSep = ""; + for(std::vector<std::string>::const_iterator it = rccOptions.begin(); + it != rccOptions.end(); + ++it) + { + rccFileOptions += listSep; + rccFileOptions += *it; + listSep = "@list_sep@"; + } + sep = ";"; + } + } + } + + for(std::vector<cmSourceFile*>::const_iterator fileIt = newFiles.begin(); + fileIt != newFiles.end(); + ++fileIt) + { + target->AddSourceFile(*fileIt); + } + + makefile->AddDefinition("_rcc_files", + cmLocalGenerator::EscapeForCMake(_rcc_files.c_str()).c_str()); + + makefile->AddDefinition("_qt_rcc_options_files", + cmLocalGenerator::EscapeForCMake(rccFileFiles.c_str()).c_str()); + makefile->AddDefinition("_qt_rcc_options_options", + cmLocalGenerator::EscapeForCMake(rccFileOptions.c_str()).c_str()); + + const char *qtRcc = makefile->GetSafeDefinition("QT_RCC_EXECUTABLE"); + makefile->AddDefinition("_qt_rcc_executable", qtRcc); + + const char* targetName = target->GetName(); + if (strcmp(qtVersion, "5") == 0) + { + cmTarget *qt5Rcc = makefile->FindTargetToUse("Qt5::rcc"); + if (!qt5Rcc) + { + cmSystemTools::Error("Qt5::rcc target not found ", + targetName); + return; + } + makefile->AddDefinition("_qt_rcc_executable", qt5Rcc->GetLocation(0)); + } + else + { + if (strcmp(qtVersion, "4") != 0) + { + cmSystemTools::Error("The CMAKE_AUTORCC feature supports only Qt 4 and " + "Qt 5 ", targetName); + } + } +} + bool cmQtAutoGenerators::Run(const char* targetDirectory, const char *config) { bool success = true; @@ -734,6 +910,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(cmMakefile* makefile, "AM_Qt5Core_VERSION_MAJOR"); } this->Sources = makefile->GetSafeDefinition("AM_SOURCES"); + this->RccSources = makefile->GetSafeDefinition("AM_RCC_SOURCES"); this->SkipMoc = makefile->GetSafeDefinition("AM_SKIP_MOC"); this->SkipUic = makefile->GetSafeDefinition("AM_SKIP_UIC"); this->Headers = makefile->GetSafeDefinition("AM_HEADERS"); @@ -743,6 +920,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(cmMakefile* makefile, this->Builddir = makefile->GetSafeDefinition("AM_CMAKE_CURRENT_BINARY_DIR"); this->MocExecutable = makefile->GetSafeDefinition("AM_QT_MOC_EXECUTABLE"); this->UicExecutable = makefile->GetSafeDefinition("AM_QT_UIC_EXECUTABLE"); + this->RccExecutable = makefile->GetSafeDefinition("AM_QT_RCC_EXECUTABLE"); std::string compileDefsPropOrig = "AM_MOC_COMPILE_DEFINITIONS"; std::string compileDefsProp = compileDefsPropOrig; if(config) @@ -793,6 +971,28 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(cmMakefile* makefile, this->UicOptions[*fileIt] = *optionIt; } } + { + const char *rccOptionsFiles + = makefile->GetSafeDefinition("AM_RCC_OPTIONS_FILES"); + const char *rccOptionsOptions + = makefile->GetSafeDefinition("AM_RCC_OPTIONS_OPTIONS"); + std::vector<std::string> rccFilesVec; + cmSystemTools::ExpandListArgument(rccOptionsFiles, rccFilesVec); + std::vector<std::string> rccOptionsVec; + cmSystemTools::ExpandListArgument(rccOptionsOptions, rccOptionsVec); + if (rccFilesVec.size() != rccOptionsVec.size()) + { + return false; + } + for (std::vector<std::string>::iterator fileIt = rccFilesVec.begin(), + optionIt = rccOptionsVec.begin(); + fileIt != rccFilesVec.end(); + ++fileIt, ++optionIt) + { + cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";"); + this->RccOptions[*fileIt] = *optionIt; + } + } this->CurrentCompileSettingsStr = this->MakeCompileSettingsString(makefile); this->RelaxedMode = makefile->IsOn("AM_RELAXED_MODE"); @@ -1044,6 +1244,11 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) this->GenerateUi(*it); } + if(!this->RccExecutable.empty()) + { + this->GenerateQrc(); + } + cmsys_ios::stringstream outStream; outStream << "/* This file is autogenerated, do not edit*/\n"; @@ -1081,6 +1286,11 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) std::cerr << "uic failed..."<< std::endl; return false; } + if (this->RunRccFailed) + { + std::cerr << "rcc failed..."<< std::endl; + return false; + } outStream.flush(); std::string automocSource = outStream.str(); if (!automocCppChanged) @@ -1677,6 +1887,79 @@ bool cmQtAutoGenerators::GenerateUi(const std::string& uiFileName) return false; } +bool cmQtAutoGenerators::GenerateQrc() +{ + std::vector<std::string> sourceFiles; + cmSystemTools::ExpandListArgument(this->RccSources, sourceFiles); + + for(std::vector<std::string>::const_iterator si = sourceFiles.begin(); + si != sourceFiles.end(); ++si) + { + std::string ext = cmsys::SystemTools::GetFilenameLastExtension(*si); + + if (ext != ".qrc") + { + continue; + } + std::vector<cmStdString> command; + command.push_back(this->RccExecutable); + + std::string basename = cmsys::SystemTools:: + GetFilenameWithoutLastExtension(*si); + + std::string rcc_output_file = this->Builddir + "qrc_" + basename + ".cpp"; + + int sourceNewerThanQrc = 0; + bool success = cmsys::SystemTools::FileTimeCompare(si->c_str(), + rcc_output_file.c_str(), + &sourceNewerThanQrc); + if (this->GenerateAll || !success || sourceNewerThanQrc >= 0) + { + std::string options; + std::map<std::string, std::string>::const_iterator optionIt + = this->RccOptions.find(*si); + if (optionIt != this->RccOptions.end()) + { + std::vector<std::string> opts; + cmSystemTools::ExpandListArgument(optionIt->second, opts); + for(std::vector<std::string>::const_iterator optIt = opts.begin(); + optIt != opts.end(); + ++optIt) + { + command.push_back(*optIt); + } + } + + command.push_back("-o"); + command.push_back(rcc_output_file); + command.push_back(*si); + + if (this->Verbose) + { + for(std::vector<cmStdString>::const_iterator cmdIt = command.begin(); + cmdIt != command.end(); + ++cmdIt) + { + std::cout << *cmdIt << " "; + } + std::cout << std::endl; + } + std::string output; + int retVal = 0; + bool result = cmSystemTools::RunSingleCommand(command, &output, &retVal); + if (!result || retVal) + { + std::cerr << "AUTORCC: error: process for " << rcc_output_file << + " failed:\n" << output << std::endl; + this->RunRccFailed = true; + cmSystemTools::RemoveFile(rcc_output_file.c_str()); + return false; + } + } + } + return true; +} + std::string cmQtAutoGenerators::Join(const std::vector<std::string>& lst, char separator) { |