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.
This commit is contained in:
parent
d350308af6
commit
8295d43713
|
@ -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``
|
||||
|
|
|
@ -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).
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue