diff options
author | Sebastian Holtermann <sebholt@xwmw.org> | 2016-04-18 18:09:23 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2016-04-22 12:49:21 (GMT) |
commit | 8295d43713b621558ce8fc67033021e6eb2a6612 (patch) | |
tree | 6be23ac691d0cae3c59badb7e8dacacacf6408ff | |
parent | d350308af6704e70f94ef00d45c4b52ad779e566 (diff) | |
download | CMake-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.rst | 8 | ||||
-rw-r--r-- | Help/release/dev/automoc-diagnostics.rst | 6 | ||||
-rw-r--r-- | Source/cmQtAutoGenerators.cxx | 69 | ||||
-rw-r--r-- | Source/cmQtAutoGenerators.h | 5 |
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); |