summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2017-02-24 14:31:27 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2017-02-24 14:31:27 (GMT)
commit31282e7854dfa4f28ebe26839599104b4f0b7008 (patch)
tree5757123f28725502fda296f16aaf04ffb3cf06d0
parentf104fe45fc9179e96065f576b0cc3529b29cd624 (diff)
parent62a1e292f29d740d0b193e45f0acd37f7ffaced6 (diff)
downloadCMake-31282e7854dfa4f28ebe26839599104b4f0b7008.zip
CMake-31282e7854dfa4f28ebe26839599104b4f0b7008.tar.gz
CMake-31282e7854dfa4f28ebe26839599104b4f0b7008.tar.bz2
Merge topic 'autogen_depends'
62a1e292 Autogen: Add hint to SKIP_AUTOMOC in error message e98465cf Autogen: Add Quote function and use it for logging 96f6f392 Autogen: Add AUTOMOC_DEPEND_FILTERS documentation 94e3f82c Autogen: Add AUTOMOC_DEPEND_FILTERS test 70ebf35c Autogen: Add AUTOMOC_DEPEND_FILTERS support 2a6fd432 Autogen: Single point of return in Run() method e9a8a207 Autogen: Log simplifications
-rw-r--r--Help/manual/cmake-properties.7.rst1
-rw-r--r--Help/manual/cmake-qt.7.rst3
-rw-r--r--Help/manual/cmake-variables.7.rst1
-rw-r--r--Help/prop_tgt/AUTOMOC.rst3
-rw-r--r--Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst45
-rw-r--r--Help/release/dev/Autogen_depends.rst10
-rw-r--r--Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst12
-rw-r--r--Modules/AutogenInfo.cmake.in1
-rw-r--r--Source/cmQtAutoGeneratorInitializer.cxx2
-rw-r--r--Source/cmQtAutoGenerators.cxx249
-rw-r--r--Source/cmQtAutoGenerators.h1
-rw-r--r--Source/cmTarget.cxx1
-rw-r--r--Tests/QtAutogen/CMakeLists.txt22
-rw-r--r--Tests/QtAutogen/mocPlugin/CMakeLists.txt11
-rw-r--r--Tests/QtAutogen/mocPlugin/StyleA.hpp2
-rw-r--r--Tests/QtAutogen/mocPlugin/StyleA_Custom.json1
-rw-r--r--Tests/QtAutogen/mocPlugin/StyleB.hpp2
-rw-r--r--Tests/QtAutogen/mocPlugin/StyleC.hpp2
-rw-r--r--Tests/QtAutogen/mocPlugin/StyleCommon.hpp7
-rw-r--r--Tests/QtAutogen/mocPlugin/StyleD.hpp2
-rw-r--r--Tests/QtAutogen/mocPlugin/StyleE.hpp2
-rw-r--r--Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json1
22 files changed, 280 insertions, 101 deletions
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 5fad10c..a3b6e6b 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -115,6 +115,7 @@ Properties on Targets
/prop_tgt/ARCHIVE_OUTPUT_NAME_CONFIG
/prop_tgt/ARCHIVE_OUTPUT_NAME
/prop_tgt/AUTOGEN_TARGET_DEPENDS
+ /prop_tgt/AUTOMOC_DEPEND_FILTERS
/prop_tgt/AUTOMOC_MOC_OPTIONS
/prop_tgt/AUTOMOC
/prop_tgt/AUTOUIC
diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst
index e9da396..3b9931e 100644
--- a/Help/manual/cmake-qt.7.rst
+++ b/Help/manual/cmake-qt.7.rst
@@ -87,6 +87,9 @@ following targets by setting the :variable:`CMAKE_AUTOMOC` variable. The
options to pass to ``moc``. The :variable:`CMAKE_AUTOMOC_MOC_OPTIONS`
variable may be populated to pre-set the options for all following targets.
+Additional ``moc`` dependency file names can be extracted from source code
+by using :prop_tgt:`AUTOMOC_DEPEND_FILTERS`.
+
Source C++ files can be excluded from :prop_tgt:`AUTOMOC` processing by
enabling :prop_sf:`SKIP_AUTOMOC` or the broader :prop_sf:`SKIP_AUTOGEN`.
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 6112e65..259d87b 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -256,6 +256,7 @@ Variables that Control the Build
/variable/CMAKE_ANDROID_STL_TYPE
/variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY
/variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY_CONFIG
+ /variable/CMAKE_AUTOMOC_DEPEND_FILTERS
/variable/CMAKE_AUTOMOC_MOC_OPTIONS
/variable/CMAKE_AUTOMOC
/variable/CMAKE_AUTORCC
diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst
index 4ac9b6e..b729c0b 100644
--- a/Help/prop_tgt/AUTOMOC.rst
+++ b/Help/prop_tgt/AUTOMOC.rst
@@ -57,6 +57,9 @@ See the documentation for this variable for more details.
The global property :prop_gbl:`AUTOGEN_TARGETS_FOLDER` can be used to group the
automoc targets together in an IDE, e.g. in MSVS.
+Additional ``moc`` dependency file names can be extracted from source code
+by using :prop_tgt:`AUTOMOC_DEPEND_FILTERS`.
+
Source C++ files can be excluded from :prop_tgt:`AUTOMOC` processing by
enabling :prop_sf:`SKIP_AUTOMOC` or the broader :prop_sf:`SKIP_AUTOGEN`.
diff --git a/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst b/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst
new file mode 100644
index 0000000..810cbf4
--- /dev/null
+++ b/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst
@@ -0,0 +1,45 @@
+AUTOMOC_DEPEND_FILTERS
+----------------------
+
+Filter definitions used by :prop_tgt:`AUTOMOC` to extract file names from
+source code as additional dependencies for the ``moc`` file.
+
+This property is only used if the :prop_tgt:`AUTOMOC` property is ``ON``
+for this target.
+
+Filters are defined as ``KEYWORD;REGULAR_EXPRESSION`` pairs. First the file
+content is searched for ``KEYWORD``. If it is found at least once, then file
+names are extracted by successively searching for ``REGULAR_EXPRESSION`` and
+taking the first match group.
+
+Consider a filter extracts the file name ``DEP`` from the content of a file
+``FOO``. If ``DEP`` changes, then the ``moc`` file for ``FOO`` gets rebuilt.
+The file ``DEP`` is searched for first in the vicinity
+of ``FOO`` and afterwards in the target's :prop_tgt:`INCLUDE_DIRECTORIES`.
+
+By default :prop_tgt:`AUTOMOC_DEPEND_FILTERS` is initialized from
+:variable:`CMAKE_AUTOMOC_DEPEND_FILTERS`, which is empty by default.
+
+See the :manual:`cmake-qt(7)` manual for more information on using CMake
+with Qt.
+
+
+Example
+-------
+
+Consider a file ``FOO.hpp`` holds a custom macro ``OBJ_JSON_FILE`` and we
+want the ``moc`` file to depend on the macro`s file name argument::
+
+ class My_Class : public QObject
+ {
+ Q_OBJECT
+ OBJ_JSON_FILE ( "DEP.json" )
+ ...
+ };
+
+Then we might use :variable:`CMAKE_AUTOMOC_DEPEND_FILTERS` to
+define a filter like this::
+
+ set(CMAKE_AUTOMOC_DEPEND_FILTERS
+ "OBJ_JSON_FILE" "[\n][ \t]*OBJ_JSON_FILE[ \t]*\\([ \t]*\"([^\"]+)\""
+ )
diff --git a/Help/release/dev/Autogen_depends.rst b/Help/release/dev/Autogen_depends.rst
new file mode 100644
index 0000000..c774386
--- /dev/null
+++ b/Help/release/dev/Autogen_depends.rst
@@ -0,0 +1,10 @@
+AutoGen depends
+---------------
+
+* Variable :variable:`CMAKE_AUTOMOC_DEPEND_FILTERS` was introduced to
+ allow :variable:`CMAKE_AUTOMOC` to extract additional dependency file names
+ for ``moc`` from the contents of source files.
+
+* The new target property :prop_tgt:`AUTOMOC_DEPEND_FILTERS` was introduced to
+ allow :prop_tgt:`AUTOMOC` to extract additional dependency file names
+ for ``moc`` from the contents of source files.
diff --git a/Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst b/Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst
new file mode 100644
index 0000000..5c3662d
--- /dev/null
+++ b/Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst
@@ -0,0 +1,12 @@
+CMAKE_AUTOMOC_DEPEND_FILTERS
+----------------------------
+
+Filter definitions used by :variable:`CMAKE_AUTOMOC`
+to extract file names from source code as additional dependencies
+for the ``moc`` file.
+
+This variable is used to initialize the :prop_tgt:`AUTOMOC_DEPEND_FILTERS`
+property on all the targets. See that target property for additional
+information.
+
+By default it is empty.
diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in
index b647ecf..fc5024f 100644
--- a/Modules/AutogenInfo.cmake.in
+++ b/Modules/AutogenInfo.cmake.in
@@ -20,6 +20,7 @@ set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@)
set(AM_MOC_INCLUDES @_moc_incs@)
set(AM_MOC_OPTIONS @_moc_options@)
set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@)
+set(AM_MOC_DEPEND_FILTERS @_moc_depend_filters@)
# UIC settings
set(AM_UIC_SKIP @_uic_skip@)
set(AM_UIC_TARGET_OPTIONS @_uic_target_options@)
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index 52112ff..de18265 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -218,6 +218,8 @@ static void MocSetupAutoTarget(
AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"
: "FALSE");
+ AddDefinitionEscaped(makefile, "_moc_depend_filters",
+ GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS"));
// Moc includes and compile definitions
{
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index d51efb4..e7e456a 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -36,6 +36,25 @@ static const char* SettingsKeyRcc = "AM_RCC_OLD_SETTINGS";
// -- Static functions
+/**
+ * @brief Returns a the string escaped and enclosed in quotes
+ */
+static std::string Quoted(const std::string& text)
+{
+ static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a",
+ "\b", "\\b", "\f", "\\f", "\n", "\\n",
+ "\r", "\\r", "\t", "\\t", "\v", "\\v" };
+
+ std::string res = text;
+ for (const char* const* it = cmArrayBegin(rep); it != cmArrayEnd(rep);
+ it += 2) {
+ cmSystemTools::ReplaceString(res, *it, *(it + 1));
+ }
+ res = '"' + res;
+ res += '"';
+ return res;
+}
+
static std::string GetConfigDefinition(cmMakefile* makefile,
const std::string& key,
const std::string& config)
@@ -244,23 +263,46 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory,
CM_AUTO_PTR<cmMakefile> mf(new cmMakefile(&gg, snapshot));
gg.SetCurrentMakefile(mf.get());
- if (!this->ReadAutogenInfoFile(mf.get(), targetDirectory, config)) {
- return false;
- }
- // Read old settings
- this->SettingsFileRead(mf.get(), targetDirectory);
- // Init and run
- this->Init(mf.get());
- if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5") {
- if (!this->RunAutogen()) {
- return false;
+ bool success = false;
+ if (this->ReadAutogenInfoFile(mf.get(), targetDirectory, config)) {
+ // Read old settings
+ this->SettingsFileRead(mf.get(), targetDirectory);
+ // Init and run
+ this->Init(mf.get());
+ if (this->RunAutogen()) {
+ // Write current settings
+ if (this->SettingsFileWrite(targetDirectory)) {
+ success = true;
+ }
}
}
- // Write latest settings
- if (!this->SettingsFileWrite(targetDirectory)) {
- return false;
+ return success;
+}
+
+bool cmQtAutoGenerators::MocDependFilterPush(const std::string& key,
+ const std::string& regExp)
+{
+ bool success = false;
+ if (!key.empty()) {
+ if (!regExp.empty()) {
+ MocDependFilter filter;
+ filter.key = key;
+ if (filter.regExp.compile(regExp)) {
+ this->MocDependFilters.push_back(filter);
+ success = true;
+ } else {
+ this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Compiling "
+ "regular expression failed.\nKey: " +
+ Quoted(key) + "\nExp.: " + Quoted(regExp));
+ }
+ } else {
+ this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Regular "
+ "expression is empty");
+ }
+ } else {
+ this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Key is empty");
}
- return true;
+ return success;
}
bool cmQtAutoGenerators::ReadAutogenInfoFile(
@@ -272,9 +314,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
filename += "/AutogenInfo.cmake";
if (!makefile->ReadListFile(filename.c_str())) {
- std::ostringstream err;
- err << "AutoGen: error processing file: " << filename << std::endl;
- this->LogError(err.str());
+ this->LogError("AutoGen: Error processing file: " + filename);
return false;
}
@@ -297,6 +337,13 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
this->QtMajorVersion =
makefile->GetSafeDefinition("AM_Qt5Core_VERSION_MAJOR");
}
+ // Check Qt version
+ if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) {
+ this->LogError("AutoGen: Error: Unsupported Qt version: " +
+ Quoted(this->QtMajorVersion));
+ return false;
+ }
+
this->MocExecutable = makefile->GetSafeDefinition("AM_QT_MOC_EXECUTABLE");
this->UicExecutable = makefile->GetSafeDefinition("AM_QT_UIC_EXECUTABLE");
this->RccExecutable = makefile->GetSafeDefinition("AM_QT_RCC_EXECUTABLE");
@@ -318,6 +365,30 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
this->MocIncludePaths);
cmSystemTools::ExpandListArgument(
makefile->GetSafeDefinition("AM_MOC_OPTIONS"), this->MocOptions);
+ {
+ std::vector<std::string> mocDependFilters;
+ cmSystemTools::ExpandListArgument(
+ makefile->GetSafeDefinition("AM_MOC_DEPEND_FILTERS"), mocDependFilters);
+ // Insert Q_PLUGIN_METADATA dependency filter
+ if (this->QtMajorVersion != "4") {
+ this->MocDependFilterPush("Q_PLUGIN_METADATA",
+ "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
+ "[^\\)]*FILE[ \t]*\"([^\"]+)\"");
+ }
+ // Insert user defined dependency filters
+ if ((mocDependFilters.size() % 2) == 0) {
+ for (std::vector<std::string>::const_iterator dit =
+ mocDependFilters.begin();
+ dit != mocDependFilters.end(); dit += 2) {
+ if (!this->MocDependFilterPush(*dit, *(dit + 1))) {
+ return false;
+ }
+ }
+ } else {
+ this->LogError("AutoMoc: Error: AUTOMOC_DEPEND_FILTERS list size is not "
+ "a multiple of 2");
+ }
+ }
// - Uic
cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_UIC_SKIP"),
@@ -333,10 +404,9 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
cmSystemTools::ExpandListArgument(
makefile->GetSafeDefinition("AM_UIC_OPTIONS_OPTIONS"), uicOptionsVec);
if (uicFilesVec.size() != uicOptionsVec.size()) {
- std::ostringstream err;
- err << "AutoGen: Error: Uic files/options lists size missmatch in: "
- << filename << std::endl;
- this->LogError(err.str());
+ this->LogError(
+ "AutoGen: Error: Uic files/options lists size missmatch in: " +
+ filename);
return false;
}
for (std::vector<std::string>::iterator fileIt = uicFilesVec.begin(),
@@ -358,10 +428,9 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
cmSystemTools::ExpandListArgument(
makefile->GetSafeDefinition("AM_RCC_OPTIONS_OPTIONS"), rccOptionsVec);
if (rccFilesVec.size() != rccOptionsVec.size()) {
- std::ostringstream err;
- err << "AutoGen: Error: RCC files/options lists size missmatch in: "
- << filename << std::endl;
- this->LogError(err.str());
+ this->LogError(
+ "AutoGen: Error: RCC files/options lists size missmatch in: " +
+ filename);
return false;
}
for (std::vector<std::string>::iterator fileIt = rccFilesVec.begin(),
@@ -381,10 +450,9 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
rccInputLists.resize(this->RccSources.size());
}
if (this->RccSources.size() != rccInputLists.size()) {
- std::ostringstream err;
- err << "AutoGen: Error: RCC sources/inputs lists size missmatch in: "
- << filename << std::endl;
- this->LogError(err.str());
+ this->LogError(
+ "AutoGen: Error: RCC sources/inputs lists size missmatch in: " +
+ filename);
return false;
}
for (std::vector<std::string>::iterator fileIt = this->RccSources.begin(),
@@ -480,12 +548,8 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory)
success = false;
// Remove old settings file to trigger full rebuild on next run
cmSystemTools::RemoveFile(filename);
- {
- std::ostringstream err;
- err << "AutoGen: Error: Writing old settings file failed: "
- << filename;
- this->LogError(err.str());
- }
+ this->LogError("AutoGen: Error: Writing old settings file failed: " +
+ filename);
}
}
return success;
@@ -564,16 +628,6 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile)
this->MocIncludes.push_back(*it);
}
}
-
- // Insert MocDependFilter for Q_PLUGIN_METADATA
- if (QtMajorVersion != "4") {
- MocDependFilter filter;
- filter.key = "Q_PLUGIN_METADATA";
- filter.regExp.compile("[\n][ \t]*"
- "Q_PLUGIN_METADATA[ \t]*\\("
- "[^\\)]*FILE[ \t]*\"([^\"]+)\"");
- this->MocDependFilters.push_back(filter);
- }
}
bool cmQtAutoGenerators::RunAutogen()
@@ -684,13 +738,13 @@ void cmQtAutoGenerators::MocFindDepends(
if (!incFile.empty()) {
mocDepends[absFilename].insert(incFile);
if (this->Verbose) {
- this->LogInfo("AutoMoc: Found dependency:\n \"" + absFilename +
- "\"\n \"" + incFile + "\"");
+ this->LogInfo("AutoMoc: Found dependency:\n " +
+ Quoted(absFilename) + "\n " + Quoted(incFile));
}
} else {
- this->LogWarning("AutoMoc: Warning: \"" + absFilename + "\"\n" +
- "Could not find dependency file \"" + match +
- "\"");
+ this->LogWarning("AutoMoc: Warning: " + Quoted(absFilename) +
+ "\n" + "Could not find dependency file " +
+ Quoted(match));
}
}
contentChars += filter.regExp.end();
@@ -843,9 +897,11 @@ bool cmQtAutoGenerators::MocParseSourceContent(
} else {
std::ostringstream ost;
ost << "AutoMoc: Error: " << absFilename << "\n"
- << "The file includes the moc file \"" << incString
- << "\", but could not find header \"" << incRealBasename << '{'
- << JoinExts(this->HeaderExtensions) << "}\"\n";
+ << "The file includes the moc file " << Quoted(incString)
+ << ", but could not find header "
+ << Quoted(incRealBasename + "{" +
+ JoinExts(this->HeaderExtensions) + "}");
+ ;
this->LogError(ost.str());
return false;
}
@@ -867,32 +923,33 @@ bool cmQtAutoGenerators::MocParseSourceContent(
fileToMoc = headerToMoc;
if (!requiresMoc && (incBasename == scannedFileBasename)) {
std::ostringstream ost;
- ost << "AutoMoc: Warning: " << absFilename << "\n"
- << "The file includes the moc file \"" << incString << "\""
+ ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
+ << "The file includes the moc file " << Quoted(incString)
<< ", but does not contain a Q_OBJECT or Q_GADGET macro.\n"
- << "Running moc on \"" << headerToMoc << "\"!\n"
- << "Include \"moc_" << incBasename
- << ".cpp\" for a compatibility with "
- "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
+ << "Running moc on " << Quoted(headerToMoc) << "!\n"
+ << "Include " << Quoted("moc_" + incBasename + ".cpp")
+ << " for a compatibility with strict mode (see "
+ "CMAKE_AUTOMOC_RELAXED_MODE).\n";
this->LogWarning(ost.str());
} else {
std::ostringstream ost;
- ost << "AutoMoc: Warning: " << absFilename << "\n"
- << "The file includes the moc file \"" << incString
- << "\" instead of \"moc_" << incBasename << ".cpp\".\n"
- << "Running moc on \"" << headerToMoc << "\"!\n"
- << "Include \"moc_" << incBasename
- << ".cpp\" for compatibility with "
- "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
+ ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
+ << "The file includes the moc file " << Quoted(incString)
+ << " instead of " << Quoted("moc_" + incBasename + ".cpp")
+ << ".\n"
+ << "Running moc on " << Quoted(headerToMoc) << "!\n"
+ << "Include " << Quoted("moc_" + incBasename + ".cpp")
+ << " for compatibility with strict mode (see "
+ "CMAKE_AUTOMOC_RELAXED_MODE).\n";
this->LogWarning(ost.str());
}
} else {
std::ostringstream ost;
- ost << "AutoMoc: Error: " << absFilename << "\n"
- << "The file includes the moc file \"" << incString
- << "\", which seems to be the moc file from a different "
+ ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
+ << "The file includes the moc file " << Quoted(incString)
+ << ". which seems to be the moc file from a different "
"source file. CMake also could not find a matching "
- "header.\n";
+ "header.";
this->LogError(ost.str());
return false;
}
@@ -906,21 +963,21 @@ bool cmQtAutoGenerators::MocParseSourceContent(
// Accept but issue a warning if moc isn't required
if (!requiresMoc) {
std::ostringstream ost;
- ost << "AutoMoc: Error: " << absFilename << "\n"
- << "The file includes the moc file \"" << incString << "\""
+ ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
+ << "The file includes the moc file " << Quoted(incString)
<< ", but does not contain a Q_OBJECT or Q_GADGET "
- "macro.\n";
+ "macro.";
this->LogWarning(ost.str());
}
} else {
// Don't allow FOO.moc include other than self in strict mode
std::ostringstream ost;
- ost << "AutoMoc: Error: " << absFilename << "\n"
- << "The file includes the moc file \"" << incString
- << "\", which seems to be the moc file from a different "
- "source file. This is not supported. Include \""
- << scannedFileBasename
- << ".moc\" to run moc on this source file.\n";
+ ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
+ << "The file includes the moc file " << Quoted(incString)
+ << ", which seems to be the moc file from a different "
+ "source file. This is not supported. Include "
+ << Quoted(scannedFileBasename + ".moc")
+ << " to run moc on this source file.";
this->LogError(ost.str());
return false;
}
@@ -943,15 +1000,15 @@ bool cmQtAutoGenerators::MocParseSourceContent(
if (relaxed && !ownMocUnderscoreInclude.empty()) {
// This is for KDE4 compatibility:
std::ostringstream ost;
- ost << "AutoMoc: Warning: " << absFilename << "\n"
+ ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
<< "The file contains a " << macroName
<< " macro, but does not include "
- << "\"" << scannedFileBasename << ".moc\", but instead includes "
- << "\"" << ownMocUnderscoreInclude << "\".\n"
- << "Running moc on \"" << absFilename << "\"!\n"
- << "Better include \"" << scannedFileBasename
- << ".moc\" for compatibility with "
- "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
+ << Quoted(scannedFileBasename + ".moc") << ", but instead includes "
+ << Quoted(ownMocUnderscoreInclude) << ".\n"
+ << "Running moc on " << Quoted(absFilename) << "!\n"
+ << "Better include " << Quoted(scannedFileBasename + ".moc")
+ << " for compatibility with strict mode (see "
+ "CMAKE_AUTOMOC_RELAXED_MODE).";
this->LogWarning(ost.str());
// Use scanned source file instead of scanned header file as moc source
@@ -962,10 +1019,12 @@ bool cmQtAutoGenerators::MocParseSourceContent(
} else {
// Otherwise always error out since it will not compile:
std::ostringstream ost;
- ost << "AutoMoc: Error: " << absFilename << "\n"
+ ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
<< "The file contains a " << macroName
<< " macro, but does not include "
- << "\"" << scannedFileBasename << ".moc\"!\n";
+ << Quoted(scannedFileBasename + ".moc") << "!\n"
+ << "Consider adding the include or enabling SKIP_AUTOMOC for this "
+ "file.";
this->LogError(ost.str());
return false;
}
@@ -1150,13 +1209,13 @@ bool cmQtAutoGenerators::MocGenerateAll(
outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc);
if (!outfile) {
success = false;
- this->LogError("AutoMoc: error opening " + this->MocCppFilenameAbs);
+ this->LogError("AutoMoc: Error opening " + this->MocCppFilenameAbs);
} else {
outfile << automocSource;
// Check for write errors
if (!outfile.good()) {
success = false;
- this->LogError("AutoMoc: error writing " + this->MocCppFilenameAbs);
+ this->LogError("AutoMoc: Error writing " + this->MocCppFilenameAbs);
}
}
}
@@ -1245,7 +1304,7 @@ bool cmQtAutoGenerators::MocGenerateFile(
{
std::ostringstream ost;
ost << "AutoMoc: Error: moc process failed for\n";
- ost << "\"" << mocFileRel << "\"\n";
+ ost << Quoted(mocFileRel) << "\n";
ost << "AutoMoc: Command:\n" << cmJoin(cmd, " ") << "\n";
ost << "AutoMoc: Command output:\n" << output << "\n";
this->LogError(ost.str());
@@ -1384,8 +1443,8 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName,
{
std::ostringstream ost;
ost << "AutoUic: Error: uic process failed for\n";
- ost << "\"" << uicFileRel << "\" needed by\n";
- ost << "\"" << realName << "\"\n";
+ ost << Quoted(uicFileRel) << " needed by\n";
+ ost << Quoted(realName) << "\n";
ost << "AutoUic: Command:\n" << cmJoin(cmd, " ") << "\n";
ost << "AutoUic: Command output:\n" << output << "\n";
this->LogError(ost.str());
@@ -1523,7 +1582,7 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
{
std::ostringstream ost;
ost << "AutoRcc: Error: rcc process failed for\n";
- ost << "\"" << rccOutputFile << "\"\n";
+ ost << Quoted(rccOutputFile) << "\n";
ost << "AutoRcc: Command:\n" << cmJoin(cmd, " ") << "\n";
ost << "AutoRcc: Command output:\n" << output << "\n";
this->LogError(ost.str());
@@ -1768,7 +1827,7 @@ bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) const
if (!dirName.empty()) {
success = cmsys::SystemTools::MakeDirectory(dirName);
if (!success) {
- this->LogError("AutoGen: Directory creation failed: " + dirName);
+ this->LogError("AutoGen: Error: Directory creation failed: " + dirName);
}
}
return success;
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index c20b83c..e4b7f60 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -33,6 +33,7 @@ private:
typedef std::pair<std::string, cmsys::RegularExpression> MacroFilter;
// - Configuration
+ bool MocDependFilterPush(const std::string& key, const std::string& regExp);
bool ReadAutogenInfoFile(cmMakefile* makefile,
const std::string& targetDirectory,
const std::string& config);
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index ad3d604..0f3d91b 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -245,6 +245,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
this->SetPropertyDefault("AUTOMOC", CM_NULLPTR);
this->SetPropertyDefault("AUTOUIC", CM_NULLPTR);
this->SetPropertyDefault("AUTORCC", CM_NULLPTR);
+ this->SetPropertyDefault("AUTOMOC_DEPEND_FILTERS", CM_NULLPTR);
this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", CM_NULLPTR);
this->SetPropertyDefault("AUTOUIC_OPTIONS", CM_NULLPTR);
this->SetPropertyDefault("AUTORCC_OPTIONS", CM_NULLPTR);
diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt
index 260331b..257c187 100644
--- a/Tests/QtAutogen/CMakeLists.txt
+++ b/Tests/QtAutogen/CMakeLists.txt
@@ -247,10 +247,7 @@ if (NOT QT_TEST_VERSION STREQUAL 4)
execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1)
execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/StyleC.json")
execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/sub/StyleD.json")
-
- execute_process(COMMAND "${CMAKE_COMMAND}" --build .
- WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin"
- )
+ execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${mocPluginBinDir}")
file(TIMESTAMP "${style_a_file}" style_a_after "${timeformat}")
file(TIMESTAMP "${style_b_file}" style_b_after "${timeformat}")
@@ -269,6 +266,23 @@ if (NOT QT_TEST_VERSION STREQUAL 4)
if (NOT style_d_after GREATER style_d_before)
message(SEND_ERROR "file (${style_d_file}) should have changed!")
endif()
+
+ # Test custom macro
+ file(TIMESTAMP "${style_c_file}" style_c_before "${timeformat}")
+ file(TIMESTAMP "${style_d_file}" style_d_before "${timeformat}")
+ execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1)
+ execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/StyleC_Custom.json")
+ execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/sub/StyleD_Custom.json")
+ execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${mocPluginBinDir}")
+ file(TIMESTAMP "${style_c_file}" style_c_after "${timeformat}")
+ file(TIMESTAMP "${style_d_file}" style_d_after "${timeformat}")
+ if (NOT style_c_after GREATER style_c_before)
+ message(SEND_ERROR "file (${style_c_file}) should have changed!")
+ endif()
+ if (NOT style_d_after GREATER style_d_before)
+ message(SEND_ERROR "file (${style_d_file}) should have changed!")
+ endif()
+
endif()
# -- Test
diff --git a/Tests/QtAutogen/mocPlugin/CMakeLists.txt b/Tests/QtAutogen/mocPlugin/CMakeLists.txt
index eed7d39..b72b05d 100644
--- a/Tests/QtAutogen/mocPlugin/CMakeLists.txt
+++ b/Tests/QtAutogen/mocPlugin/CMakeLists.txt
@@ -1,5 +1,10 @@
cmake_minimum_required(VERSION 3.8)
+set(CMAKE_AUTOMOC_DEPEND_FILTERS
+ "A_CUSTOM_MACRO"
+ "[\n][ \t]*A_CUSTOM_MACRO[ \t\r\n]*\\([^,]+,[ \t\r\n]*\"([^\"]+)\""
+ )
+
if (NOT QT_TEST_VERSION STREQUAL 5)
message(SEND_ERROR "Invalid Qt version specified.")
endif()
@@ -9,8 +14,10 @@ if(Qt5_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC)
add_definitions(${CMAKE_CXX_COMPILE_OPTIONS_PIC})
endif()
-configure_file(jsonIn/StyleC.json jsonFiles/StyleC.json @ONLY)
-configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD.json @ONLY)
+configure_file(jsonIn/StyleC.json jsonFiles/StyleC.json)
+configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD.json)
+configure_file(jsonIn/StyleC.json jsonFiles/StyleC_Custom.json)
+configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD_Custom.json)
# Enable automoc
set(CMAKE_AUTOMOC TRUE)
diff --git a/Tests/QtAutogen/mocPlugin/StyleA.hpp b/Tests/QtAutogen/mocPlugin/StyleA.hpp
index b105b02..1b6154d 100644
--- a/Tests/QtAutogen/mocPlugin/StyleA.hpp
+++ b/Tests/QtAutogen/mocPlugin/StyleA.hpp
@@ -1,6 +1,7 @@
#ifndef STYLEA_HPP
#define STYLEA_HPP
+#include "StyleCommon.hpp"
#include <QStylePlugin>
class StyleA : public QStylePlugin
@@ -8,6 +9,7 @@ class StyleA : public QStylePlugin
Q_OBJECT
// Json file in local directory
Q_PLUGIN_METADATA(IID "org.styles.A" FILE "StyleA.json")
+ A_CUSTOM_MACRO(SomeArg, "StyleA_Custom.json", AnotherArg)
public:
QStyle* create(const QString& key);
};
diff --git a/Tests/QtAutogen/mocPlugin/StyleA_Custom.json b/Tests/QtAutogen/mocPlugin/StyleA_Custom.json
new file mode 100644
index 0000000..cc33953
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleA_Custom.json
@@ -0,0 +1 @@
+{ "Keys": [ "Rocket", "Starbuster" ] }
diff --git a/Tests/QtAutogen/mocPlugin/StyleB.hpp b/Tests/QtAutogen/mocPlugin/StyleB.hpp
index ba89127..163c9b2 100644
--- a/Tests/QtAutogen/mocPlugin/StyleB.hpp
+++ b/Tests/QtAutogen/mocPlugin/StyleB.hpp
@@ -1,6 +1,7 @@
#ifndef STYLEB_HPP
#define STYLEB_HPP
+#include "StyleCommon.hpp"
#include <QStylePlugin>
class StyleB : public QStylePlugin
@@ -8,6 +9,7 @@ class StyleB : public QStylePlugin
Q_OBJECT
// Json file in local subdirectory
Q_PLUGIN_METADATA(IID "org.styles.B" FILE "jsonIn/StyleB.json")
+ A_CUSTOM_MACRO(SomeArg, "jsonIn/StyleB_Custom.json", AnotherArg)
public:
QStyle* create(const QString& key);
};
diff --git a/Tests/QtAutogen/mocPlugin/StyleC.hpp b/Tests/QtAutogen/mocPlugin/StyleC.hpp
index 9f71d75..52a887a 100644
--- a/Tests/QtAutogen/mocPlugin/StyleC.hpp
+++ b/Tests/QtAutogen/mocPlugin/StyleC.hpp
@@ -1,6 +1,7 @@
#ifndef STYLEC_HPP
#define STYLEC_HPP
+#include "StyleCommon.hpp"
#include <QStylePlugin>
class StyleC : public QStylePlugin
@@ -8,6 +9,7 @@ class StyleC : public QStylePlugin
Q_OBJECT
// Json file in global root directory
Q_PLUGIN_METADATA(IID "org.styles.C" FILE "StyleC.json")
+ A_CUSTOM_MACRO(SomeArg, "StyleC_Custom.json", AnotherArg)
public:
QStyle* create(const QString& key);
};
diff --git a/Tests/QtAutogen/mocPlugin/StyleCommon.hpp b/Tests/QtAutogen/mocPlugin/StyleCommon.hpp
new file mode 100644
index 0000000..f1a7ec6
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleCommon.hpp
@@ -0,0 +1,7 @@
+#ifndef STYLECOMMON_HPP
+#define STYLECOMMON_HPP
+
+// Empty test macro definition
+#define A_CUSTOM_MACRO(name, jsonFile, pluginRegistrations)
+
+#endif
diff --git a/Tests/QtAutogen/mocPlugin/StyleD.hpp b/Tests/QtAutogen/mocPlugin/StyleD.hpp
index e58444d..df8a439 100644
--- a/Tests/QtAutogen/mocPlugin/StyleD.hpp
+++ b/Tests/QtAutogen/mocPlugin/StyleD.hpp
@@ -1,6 +1,7 @@
#ifndef STYLED_HPP
#define STYLED_HPP
+#include "StyleCommon.hpp"
#include <QStylePlugin>
class StyleD : public QStylePlugin
@@ -8,6 +9,7 @@ class StyleD : public QStylePlugin
Q_OBJECT
// Json file in global sub director
Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json")
+ A_CUSTOM_MACRO(SomeArg, "sub/StyleD_Custom.json", AnotherArg)
public:
QStyle* create(const QString& key);
};
diff --git a/Tests/QtAutogen/mocPlugin/StyleE.hpp b/Tests/QtAutogen/mocPlugin/StyleE.hpp
index 80e0b79..e7915a8 100644
--- a/Tests/QtAutogen/mocPlugin/StyleE.hpp
+++ b/Tests/QtAutogen/mocPlugin/StyleE.hpp
@@ -1,6 +1,7 @@
#ifndef STYLEE_HPP
#define STYLEE_HPP
+#include "StyleCommon.hpp"
#include <QStylePlugin>
class StyleE : public QStylePlugin
@@ -8,6 +9,7 @@ class StyleE : public QStylePlugin
Q_OBJECT
// No Json file
Q_PLUGIN_METADATA(IID "org.styles.E")
+ A_CUSTOM_MACRO(SomeArg, InvalidFileArg, AnotherArg)
public:
QStyle* create(const QString& key);
};
diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json
new file mode 100644
index 0000000..129cac4
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json
@@ -0,0 +1 @@
+{ "Keys": [ "Rocket", "StarbusterB" ] }