|
|
@@ -166,6 +166,112 @@ static std::string getAutogenTargetDir(cmTarget const* target)
|
|
|
return targetDir;
|
|
|
}
|
|
|
|
|
|
+std::string cmQtAutoGenerators::ListQt5RccInputs(cmSourceFile* sf,
|
|
|
+ cmTarget const* target,
|
|
|
+ std::vector<std::string>& depends)
|
|
|
+{
|
|
|
+ std::string rccCommand = this->GetRccExecutable(target);
|
|
|
+ std::vector<std::string> qrcEntries;
|
|
|
+
|
|
|
+ std::vector<std::string> command;
|
|
|
+ command.push_back(rccCommand);
|
|
|
+ command.push_back("--list");
|
|
|
+
|
|
|
+ std::string absFile = cmsys::SystemTools::GetRealPath(
|
|
|
+ sf->GetFullPath().c_str());
|
|
|
+
|
|
|
+ command.push_back(absFile);
|
|
|
+
|
|
|
+ std::string output;
|
|
|
+ int retVal = 0;
|
|
|
+ bool result = cmSystemTools::RunSingleCommand(command, &output,
|
|
|
+ &retVal, 0,
|
|
|
+ cmSystemTools::OUTPUT_NONE);
|
|
|
+ if (!result || retVal)
|
|
|
+ {
|
|
|
+ std::cerr << "AUTOGEN: error: Rcc list process for " << sf->GetFullPath()
|
|
|
+ << " failed:\n" << output << std::endl;
|
|
|
+ return std::string();
|
|
|
+ }
|
|
|
+
|
|
|
+ std::istringstream ostr(output);
|
|
|
+ std::string oline;
|
|
|
+ while(std::getline(ostr, oline))
|
|
|
+ {
|
|
|
+ if (oline.empty())
|
|
|
+ {
|
|
|
+ // The output of rcc --list contains many empty lines.
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (cmHasLiteralPrefix(oline, "RCC: Error in"))
|
|
|
+ {
|
|
|
+ static std::string searchString = "Cannot find file '";
|
|
|
+
|
|
|
+ std::string::size_type pos = oline.find(searchString);
|
|
|
+ if (pos == std::string::npos)
|
|
|
+ {
|
|
|
+ std::cerr << "AUTOGEN: error: Rcc lists unparsable output "
|
|
|
+ << oline << std::endl;
|
|
|
+ return std::string();
|
|
|
+ }
|
|
|
+ pos += searchString.length();
|
|
|
+ std::string::size_type sz = oline.size() - pos - 1;
|
|
|
+ qrcEntries.push_back(oline.substr(pos, sz));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ qrcEntries.push_back(oline);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ depends.insert(depends.end(), qrcEntries.begin(), qrcEntries.end());
|
|
|
+ std::string entriesList;
|
|
|
+ const char* sep = "";
|
|
|
+ for(std::vector<std::string>::const_iterator it = qrcEntries.begin();
|
|
|
+ it != qrcEntries.end(); ++it)
|
|
|
+ {
|
|
|
+ entriesList += sep;
|
|
|
+ entriesList += *it;
|
|
|
+ sep = "@list_sep@";
|
|
|
+ }
|
|
|
+ return entriesList;
|
|
|
+}
|
|
|
+
|
|
|
+std::string cmQtAutoGenerators::ListQt4RccInputs(cmSourceFile* sf,
|
|
|
+ std::vector<std::string>& depends)
|
|
|
+{
|
|
|
+ const std::string qrcContents = ReadAll(sf->GetFullPath());
|
|
|
+
|
|
|
+ cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
|
|
|
+
|
|
|
+ std::string entriesList;
|
|
|
+ const char* sep = "";
|
|
|
+
|
|
|
+ size_t offset = 0;
|
|
|
+ while (fileMatchRegex.find(qrcContents.c_str() + offset))
|
|
|
+ {
|
|
|
+ std::string qrcEntry = fileMatchRegex.match(1);
|
|
|
+
|
|
|
+ offset += qrcEntry.size();
|
|
|
+
|
|
|
+ cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
|
|
|
+ fileReplaceRegex.find(qrcEntry);
|
|
|
+ std::string tag = fileReplaceRegex.match(1);
|
|
|
+
|
|
|
+ qrcEntry = qrcEntry.substr(tag.size());
|
|
|
+
|
|
|
+ if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str()))
|
|
|
+ {
|
|
|
+ qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry;
|
|
|
+ }
|
|
|
+
|
|
|
+ entriesList += sep;
|
|
|
+ entriesList += qrcEntry;
|
|
|
+ sep = "@list_sep@";
|
|
|
+ depends.push_back(qrcEntry);
|
|
|
+ }
|
|
|
+ return entriesList;
|
|
|
+}
|
|
|
+
|
|
|
bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target)
|
|
|
{
|
|
|
cmMakefile* makefile = target->GetMakefile();
|
|
|
@@ -271,6 +377,61 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+#endif
|
|
|
+
|
|
|
+ std::vector<std::string> rcc_output;
|
|
|
+ if(makefile->GetLocalGenerator()->GetGlobalGenerator()->GetName() == "Ninja"
|
|
|
+#if defined(_WIN32) && !defined(__CYGWIN__)
|
|
|
+ || usePRE_BUILD
|
|
|
+#endif
|
|
|
+ )
|
|
|
+ {
|
|
|
+ std::vector<cmSourceFile*> srcFiles;
|
|
|
+ target->GetConfigCommonSourceFiles(srcFiles);
|
|
|
+ for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
|
|
|
+ fileIt != srcFiles.end();
|
|
|
+ ++fileIt)
|
|
|
+ {
|
|
|
+ cmSourceFile* sf = *fileIt;
|
|
|
+ std::string absFile = cmsys::SystemTools::GetRealPath(
|
|
|
+ sf->GetFullPath().c_str());
|
|
|
+
|
|
|
+ std::string ext = sf->GetExtension();
|
|
|
+
|
|
|
+ if (target->GetPropertyAsBool("AUTORCC"))
|
|
|
+ {
|
|
|
+ if (ext == "qrc"
|
|
|
+ && !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")))
|
|
|
+ {
|
|
|
+ std::string basename = cmsys::SystemTools::
|
|
|
+ GetFilenameWithoutLastExtension(absFile);
|
|
|
+
|
|
|
+ std::string rcc_output_dir = target->GetSupportDirectory();
|
|
|
+ cmSystemTools::MakeDirectory(rcc_output_dir.c_str());
|
|
|
+ std::string rcc_output_file = rcc_output_dir;
|
|
|
+ rcc_output_file += "/qrc_" + basename + ".cpp";
|
|
|
+ rcc_output.push_back(rcc_output_file);
|
|
|
+
|
|
|
+ if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED")))
|
|
|
+ {
|
|
|
+ if (qtMajorVersion == "5")
|
|
|
+ {
|
|
|
+ this->ListQt5RccInputs(sf, target, depends);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ this->ListQt4RccInputs(sf, depends);
|
|
|
+ }
|
|
|
+#if defined(_WIN32) && !defined(__CYGWIN__)
|
|
|
+ usePRE_BUILD = false;
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+#if defined(_WIN32) && !defined(__CYGWIN__)
|
|
|
if(usePRE_BUILD)
|
|
|
{
|
|
|
// Add the pre-build command directly to bypass the OBJECT_LIBRARY
|
|
|
@@ -287,10 +448,29 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target)
|
|
|
else
|
|
|
#endif
|
|
|
{
|
|
|
- cmTarget* autogenTarget = makefile->AddUtilityCommand(
|
|
|
+ cmTarget* autogenTarget = 0;
|
|
|
+ if (!rcc_output.empty())
|
|
|
+ {
|
|
|
+ makefile->AddCustomCommandToOutput(rcc_output, depends, "",
|
|
|
+ commandLines, 0,
|
|
|
+ workingDirectory.c_str(),
|
|
|
+ false, false);
|
|
|
+
|
|
|
+ cmCustomCommandLines no_commands;
|
|
|
+ autogenTarget = makefile->AddUtilityCommand(
|
|
|
+ autogenTargetName, true,
|
|
|
+ workingDirectory.c_str(), rcc_output,
|
|
|
+ no_commands, false, autogenComment.c_str());
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ autogenTarget = makefile->AddUtilityCommand(
|
|
|
autogenTargetName, true,
|
|
|
workingDirectory.c_str(), depends,
|
|
|
commandLines, false, autogenComment.c_str());
|
|
|
+ }
|
|
|
+
|
|
|
// Set target folder
|
|
|
const char* autogenFolder = makefile->GetCMakeInstance()->GetProperty(
|
|
|
"AUTOMOC_TARGETS_FOLDER");
|
|
|
@@ -418,6 +598,8 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target)
|
|
|
inputFile += "/Modules/AutogenInfo.cmake.in";
|
|
|
std::string outputFile = targetDir;
|
|
|
outputFile += "/AutogenInfo.cmake";
|
|
|
+ makefile->AddDefinition("_qt_rcc_inputs",
|
|
|
+ makefile->GetDefinition("_qt_rcc_inputs_" + target->GetName()));
|
|
|
makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(),
|
|
|
false, true, false);
|
|
|
|
|
|
@@ -869,9 +1051,12 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target)
|
|
|
std::vector<cmSourceFile*> srcFiles;
|
|
|
target->GetConfigCommonSourceFiles(srcFiles);
|
|
|
|
|
|
+ std::string qrcInputs;
|
|
|
+ const char* qrcInputsSep = "";
|
|
|
+
|
|
|
std::string rccFileFiles;
|
|
|
std::string rccFileOptions;
|
|
|
- const char *sep = "";
|
|
|
+ const char *optionSep = "";
|
|
|
|
|
|
const char *qtVersion = makefile->GetDefinition("_target_qt_version");
|
|
|
|
|
|
@@ -880,6 +1065,11 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target)
|
|
|
{
|
|
|
cmSystemTools::ExpandListArgument(opts, rccOptions);
|
|
|
}
|
|
|
+ std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
|
|
|
+ if (qtMajorVersion == "")
|
|
|
+ {
|
|
|
+ qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
|
|
|
+ }
|
|
|
|
|
|
for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
|
|
|
fileIt != srcFiles.end();
|
|
|
@@ -909,9 +1099,9 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target)
|
|
|
|
|
|
if (!rccOptions.empty())
|
|
|
{
|
|
|
- rccFileFiles += sep;
|
|
|
+ rccFileFiles += optionSep;
|
|
|
rccFileFiles += absFile;
|
|
|
- rccFileOptions += sep;
|
|
|
+ rccFileOptions += optionSep;
|
|
|
}
|
|
|
const char *listSep = "";
|
|
|
for(std::vector<std::string>::const_iterator it = rccOptions.begin();
|
|
|
@@ -922,10 +1112,34 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target)
|
|
|
rccFileOptions += *it;
|
|
|
listSep = "@list_sep@";
|
|
|
}
|
|
|
- sep = ";";
|
|
|
+ optionSep = ";";
|
|
|
+
|
|
|
+ std::vector<std::string> depends;
|
|
|
+
|
|
|
+ std::string entriesList;
|
|
|
+ if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED")))
|
|
|
+ {
|
|
|
+ if (qtMajorVersion == "5")
|
|
|
+ {
|
|
|
+ entriesList = this->ListQt5RccInputs(sf, target, depends);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ entriesList = this->ListQt4RccInputs(sf, depends);
|
|
|
+ }
|
|
|
+ if (entriesList.empty())
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ qrcInputs += qrcInputsSep;
|
|
|
+ qrcInputs += entriesList;
|
|
|
+ qrcInputsSep = ";";
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ makefile->AddDefinition("_qt_rcc_inputs_" + target->GetName(),
|
|
|
+ cmLocalGenerator::EscapeForCMake(qrcInputs).c_str());
|
|
|
|
|
|
makefile->AddDefinition("_rcc_files",
|
|
|
cmLocalGenerator::EscapeForCMake(_rcc_files).c_str());
|
|
|
@@ -1153,6 +1367,28 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(cmMakefile* makefile,
|
|
|
cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";");
|
|
|
this->RccOptions[*fileIt] = *optionIt;
|
|
|
}
|
|
|
+
|
|
|
+ const char *rccInputs = makefile->GetSafeDefinition("AM_RCC_INPUTS");
|
|
|
+ std::vector<std::string> rccInputLists;
|
|
|
+ cmSystemTools::ExpandListArgument(rccInputs, rccInputLists);
|
|
|
+
|
|
|
+ if (this->RccSources.size() != rccInputLists.size())
|
|
|
+ {
|
|
|
+ cmSystemTools::Error("Error processing file: ", filename.c_str());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (std::vector<std::string>::iterator fileIt = this->RccSources.begin(),
|
|
|
+ inputIt = rccInputLists.begin();
|
|
|
+ fileIt != this->RccSources.end();
|
|
|
+ ++fileIt, ++inputIt)
|
|
|
+ {
|
|
|
+ cmSystemTools::ReplaceString(*inputIt, "@list_sep@", ";");
|
|
|
+ std::vector<std::string> rccInputFiles;
|
|
|
+ cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles);
|
|
|
+
|
|
|
+ this->RccInputs[*fileIt] = rccInputFiles;
|
|
|
+ }
|
|
|
}
|
|
|
this->CurrentCompileSettingsStr = this->MakeCompileSettingsString(makefile);
|
|
|
|
|
|
@@ -2075,6 +2311,25 @@ bool cmQtAutoGenerators::GenerateUi(const std::string& realName,
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+bool cmQtAutoGenerators::InputFilesNewerThanQrc(const std::string& qrcFile,
|
|
|
+ const std::string& rccOutput)
|
|
|
+{
|
|
|
+ std::vector<std::string> const& files = this->RccInputs[qrcFile];
|
|
|
+ for (std::vector<std::string>::const_iterator it = files.begin();
|
|
|
+ it != files.end(); ++it)
|
|
|
+ {
|
|
|
+ int inputNewerThanQrc = 0;
|
|
|
+ bool success = cmsys::SystemTools::FileTimeCompare(it->c_str(),
|
|
|
+ rccOutput.c_str(),
|
|
|
+ &inputNewerThanQrc);
|
|
|
+ if (!success || inputNewerThanQrc >= 0)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
bool cmQtAutoGenerators::GenerateQrc()
|
|
|
{
|
|
|
for(std::vector<std::string>::const_iterator si = this->RccSources.begin();
|
|
|
@@ -2097,10 +2352,14 @@ bool cmQtAutoGenerators::GenerateQrc()
|
|
|
+ ".dir/qrc_" + basename + ".cpp";
|
|
|
|
|
|
int sourceNewerThanQrc = 0;
|
|
|
- bool success = cmsys::SystemTools::FileTimeCompare(*si,
|
|
|
- rcc_output_file,
|
|
|
+ bool generateQrc = !cmsys::SystemTools::FileTimeCompare(*si,
|
|
|
+ rcc_output_file.c_str(),
|
|
|
&sourceNewerThanQrc);
|
|
|
- if (this->GenerateAll || !success || sourceNewerThanQrc >= 0)
|
|
|
+ generateQrc = generateQrc || (sourceNewerThanQrc >= 0);
|
|
|
+ generateQrc = generateQrc || this->InputFilesNewerThanQrc(*si,
|
|
|
+ rcc_output_file);
|
|
|
+
|
|
|
+ if (this->GenerateAll || generateQrc)
|
|
|
{
|
|
|
std::map<std::string, std::string>::const_iterator optionIt
|
|
|
= this->RccOptions.find(*si);
|