summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Holtermann <sebholt@xwmw.org>2016-04-18 18:09:23 (GMT)
committerBrad King <brad.king@kitware.com>2016-04-22 12:49:21 (GMT)
commit8295d43713b621558ce8fc67033021e6eb2a6612 (patch)
tree6be23ac691d0cae3c59badb7e8dacacacf6408ff
parentd350308af6704e70f94ef00d45c4b52ad779e566 (diff)
downloadCMake-8295d43713b621558ce8fc67033021e6eb2a6612.zip
CMake-8295d43713b621558ce8fc67033021e6eb2a6612.tar.gz
CMake-8295d43713b621558ce8fc67033021e6eb2a6612.tar.bz2
Autogen: Check added for name collisions of generated moc files
The test exits with an error if two or more source files would generate the same moc file.
-rw-r--r--Help/prop_tgt/AUTOMOC.rst8
-rw-r--r--Help/release/dev/automoc-diagnostics.rst6
-rw-r--r--Source/cmQtAutoGenerators.cxx69
-rw-r--r--Source/cmQtAutoGenerators.h5
4 files changed, 87 insertions, 1 deletions
diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst
index bd1ace8..8143ba9 100644
--- a/Help/prop_tgt/AUTOMOC.rst
+++ b/Help/prop_tgt/AUTOMOC.rst
@@ -13,7 +13,13 @@ source files at build time and invoke moc accordingly.
* If an ``#include`` statement like ``#include "moc_foo.cpp"`` is found,
the ``Q_OBJECT`` class declaration is expected in the header, and
- ``moc`` is run on the header file.
+ ``moc`` is run on the header file. A ``moc_foo.cpp`` file will be
+ generated from the source's header into the
+ :variable:`CMAKE_CURRENT_BINARY_DIR` directory. This allows the
+ compiler to find the included ``moc_foo.cpp`` file regardless of the
+ location the original source. However, if multiple source files
+ in different directories do this then their generated moc files would
+ collide. In this case a diagnostic will be issued.
* If an ``#include`` statement like ``#include "foo.moc"`` is found,
then a ``Q_OBJECT`` is expected in the current source file and ``moc``
diff --git a/Help/release/dev/automoc-diagnostics.rst b/Help/release/dev/automoc-diagnostics.rst
new file mode 100644
index 0000000..d89f2e1
--- /dev/null
+++ b/Help/release/dev/automoc-diagnostics.rst
@@ -0,0 +1,6 @@
+automoc-diagnostics
+-------------------
+
+* :prop_tgt:`AUTOMOC` now diagnoses name collisions when multiple source
+ files in different directories use ``#include <moc_foo.cpp>`` with the
+ same name (because the generated ``moc_foo.cpp`` files would collide).
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index c07a0a6..08749dd 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -1067,6 +1067,26 @@ bool cmQtAutoGenerators::GenerateMocFiles(
const std::map<std::string, std::string>& includedMocs,
const std::map<std::string, std::string>& notIncludedMocs )
{
+ // look for name collisions
+ {
+ std::multimap<std::string, std::string> collisions;
+ // Test merged map of included and notIncluded
+ std::map<std::string, std::string> mergedMocs ( includedMocs );
+ mergedMocs.insert ( notIncludedMocs.begin(), notIncludedMocs.end() );
+ if( this->NameCollisionTest ( mergedMocs, collisions ) )
+ {
+ std::cerr <<
+ "AUTOGEN: error: "
+ "The same moc file will be generated "
+ "from different sources." << std::endl <<
+ "To avoid this error either" << std::endl <<
+ "- rename the source files or" << std::endl <<
+ "- do not include the (moc_NAME.cpp|NAME.moc) file" << std::endl;
+ this->NameCollisionLog ( collisions );
+ ::exit(EXIT_FAILURE);
+ }
+ }
+
// generate moc files that are included by source files.
for(std::map<std::string, std::string>::const_iterator
it = includedMocs.begin(); it != includedMocs.end(); ++it)
@@ -1442,6 +1462,55 @@ bool cmQtAutoGenerators::GenerateQrc (
return true;
}
+/**
+ * @brief Collects name collisions as output/input pairs
+ * @return True if there were collisions
+ */
+bool cmQtAutoGenerators::NameCollisionTest(
+ const std::map<std::string, std::string >& genFiles,
+ std::multimap<std::string, std::string>& collisions)
+{
+ typedef std::map<std::string, std::string>::const_iterator Iter;
+ typedef std::map<std::string, std::string>::value_type VType;
+ for(Iter ait = genFiles.begin(); ait != genFiles.end(); ++ait )
+ {
+ bool first_match ( true );
+ for (Iter bit = (++Iter(ait)); bit != genFiles.end(); ++bit)
+ {
+ if(ait->second == bit->second)
+ {
+ if (first_match)
+ {
+ if (collisions.find(ait->second) != collisions.end())
+ {
+ // We already know of this collision from before
+ break;
+ }
+ collisions.insert(VType(ait->second, ait->first));
+ first_match = false;
+ }
+ collisions.insert(VType(bit->second, bit->first));
+ }
+ }
+ }
+
+ return !collisions.empty();
+}
+
+void cmQtAutoGenerators::NameCollisionLog(
+ const std::multimap<std::string, std::string>& collisions)
+{
+ typedef std::multimap<std::string, std::string>::const_iterator Iter;
+
+ std::stringstream sbuf;
+ for(Iter it = collisions.begin(); it != collisions.end(); ++it )
+ {
+ sbuf << it->first << " : " << it->second << std::endl;
+ }
+ sbuf.flush();
+ std::cerr << sbuf.str();
+}
+
void cmQtAutoGenerators::LogCommand(const std::vector<std::string>& command)
{
std::stringstream sbuf;
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index 68ab480..d529bf9 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -78,6 +78,11 @@ private:
void Init();
+ bool NameCollisionTest(const std::map<std::string, std::string >& genFiles,
+ std::multimap<std::string, std::string>& collisions );
+ void NameCollisionLog(
+ const std::multimap<std::string, std::string>& collisions );
+
void LogCommand(const std::vector<std::string>& command);
std::string JoinExts(const std::vector<std::string>& lst);