mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-04 05:10:10 -05:00
Autogen: Add support for generated .qrc files
This commit is contained in:
@@ -24,47 +24,62 @@ static std::string utilStripCR(std::string const& line)
|
||||
/// @brief Reads the resource files list from from a .qrc file - Qt4 version
|
||||
/// @return True if the .qrc file was successfully parsed
|
||||
static bool RccListInputsQt4(const std::string& fileName,
|
||||
std::vector<std::string>& files)
|
||||
std::vector<std::string>& files,
|
||||
std::string* errorMessage)
|
||||
{
|
||||
// Qrc file directory
|
||||
std::string qrcDir(cmsys::SystemTools::GetFilenamePath(fileName));
|
||||
if (!qrcDir.empty()) {
|
||||
qrcDir += '/';
|
||||
}
|
||||
|
||||
// Read file into string
|
||||
bool allGood = true;
|
||||
// Read qrc file content into string
|
||||
std::string qrcContents;
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << cmsys::ifstream(fileName).rdbuf();
|
||||
qrcContents = stream.str();
|
||||
}
|
||||
|
||||
cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
|
||||
cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
|
||||
|
||||
size_t offset = 0;
|
||||
while (fileMatchRegex.find(qrcContents.c_str() + offset)) {
|
||||
std::string qrcEntry = fileMatchRegex.match(1);
|
||||
offset += qrcEntry.size();
|
||||
{
|
||||
fileReplaceRegex.find(qrcEntry);
|
||||
std::string tag = fileReplaceRegex.match(1);
|
||||
qrcEntry = qrcEntry.substr(tag.size());
|
||||
cmsys::ifstream ifs(fileName.c_str());
|
||||
if (ifs) {
|
||||
std::ostringstream osst;
|
||||
osst << ifs.rdbuf();
|
||||
qrcContents = osst.str();
|
||||
} else {
|
||||
if (errorMessage != CM_NULLPTR) {
|
||||
std::ostringstream ost;
|
||||
ost << "AutoRcc: Error: Rcc file not readable:\n"
|
||||
<< cmQtAutoGeneratorCommon::Quoted(fileName) << "\n";
|
||||
*errorMessage = ost.str();
|
||||
}
|
||||
allGood = false;
|
||||
}
|
||||
if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) {
|
||||
qrcEntry = qrcDir + qrcEntry;
|
||||
}
|
||||
files.push_back(qrcEntry);
|
||||
}
|
||||
return true;
|
||||
if (allGood) {
|
||||
// qrc file directory
|
||||
std::string qrcDir(cmsys::SystemTools::GetFilenamePath(fileName));
|
||||
if (!qrcDir.empty()) {
|
||||
qrcDir += '/';
|
||||
}
|
||||
|
||||
cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
|
||||
cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
|
||||
|
||||
size_t offset = 0;
|
||||
while (fileMatchRegex.find(qrcContents.c_str() + offset)) {
|
||||
std::string qrcEntry = fileMatchRegex.match(1);
|
||||
offset += qrcEntry.size();
|
||||
{
|
||||
fileReplaceRegex.find(qrcEntry);
|
||||
std::string tag = fileReplaceRegex.match(1);
|
||||
qrcEntry = qrcEntry.substr(tag.size());
|
||||
}
|
||||
if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) {
|
||||
qrcEntry = qrcDir + qrcEntry;
|
||||
}
|
||||
files.push_back(qrcEntry);
|
||||
}
|
||||
}
|
||||
return allGood;
|
||||
}
|
||||
|
||||
/// @brief Reads the resource files list from from a .qrc file - Qt5 version
|
||||
/// @return True if the .qrc file was successfully parsed
|
||||
static bool RccListInputsQt5(const std::string& rccCommand,
|
||||
const std::string& fileName,
|
||||
std::vector<std::string>& files)
|
||||
std::vector<std::string>& files,
|
||||
std::string* errorMessage)
|
||||
{
|
||||
if (rccCommand.empty()) {
|
||||
cmSystemTools::Error("AutoRcc: Error: rcc executable not available\n");
|
||||
@@ -104,11 +119,14 @@ static bool RccListInputsQt5(const std::string& rccCommand,
|
||||
CM_NULLPTR, cmSystemTools::OUTPUT_NONE);
|
||||
}
|
||||
if (!result || retVal) {
|
||||
std::ostringstream err;
|
||||
err << "AUTOGEN: error: Rcc list process for " << fileName << " failed:\n"
|
||||
<< rccStdOut << "\n"
|
||||
<< rccStdErr << std::endl;
|
||||
cmSystemTools::Error(err.str().c_str());
|
||||
if (errorMessage != CM_NULLPTR) {
|
||||
std::ostringstream ost;
|
||||
ost << "AutoRcc: Error: Rcc list process for " << fileName
|
||||
<< " failed:\n"
|
||||
<< rccStdOut << "\n"
|
||||
<< rccStdErr << "\n";
|
||||
*errorMessage = ost.str();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -134,10 +152,12 @@ static bool RccListInputsQt5(const std::string& rccCommand,
|
||||
|
||||
std::string::size_type pos = eline.find(searchString);
|
||||
if (pos == std::string::npos) {
|
||||
std::ostringstream err;
|
||||
err << "AUTOGEN: error: Rcc lists unparsable output " << eline
|
||||
<< std::endl;
|
||||
cmSystemTools::Error(err.str().c_str());
|
||||
if (errorMessage != CM_NULLPTR) {
|
||||
std::ostringstream ost;
|
||||
ost << "AutoRcc: Error: Rcc lists unparsable output:\n"
|
||||
<< cmQtAutoGeneratorCommon::Quoted(eline) << "\n";
|
||||
*errorMessage = ost.str();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
pos += searchString.length();
|
||||
@@ -154,13 +174,42 @@ static bool RccListInputsQt5(const std::string& rccCommand,
|
||||
|
||||
const char* cmQtAutoGeneratorCommon::listSep = "@LSEP@";
|
||||
|
||||
std::string cmQtAutoGeneratorCommon::Quoted(const std::string& text)
|
||||
{
|
||||
static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a",
|
||||
"\b", "\\b", "\f", "\\f", "\n", "\\n",
|
||||
"\r", "\\r", "\t", "\\t", "\v", "\\v" };
|
||||
|
||||
std::string res = text;
|
||||
for (const char* const* it = cmArrayBegin(rep); it != cmArrayEnd(rep);
|
||||
it += 2) {
|
||||
cmSystemTools::ReplaceString(res, *it, *(it + 1));
|
||||
}
|
||||
res = '"' + res;
|
||||
res += '"';
|
||||
return res;
|
||||
}
|
||||
|
||||
bool cmQtAutoGeneratorCommon::RccListInputs(const std::string& qtMajorVersion,
|
||||
const std::string& rccCommand,
|
||||
const std::string& fileName,
|
||||
std::vector<std::string>& files)
|
||||
std::vector<std::string>& files,
|
||||
std::string* errorMessage)
|
||||
{
|
||||
if (qtMajorVersion == "4") {
|
||||
return RccListInputsQt4(fileName, files);
|
||||
bool allGood = false;
|
||||
if (cmsys::SystemTools::FileExists(fileName.c_str())) {
|
||||
if (qtMajorVersion == "4") {
|
||||
allGood = RccListInputsQt4(fileName, files, errorMessage);
|
||||
} else {
|
||||
allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage);
|
||||
}
|
||||
} else {
|
||||
if (errorMessage != CM_NULLPTR) {
|
||||
std::ostringstream ost;
|
||||
ost << "AutoRcc: Error: Rcc file does not exist:\n"
|
||||
<< cmQtAutoGeneratorCommon::Quoted(fileName) << "\n";
|
||||
*errorMessage = ost.str();
|
||||
}
|
||||
}
|
||||
return RccListInputsQt5(rccCommand, fileName, files);
|
||||
return allGood;
|
||||
}
|
||||
|
||||
@@ -17,13 +17,18 @@ public:
|
||||
static const char* listSep;
|
||||
|
||||
public:
|
||||
/// @brief Returns a the string escaped and enclosed in quotes
|
||||
///
|
||||
static std::string Quoted(const std::string& text);
|
||||
|
||||
/// @brief Reads the resource files list from from a .qrc file
|
||||
/// @arg fileName Must be the absolute path of the .qrc file
|
||||
/// @return True if the rcc file was successfully parsed
|
||||
static bool RccListInputs(const std::string& qtMajorVersion,
|
||||
const std::string& rccCommand,
|
||||
const std::string& fileName,
|
||||
std::vector<std::string>& files);
|
||||
std::vector<std::string>& files,
|
||||
std::string* errorMessage = CM_NULLPTR);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -490,13 +490,15 @@ static void RccSetupAutoTarget(cmGeneratorTarget const* target,
|
||||
// qrc file entries
|
||||
{
|
||||
std::string entriesList = "{";
|
||||
// Read input file list only for non generated .qrc files.
|
||||
if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
|
||||
std::string error;
|
||||
std::vector<std::string> files;
|
||||
if (cmQtAutoGeneratorCommon::RccListInputs(
|
||||
qtMajorVersion, rccCommand, absFile, files)) {
|
||||
qtMajorVersion, rccCommand, absFile, files, &error)) {
|
||||
entriesList += cmJoin(files, cmQtAutoGeneratorCommon::listSep);
|
||||
} else {
|
||||
return;
|
||||
cmSystemTools::Error(error.c_str());
|
||||
}
|
||||
}
|
||||
entriesList += "}";
|
||||
@@ -690,8 +692,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
|
||||
#endif
|
||||
) {
|
||||
if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
|
||||
cmQtAutoGeneratorCommon::RccListInputs(
|
||||
qtMajorVersion, rccCommand, absFile, depends);
|
||||
{
|
||||
std::string error;
|
||||
if (!cmQtAutoGeneratorCommon::RccListInputs(
|
||||
qtMajorVersion, rccCommand, absFile, depends, &error)) {
|
||||
cmSystemTools::Error(error.c_str());
|
||||
}
|
||||
}
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
// Cannot use PRE_BUILD because the resource files themselves
|
||||
// may not be sources within the target so VS may not know the
|
||||
|
||||
@@ -37,23 +37,9 @@ static const char* SettingsKeyRcc = "AM_RCC_OLD_SETTINGS";
|
||||
|
||||
// -- Static functions
|
||||
|
||||
/**
|
||||
* @brief Returns a the string escaped and enclosed in quotes
|
||||
*/
|
||||
static std::string Quoted(const std::string& text)
|
||||
inline static std::string Quoted(const std::string& text)
|
||||
{
|
||||
static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a",
|
||||
"\b", "\\b", "\f", "\\f", "\n", "\\n",
|
||||
"\r", "\\r", "\t", "\\t", "\v", "\\v" };
|
||||
|
||||
std::string res = text;
|
||||
for (const char* const* it = cmArrayBegin(rep); it != cmArrayEnd(rep);
|
||||
it += 2) {
|
||||
cmSystemTools::ReplaceString(res, *it, *(it + 1));
|
||||
}
|
||||
res = '"' + res;
|
||||
res += '"';
|
||||
return res;
|
||||
return cmQtAutoGeneratorCommon::Quoted(text);
|
||||
}
|
||||
|
||||
static void InfoGet(cmMakefile* makefile, const char* key, std::string& value)
|
||||
@@ -403,7 +389,8 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
|
||||
} else {
|
||||
this->LogError(
|
||||
"AutoMoc: Error: AUTOMOC_DEPEND_FILTERS list size is not "
|
||||
"a multiple of 2");
|
||||
"a multiple of 2 in:\n" +
|
||||
Quoted(filename));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -431,8 +418,8 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
|
||||
}
|
||||
} else {
|
||||
this->LogError(
|
||||
"AutoGen: Error: Uic files/options lists size missmatch in: " +
|
||||
filename);
|
||||
"AutoGen: Error: Uic files/options lists size missmatch in:\n" +
|
||||
Quoted(filename));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -447,7 +434,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
|
||||
std::vector<std::string> rccOptionsVec;
|
||||
InfoGet(makefile, "AM_RCC_OPTIONS_FILES", rccFilesVec);
|
||||
InfoGet(makefile, "AM_RCC_OPTIONS_OPTIONS", rccOptionsVec);
|
||||
if (rccFilesVec.size() != rccOptionsVec.size()) {
|
||||
if (rccFilesVec.size() == rccOptionsVec.size()) {
|
||||
for (std::vector<std::string>::iterator
|
||||
fileIt = rccFilesVec.begin(),
|
||||
optionIt = rccOptionsVec.begin();
|
||||
@@ -459,8 +446,8 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
|
||||
}
|
||||
} else {
|
||||
this->LogError(
|
||||
"AutoGen: Error: RCC files/options lists size missmatch in: " +
|
||||
filename);
|
||||
"AutoGen: Error: RCC files/options lists size missmatch in:\n" +
|
||||
Quoted(filename));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -484,8 +471,8 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
|
||||
}
|
||||
} else {
|
||||
this->LogError(
|
||||
"AutoGen: Error: RCC sources/inputs lists size missmatch in: " +
|
||||
filename);
|
||||
"AutoGen: Error: RCC sources/inputs lists size missmatch in:\n" +
|
||||
Quoted(filename));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1574,13 +1561,30 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
|
||||
// Test if the resources list file is newer than build file
|
||||
generateRcc = FileAbsentOrOlder(rccBuildFile, rccInputFile);
|
||||
if (!generateRcc) {
|
||||
// Test if any resource file is newer than the build file
|
||||
const std::vector<std::string>& files = this->RccInputs[rccInputFile];
|
||||
for (std::vector<std::string>::const_iterator it = files.begin();
|
||||
it != files.end(); ++it) {
|
||||
if (FileAbsentOrOlder(rccBuildFile, *it)) {
|
||||
generateRcc = true;
|
||||
break;
|
||||
// Acquire input file list
|
||||
std::vector<std::string> readFiles;
|
||||
const std::vector<std::string>* files = &this->RccInputs[rccInputFile];
|
||||
if (files->empty()) {
|
||||
// Read input file list from qrc file
|
||||
std::string error;
|
||||
if (cmQtAutoGeneratorCommon::RccListInputs(
|
||||
this->QtMajorVersion, this->RccExecutable, rccInputFile,
|
||||
readFiles, &error)) {
|
||||
files = &readFiles;
|
||||
} else {
|
||||
files = CM_NULLPTR;
|
||||
this->LogError(error);
|
||||
this->RunRccFailed = true;
|
||||
}
|
||||
}
|
||||
// Test if any input file is newer than the build file
|
||||
if (files != CM_NULLPTR) {
|
||||
for (std::vector<std::string>::const_iterator it = files->begin();
|
||||
it != files->end(); ++it) {
|
||||
if (FileAbsentOrOlder(rccBuildFile, *it)) {
|
||||
generateRcc = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user