Commit 37ef18a4 authored by Sebastian Holtermann's avatar Sebastian Holtermann
Browse files

Autogen: Pass RCC build names and function names in info file

- The output file name of the `rcc` command get computed once
  in the AUTOGEN initializer and is passed in the info file.

- The function name for the `-name` option of `rcc` gets computed
  once in the AUTOGEN initializer and is passed along with the
  other `rcc` options in the info file.
parent 761b3d79
......@@ -30,6 +30,6 @@ set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@)
set(AM_UIC_SEARCH_PATHS @_uic_search_paths@)
# RCC settings
set(AM_RCC_SOURCES @_rcc_files@)
set(AM_RCC_BUILDS @_rcc_builds@)
set(AM_RCC_OPTIONS @_rcc_options@)
set(AM_RCC_INPUTS @_rcc_inputs@)
set(AM_RCC_OPTIONS_FILES @_rcc_options_files@)
set(AM_RCC_OPTIONS_OPTIONS @_rcc_options_options@)
......@@ -16,13 +16,17 @@ class cmQtAutoGenDigestQrc
public:
cmQtAutoGenDigestQrc()
: Generated(false)
, Unique(false)
{
}
public:
std::string QrcFile;
std::string QrcName;
std::string PathChecksum;
std::string RccFile;
bool Generated;
bool Unique;
std::vector<std::string> Options;
std::vector<std::string> Resources;
};
......
......@@ -580,40 +580,25 @@ static std::string RccGetExecutable(cmGeneratorTarget const* target,
static void SetupAutoTargetRcc(const cmQtAutoGenDigest& digest)
{
cmGeneratorTarget const* target = digest.Target;
cmMakefile* makefile = target->Target->GetMakefile();
std::vector<std::string> rccFiles;
std::vector<std::string> rccInputs;
std::vector<std::string> rccFileFiles;
std::vector<std::string> rccFileOptions;
std::vector<std::string> rccBuilds;
std::vector<std::vector<std::string>> rccOptions;
std::vector<std::vector<std::string>> rccInputs;
for (const cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
const std::string absFile = qrcDigest.QrcFile;
// Register file
rccFiles.push_back(absFile);
// Register (known) resource files
{
std::string entriesList = "{";
if (!qrcDigest.Generated) {
entriesList += cmJoin(qrcDigest.Resources, cmQtAutoGen::listSep);
}
entriesList += "}";
rccInputs.push_back(entriesList);
}
// rcc options for this qrc file
if (!qrcDigest.Options.empty()) {
rccFileFiles.push_back(absFile);
rccFileOptions.push_back(
cmJoin(qrcDigest.Options, cmQtAutoGen::listSep));
}
rccFiles.push_back(qrcDigest.QrcFile);
rccBuilds.push_back(qrcDigest.RccFile);
rccOptions.push_back(qrcDigest.Options);
rccInputs.push_back(qrcDigest.Resources);
}
cmMakefile* makefile = digest.Target->Target->GetMakefile();
AddDefinitionEscaped(makefile, "_qt_rcc_executable",
RccGetExecutable(target, digest.QtVersionMajor));
RccGetExecutable(digest.Target, digest.QtVersionMajor));
AddDefinitionEscaped(makefile, "_rcc_files", rccFiles);
AddDefinitionEscaped(makefile, "_rcc_builds", rccBuilds);
AddDefinitionEscaped(makefile, "_rcc_options", rccOptions);
AddDefinitionEscaped(makefile, "_rcc_inputs", rccInputs);
AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles);
AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions);
}
void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
......@@ -746,6 +731,8 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
{
cmQtAutoGenDigestQrc qrcDigest;
qrcDigest.QrcFile = cmSystemTools::GetRealPath(fPath);
qrcDigest.QrcName =
cmSystemTools::GetFilenameWithoutLastExtension(qrcDigest.QrcFile);
qrcDigest.Generated = sf->GetPropertyAsBool("GENERATED");
// RCC options
{
......@@ -822,36 +809,65 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
// Process qrc files
if (!digest.Qrcs.empty()) {
const bool QtV5 = (digest.QtVersionMajor == "5");
const cmFilePathChecksum fpathCheckSum(makefile);
const std::string rcc = RccGetExecutable(target, digest.QtVersionMajor);
// Target rcc options
std::vector<std::string> optionsTarget;
cmSystemTools::ExpandListArgument(
GetSafeProperty(target, "AUTORCC_OPTIONS"), optionsTarget);
// Check if file name is unique
for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
// RCC output file name
{
std::string rccFile = autogenBuildDir + "/";
rccFile += fpathCheckSum.getPart(qrcDigest.QrcFile);
rccFile += "/qrc_";
rccFile +=
cmSystemTools::GetFilenameWithoutLastExtension(qrcDigest.QrcFile);
rccFile += ".cpp";
AddGeneratedSource(target, rccFile, cmQtAutoGen::RCC);
autogenProvides.push_back(rccFile);
qrcDigest.RccFile = std::move(rccFile);
qrcDigest.Unique = true;
for (const cmQtAutoGenDigestQrc& qrcDig2 : digest.Qrcs) {
if ((&qrcDigest != &qrcDig2) &&
(qrcDigest.QrcName == qrcDig2.QrcName)) {
qrcDigest.Unique = false;
break;
}
}
// RCC options
}
// Path checksum
{
const cmFilePathChecksum fpathCheckSum(makefile);
for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
qrcDigest.PathChecksum = fpathCheckSum.getPart(qrcDigest.QrcFile);
}
}
// RCC output file name
for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
std::string rccFile = autogenBuildDir + "/";
rccFile += qrcDigest.PathChecksum;
rccFile += "/qrc_";
rccFile += qrcDigest.QrcName;
rccFile += ".cpp";
qrcDigest.RccFile = std::move(rccFile);
}
// RCC options
for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
// Target options
std::vector<std::string> opts = optionsTarget;
// Merge computed "-name XYZ" option
{
std::vector<std::string> opts = optionsTarget;
if (!qrcDigest.Options.empty()) {
cmQtAutoGen::RccMergeOptions(opts, qrcDigest.Options, QtV5);
std::string name = qrcDigest.QrcName;
// Replace '-' with '_'. The former is not valid for symbol names.
std::replace(name.begin(), name.end(), '-', '_');
if (!qrcDigest.Unique) {
name += "_";
name += qrcDigest.PathChecksum;
}
qrcDigest.Options = std::move(opts);
std::vector<std::string> nameOpts;
nameOpts.emplace_back("-name");
nameOpts.emplace_back(std::move(name));
cmQtAutoGen::RccMergeOptions(opts, nameOpts, QtV5);
}
// GENERATED or not
// Merge file option
cmQtAutoGen::RccMergeOptions(opts, qrcDigest.Options, QtV5);
qrcDigest.Options = std::move(opts);
}
for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
// Register file at target
AddGeneratedSource(target, qrcDigest.RccFile, cmQtAutoGen::RCC);
autogenProvides.push_back(qrcDigest.RccFile);
if (qrcDigest.Generated) {
// Add GENERATED qrc file to the dependencies
autogenDepends.insert(qrcDigest.QrcFile);
......
......@@ -166,22 +166,6 @@ static std::string SubDirPrefix(const std::string& fileName)
return res;
}
static bool FileNameIsUnique(const std::string& filePath,
const std::map<std::string, std::string>& fileMap)
{
size_t count(0);
const std::string fileName = cmSystemTools::GetFilenameName(filePath);
for (const auto& item : fileMap) {
if (cmSystemTools::GetFilenameName(item.first) == fileName) {
++count;
if (count > 1) {
return false;
}
}
}
return true;
}
static bool ReadAll(std::string& content, const std::string& filename)
{
bool success = false;
......@@ -473,51 +457,51 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
// - Rcc
if (this->RccEnabled()) {
InfoGet(makefile, "AM_RCC_SOURCES", this->RccSources);
// File options
{
std::vector<std::string> rccFilesVec;
std::vector<std::string> rccOptionsVec;
InfoGet(makefile, "AM_RCC_OPTIONS_FILES", rccFilesVec);
InfoGet(makefile, "AM_RCC_OPTIONS_OPTIONS", rccOptionsVec);
if (rccFilesVec.size() == rccOptionsVec.size()) {
for (std::vector<std::string>::iterator
fileIt = rccFilesVec.begin(),
optionIt = rccOptionsVec.begin();
fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) {
// Replace item separator
cmSystemTools::ReplaceString(*optionIt, cmQtAutoGen::listSep, ";");
this->RccOptions[*fileIt] = *optionIt;
}
} else {
this->LogError(
"AutoGen: Error: RCC files/options lists size missmatch in:\n" +
Quoted(filename));
return false;
}
}
// File lists
auto sources = InfoGetList(makefile, "AM_RCC_SOURCES");
auto builds = InfoGetList(makefile, "AM_RCC_BUILDS");
auto options = InfoGetLists(makefile, "AM_RCC_OPTIONS");
auto inputs = InfoGetLists(makefile, "AM_RCC_INPUTS");
if (sources.size() != builds.size()) {
std::ostringstream ost;
ost << "AutoRcc: Error: sources/builds list sizes missmatch ("
<< sources.size() << "/" << builds.size() << ")"
<< " in\n " << Quoted(filename);
this->LogError(ost.str());
return false;
}
if (sources.size() != options.size()) {
std::ostringstream ost;
ost << "AutoRcc: Error: sources/options list sizes missmatch ("
<< sources.size() << "/" << options.size() << ")"
<< " in\n " << Quoted(filename);
this->LogError(ost.str());
return false;
}
if (sources.size() != inputs.size()) {
std::ostringstream ost;
ost << "AutoRcc: Error: sources/inputs list sizes missmatch ("
<< sources.size() << "/" << inputs.size() << ")"
<< " in\n " << Quoted(filename);
this->LogError(ost.str());
return false;
}
{
std::vector<std::string> rccInputLists;
InfoGet(makefile, "AM_RCC_INPUTS", rccInputLists);
if (this->RccSources.size() == rccInputLists.size()) {
for (std::vector<std::string>::iterator
fileIt = this->RccSources.begin(),
inputIt = rccInputLists.begin();
fileIt != this->RccSources.end(); ++fileIt, ++inputIt) {
// Remove braces
*inputIt = inputIt->substr(1, inputIt->size() - 2);
// Replace item separator
cmSystemTools::ReplaceString(*inputIt, cmQtAutoGen::listSep, ";");
std::vector<std::string> rccInputFiles;
cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles);
this->RccInputs[*fileIt] = rccInputFiles;
}
} else {
this->LogError(
"AutoGen: Error: RCC sources/inputs lists size missmatch in:\n" +
Quoted(filename));
return false;
auto srcItEnd = sources.end();
auto srcIt = sources.begin();
auto bldIt = builds.begin();
auto optIt = options.begin();
auto inpIt = inputs.begin();
while (srcIt != srcItEnd) {
this->RccJobs.push_back(RccJob{ std::move(*srcIt), std::move(*bldIt),
std::move(*optIt),
std::move(*inpIt) });
++srcIt;
++bldIt;
++optIt;
++inpIt;
}
}
}
......@@ -560,8 +544,14 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
if (this->RccEnabled()) {
std::string str;
str += this->RccExecutable;
str += sep;
str += JoinOptionsMap(this->RccOptions);
for (const RccJob& rccJob : this->RccJobs) {
str += sep;
str += rccJob.QrcFile;
str += sep;
str += rccJob.RccFile;
str += sep;
str += JoinOptionsList(rccJob.Options);
}
str += sep;
this->SettingsStringRcc = crypt.HashString(str);
}
......@@ -1622,33 +1612,9 @@ bool cmQtAutoGenerators::RccGenerateAll()
return true;
}
// generate single map with input / output names
std::map<std::string, std::string> qrcGenMap;
{
const std::string qrcPrefix = "qrc_";
const std::string qrcSuffix = this->ConfigSuffix + ".cpp";
for (const std::string& src : this->RccSources) {
qrcGenMap[src] = this->ChecksumedPath(src, qrcPrefix, qrcSuffix);
}
}
// look for name collisions
{
std::multimap<std::string, std::string> collisions;
if (this->NameCollisionTest(qrcGenMap, collisions)) {
std::ostringstream ost;
ost << "AutoRcc: Error: The same qrc_NAME.cpp file"
" will be generated from different sources.\n"
"To avoid this error rename the source .qrc files.\n";
this->LogErrorNameCollision(ost.str(), collisions);
return false;
}
}
// generate qrc files
for (const auto& item : qrcGenMap) {
bool unique = FileNameIsUnique(item.first, qrcGenMap);
if (!this->RccGenerateFile(item.first, item.second, unique)) {
// Generate qrc files
for (const RccJob& rccJob : this->RccJobs) {
if (!this->RccGenerateFile(rccJob)) {
if (this->RccRunFailed) {
return false;
}
......@@ -1660,28 +1626,37 @@ bool cmQtAutoGenerators::RccGenerateAll()
/**
* @return True if a rcc file was created. False may indicate an error.
*/
bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
const std::string& rccOutputFile,
bool unique_n)
bool cmQtAutoGenerators::RccGenerateFile(const RccJob& rccJob)
{
bool rccGenerated = false;
bool generateRcc = this->RccSettingsChanged;
const std::string rccBuildFile =
cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, rccOutputFile);
std::string rccFileAbs;
if (this->ConfigSuffix.empty()) {
rccFileAbs = rccJob.RccFile;
} else {
rccFileAbs = SubDirPrefix(rccJob.RccFile);
rccFileAbs +=
cmSystemTools::GetFilenameWithoutLastExtension(rccJob.RccFile);
rccFileAbs += this->ConfigSuffix;
rccFileAbs += cmSystemTools::GetFilenameLastExtension(rccJob.RccFile);
}
const std::string rccFileRel = cmSystemTools::RelativePath(
this->AutogenBuildDir.c_str(), rccFileAbs.c_str());
// Check if regeneration is required
if (!generateRcc) {
// Test if the resources list file is newer than build file
generateRcc = FileAbsentOrOlder(rccBuildFile, rccInputFile);
generateRcc = FileAbsentOrOlder(rccFileAbs, rccJob.QrcFile);
if (!generateRcc) {
// Acquire input file list
std::vector<std::string> readFiles;
const std::vector<std::string>* files = &this->RccInputs[rccInputFile];
const std::vector<std::string>* files = &rccJob.Inputs;
if (files->empty()) {
// Read input file list from qrc file
std::string error;
if (cmQtAutoGen::RccListInputs(this->QtMajorVersion,
this->RccExecutable, rccInputFile,
this->RccExecutable, rccJob.QrcFile,
readFiles, &error)) {
files = &readFiles;
} else {
......@@ -1693,7 +1668,7 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
// Test if any input file is newer than the build file
if (files != nullptr) {
for (const std::string& file : *files) {
if (FileAbsentOrOlder(rccBuildFile, file)) {
if (FileAbsentOrOlder(rccFileAbs, file)) {
generateRcc = true;
break;
}
......@@ -1705,37 +1680,18 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
if (generateRcc) {
// Log
if (this->Verbose) {
this->LogBold("Generating RCC source " + rccOutputFile);
this->LogBold("Generating RCC source " + rccFileRel);
}
// Make sure the parent directory exists
if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccBuildFile)) {
// Compose symbol name
std::string symbolName =
cmSystemTools::GetFilenameWithoutLastExtension(rccInputFile);
if (!unique_n) {
symbolName += "_";
symbolName += FPathChecksum.getPart(rccInputFile);
}
// Replace '-' with '_'. The former is valid for
// file names but not for symbol names.
std::replace(symbolName.begin(), symbolName.end(), '-', '_');
if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccFileAbs)) {
// Compose rcc command
std::vector<std::string> cmd;
cmd.push_back(this->RccExecutable);
{
std::map<std::string, std::string>::const_iterator optionIt =
this->RccOptions.find(rccInputFile);
if (optionIt != this->RccOptions.end()) {
cmSystemTools::ExpandListArgument(optionIt->second, cmd);
}
}
cmd.push_back("-name");
cmd.push_back(symbolName);
cmd.insert(cmd.end(), rccJob.Options.begin(), rccJob.Options.end());
cmd.push_back("-o");
cmd.push_back(rccBuildFile);
cmd.push_back(rccInputFile);
cmd.push_back(rccFileAbs);
cmd.push_back(rccJob.QrcFile);
std::string output;
if (this->RunCommand(cmd, output)) {
......@@ -1746,12 +1702,12 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
{
std::ostringstream ost;
ost << "AutoRcc: Error: rcc process failed for\n";
ost << Quoted(rccOutputFile) << "\n";
ost << Quoted(rccFileRel) << "\n";
ost << "AutoRcc: Command:\n" << QuotedCommand(cmd) << "\n";
ost << "AutoRcc: Command output:\n" << output << "\n";
this->LogError(ost.str());
}
cmSystemTools::RemoveFile(rccBuildFile);
cmSystemTools::RemoveFile(rccFileAbs);
this->RccRunFailed = true;
}
} else {
......@@ -1762,17 +1718,14 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
// For a multi configuration generator generate a wrapper file
if (!this->ConfigSuffix.empty() && !this->RccRunFailed) {
// Wrapper file name
const std::string cppSuffix = ".cpp";
const size_t suffixLength = this->ConfigSuffix.size() + cppSuffix.size();
const std::string wrapperFileRel =
rccOutputFile.substr(0, rccOutputFile.size() - suffixLength) + cppSuffix;
const std::string wrapperFileAbs = cmSystemTools::CollapseCombinedPath(
this->AutogenBuildDir, wrapperFileRel);
const std::string& wrapperFileAbs = rccJob.RccFile;
const std::string wrapperFileRel = cmSystemTools::RelativePath(
this->AutogenBuildDir.c_str(), wrapperFileAbs.c_str());
// Wrapper file content
std::string content =
"// This is an autogenerated configuration wrapper file. Do not edit.\n"
"#include \"";
content += cmSystemTools::GetFilenameName(rccBuildFile);
std::string content = "// This is an autogenerated configuration "
"wrapper file. Do not edit.\n"
"#include \"";
content += cmSystemTools::GetFilenameName(rccFileRel);
content += "\"\n";
// Write content to file
if (this->FileDiffers(wrapperFileAbs, content)) {
......
......@@ -46,6 +46,15 @@ private:
cmsys::RegularExpression RegExp;
};
/// @brief RCC job
struct RccJob
{
std::string QrcFile;
std::string RccFile;
std::vector<std::string> Options;
std::vector<std::string> Inputs;
};
// -- Configuration
bool MocDependFilterPush(const std::string& key, const std::string& regExp);
bool ReadAutogenInfoFile(cmMakefile* makefile,
......@@ -135,8 +144,7 @@ private:
// -- Rcc file generation
bool RccGenerateAll();
bool RccGenerateFile(const std::string& qrcInputFile,
const std::string& qrcOutputFile, bool unique_n);
bool RccGenerateFile(const RccJob& rccJob);
// -- Logging
void LogErrorNameCollision(
......@@ -227,9 +235,7 @@ private:
// -- Rcc
bool RccSettingsChanged;
bool RccRunFailed;
std::vector<std::string> RccSources;
std::map<std::string, std::string> RccOptions;
std::map<std::string, std::vector<std::string>> RccInputs;
std::vector<RccJob> RccJobs;
};
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment