summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/prop_tgt/AUTORCC.rst5
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/cmFilePathUuid.cxx132
-rw-r--r--Source/cmFilePathUuid.h77
-rw-r--r--Source/cmQtAutoGeneratorInitializer.cxx76
-rw-r--r--Source/cmQtAutoGenerators.cxx88
-rw-r--r--Source/cmQtAutoGenerators.h6
-rw-r--r--Tests/QtAutogen/CMakeLists.txt4
-rw-r--r--Tests/QtAutogen/sameName/CMakeLists.txt21
-rw-r--r--Tests/QtAutogen/sameName/aaa/bbb/data.qrc6
-rw-r--r--Tests/QtAutogen/sameName/aaa/bbb/item.cpp10
-rw-r--r--Tests/QtAutogen/sameName/aaa/bbb/item.hpp18
-rw-r--r--Tests/QtAutogen/sameName/aaa/data.qrc6
-rw-r--r--Tests/QtAutogen/sameName/aaa/item.cpp8
-rw-r--r--Tests/QtAutogen/sameName/aaa/item.hpp16
-rw-r--r--Tests/QtAutogen/sameName/bbb/aaa/data.qrc6
-rw-r--r--Tests/QtAutogen/sameName/bbb/aaa/item.cpp10
-rw-r--r--Tests/QtAutogen/sameName/bbb/aaa/item.hpp18
-rw-r--r--Tests/QtAutogen/sameName/bbb/data.qrc6
-rw-r--r--Tests/QtAutogen/sameName/bbb/item.cpp8
-rw-r--r--Tests/QtAutogen/sameName/bbb/item.hpp16
-rw-r--r--Tests/QtAutogen/sameName/ccc/data.qrc6
-rw-r--r--Tests/QtAutogen/sameName/ccc/item.cpp23
-rw-r--r--Tests/QtAutogen/sameName/ccc/item.hpp16
-rw-r--r--Tests/QtAutogen/sameName/data.qrc5
-rw-r--r--Tests/QtAutogen/sameName/item.cpp5
-rw-r--r--Tests/QtAutogen/sameName/item.hpp13
-rw-r--r--Tests/QtAutogen/sameName/main.cpp16
28 files changed, 562 insertions, 61 deletions
diff --git a/Help/prop_tgt/AUTORCC.rst b/Help/prop_tgt/AUTORCC.rst
index 8dce6b1..158fdf8 100644
--- a/Help/prop_tgt/AUTORCC.rst
+++ b/Help/prop_tgt/AUTORCC.rst
@@ -19,5 +19,10 @@ Additional command line options for rcc can be set via the
The global property :prop_gbl:`AUTOGEN_TARGETS_FOLDER` can be used to group
the autorcc targets together in an IDE, e.g. in MSVS.
+When there are multiple ``.qrc`` files with the same name, CMake will
+generate unspecified unique names for ``rcc``. Therefore if
+``Q_INIT_RESOURCE()`` or ``Q_CLEANUP_RESOURCE()`` need to be used the
+``.qrc`` file name must be unique.
+
See the :manual:`cmake-qt(7)` manual for more information on using CMake
with Qt.
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index a790994..cdc8fb1 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -238,6 +238,8 @@ set(SRCS
cmFileLockPool.h
cmFileLockResult.cxx
cmFileLockResult.h
+ cmFilePathUuid.cxx
+ cmFilePathUuid.h
cmFileTimeComparison.cxx
cmFileTimeComparison.h
cmFortranLexer.cxx
diff --git a/Source/cmFilePathUuid.cxx b/Source/cmFilePathUuid.cxx
new file mode 100644
index 0000000..2839b63
--- /dev/null
+++ b/Source/cmFilePathUuid.cxx
@@ -0,0 +1,132 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2016 Sebastian Holtermann (sebholt@xwmw.org)
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+
+#include "cmFilePathUuid.h"
+
+#include "cmCryptoHash.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmsys/Base64.h"
+
+cmFilePathUuid::cmFilePathUuid(cmMakefile* makefile)
+{
+ initParentDirs(makefile->GetCurrentSourceDirectory(),
+ makefile->GetCurrentBinaryDirectory(),
+ makefile->GetHomeDirectory(),
+ makefile->GetHomeOutputDirectory());
+}
+
+cmFilePathUuid::cmFilePathUuid(const std::string& currentSrcDir,
+ const std::string& currentBinDir,
+ const std::string& projectSrcDir,
+ const std::string& projectBinDir)
+{
+ initParentDirs(currentSrcDir, currentBinDir, projectSrcDir, projectBinDir);
+}
+
+void cmFilePathUuid::initParentDirs(const std::string& currentSrcDir,
+ const std::string& currentBinDir,
+ const std::string& projectSrcDir,
+ const std::string& projectBinDir)
+{
+ parentDirs[0].first = cmsys::SystemTools::GetRealPath(currentSrcDir);
+ parentDirs[1].first = cmsys::SystemTools::GetRealPath(currentBinDir);
+ parentDirs[2].first = cmsys::SystemTools::GetRealPath(projectSrcDir);
+ parentDirs[3].first = cmsys::SystemTools::GetRealPath(projectBinDir);
+
+ parentDirs[0].second = "CurrentSource";
+ parentDirs[1].second = "CurrentBinary";
+ parentDirs[2].second = "ProjectSource";
+ parentDirs[3].second = "ProjectBinary";
+}
+
+std::string cmFilePathUuid::get(const std::string& filePath,
+ const char* outputPrefix,
+ const char* outputSuffix)
+{
+ std::string sourceFilename = cmsys::SystemTools::GetFilenameName(filePath);
+ std::string sourceBasename =
+ cmsys::SystemTools::GetFilenameWithoutLastExtension(sourceFilename);
+
+ // Acquire checksum string
+ std::string checksum;
+ {
+ std::string sourceRelPath;
+ std::string sourceRelSeed;
+ GetRelPathSeed(filePath, sourceRelPath, sourceRelSeed);
+ checksum = GetChecksumString(sourceFilename, sourceRelPath, sourceRelSeed);
+ }
+
+ // Compose the file name
+ std::string uuid;
+ if (outputPrefix) {
+ uuid += outputPrefix;
+ }
+ uuid += sourceBasename.substr(0, partLengthName);
+ uuid += "_";
+ uuid += checksum.substr(0, partLengthCheckSum);
+ if (outputSuffix) {
+ uuid += outputSuffix;
+ }
+ return uuid;
+}
+
+void cmFilePathUuid::GetRelPathSeed(const std::string& filePath,
+ std::string& sourceRelPath,
+ std::string& sourceRelSeed)
+{
+ const std::string sourceNameReal = cmsys::SystemTools::GetRealPath(filePath);
+ std::string parentDirectory;
+ // Find closest project parent directory
+ for (size_t ii = 0; ii != numParentDirs; ++ii) {
+ const std::string& pDir = parentDirs[ii].first;
+ if (!pDir.empty() &&
+ cmsys::SystemTools::IsSubDirectory(sourceNameReal, pDir)) {
+ sourceRelSeed = parentDirs[ii].second;
+ parentDirectory = pDir;
+ break;
+ }
+ }
+ // Check if the file path is below a known project directory
+ if (parentDirectory.empty()) {
+ // Use file syste root as fallback parent directory
+ sourceRelSeed = "FileSystemRoot";
+ cmsys::SystemTools::SplitPathRootComponent(sourceNameReal,
+ &parentDirectory);
+ }
+ sourceRelPath = cmsys::SystemTools::RelativePath(
+ parentDirectory, cmsys::SystemTools::GetParentDirectory(sourceNameReal));
+}
+
+std::string cmFilePathUuid::GetChecksumString(
+ const std::string& sourceFilename, const std::string& sourceRelPath,
+ const std::string& sourceRelSeed)
+{
+ std::string checksumBase64;
+ {
+ // Calculate the file ( seed + relative path + name ) checksum
+ std::vector<unsigned char> hashBytes =
+ cmCryptoHash::New("SHA256")->ByteHashString(
+ (sourceRelSeed + sourceRelPath + sourceFilename).c_str());
+ // Convert hash bytes to Base64 text string
+ std::vector<unsigned char> base64Bytes(hashBytes.size() * 2, 0);
+ cmsysBase64_Encode(&hashBytes[0], hashBytes.size(), &base64Bytes[0], 0);
+ checksumBase64 = reinterpret_cast<const char*>(&base64Bytes[0]);
+ }
+ // Base64 allows '/', '+' and '=' characters which are problematic
+ // when used in file names. Replace them with safer alternatives.
+ std::replace(checksumBase64.begin(), checksumBase64.end(), '/', '-');
+ std::replace(checksumBase64.begin(), checksumBase64.end(), '+', '_');
+ std::replace(checksumBase64.begin(), checksumBase64.end(), '=', '_');
+
+ return checksumBase64;
+}
diff --git a/Source/cmFilePathUuid.h b/Source/cmFilePathUuid.h
new file mode 100644
index 0000000..42e89b1
--- /dev/null
+++ b/Source/cmFilePathUuid.h
@@ -0,0 +1,77 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2016 Sebastian Holtermann (sebholt@xwmw.org)
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+
+#ifndef cmFilePathUuid_h
+#define cmFilePathUuid_h
+
+#include "cmStandardIncludes.h"
+
+#include <string>
+#include <utility>
+
+class cmMakefile;
+
+/** \class cmFilePathUuid
+ * @brief Generates a unique pathless file name with a checksum component
+ * calculated from the file path.
+ *
+ * The checksum is calculated from the relative file path to the
+ * closest known project directory. This guarantees reproducibility
+ * when source and build directory differ e.g. for different project
+ * build directories.
+ */
+class cmFilePathUuid
+{
+public:
+ /// Maximum number of characters to use from the file name
+ static const size_t partLengthName = 14;
+ /// Maximum number of characters to use from the path checksum
+ static const size_t partLengthCheckSum = 14;
+
+ /// @brief Initilizes the parent directories from a makefile
+ cmFilePathUuid(cmMakefile* makefile);
+
+ /// @brief Initilizes the parent directories manually
+ cmFilePathUuid(const std::string& currentSrcDir,
+ const std::string& currentBinDir,
+ const std::string& projectSrcDir,
+ const std::string& projectBinDir);
+
+ /* @brief Calculates and returns the uuid for a file path
+ *
+ * @arg outputPrefix optional string to prepend to the result
+ * @arg outputSuffix optional string to append to the result
+ */
+ std::string get(const std::string& filePath, const char* outputPrefix = NULL,
+ const char* outputSuffix = NULL);
+
+private:
+ void initParentDirs(const std::string& currentSrcDir,
+ const std::string& currentBinDir,
+ const std::string& projectSrcDir,
+ const std::string& projectBinDir);
+
+ /// Returns the relative path and the parent directory key string (seed)
+ void GetRelPathSeed(const std::string& filePath, std::string& sourceRelPath,
+ std::string& sourceRelSeed);
+
+ std::string GetChecksumString(const std::string& sourceFilename,
+ const std::string& sourceRelPath,
+ const std::string& sourceRelSeed);
+
+ /// Size of the parent directory list
+ static const size_t numParentDirs = 4;
+ /// List of (directory name, seed name) pairs
+ std::pair<std::string, std::string> parentDirs[numParentDirs];
+};
+
+#endif
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index d5634e8b..7efb333 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -13,6 +13,7 @@
#include "cmQtAutoGeneratorInitializer.h"
+#include "cmFilePathUuid.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
@@ -25,6 +26,34 @@
#include "cmGlobalVisualStudioGenerator.h"
#endif
+static std::string GetAutogenTargetName(cmGeneratorTarget const* target)
+{
+ std::string autogenTargetName = target->GetName();
+ autogenTargetName += "_automoc";
+ return autogenTargetName;
+}
+
+static std::string GetAutogenTargetDir(cmGeneratorTarget const* target)
+{
+ cmMakefile* makefile = target->Target->GetMakefile();
+ std::string targetDir = makefile->GetCurrentBinaryDirectory();
+ targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
+ targetDir += "/";
+ targetDir += GetAutogenTargetName(target);
+ targetDir += ".dir/";
+ return targetDir;
+}
+
+static std::string GetAutogenTargetBuildDir(cmGeneratorTarget const* target)
+{
+ cmMakefile* makefile = target->Target->GetMakefile();
+ std::string targetDir = makefile->GetCurrentBinaryDirectory();
+ targetDir += "/";
+ targetDir += GetAutogenTargetName(target);
+ targetDir += ".dir/";
+ return targetDir;
+}
+
static void SetupSourceFiles(cmGeneratorTarget const* target,
std::vector<std::string>& skipMoc,
std::vector<std::string>& mocSources,
@@ -38,6 +67,7 @@ static void SetupSourceFiles(cmGeneratorTarget const* target,
std::vector<std::string> newRccFiles;
+ cmFilePathUuid fpathUuid(makefile);
for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
fileIt != srcFiles.end(); ++fileIt) {
cmSourceFile* sf = *fileIt;
@@ -55,13 +85,12 @@ static void SetupSourceFiles(cmGeneratorTarget const* target,
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";
+ std::string rcc_output_file = GetAutogenTargetBuildDir(target);
+ // Create output directory
+ cmSystemTools::MakeDirectory(rcc_output_file.c_str());
+ rcc_output_file += fpathUuid.get(absFile, "qrc_", ".cpp");
+
makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
rcc_output_file.c_str(), false);
makefile->GetOrCreateSource(rcc_output_file, true);
@@ -365,24 +394,6 @@ static void MergeRccOptions(std::vector<std::string>& opts,
opts.insert(opts.end(), extraOpts.begin(), extraOpts.end());
}
-std::string GetAutogenTargetName(cmGeneratorTarget const* target)
-{
- std::string autogenTargetName = target->GetName();
- autogenTargetName += "_automoc";
- return autogenTargetName;
-}
-
-std::string GetAutogenTargetDir(cmGeneratorTarget const* target)
-{
- cmMakefile* makefile = target->Target->GetMakefile();
- std::string targetDir = makefile->GetCurrentBinaryDirectory();
- targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
- targetDir += "/";
- targetDir += GetAutogenTargetName(target);
- targetDir += ".dir/";
- return targetDir;
-}
-
static void copyTargetProperty(cmTarget* destinationTarget,
cmTarget* sourceTarget,
const std::string& propertyName)
@@ -737,6 +748,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
) {
std::vector<cmSourceFile*> srcFiles;
target->GetConfigCommonSourceFiles(srcFiles);
+ cmFilePathUuid fpathUuid(makefile);
for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
fileIt != srcFiles.end(); ++fileIt) {
cmSourceFile* sf = *fileIt;
@@ -747,15 +759,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
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);
-
+ {
+ std::string rcc_output_file = GetAutogenTargetBuildDir(target);
+ // Create output directory
+ cmSystemTools::MakeDirectory(rcc_output_file.c_str());
+ rcc_output_file += fpathUuid.get(absFile, "qrc_", ".cpp");
+ rcc_output.push_back(rcc_output_file);
+ }
if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
if (qtMajorVersion == "5") {
ListQt5RccInputs(sf, target, depends);
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 174760f..a261962 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -14,6 +14,7 @@
#include "cmQtAutoGenerators.h"
#include "cmAlgorithms.h"
+#include "cmFilePathUuid.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
@@ -87,6 +88,23 @@ static std::string extractSubDir(const std::string& absPath,
return subDir;
}
+static bool FileNameIsUnique(const std::string& filePath,
+ const std::map<std::string, std::string>& fileMap)
+{
+ size_t count(0);
+ const std::string fileName = cmsys::SystemTools::GetFilenameName(filePath);
+ for (std::map<std::string, std::string>::const_iterator si = fileMap.begin();
+ si != fileMap.end(); ++si) {
+ if (cmsys::SystemTools::GetFilenameName(si->first) == fileName) {
+ ++count;
+ if (count > 1) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
cmQtAutoGenerators::cmQtAutoGenerators()
: Verbose(cmsys::SystemTools::HasEnv("VERBOSE"))
, ColorOutput(true)
@@ -358,11 +376,13 @@ void cmQtAutoGenerators::WriteOldMocDefinitionsFile(
void cmQtAutoGenerators::Init()
{
+ this->TargetBuildSubDir = this->TargetName;
+ this->TargetBuildSubDir += ".dir/";
+
this->OutMocCppFilenameRel = this->TargetName;
this->OutMocCppFilenameRel += ".cpp";
- this->OutMocCppFilename = this->Builddir;
- this->OutMocCppFilename += this->OutMocCppFilenameRel;
+ this->OutMocCppFilenameAbs = this->Builddir + this->OutMocCppFilenameRel;
std::vector<std::string> cdefList;
cmSystemTools::ExpandListArgument(this->MocCompileDefinitionsStr, cdefList);
@@ -439,7 +459,7 @@ static std::string ReadAll(const std::string& filename)
bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
{
- if (!cmsys::SystemTools::FileExists(this->OutMocCppFilename.c_str()) ||
+ if (!cmsys::SystemTools::FileExists(this->OutMocCppFilenameAbs.c_str()) ||
(this->OldCompileSettingsStr != this->CurrentCompileSettingsStr)) {
this->GenerateAll = true;
}
@@ -933,6 +953,8 @@ void cmQtAutoGenerators::ParseHeaders(
std::map<std::string, std::string>& notIncludedMocs,
std::map<std::string, std::vector<std::string> >& includedUis)
{
+ cmFilePathUuid fpathUuid(this->Srcdir, this->Builddir,
+ this->ProjectSourceDir, this->ProjectBinaryDir);
for (std::set<std::string>::const_iterator hIt = absHeaders.begin();
hIt != absHeaders.end(); ++hIt) {
const std::string& headerName = *hIt;
@@ -946,13 +968,10 @@ void cmQtAutoGenerators::ParseHeaders(
this->LogInfo(err.str());
}
- const std::string basename =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(headerName);
-
- const std::string currentMoc = "moc_" + basename + ".cpp";
std::string macroName;
if (requiresMocing(contents, macroName)) {
- notIncludedMocs[headerName] = currentMoc;
+ notIncludedMocs[headerName] =
+ this->TargetBuildSubDir + fpathUuid.get(headerName, "moc_", ".cpp");
}
}
this->ParseForUic(headerName, contents, includedUis);
@@ -1029,7 +1048,7 @@ bool cmQtAutoGenerators::GenerateMocFiles(
// check if we even need to update _automoc.cpp
if (!automocCppChanged) {
// compare contents of the _automoc.cpp file
- const std::string oldContents = ReadAll(this->OutMocCppFilename);
+ const std::string oldContents = ReadAll(this->OutMocCppFilenameAbs);
if (oldContents == automocSource) {
// nothing changed: don't touch the _automoc.cpp file
if (this->Verbose) {
@@ -1052,7 +1071,7 @@ bool cmQtAutoGenerators::GenerateMocFiles(
}
{
cmsys::ofstream outfile;
- outfile.open(this->OutMocCppFilename.c_str(), std::ios::trunc);
+ outfile.open(this->OutMocCppFilenameAbs.c_str(), std::ios::trunc);
outfile << automocSource;
outfile.close();
}
@@ -1183,7 +1202,7 @@ bool cmQtAutoGenerators::GenerateUi(const std::string& realName,
cmsys::SystemTools::MakeDirectory(this->Builddir.c_str());
}
- const ::std::string uiBuildFile = this->Builddir + uiOutputFile;
+ const std::string uiBuildFile = this->Builddir + uiOutputFile;
int sourceNewerThanUi = 0;
bool success = cmsys::SystemTools::FileTimeCompare(uiInputFile, uiBuildFile,
@@ -1255,15 +1274,18 @@ bool cmQtAutoGenerators::GenerateQrcFiles()
{
// generate single map with input / output names
std::map<std::string, std::string> qrcGenMap;
- for (std::vector<std::string>::const_iterator si = this->RccSources.begin();
- si != this->RccSources.end(); ++si) {
- const std::string ext = cmsys::SystemTools::GetFilenameLastExtension(*si);
- if (ext == ".qrc") {
- std::string basename =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(*si);
- std::string qrcOutputFile = "CMakeFiles/" + this->OriginTargetName +
- ".dir/qrc_" + basename + ".cpp";
- qrcGenMap[*si] = qrcOutputFile;
+ {
+ cmFilePathUuid fpathUuid(this->Srcdir, this->Builddir,
+ this->ProjectSourceDir, this->ProjectBinaryDir);
+ for (std::vector<std::string>::const_iterator si =
+ this->RccSources.begin();
+ si != this->RccSources.end(); ++si) {
+ const std::string ext =
+ cmsys::SystemTools::GetFilenameLastExtension(*si);
+ if (ext == ".qrc") {
+ qrcGenMap[*si] =
+ (this->TargetBuildSubDir + fpathUuid.get(*si, "qrc_", ".cpp"));
+ }
}
}
@@ -1285,7 +1307,8 @@ bool cmQtAutoGenerators::GenerateQrcFiles()
for (std::map<std::string, std::string>::const_iterator si =
qrcGenMap.begin();
si != qrcGenMap.end(); ++si) {
- if (!this->GenerateQrc(si->first, si->second)) {
+ bool unique = FileNameIsUnique(si->first, qrcGenMap);
+ if (!this->GenerateQrc(si->first, si->second, unique)) {
if (this->RunRccFailed) {
return false;
}
@@ -1295,11 +1318,24 @@ bool cmQtAutoGenerators::GenerateQrcFiles()
}
bool cmQtAutoGenerators::GenerateQrc(const std::string& qrcInputFile,
- const std::string& qrcOutputFile)
+ const std::string& qrcOutputFile,
+ bool unique_n)
{
- const std::string basename =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(qrcInputFile);
- const ::std::string qrcBuildFile = this->Builddir + qrcOutputFile;
+ std::string symbolName;
+ if (unique_n) {
+ symbolName =
+ cmsys::SystemTools::GetFilenameWithoutLastExtension(qrcInputFile);
+ } else {
+ symbolName =
+ cmsys::SystemTools::GetFilenameWithoutLastExtension(qrcOutputFile);
+ // Remove "qrc_" at string begin
+ symbolName.erase(0, 4);
+ }
+ // Replace '-' with '_'. The former is valid for
+ // file names but not for symbol names.
+ std::replace(symbolName.begin(), symbolName.end(), '-', '_');
+
+ const std::string qrcBuildFile = this->Builddir + qrcOutputFile;
int sourceNewerThanQrc = 0;
bool generateQrc = !cmsys::SystemTools::FileTimeCompare(
@@ -1325,7 +1361,7 @@ bool cmQtAutoGenerators::GenerateQrc(const std::string& qrcInputFile,
}
command.push_back("-name");
- command.push_back(basename);
+ command.push_back(symbolName);
command.push_back("-o");
command.push_back(qrcBuildFile);
command.push_back(qrcInputFile);
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index 86913f0..fab2d19 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -51,7 +51,8 @@ private:
const std::string& uiOutputFile);
bool GenerateQrcFiles();
bool GenerateQrc(const std::string& qrcInputFile,
- const std::string& qrcOutputFile);
+ const std::string& qrcOutputFile, bool unique_n);
+
void ParseCppFile(
const std::string& absFilename,
const std::vector<std::string>& headerExtensions,
@@ -123,8 +124,9 @@ private:
std::string CurrentCompileSettingsStr;
std::string OldCompileSettingsStr;
+ std::string TargetBuildSubDir;
std::string OutMocCppFilenameRel;
- std::string OutMocCppFilename;
+ std::string OutMocCppFilenameAbs;
std::list<std::string> MocIncludes;
std::list<std::string> MocDefinitions;
std::vector<std::string> MocOptions;
diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt
index d5aca55..e35e1d1 100644
--- a/Tests/QtAutogen/CMakeLists.txt
+++ b/Tests/QtAutogen/CMakeLists.txt
@@ -110,6 +110,10 @@ set_target_properties(
AUTOMOC TRUE
)
+# Test AUTOMOC and AUTORCC on source files with the same name
+# but in different subdirectories
+add_subdirectory(sameName)
+
include(GenerateExportHeader)
# The order is relevant here. B depends on A, and B headers depend on A
# headers both subdirectories use CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE and we
diff --git a/Tests/QtAutogen/sameName/CMakeLists.txt b/Tests/QtAutogen/sameName/CMakeLists.txt
new file mode 100644
index 0000000..ed045fb
--- /dev/null
+++ b/Tests/QtAutogen/sameName/CMakeLists.txt
@@ -0,0 +1,21 @@
+# Test AUTOMOC and AUTORCC on source files with the same name
+# but in different subdirectories
+
+add_executable(sameName
+ aaa/bbb/item.cpp
+ aaa/bbb/data.qrc
+ aaa/item.cpp
+ aaa/data.qrc
+ bbb/aaa/item.cpp
+ bbb/aaa/data.qrc
+ bbb/item.cpp
+ bbb/data.qrc
+ ccc/item.cpp
+ ccc/data.qrc
+ item.cpp
+ data.qrc
+ main.cpp
+)
+target_include_directories(sameName PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
+target_link_libraries(sameName ${QT_LIBRARIES})
+set_target_properties( sameName PROPERTIES AUTOMOC TRUE AUTORCC TRUE )
diff --git a/Tests/QtAutogen/sameName/aaa/bbb/data.qrc b/Tests/QtAutogen/sameName/aaa/bbb/data.qrc
new file mode 100644
index 0000000..0ea3537
--- /dev/null
+++ b/Tests/QtAutogen/sameName/aaa/bbb/data.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="aaa/bbb">
+ <file>item.hpp</file>
+ <file>item.cpp</file>
+</qresource>
+</RCC>
diff --git a/Tests/QtAutogen/sameName/aaa/bbb/item.cpp b/Tests/QtAutogen/sameName/aaa/bbb/item.cpp
new file mode 100644
index 0000000..20d0044
--- /dev/null
+++ b/Tests/QtAutogen/sameName/aaa/bbb/item.cpp
@@ -0,0 +1,10 @@
+#include "item.hpp"
+
+namespace aaa {
+namespace bbb {
+
+void Item::go()
+{
+}
+}
+}
diff --git a/Tests/QtAutogen/sameName/aaa/bbb/item.hpp b/Tests/QtAutogen/sameName/aaa/bbb/item.hpp
new file mode 100644
index 0000000..0855043
--- /dev/null
+++ b/Tests/QtAutogen/sameName/aaa/bbb/item.hpp
@@ -0,0 +1,18 @@
+#ifndef AAA_BBB_ITEM_HPP
+#define AAA_BBB_ITEM_HPP
+
+#include <QObject>
+
+namespace aaa {
+namespace bbb {
+
+class Item : public QObject
+{
+ Q_OBJECT
+ Q_SLOT
+ void go();
+};
+}
+}
+
+#endif
diff --git a/Tests/QtAutogen/sameName/aaa/data.qrc b/Tests/QtAutogen/sameName/aaa/data.qrc
new file mode 100644
index 0000000..379af60
--- /dev/null
+++ b/Tests/QtAutogen/sameName/aaa/data.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="aaa/">
+ <file>item.hpp</file>
+ <file>item.cpp</file>
+</qresource>
+</RCC>
diff --git a/Tests/QtAutogen/sameName/aaa/item.cpp b/Tests/QtAutogen/sameName/aaa/item.cpp
new file mode 100644
index 0000000..95dd3b6
--- /dev/null
+++ b/Tests/QtAutogen/sameName/aaa/item.cpp
@@ -0,0 +1,8 @@
+#include "item.hpp"
+
+namespace aaa {
+
+void Item::go()
+{
+}
+}
diff --git a/Tests/QtAutogen/sameName/aaa/item.hpp b/Tests/QtAutogen/sameName/aaa/item.hpp
new file mode 100644
index 0000000..b63466f
--- /dev/null
+++ b/Tests/QtAutogen/sameName/aaa/item.hpp
@@ -0,0 +1,16 @@
+#ifndef AAA_ITEM_HPP
+#define AAA_ITEM_HPP
+
+#include <QObject>
+
+namespace aaa {
+
+class Item : public QObject
+{
+ Q_OBJECT
+ Q_SLOT
+ void go();
+};
+}
+
+#endif
diff --git a/Tests/QtAutogen/sameName/bbb/aaa/data.qrc b/Tests/QtAutogen/sameName/bbb/aaa/data.qrc
new file mode 100644
index 0000000..da98009
--- /dev/null
+++ b/Tests/QtAutogen/sameName/bbb/aaa/data.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="bbb/aaa/">
+ <file>item.hpp</file>
+ <file>item.cpp</file>
+</qresource>
+</RCC>
diff --git a/Tests/QtAutogen/sameName/bbb/aaa/item.cpp b/Tests/QtAutogen/sameName/bbb/aaa/item.cpp
new file mode 100644
index 0000000..ac4b2c2
--- /dev/null
+++ b/Tests/QtAutogen/sameName/bbb/aaa/item.cpp
@@ -0,0 +1,10 @@
+#include "item.hpp"
+
+namespace bbb {
+namespace aaa {
+
+void Item::go()
+{
+}
+}
+}
diff --git a/Tests/QtAutogen/sameName/bbb/aaa/item.hpp b/Tests/QtAutogen/sameName/bbb/aaa/item.hpp
new file mode 100644
index 0000000..be07ca8
--- /dev/null
+++ b/Tests/QtAutogen/sameName/bbb/aaa/item.hpp
@@ -0,0 +1,18 @@
+#ifndef BBB_AAA_ITEM_HPP
+#define BBB_AAA_ITEM_HPP
+
+#include <QObject>
+
+namespace bbb {
+namespace aaa {
+
+class Item : public QObject
+{
+ Q_OBJECT
+ Q_SLOT
+ void go();
+};
+}
+}
+
+#endif
diff --git a/Tests/QtAutogen/sameName/bbb/data.qrc b/Tests/QtAutogen/sameName/bbb/data.qrc
new file mode 100644
index 0000000..5b080f5
--- /dev/null
+++ b/Tests/QtAutogen/sameName/bbb/data.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="bbb/">
+ <file>item.hpp</file>
+ <file>item.cpp</file>
+</qresource>
+</RCC>
diff --git a/Tests/QtAutogen/sameName/bbb/item.cpp b/Tests/QtAutogen/sameName/bbb/item.cpp
new file mode 100644
index 0000000..f97a143
--- /dev/null
+++ b/Tests/QtAutogen/sameName/bbb/item.cpp
@@ -0,0 +1,8 @@
+#include "item.hpp"
+
+namespace bbb {
+
+void Item::go()
+{
+}
+}
diff --git a/Tests/QtAutogen/sameName/bbb/item.hpp b/Tests/QtAutogen/sameName/bbb/item.hpp
new file mode 100644
index 0000000..5b7f985
--- /dev/null
+++ b/Tests/QtAutogen/sameName/bbb/item.hpp
@@ -0,0 +1,16 @@
+#ifndef BBB_ITEM_HPP
+#define BBB_ITEM_HPP
+
+#include <QObject>
+
+namespace bbb {
+
+class Item : public QObject
+{
+ Q_OBJECT
+ Q_SLOT
+ void go();
+};
+}
+
+#endif
diff --git a/Tests/QtAutogen/sameName/ccc/data.qrc b/Tests/QtAutogen/sameName/ccc/data.qrc
new file mode 100644
index 0000000..f934c39
--- /dev/null
+++ b/Tests/QtAutogen/sameName/ccc/data.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="ccc/">
+ <file>item.hpp</file>
+ <file>item.cpp</file>
+</qresource>
+</RCC>
diff --git a/Tests/QtAutogen/sameName/ccc/item.cpp b/Tests/QtAutogen/sameName/ccc/item.cpp
new file mode 100644
index 0000000..d90b2b8
--- /dev/null
+++ b/Tests/QtAutogen/sameName/ccc/item.cpp
@@ -0,0 +1,23 @@
+#include "item.hpp"
+
+namespace ccc {
+
+void Item::go()
+{
+}
+
+class MocTest : public QObject
+{
+ Q_OBJECT;
+ Q_SLOT
+ void go();
+};
+
+void MocTest::go()
+{
+}
+}
+
+// Include own moc files
+#include "item.moc"
+#include "moc_item.cpp"
diff --git a/Tests/QtAutogen/sameName/ccc/item.hpp b/Tests/QtAutogen/sameName/ccc/item.hpp
new file mode 100644
index 0000000..96fcc24
--- /dev/null
+++ b/Tests/QtAutogen/sameName/ccc/item.hpp
@@ -0,0 +1,16 @@
+#ifndef CCC_ITEM_HPP
+#define CCC_ITEM_HPP
+
+#include <QObject>
+
+namespace ccc {
+
+class Item : public QObject
+{
+ Q_OBJECT
+ Q_SLOT
+ void go();
+};
+}
+
+#endif
diff --git a/Tests/QtAutogen/sameName/data.qrc b/Tests/QtAutogen/sameName/data.qrc
new file mode 100644
index 0000000..4ce0b4e
--- /dev/null
+++ b/Tests/QtAutogen/sameName/data.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>main.cpp</file>
+</qresource>
+</RCC>
diff --git a/Tests/QtAutogen/sameName/item.cpp b/Tests/QtAutogen/sameName/item.cpp
new file mode 100644
index 0000000..e013cf3
--- /dev/null
+++ b/Tests/QtAutogen/sameName/item.cpp
@@ -0,0 +1,5 @@
+#include "item.hpp"
+
+void Item::go()
+{
+}
diff --git a/Tests/QtAutogen/sameName/item.hpp b/Tests/QtAutogen/sameName/item.hpp
new file mode 100644
index 0000000..91bba3b
--- /dev/null
+++ b/Tests/QtAutogen/sameName/item.hpp
@@ -0,0 +1,13 @@
+#ifndef ITEM_HPP
+#define ITEM_HPP
+
+#include <QObject>
+
+class Item : public QObject
+{
+ Q_OBJECT
+ Q_SLOT
+ void go();
+};
+
+#endif
diff --git a/Tests/QtAutogen/sameName/main.cpp b/Tests/QtAutogen/sameName/main.cpp
new file mode 100644
index 0000000..a4ffcb3
--- /dev/null
+++ b/Tests/QtAutogen/sameName/main.cpp
@@ -0,0 +1,16 @@
+#include "aaa/bbb/item.hpp"
+#include "aaa/item.hpp"
+#include "bbb/aaa/item.hpp"
+#include "bbb/item.hpp"
+#include "ccc/item.hpp"
+
+int main(int argv, char** args)
+{
+ // Object instances
+ ::aaa::Item aaa_item;
+ ::aaa::bbb::Item aaa_bbb_item;
+ ::bbb::Item bbb_item;
+ ::bbb::aaa::Item bbb_aaa_item;
+ ::ccc::Item ccc_item;
+ return 0;
+}