Autogen: Detect rcc feature once during configuration

We used to detect the `rcc` features before every `rcc` list invocation
wich resulted in `rcc` be called twice for every listing operation.

Now we detect the `rcc` list capabilities once during configuration and
pass it to the cmake_autorcc target in the info file.
This commit is contained in:
Sebastian Holtermann 2017-11-19 12:22:49 +01:00
parent 2a85b5ac76
commit ab9d5896ae
7 changed files with 109 additions and 103 deletions

View File

@ -7,5 +7,5 @@ set(ARCC_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/")
set(ARCC_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/")
set(ARCC_BUILD_DIR @_build_dir@)
# Qt environment
set(ARCC_QT_VERSION_MAJOR @_qt_version_major@)
set(ARCC_QT_RCC_EXECUTABLE @_qt_rcc_executable@)
set(ARCC_RCC_EXECUTABLE @_qt_rcc_executable@)
set(ARCC_RCC_LIST_OPTIONS @_qt_rcc_list_options@)

View File

@ -80,16 +80,6 @@ void MergeOptions(std::vector<std::string>& baseOpts,
baseOpts.insert(baseOpts.end(), extraOpts.begin(), extraOpts.end());
}
static std::string utilStripCR(std::string const& line)
{
// Strip CR characters rcc may have printed (possibly more than one!).
std::string::size_type cr = line.find('\r');
if (cr != std::string::npos) {
return line.substr(0, cr);
}
return 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(std::string const& fileName,
@ -107,10 +97,10 @@ static bool RccListInputsQt4(std::string const& fileName,
qrcContents = osst.str();
} else {
if (errorMessage != nullptr) {
std::ostringstream ost;
ost << "rcc file not readable:\n"
<< " " << cmQtAutoGen::Quoted(fileName) << "\n";
*errorMessage = ost.str();
std::string& err = *errorMessage;
err = "rcc file not readable:\n ";
err += cmQtAutoGen::Quoted(fileName);
err += "\n";
}
allGood = false;
}
@ -146,6 +136,7 @@ static bool RccListInputsQt4(std::string const& fileName,
/// @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(std::string const& rccCommand,
std::vector<std::string> const& rccListOptions,
std::string const& fileName,
std::vector<std::string>& files,
std::string* errorMessage)
@ -155,24 +146,6 @@ static bool RccListInputsQt5(std::string const& rccCommand,
return false;
}
// Read rcc features
bool hasDashDashList = false;
{
std::vector<std::string> command;
command.push_back(rccCommand);
command.push_back("--help");
std::string rccStdOut;
std::string rccStdErr;
int retVal = 0;
bool result = cmSystemTools::RunSingleCommand(
command, &rccStdOut, &rccStdErr, &retVal, nullptr,
cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto);
if (result && retVal == 0 &&
rccStdOut.find("--list") != std::string::npos) {
hasDashDashList = true;
}
}
std::string const fileDir = cmSystemTools::GetFilenamePath(fileName);
std::string const fileNameName = cmSystemTools::GetFilenameName(fileName);
@ -184,7 +157,8 @@ static bool RccListInputsQt5(std::string const& rccCommand,
{
std::vector<std::string> command;
command.push_back(rccCommand);
command.push_back(hasDashDashList ? "--list" : "-list");
command.insert(command.end(), rccListOptions.begin(),
rccListOptions.end());
command.push_back(fileNameName);
result = cmSystemTools::RunSingleCommand(
command, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(),
@ -192,22 +166,32 @@ static bool RccListInputsQt5(std::string const& rccCommand,
}
if (!result || retVal) {
if (errorMessage != nullptr) {
std::ostringstream ost;
ost << "rcc list process failed for\n " << cmQtAutoGen::Quoted(fileName)
<< "\n"
<< rccStdOut << "\n"
<< rccStdErr << "\n";
*errorMessage = ost.str();
std::string& err = *errorMessage;
err = "rcc list process failed for:\n ";
err += cmQtAutoGen::Quoted(fileName);
err += "\n";
err += rccStdOut;
err += "\n";
err += rccStdErr;
err += "\n";
}
return false;
}
// Lambda to strip CR characters
auto StripCR = [](std::string& line) {
std::string::size_type cr = line.find('\r');
if (cr != std::string::npos) {
line = line.substr(0, cr);
}
};
// Parse rcc std output
{
std::istringstream ostr(rccStdOut);
std::string oline;
while (std::getline(ostr, oline)) {
oline = utilStripCR(oline);
StripCR(oline);
if (!oline.empty()) {
files.push_back(oline);
}
@ -218,17 +202,17 @@ static bool RccListInputsQt5(std::string const& rccCommand,
std::istringstream estr(rccStdErr);
std::string eline;
while (std::getline(estr, eline)) {
eline = utilStripCR(eline);
StripCR(eline);
if (cmHasLiteralPrefix(eline, "RCC: Error in")) {
static std::string searchString = "Cannot find file '";
std::string::size_type pos = eline.find(searchString);
if (pos == std::string::npos) {
if (errorMessage != nullptr) {
std::ostringstream ost;
ost << "rcc lists unparsable output:\n"
<< cmQtAutoGen::Quoted(eline) << "\n";
*errorMessage = ost.str();
std::string& err = *errorMessage;
err = "rcc lists unparsable output:\n";
err += cmQtAutoGen::Quoted(eline);
err += "\n";
}
return false;
}
@ -349,25 +333,26 @@ void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts,
MergeOptions(baseOpts, newOpts, valueOpts, isQt5);
}
bool cmQtAutoGen::RccListInputs(std::string const& qtMajorVersion,
std::string const& rccCommand,
bool cmQtAutoGen::RccListInputs(std::string const& rccCommand,
std::vector<std::string> const& rccListOptions,
std::string const& fileName,
std::vector<std::string>& files,
std::string* errorMessage)
{
bool allGood = false;
if (cmSystemTools::FileExists(fileName.c_str())) {
if (qtMajorVersion == "4") {
if (rccListOptions.empty()) {
allGood = RccListInputsQt4(fileName, files, errorMessage);
} else {
allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage);
allGood = RccListInputsQt5(rccCommand, rccListOptions, fileName, files,
errorMessage);
}
} else {
if (errorMessage != nullptr) {
std::ostringstream ost;
ost << "rcc file does not exist:\n"
<< " " << cmQtAutoGen::Quoted(fileName) << "\n";
*errorMessage = ost.str();
std::string& err = *errorMessage;
err = "rcc resource file does not exist:\n ";
err += cmQtAutoGen::Quoted(fileName);
err += "\n";
}
}
return allGood;

View File

@ -61,9 +61,9 @@ public:
/// @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(std::string const& qtMajorVersion,
std::string const& rccCommand,
/// @return True if the rcc file was successfully read
static bool RccListInputs(std::string const& rccCommand,
std::vector<std::string> const& rccListOptions,
std::string const& fileName,
std::vector<std::string>& files,
std::string* errorMessage = nullptr);

View File

@ -14,6 +14,7 @@
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmProcessOutput.h"
#include "cmSourceFile.h"
#include "cmSourceGroup.h"
#include "cmState.h"
@ -190,40 +191,6 @@ static bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin,
return cycle;
}
static std::string RccGetExecutable(cmGeneratorTarget const* target,
std::string const& qtMajorVersion)
{
std::string rccExec;
std::string err;
cmLocalGenerator* localGen = target->GetLocalGenerator();
if (qtMajorVersion == "5") {
cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::rcc");
if (tgt != nullptr) {
rccExec = SafeString(tgt->ImportedGetLocation(""));
} else {
err = "AUTORCC: Qt5::rcc target not found";
}
} else if (qtMajorVersion == "4") {
cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::rcc");
if (tgt != nullptr) {
rccExec = SafeString(tgt->ImportedGetLocation(""));
} else {
err = "AUTORCC: Qt4::rcc target not found";
}
} else {
err = "The AUTORCC feature supports only Qt 4 and Qt 5";
}
if (!err.empty()) {
err += " (";
err += target->GetName();
err += ")";
cmSystemTools::Error(err.c_str());
}
return rccExec;
}
cmQtAutoGeneratorInitializer::cmQtAutoGeneratorInitializer(
cmGeneratorTarget* target, bool mocEnabled, bool uicEnabled, bool rccEnabled,
std::string const& qtVersionMajor)
@ -368,6 +335,56 @@ void cmQtAutoGeneratorInitializer::InitCustomTargets()
this->Target->AddIncludeDirectory(includeDir, true);
}
// Acquire rcc executable and features
if (this->RccEnabled) {
{
std::string err;
if (this->QtVersionMajor == "5") {
cmGeneratorTarget* tgt =
localGen->FindGeneratorTargetToUse("Qt5::rcc");
if (tgt != nullptr) {
this->RccExecutable = SafeString(tgt->ImportedGetLocation(""));
} else {
err = "AUTORCC: Qt5::rcc target not found";
}
} else if (QtVersionMajor == "4") {
cmGeneratorTarget* tgt =
localGen->FindGeneratorTargetToUse("Qt4::rcc");
if (tgt != nullptr) {
this->RccExecutable = SafeString(tgt->ImportedGetLocation(""));
} else {
err = "AUTORCC: Qt4::rcc target not found";
}
} else {
err = "The AUTORCC feature supports only Qt 4 and Qt 5";
}
if (!err.empty()) {
err += " (";
err += this->Target->GetName();
err += ")";
cmSystemTools::Error(err.c_str());
}
}
// Detect if rcc supports (-)-list
if (!this->RccExecutable.empty() && (this->QtVersionMajor == "5")) {
std::vector<std::string> command;
command.push_back(this->RccExecutable);
command.push_back("--help");
std::string rccStdOut;
std::string rccStdErr;
int retVal = 0;
bool result = cmSystemTools::RunSingleCommand(
command, &rccStdOut, &rccStdErr, &retVal, nullptr,
cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto);
if (result && retVal == 0 &&
rccStdOut.find("--list") != std::string::npos) {
this->RccListOptions.push_back("--list");
} else {
this->RccListOptions.push_back("-list");
}
}
}
// Extract relevant source files
std::vector<std::string> generatedSources;
std::vector<std::string> generatedHeaders;
@ -548,8 +565,6 @@ void cmQtAutoGeneratorInitializer::InitCustomTargets()
// Process qrc files
if (!this->Qrcs.empty()) {
const bool QtV5 = (this->QtVersionMajor == "5");
std::string const rcc =
RccGetExecutable(this->Target, this->QtVersionMajor);
// Target rcc options
std::vector<std::string> optionsTarget;
cmSystemTools::ExpandListArgument(
@ -673,9 +688,9 @@ void cmQtAutoGeneratorInitializer::InitCustomTargets()
// Add the resource files to the dependencies
{
std::string error;
if (cmQtAutoGen::RccListInputs(this->QtVersionMajor, rcc,
qrc.QrcFile, qrc.Resources,
&error)) {
if (cmQtAutoGen::RccListInputs(this->RccExecutable,
this->RccListOptions, qrc.QrcFile,
qrc.Resources, &error)) {
for (std::string const& fileName : qrc.Resources) {
// Add resource file to the custom command dependencies
ccDepends.push_back(fileName);
@ -881,8 +896,9 @@ void cmQtAutoGeneratorInitializer::SetupCustomTargets()
}
}
if (this->RccEnabled) {
AddDefinitionEscaped(makefile, "_qt_rcc_executable",
RccGetExecutable(this->Target, this->QtVersionMajor));
AddDefinitionEscaped(makefile, "_qt_rcc_executable", this->RccExecutable);
AddDefinitionEscaped(makefile, "_qt_rcc_list_options",
this->RccListOptions);
}
// Create info directory on demand

View File

@ -65,8 +65,11 @@ private:
bool MocEnabled;
bool UicEnabled;
bool RccEnabled;
// Qt
std::string QtVersionMajor;
std::string QtVersionMinor;
std::string RccExecutable;
std::vector<std::string> RccListOptions;
// Configurations
std::string ConfigDefault;
std::vector<std::string> ConfigsList;

View File

@ -78,8 +78,8 @@ bool cmQtAutoGeneratorRcc::InfoFileRead(cmMakefile* makefile)
this->AutogenBuildDir = InfoGet("ARCC_BUILD_DIR");
// - Qt environment
this->QtMajorVersion = InfoGet("ARCC_QT_VERSION_MAJOR");
this->RccExecutable = InfoGet("ARCC_QT_RCC_EXECUTABLE");
this->RccExecutable = InfoGet("ARCC_RCC_EXECUTABLE");
this->RccListOptions = InfoGetList("ARCC_RCC_LIST_OPTIONS");
// - Job
this->QrcFile = InfoGet("ARCC_SOURCE");
@ -135,6 +135,8 @@ void cmQtAutoGeneratorRcc::SettingsFileRead(cmMakefile* makefile)
std::string str;
str += this->RccExecutable;
str += sep;
str += cmJoin(this->RccListOptions, ";");
str += sep;
str += this->QrcFile;
str += sep;
str += this->RccFile;
@ -307,7 +309,7 @@ bool cmQtAutoGeneratorRcc::RccGenerate()
} else {
// Read input file list from qrc file
std::string error;
if (cmQtAutoGen::RccListInputs(this->QtMajorVersion, this->RccExecutable,
if (cmQtAutoGen::RccListInputs(this->RccExecutable, this->RccListOptions,
this->QrcFile, readFiles, &error)) {
files = &readFiles;
} else {

View File

@ -44,8 +44,8 @@ private:
std::string AutogenBuildDir;
cmFilePathChecksum FilePathChecksum;
// -- Qt environment
std::string QtMajorVersion;
std::string RccExecutable;
std::vector<std::string> RccListOptions;
// -- Job
std::string QrcFile;
std::string RccFile;