summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCraig Scott <craig.scott@crascit.com>2023-04-10 22:05:54 (GMT)
committerKitware Robot <kwrobot@kitware.com>2023-04-10 22:06:06 (GMT)
commite245b4df7505f2190dbc1442b7ceb94fc507a40e (patch)
tree4ec32f0f25d3cfa2c76ee04a7545d4361671a1da
parent453cf8a1968081731b667edd01ff942adf1f7bcc (diff)
parentc5c3aff1f5aa36d44f3c639726dd36eedc28f823 (diff)
downloadCMake-e245b4df7505f2190dbc1442b7ceb94fc507a40e.zip
CMake-e245b4df7505f2190dbc1442b7ceb94fc507a40e.tar.gz
CMake-e245b4df7505f2190dbc1442b7ceb94fc507a40e.tar.bz2
Merge topic 'automoc-macro-names'
c5c3aff1f5 Autogen: Add INTERFACE_AUTOMOC_MACRO_NAMES target property 69cf9700e6 Autogen: Defer setup until Generate step 7cecb6353e cmGeneratorTarget: Factor out EvaluatedTargetProperty infrastructure 2daba01ddf cmGeneratorTarget: Avoid incidental include-what-you-use warning 850b4d990c IWYU: Add mapping for 'std::remove_reference<Defer &>::type' Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !8391
-rw-r--r--Auxiliary/vim/syntax/cmake.vim1
-rw-r--r--Help/manual/cmake-properties.7.rst1
-rw-r--r--Help/prop_tgt/AUTOMOC_MACRO_NAMES.rst8
-rw-r--r--Help/prop_tgt/INTERFACE_AUTOMOC_MACRO_NAMES.rst89
-rw-r--r--Help/release/dev/automoc-macro-names.rst5
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/cmEvaluatedTargetProperty.cxx111
-rw-r--r--Source/cmEvaluatedTargetProperty.h80
-rw-r--r--Source/cmExportBuildFileGenerator.cxx3
-rw-r--r--Source/cmExportInstallFileGenerator.cxx3
-rw-r--r--Source/cmGeneratorTarget.cxx230
-rw-r--r--Source/cmGeneratorTarget.h22
-rw-r--r--Source/cmGlobalGenerator.cxx22
-rw-r--r--Source/cmGlobalGenerator.h6
-rw-r--r--Source/cmQtAutoGenInitializer.cxx19
-rw-r--r--Tests/QtAutogen/MocInterfaceMacroNames/CMakeLists.txt61
-rw-r--r--Tests/QtAutogen/MocInterfaceMacroNames/CheckAutogenJson.cmake27
-rw-r--r--Tests/QtAutogen/MocInterfaceMacroNames/CheckExportTargets.cmake45
-rw-r--r--Tests/QtAutogen/MocInterfaceMacroNames/dummy.cpp4
-rw-r--r--Tests/QtAutogen/MocInterfaceMacroNames/shared_lib.cpp6
-rw-r--r--Tests/QtAutogen/MocInterfaceMacroNames/static_lib.cpp3
-rw-r--r--Tests/QtAutogen/Tests.cmake1
-rw-r--r--Utilities/IWYU/mapping.imp1
-rwxr-xr-xbootstrap1
24 files changed, 550 insertions, 201 deletions
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim
index 3a44d7a..d6b5b19 100644
--- a/Auxiliary/vim/syntax/cmake.vim
+++ b/Auxiliary/vim/syntax/cmake.vim
@@ -220,6 +220,7 @@ syn keyword cmakeProperty contained
\ INSTALL_RPATH
\ INSTALL_RPATH_USE_LINK_PATH
\ INTERFACE_AUTOUIC_OPTIONS
+ \ INTERFACE_AUTOMOC_MACRO_NAMES
\ INTERFACE_COMPILE_DEFINITIONS
\ INTERFACE_COMPILE_FEATURES
\ INTERFACE_COMPILE_OPTIONS
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 8559b0b..c0e2ee2 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -273,6 +273,7 @@ Properties on Targets
/prop_tgt/INSTALL_REMOVE_ENVIRONMENT_RPATH
/prop_tgt/INSTALL_RPATH
/prop_tgt/INSTALL_RPATH_USE_LINK_PATH
+ /prop_tgt/INTERFACE_AUTOMOC_MACRO_NAMES
/prop_tgt/INTERFACE_AUTOUIC_OPTIONS
/prop_tgt/INTERFACE_COMPILE_DEFINITIONS
/prop_tgt/INTERFACE_COMPILE_FEATURES
diff --git a/Help/prop_tgt/AUTOMOC_MACRO_NAMES.rst b/Help/prop_tgt/AUTOMOC_MACRO_NAMES.rst
index 072e7f7..a4a9ba2 100644
--- a/Help/prop_tgt/AUTOMOC_MACRO_NAMES.rst
+++ b/Help/prop_tgt/AUTOMOC_MACRO_NAMES.rst
@@ -3,7 +3,7 @@ AUTOMOC_MACRO_NAMES
.. versionadded:: 3.10
-A :ref:`semicolon-separated list <CMake Language Lists>` list of macro names used by
+A :ref:`semicolon-separated list <CMake Language Lists>` of macro names used by
:prop_tgt:`AUTOMOC` to determine if a C++ file needs to be processed by ``moc``.
This property is only used if the :prop_tgt:`AUTOMOC` property is ``ON``
@@ -21,6 +21,8 @@ then the file will be processed by ``moc``.
By default ``AUTOMOC_MACRO_NAMES`` is initialized from
:variable:`CMAKE_AUTOMOC_MACRO_NAMES`.
+See also the :prop_tgt:`INTERFACE_AUTOMOC_MACRO_NAMES` target property.
+
See the :manual:`cmake-qt(7)` manual for more information on using CMake
with Qt.
@@ -29,6 +31,8 @@ Example
In this case the ``Q_OBJECT`` macro is hidden inside another macro
called ``CUSTOM_MACRO``. To let CMake know that source files that contain
-``CUSTOM_MACRO`` need to be ``moc`` processed, we call::
+``CUSTOM_MACRO`` need to be ``moc`` processed, we call:
+
+.. code-block:: cmake
set_property(TARGET tgt APPEND PROPERTY AUTOMOC_MACRO_NAMES "CUSTOM_MACRO")
diff --git a/Help/prop_tgt/INTERFACE_AUTOMOC_MACRO_NAMES.rst b/Help/prop_tgt/INTERFACE_AUTOMOC_MACRO_NAMES.rst
new file mode 100644
index 0000000..502775c
--- /dev/null
+++ b/Help/prop_tgt/INTERFACE_AUTOMOC_MACRO_NAMES.rst
@@ -0,0 +1,89 @@
+INTERFACE_AUTOMOC_MACRO_NAMES
+-----------------------------
+
+.. versionadded:: 3.27
+
+A :ref:`semicolon-separated list <CMake Language Lists>` of macro names for
+:prop_tgt:`AUTOMOC` to be propagated to consumers.
+
+When a target with :prop_tgt:`AUTOMOC` enabled links to a library that sets
+``INTERFACE_AUTOMOC_MACRO_NAMES``, the target inherits the listed macro names
+and merges them with those specified in its own :prop_tgt:`AUTOMOC_MACRO_NAMES`
+property. The target will then automatically generate MOC files for source
+files that contain the inherited macro names too, not just the macro names
+specified in its own :prop_tgt:`AUTOMOC_MACRO_NAMES` property.
+
+By default ``INTERFACE_AUTOMOC_MACRO_NAMES`` is empty.
+
+See the :manual:`cmake-qt(7)` manual for more information on using CMake
+with Qt.
+
+Example 1
+^^^^^^^^^
+
+In this example, ``myapp`` inherits the macro names ``STATIC_LIB_1`` and
+``STATIC_LIB_2`` from ``static_lib``. The ``moc`` tool will then automatically
+be run on any of the ``myapp`` sources which contain ``STATIC_LIB_1`` or
+``STATIC_LIB_2``.
+
+.. code-block:: cmake
+
+ set(AUTOMOC ON)
+ add_executable(myapp main.cpp)
+ target_link_libraries(myapp PRIVATE static_lib)
+
+ add_library(static_lib STATIC static.cpp)
+ set_property(TARGET static_lib PROPERTY
+ INTERFACE_AUTOMOC_MACRO_NAMES "STATIC_LIB_1;STATIC_LIB_2"
+ )
+
+Example 2
+^^^^^^^^^
+
+In this example, the ``INTERFACE_AUTOMOC_MACRO_NAMES`` target property of the
+various ``*_deep_lib`` libraries will propagate to ``shared_lib``,
+``static_lib`` and ``interface_lib``. Because the linking relationships are
+specified as ``PUBLIC`` and ``INTERFACE``, those macro names will also further
+propagate transitively up to ``app``.
+
+.. code-block:: cmake
+
+ set(AUTOMOC ON)
+
+ add_library(shared_deep_lib SHARED deep_lib.cpp)
+ add_library(static_deep_lib STATIC deep_lib.cpp)
+ add_library(interface_deep_lib INTERFACE)
+
+ set_property(TARGET shared_deep_lib PROPERTY
+ INTERFACE_AUTOMOC_MACRO_NAMES "SHARED_LINK_LIB"
+ )
+ set_property(TARGET static_deep_lib PROPERTY
+ INTERFACE_AUTOMOC_MACRO_NAMES "STATIC_LINK_LIB"
+ )
+ set_property(TARGET interface_deep_lib PROPERTY
+ INTERFACE_AUTOMOC_MACRO_NAMES "INTERFACE_LINK_LIB"
+ )
+
+ add_library(shared_lib SHARED lib.cpp)
+ add_library(static_lib STATIC lib.cpp)
+ add_library(interface_lib INTERFACE)
+
+ # PUBLIC and INTERFACE here ensure the macro names propagate to any
+ # consumers of shared_lib, static_lib or interface_lib too
+ target_link_libraries(shared_lib PUBLIC shared_deep_lib)
+ target_link_libraries(static_lib PUBLIC static_deep_lib)
+ target_link_libraries(interface_lib INTERFACE interface_deep_lib)
+
+ # This consumer will receive all three of the above custom macro names as
+ # transitive usage requirements
+ add_executable(app main.cpp)
+ target_link_libraries(app PRIVATE shared_lib static_lib interface_lib)
+
+In the above:
+
+* ``shared_lib`` sources will be processed by ``moc`` if they contain
+ ``SHARED_LINK_LIB``.
+* ``static_lib`` sources will be processed by ``moc`` if they contain
+ ``STATIC_LINK_LIB``.
+* ``app`` sources will be processed by ``moc`` if they contain
+ ``SHARED_LINK_LIB``, ``STATIC_LINK_LIB`` or ``INTERFACE_LINK_LIB``.
diff --git a/Help/release/dev/automoc-macro-names.rst b/Help/release/dev/automoc-macro-names.rst
new file mode 100644
index 0000000..9c037b3
--- /dev/null
+++ b/Help/release/dev/automoc-macro-names.rst
@@ -0,0 +1,5 @@
+automoc-macro-names
+-------------------
+
+* The :prop_tgt:`INTERFACE_AUTOMOC_MACRO_NAMES` target property was added to
+ specify macro names for ``moc`` as a transitive usage requirement.
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index b691d38..4a7d9bc 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -193,6 +193,8 @@ add_library(
cmDyndepCollation.h
cmELF.h
cmELF.cxx
+ cmEvaluatedTargetProperty.cxx
+ cmEvaluatedTargetProperty.h
cmExprParserHelper.cxx
cmExportBuildAndroidMKGenerator.h
cmExportBuildAndroidMKGenerator.cxx
diff --git a/Source/cmEvaluatedTargetProperty.cxx b/Source/cmEvaluatedTargetProperty.cxx
new file mode 100644
index 0000000..1173690
--- /dev/null
+++ b/Source/cmEvaluatedTargetProperty.cxx
@@ -0,0 +1,111 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmEvaluatedTargetProperty.h"
+
+#include <unordered_map>
+#include <utility>
+
+#include "cmGeneratorExpressionContext.h"
+#include "cmGeneratorTarget.h"
+#include "cmLinkItem.h"
+#include "cmStringAlgorithms.h"
+
+struct cmGeneratorExpressionDAGChecker;
+
+EvaluatedTargetPropertyEntry::EvaluatedTargetPropertyEntry(
+ cmLinkImplItem const& item, cmListFileBacktrace bt)
+ : LinkImplItem(item)
+ , Backtrace(std::move(bt))
+{
+}
+
+EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry(
+ cmGeneratorTarget const* thisTarget, std::string const& config,
+ std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
+ cmGeneratorTarget::TargetPropertyEntry& entry)
+{
+ EvaluatedTargetPropertyEntry ee(entry.LinkImplItem, entry.GetBacktrace());
+ cmExpandList(entry.Evaluate(thisTarget->GetLocalGenerator(), config,
+ thisTarget, dagChecker, lang),
+ ee.Values);
+ if (entry.GetHadContextSensitiveCondition()) {
+ ee.ContextDependent = true;
+ }
+ return ee;
+}
+
+EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries(
+ cmGeneratorTarget const* thisTarget, std::string const& config,
+ std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
+ std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>> const&
+ in)
+{
+ EvaluatedTargetPropertyEntries out;
+ out.Entries.reserve(in.size());
+ for (auto const& entry : in) {
+ out.Entries.emplace_back(EvaluateTargetPropertyEntry(
+ thisTarget, config, lang, dagChecker, *entry));
+ }
+ return out;
+}
+
+namespace {
+void addInterfaceEntry(cmGeneratorTarget const* headTarget,
+ std::string const& config, std::string const& prop,
+ std::string const& lang,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ EvaluatedTargetPropertyEntries& entries,
+ cmGeneratorTarget::LinkInterfaceFor interfaceFor,
+ std::vector<cmLinkImplItem> const& libraries)
+{
+ for (cmLinkImplItem const& lib : libraries) {
+ if (lib.Target) {
+ EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
+ // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
+ // caller's property and hand-evaluate it as if it were compiled.
+ // Create a context as cmCompiledGeneratorExpression::Evaluate does.
+ cmGeneratorExpressionContext context(
+ headTarget->GetLocalGenerator(), config, false, headTarget, headTarget,
+ true, lib.Backtrace, lang);
+ cmExpandList(lib.Target->EvaluateInterfaceProperty(
+ prop, &context, dagChecker, interfaceFor),
+ ee.Values);
+ ee.ContextDependent = context.HadContextSensitiveCondition;
+ entries.Entries.emplace_back(std::move(ee));
+ }
+ }
+}
+}
+
+void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
+ std::string const& config, std::string const& prop,
+ std::string const& lang,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ EvaluatedTargetPropertyEntries& entries,
+ IncludeRuntimeInterface searchRuntime,
+ cmGeneratorTarget::LinkInterfaceFor interfaceFor)
+{
+ if (searchRuntime == IncludeRuntimeInterface::Yes) {
+ if (cmLinkImplementation const* impl =
+ headTarget->GetLinkImplementation(config, interfaceFor)) {
+ entries.HadContextSensitiveCondition =
+ impl->HadContextSensitiveCondition;
+
+ auto runtimeLibIt = impl->LanguageRuntimeLibraries.find(lang);
+ if (runtimeLibIt != impl->LanguageRuntimeLibraries.end()) {
+ addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
+ interfaceFor, runtimeLibIt->second);
+ }
+ addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
+ interfaceFor, impl->Libraries);
+ }
+ } else {
+ if (cmLinkImplementationLibraries const* impl =
+ headTarget->GetLinkImplementationLibraries(config, interfaceFor)) {
+ entries.HadContextSensitiveCondition =
+ impl->HadContextSensitiveCondition;
+ addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
+ interfaceFor, impl->Libraries);
+ }
+ }
+}
diff --git a/Source/cmEvaluatedTargetProperty.h b/Source/cmEvaluatedTargetProperty.h
new file mode 100644
index 0000000..e413ab0
--- /dev/null
+++ b/Source/cmEvaluatedTargetProperty.h
@@ -0,0 +1,80 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "cmGeneratorTarget.h"
+#include "cmListFileCache.h"
+
+class cmLinkImplItem;
+struct cmGeneratorExpressionDAGChecker;
+
+// Represent a target property entry after evaluating generator expressions
+// and splitting up lists.
+struct EvaluatedTargetPropertyEntry
+{
+ EvaluatedTargetPropertyEntry(cmLinkImplItem const& item,
+ cmListFileBacktrace bt);
+
+ // Move-only.
+ EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry&&) = default;
+ EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry const&) = delete;
+ EvaluatedTargetPropertyEntry& operator=(EvaluatedTargetPropertyEntry&&) =
+ delete;
+ EvaluatedTargetPropertyEntry& operator=(
+ EvaluatedTargetPropertyEntry const&) = delete;
+
+ cmLinkImplItem const& LinkImplItem;
+ cmListFileBacktrace Backtrace;
+ std::vector<std::string> Values;
+ bool ContextDependent = false;
+};
+
+EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry(
+ cmGeneratorTarget const* thisTarget, std::string const& config,
+ std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
+ cmGeneratorTarget::TargetPropertyEntry& entry);
+
+struct EvaluatedTargetPropertyEntries
+{
+ std::vector<EvaluatedTargetPropertyEntry> Entries;
+ bool HadContextSensitiveCondition = false;
+};
+
+EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries(
+ cmGeneratorTarget const* thisTarget, std::string const& config,
+ std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
+ std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>> const&
+ in);
+
+// IncludeRuntimeInterface is used to break the cycle in computing
+// the necessary transitive dependencies of targets that can occur
+// now that we have implicit language runtime targets.
+//
+// To determine the set of languages that a target has we need to iterate
+// all the sources which includes transitive INTERFACE sources.
+// Therefore we can't determine what language runtimes are needed
+// for a target until after all sources are computed.
+//
+// Therefore while computing the applicable INTERFACE_SOURCES we
+// must ignore anything in LanguageRuntimeLibraries or we would
+// create a cycle ( INTERFACE_SOURCES requires LanguageRuntimeLibraries,
+// LanguageRuntimeLibraries requires INTERFACE_SOURCES).
+//
+enum class IncludeRuntimeInterface
+{
+ Yes,
+ No
+};
+
+void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
+ std::string const& config, std::string const& prop,
+ std::string const& lang,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ EvaluatedTargetPropertyEntries& entries,
+ IncludeRuntimeInterface searchRuntime,
+ cmGeneratorTarget::LinkInterfaceFor interfaceFor =
+ cmGeneratorTarget::LinkInterfaceFor::Usage);
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index caf8ac2..437ae69 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -106,6 +106,9 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gte,
cmGeneratorExpression::BuildInterface,
properties);
+ this->PopulateInterfaceProperty("INTERFACE_AUTOMOC_MACRO_NAMES", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties);
this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gte,
cmGeneratorExpression::BuildInterface,
properties);
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index def8227..51c91f3 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -110,6 +110,9 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gt,
cmGeneratorExpression::InstallInterface,
properties);
+ this->PopulateInterfaceProperty("INTERFACE_AUTOMOC_MACRO_NAMES", gt,
+ cmGeneratorExpression::InstallInterface,
+ properties);
this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gt,
cmGeneratorExpression::InstallInterface,
properties);
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index bc5505f..90cddb5 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -27,6 +27,7 @@
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmCustomCommandGenerator.h"
+#include "cmEvaluatedTargetProperty.h"
#include "cmFileSet.h"
#include "cmFileTimes.h"
#include "cmGeneratedFileStream.h"
@@ -89,31 +90,38 @@ cmTargetPropertyComputer::ComputeLocation<cmGeneratorTarget>(
return tgt->GetLocation(config);
}
-class cmGeneratorTarget::TargetPropertyEntry
-{
-protected:
- static cmLinkImplItem NoLinkImplItem;
+cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem;
+class TargetPropertyEntryString : public cmGeneratorTarget::TargetPropertyEntry
+{
public:
- TargetPropertyEntry(cmLinkImplItem const& item)
- : LinkImplItem(item)
+ TargetPropertyEntryString(BT<std::string> propertyValue,
+ cmLinkImplItem const& item = NoLinkImplItem)
+ : cmGeneratorTarget::TargetPropertyEntry(item)
+ , PropertyValue(std::move(propertyValue))
{
}
- virtual ~TargetPropertyEntry() = default;
- virtual const std::string& Evaluate(
- cmLocalGenerator* lg, const std::string& config,
- cmGeneratorTarget const* headTarget,
- cmGeneratorExpressionDAGChecker* dagChecker,
- std::string const& language) const = 0;
+ const std::string& Evaluate(cmLocalGenerator*, const std::string&,
+ cmGeneratorTarget const*,
+ cmGeneratorExpressionDAGChecker*,
+ std::string const&) const override
+ {
+ return this->PropertyValue.Value;
+ }
- virtual cmListFileBacktrace GetBacktrace() const = 0;
- virtual std::string const& GetInput() const = 0;
- virtual bool GetHadContextSensitiveCondition() const { return false; }
+ cmListFileBacktrace GetBacktrace() const override
+ {
+ return this->PropertyValue.Backtrace;
+ }
+ std::string const& GetInput() const override
+ {
+ return this->PropertyValue.Value;
+ }
- cmLinkImplItem const& LinkImplItem;
+private:
+ BT<std::string> PropertyValue;
};
-cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem;
class TargetPropertyEntryGenex : public cmGeneratorTarget::TargetPropertyEntry
{
@@ -150,37 +158,6 @@ private:
const std::unique_ptr<cmCompiledGeneratorExpression> ge;
};
-class TargetPropertyEntryString : public cmGeneratorTarget::TargetPropertyEntry
-{
-public:
- TargetPropertyEntryString(BT<std::string> propertyValue,
- cmLinkImplItem const& item = NoLinkImplItem)
- : cmGeneratorTarget::TargetPropertyEntry(item)
- , PropertyValue(std::move(propertyValue))
- {
- }
-
- const std::string& Evaluate(cmLocalGenerator*, const std::string&,
- cmGeneratorTarget const*,
- cmGeneratorExpressionDAGChecker*,
- std::string const&) const override
- {
- return this->PropertyValue.Value;
- }
-
- cmListFileBacktrace GetBacktrace() const override
- {
- return this->PropertyValue.Backtrace;
- }
- std::string const& GetInput() const override
- {
- return this->PropertyValue.Value;
- }
-
-private:
- BT<std::string> PropertyValue;
-};
-
class TargetPropertyEntryFileSet
: public cmGeneratorTarget::TargetPropertyEntry
{
@@ -263,6 +240,18 @@ std::unique_ptr<
cm::make_unique<TargetPropertyEntryString>(propertyValue));
}
+cmGeneratorTarget::TargetPropertyEntry::TargetPropertyEntry(
+ cmLinkImplItem const& item)
+ : LinkImplItem(item)
+{
+}
+
+bool cmGeneratorTarget::TargetPropertyEntry::GetHadContextSensitiveCondition()
+ const
+{
+ return false;
+}
+
static void CreatePropertyGeneratorExpressions(
cmake& cmakeInstance, cmBTStringRange entries,
std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>>& items,
@@ -274,69 +263,6 @@ static void CreatePropertyGeneratorExpressions(
}
}
-namespace {
-// Represent a target property entry after evaluating generator expressions
-// and splitting up lists.
-struct EvaluatedTargetPropertyEntry
-{
- EvaluatedTargetPropertyEntry(cmLinkImplItem const& item,
- cmListFileBacktrace bt)
- : LinkImplItem(item)
- , Backtrace(std::move(bt))
- {
- }
-
- // Move-only.
- EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry&&) = default;
- EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry const&) = delete;
- EvaluatedTargetPropertyEntry& operator=(EvaluatedTargetPropertyEntry&&) =
- delete;
- EvaluatedTargetPropertyEntry& operator=(
- EvaluatedTargetPropertyEntry const&) = delete;
-
- cmLinkImplItem const& LinkImplItem;
- cmListFileBacktrace Backtrace;
- std::vector<std::string> Values;
- bool ContextDependent = false;
-};
-
-EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry(
- cmGeneratorTarget const* thisTarget, std::string const& config,
- std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
- cmGeneratorTarget::TargetPropertyEntry& entry)
-{
- EvaluatedTargetPropertyEntry ee(entry.LinkImplItem, entry.GetBacktrace());
- cmExpandList(entry.Evaluate(thisTarget->GetLocalGenerator(), config,
- thisTarget, dagChecker, lang),
- ee.Values);
- if (entry.GetHadContextSensitiveCondition()) {
- ee.ContextDependent = true;
- }
- return ee;
-}
-
-struct EvaluatedTargetPropertyEntries
-{
- std::vector<EvaluatedTargetPropertyEntry> Entries;
- bool HadContextSensitiveCondition = false;
-};
-
-EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries(
- cmGeneratorTarget const* thisTarget, std::string const& config,
- std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
- std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>> const&
- in)
-{
- EvaluatedTargetPropertyEntries out;
- out.Entries.reserve(in.size());
- for (auto const& entry : in) {
- out.Entries.emplace_back(EvaluateTargetPropertyEntry(
- thisTarget, config, lang, dagChecker, *entry));
- }
- return out;
-}
-}
-
cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
: Target(t)
{
@@ -1607,84 +1533,6 @@ void AddLangSpecificImplicitIncludeDirectories(
}
}
-void addInterfaceEntry(cmGeneratorTarget const* headTarget,
- std::string const& config, std::string const& prop,
- std::string const& lang,
- cmGeneratorExpressionDAGChecker* dagChecker,
- EvaluatedTargetPropertyEntries& entries,
- LinkInterfaceFor interfaceFor,
- std::vector<cmLinkImplItem> const& libraries)
-{
- for (cmLinkImplItem const& lib : libraries) {
- if (lib.Target) {
- EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
- // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
- // caller's property and hand-evaluate it as if it were compiled.
- // Create a context as cmCompiledGeneratorExpression::Evaluate does.
- cmGeneratorExpressionContext context(
- headTarget->GetLocalGenerator(), config, false, headTarget, headTarget,
- true, lib.Backtrace, lang);
- cmExpandList(lib.Target->EvaluateInterfaceProperty(
- prop, &context, dagChecker, interfaceFor),
- ee.Values);
- ee.ContextDependent = context.HadContextSensitiveCondition;
- entries.Entries.emplace_back(std::move(ee));
- }
- }
-}
-
-// IncludeRuntimeInterface is used to break the cycle in computing
-// the necessary transitive dependencies of targets that can occur
-// now that we have implicit language runtime targets.
-//
-// To determine the set of languages that a target has we need to iterate
-// all the sources which includes transitive INTERFACE sources.
-// Therefore we can't determine what language runtimes are needed
-// for a target until after all sources are computed.
-//
-// Therefore while computing the applicable INTERFACE_SOURCES we
-// must ignore anything in LanguageRuntimeLibraries or we would
-// create a cycle ( INTERFACE_SOURCES requires LanguageRuntimeLibraries,
-// LanguageRuntimeLibraries requires INTERFACE_SOURCES).
-//
-enum class IncludeRuntimeInterface
-{
- Yes,
- No
-};
-void AddInterfaceEntries(
- cmGeneratorTarget const* headTarget, std::string const& config,
- std::string const& prop, std::string const& lang,
- cmGeneratorExpressionDAGChecker* dagChecker,
- EvaluatedTargetPropertyEntries& entries,
- IncludeRuntimeInterface searchRuntime,
- LinkInterfaceFor interfaceFor = LinkInterfaceFor::Usage)
-{
- if (searchRuntime == IncludeRuntimeInterface::Yes) {
- if (cmLinkImplementation const* impl =
- headTarget->GetLinkImplementation(config, interfaceFor)) {
- entries.HadContextSensitiveCondition =
- impl->HadContextSensitiveCondition;
-
- auto runtimeLibIt = impl->LanguageRuntimeLibraries.find(lang);
- if (runtimeLibIt != impl->LanguageRuntimeLibraries.end()) {
- addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
- interfaceFor, runtimeLibIt->second);
- }
- addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
- interfaceFor, impl->Libraries);
- }
- } else {
- if (cmLinkImplementationLibraries const* impl =
- headTarget->GetLinkImplementationLibraries(config, interfaceFor)) {
- entries.HadContextSensitiveCondition =
- impl->HadContextSensitiveCondition;
- addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
- interfaceFor, impl->Libraries);
- }
- }
-}
-
void AddObjectEntries(cmGeneratorTarget const* headTarget,
std::string const& config,
cmGeneratorExpressionDAGChecker* dagChecker,
@@ -8977,10 +8825,10 @@ std::string cmGeneratorTarget::GenerateHeaderSetVerificationFile(
cmGeneratedFileStream fout(filename);
fout.SetCopyIfDifferent(true);
- // IWYU pragma: associated allows include what you use to
+ // The IWYU "associated" pragma tells include-what-you-use to
// consider the headerFile as part of the entire language
// unit within include-what-you-use and as a result allows
- // one to get IWYU advice for headers :)
+ // one to get IWYU advice for headers.
fout << "#include <" << headerFilename << "> // IWYU pragma: associated\n";
fout.close();
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 256ca3b..87227fd 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -1291,3 +1291,25 @@ private:
};
mutable std::map<std::string, InfoByConfig> Configs;
};
+
+class cmGeneratorTarget::TargetPropertyEntry
+{
+protected:
+ static cmLinkImplItem NoLinkImplItem;
+
+public:
+ TargetPropertyEntry(cmLinkImplItem const& item);
+ virtual ~TargetPropertyEntry() = default;
+
+ virtual const std::string& Evaluate(
+ cmLocalGenerator* lg, const std::string& config,
+ cmGeneratorTarget const* headTarget,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ std::string const& language) const = 0;
+
+ virtual cmListFileBacktrace GetBacktrace() const = 0;
+ virtual std::string const& GetInput() const = 0;
+ virtual bool GetHadContextSensitiveCondition() const;
+
+ cmLinkImplItem const& LinkImplItem;
+};
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index eb3f433..3563a1a 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1544,8 +1544,9 @@ bool cmGlobalGenerator::Compute()
}
#ifndef CMAKE_BOOTSTRAP
- cmQtAutoGenGlobalInitializer qtAutoGen(this->LocalGenerators);
- if (!qtAutoGen.InitializeCustomTargets()) {
+ this->QtAutoGen =
+ cm::make_unique<cmQtAutoGenGlobalInitializer>(this->LocalGenerators);
+ if (!this->QtAutoGen->InitializeCustomTargets()) {
return false;
}
#endif
@@ -1565,12 +1566,6 @@ bool cmGlobalGenerator::Compute()
}
}
-#ifndef CMAKE_BOOTSTRAP
- if (!qtAutoGen.SetupCustomTargets()) {
- return false;
- }
-#endif
-
for (const auto& localGen : this->LocalGenerators) {
cmMakefile* mf = localGen->GetMakefile();
for (const auto& g : mf->GetInstallGenerators()) {
@@ -1635,6 +1630,17 @@ void cmGlobalGenerator::Generate()
this->CMakeInstance->UpdateProgress("Generating", 0.1f);
+#ifndef CMAKE_BOOTSTRAP
+ if (!this->QtAutoGen->SetupCustomTargets()) {
+ if (!cmSystemTools::GetErrorOccurredFlag()) {
+ this->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "Problem setting up custom targets for QtAutoGen");
+ }
+ return;
+ }
+#endif
+
// Generate project files
for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
this->SetCurrentMakefile(this->LocalGenerators[i]->GetMakefile());
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 0e0624a..dde3648 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -50,6 +50,7 @@ class cmLinkLineComputer;
class cmLocalGenerator;
class cmMakefile;
class cmOutputConverter;
+class cmQtAutoGenGlobalInitializer;
class cmSourceFile;
class cmState;
class cmStateDirectory;
@@ -683,6 +684,11 @@ protected:
cmake* CMakeInstance;
std::vector<std::unique_ptr<cmMakefile>> Makefiles;
LocalGeneratorVector LocalGenerators;
+
+#ifndef CMAKE_BOOTSTRAP
+ std::unique_ptr<cmQtAutoGenGlobalInitializer> QtAutoGen;
+#endif
+
cmMakefile* CurrentConfigureMakefile;
// map from project name to vector of local generators in that project
std::map<std::string, std::vector<cmLocalGenerator*>> ProjectMap;
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index ba4c4d8..782c154 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -28,8 +28,10 @@
#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
+#include "cmEvaluatedTargetProperty.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLinkItem.h"
@@ -1691,6 +1693,23 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
info.SetArray("MOC_OPTIONS", this->Moc.Options);
info.SetBool("MOC_RELAXED_MODE", this->Moc.RelaxedMode);
info.SetBool("MOC_PATH_PREFIX", this->Moc.PathPrefix);
+
+ cmGeneratorExpressionDAGChecker dagChecker(
+ this->GenTarget, "AUTOMOC_MACRO_NAMES", nullptr, nullptr);
+ EvaluatedTargetPropertyEntries InterfaceAutoMocMacroNamesEntries;
+
+ AddInterfaceEntries(this->GenTarget, this->ConfigDefault,
+ "INTERFACE_AUTOMOC_MACRO_NAMES", "CXX", &dagChecker,
+ InterfaceAutoMocMacroNamesEntries,
+ IncludeRuntimeInterface::Yes);
+
+ for (auto const& entry : InterfaceAutoMocMacroNamesEntries.Entries) {
+ this->Moc.MacroNames.insert(this->Moc.MacroNames.end(),
+ entry.Values.begin(), entry.Values.end());
+ }
+ this->Moc.MacroNames.erase(cmRemoveDuplicates(this->Moc.MacroNames),
+ this->Moc.MacroNames.end());
+
info.SetArray("MOC_MACRO_NAMES", this->Moc.MacroNames);
info.SetArrayArray(
"MOC_DEPEND_FILTERS", this->Moc.DependFilters,
diff --git a/Tests/QtAutogen/MocInterfaceMacroNames/CMakeLists.txt b/Tests/QtAutogen/MocInterfaceMacroNames/CMakeLists.txt
new file mode 100644
index 0000000..7744d78
--- /dev/null
+++ b/Tests/QtAutogen/MocInterfaceMacroNames/CMakeLists.txt
@@ -0,0 +1,61 @@
+cmake_minimum_required(VERSION 3.16)
+project(MocInterfaceMacroNames)
+
+include("../AutogenCoreTest.cmake")
+
+set(CMAKE_AUTOMOC ON)
+
+add_executable(dummy dummy.cpp)
+target_link_libraries(dummy PRIVATE static_lib interface_lib shared_lib)
+
+add_library(shared_lib SHARED shared_lib.cpp)
+set_target_properties(shared_lib PROPERTIES INTERFACE_AUTOMOC_MACRO_NAMES "SHARED_LIB_MACRO")
+
+add_library(interface_lib INTERFACE)
+set_target_properties(interface_lib PROPERTIES INTERFACE_AUTOMOC_MACRO_NAMES "INTERFACE_LIB_MACRO")
+
+add_library(static_lib STATIC static_lib.cpp)
+set_target_properties(static_lib PROPERTIES INTERFACE_AUTOMOC_MACRO_NAMES "STATIC_LIB_MACRO")
+
+set(AUTOGEN_INFO_FILE "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/dummy_autogen.dir/AutogenInfo.json")
+set(CHECK_AUTOGEN_JSON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CheckAutogenJson.cmake")
+message(STATUS "AutogenInfo.json: ${AUTOGEN_INFO_FILE}")
+
+add_custom_command(TARGET dummy POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -DFILE_PATH=${AUTOGEN_INFO_FILE} -P ${CHECK_AUTOGEN_JSON_PATH}
+)
+
+install(TARGETS shared_lib EXPORT shared_lib)
+install(TARGETS interface_lib EXPORT interface_lib)
+install(TARGETS static_lib EXPORT static_lib)
+
+install(EXPORT shared_lib FILE shared_libTargets.cmake DESTINATION lib/cmake/shared_lib)
+install(EXPORT interface_lib FILE interface_libTargets.cmake DESTINATION lib/cmake/interface_lib)
+install(EXPORT static_lib FILE static_libTargets.cmake DESTINATION lib/cmake/static_lib)
+
+set(CHECK_EXPORT_TARGETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CheckExportTargets.cmake")
+set(EXPORT_FOLDER_PATH "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Export")
+
+add_custom_command(TARGET dummy POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -DFOLDER_PATH=${EXPORT_FOLDER_PATH} -P ${CHECK_EXPORT_TARGETS_PATH}
+)
+
+# check if INTERFACE_AUTOMOC_MACRO_NAMES were transferred to the *_link libraries correctly
+add_executable(dummy_link dummy.cpp)
+target_link_libraries(dummy_link PRIVATE static_link_lib interface_link_lib shared_link_lib)
+
+add_library(shared_link_lib SHARED shared_lib.cpp)
+target_link_libraries(shared_link_lib PUBLIC shared_lib)
+
+add_library(interface_link_lib INTERFACE)
+target_link_libraries(interface_link_lib INTERFACE interface_lib)
+
+add_library(static_link_lib STATIC static_lib.cpp)
+target_link_libraries(static_link_lib PUBLIC static_lib)
+
+set(AUTOGEN_INFO_FILE "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/dummy_link_autogen.dir/AutogenInfo.json")
+message(STATUS "AutogenInfo.json: ${AUTOGEN_INFO_FILE}")
+
+add_custom_command(TARGET dummy_link POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -DFILE_PATH=${AUTOGEN_INFO_FILE} -P ${CHECK_AUTOGEN_JSON_PATH}
+)
diff --git a/Tests/QtAutogen/MocInterfaceMacroNames/CheckAutogenJson.cmake b/Tests/QtAutogen/MocInterfaceMacroNames/CheckAutogenJson.cmake
new file mode 100644
index 0000000..338f345
--- /dev/null
+++ b/Tests/QtAutogen/MocInterfaceMacroNames/CheckAutogenJson.cmake
@@ -0,0 +1,27 @@
+
+
+set(expected_values "SHARED_LIB_MACRO" "INTERFACE_LIB_MACRO" "STATIC_LIB_MACRO")
+function(checkAutoMocMacroNames FILE_PATH)
+ message(STATUS "Checking for auto moc macro names in ${FILE_PATH}")
+ file(READ ${FILE_PATH} FILE_CONTENT)
+ string(JSON MOC_MACRO_NAMES_ARR GET ${FILE_CONTENT} MOC_MACRO_NAMES)
+ # get the length of MOC_MACRO_NAMES in JSON
+ string(JSON MOC_MACRO_NAMES_LENGTH LENGTH ${MOC_MACRO_NAMES_ARR})
+ if(${MOC_MACRO_NAMES_LENGTH} EQUAL 0)
+ message(FATAL_ERROR "MOC_MACRO_NAMES is empty")
+ endif()
+ message(STATUS "MOC_MACRO_NAMES: ${MOC_MACRO_NAMES_ARR}")
+
+ math(EXPR last_index "${MOC_MACRO_NAMES_LENGTH} - 1")
+ set(reverse_index ${last_index})
+ foreach(expected_value IN LISTS expected_values)
+ string(JSON element GET ${MOC_MACRO_NAMES_ARR} ${reverse_index})
+ # check if element equals to expected value
+ if(NOT ${element} STREQUAL ${expected_value})
+ message(FATAL_ERROR "MOC_MACRO_NAMES is expected to contain ${expected_value} but contains ${element}")
+ endif()
+ math(EXPR reverse_index "${reverse_index} - 1")
+ endforeach()
+endfunction()
+
+checkAutoMocMacroNames(${FILE_PATH})
diff --git a/Tests/QtAutogen/MocInterfaceMacroNames/CheckExportTargets.cmake b/Tests/QtAutogen/MocInterfaceMacroNames/CheckExportTargets.cmake
new file mode 100644
index 0000000..9db23f6
--- /dev/null
+++ b/Tests/QtAutogen/MocInterfaceMacroNames/CheckExportTargets.cmake
@@ -0,0 +1,45 @@
+
+set(TARGET_NAMES "static_lib" "shared_lib" "interface_lib")
+set(static_lib_FOUND "0")
+set(shared_lib_FOUND "0")
+set(interface_lib_FOUND "0")
+
+macro(checkExportTargets FOLDER_PATH)
+ message("Checking folder: ${FOLDER_PATH}")
+ file(GLOB sources_list LIST_DIRECTORIES true RELATIVE ${FOLDER_PATH} ${FOLDER_PATH}/*)
+ message("Found files and folders: ${sources_list}")
+ foreach(source ${sources_list})
+ set(SOURCE_ABS "${FOLDER_PATH}/${source}")
+ if(IS_DIRECTORY ${SOURCE_ABS})
+ message("Found subfolder: ${source}")
+ checkExportTargets(${SOURCE_ABS})
+ else()
+ message("Found file: ${source}")
+ foreach(TARGET_NAME ${TARGET_NAMES})
+ set(TARGETS_FILE "${TARGET_NAME}Targets.cmake")
+ if(${source} STREQUAL ${TARGETS_FILE})
+ message("Found ${TARGETS_FILE} in ${FOLDER_PATH}")
+ string(TOUPPER ${TARGET_NAME} TARGET_NAME_UPPER)
+ set(expected_macro "${TARGET_NAME_UPPER}_MACRO")
+ set(expected_string "INTERFACE_AUTOMOC_MACRO_NAMES \"${expected_macro}\"")
+ file(READ ${FOLDER_PATH}/${source} contents)
+ if (NOT contents MATCHES ${expected_string})
+ message(FATAL_ERROR "Expected ${expected_string} in ${FOLDER_PATH}/${source}")
+ else()
+ message("Found ${expected_string} in ${FOLDER_PATH}/${source}")
+ set(${TARGET_NAME}_FOUND "1")
+ endif()
+ endif()
+ endforeach()
+ endif()
+ endforeach()
+endmacro()
+
+checkExportTargets(${FOLDER_PATH})
+
+foreach(TARGET_NAME ${TARGET_NAMES})
+ # check if the target found equals the expected value
+ if(NOT ${TARGET_NAME}_FOUND STREQUAL "1")
+ message(FATAL_ERROR "Did not find ${TARGET_NAME}Targets.cmake")
+ endif()
+endforeach()
diff --git a/Tests/QtAutogen/MocInterfaceMacroNames/dummy.cpp b/Tests/QtAutogen/MocInterfaceMacroNames/dummy.cpp
new file mode 100644
index 0000000..f8b643a
--- /dev/null
+++ b/Tests/QtAutogen/MocInterfaceMacroNames/dummy.cpp
@@ -0,0 +1,4 @@
+int main()
+{
+ return 0;
+}
diff --git a/Tests/QtAutogen/MocInterfaceMacroNames/shared_lib.cpp b/Tests/QtAutogen/MocInterfaceMacroNames/shared_lib.cpp
new file mode 100644
index 0000000..3a5c482
--- /dev/null
+++ b/Tests/QtAutogen/MocInterfaceMacroNames/shared_lib.cpp
@@ -0,0 +1,6 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ void foo()
+{
+}
diff --git a/Tests/QtAutogen/MocInterfaceMacroNames/static_lib.cpp b/Tests/QtAutogen/MocInterfaceMacroNames/static_lib.cpp
new file mode 100644
index 0000000..3695dc9
--- /dev/null
+++ b/Tests/QtAutogen/MocInterfaceMacroNames/static_lib.cpp
@@ -0,0 +1,3 @@
+void foo()
+{
+}
diff --git a/Tests/QtAutogen/Tests.cmake b/Tests/QtAutogen/Tests.cmake
index b507ab5..412d511 100644
--- a/Tests/QtAutogen/Tests.cmake
+++ b/Tests/QtAutogen/Tests.cmake
@@ -7,6 +7,7 @@ ADD_AUTOGEN_TEST(GlobalAutogenTarget)
ADD_AUTOGEN_TEST(GlobalAutogenExecutable)
ADD_AUTOGEN_TEST(LowMinimumVersion lowMinimumVersion)
ADD_AUTOGEN_TEST(ManySources manySources)
+ADD_AUTOGEN_TEST(MocInterfaceMacroNames)
ADD_AUTOGEN_TEST(MocOnly mocOnly)
ADD_AUTOGEN_TEST(MocOptions mocOptions)
ADD_AUTOGEN_TEST(ObjectLibrary someProgram)
diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp
index 1afad43..6443632 100644
--- a/Utilities/IWYU/mapping.imp
+++ b/Utilities/IWYU/mapping.imp
@@ -99,6 +99,7 @@
{ symbol: [ "std::enable_if<true, std::chrono::duration<long, std::ratio<60, 1> > >::type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::enable_if<true, std::chrono::duration<long, std::ratio<1, 1000> > >::type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "__gnu_cxx::__enable_if<true, bool>::__type", private, "\"cmConfigure.h\"", public ] },
+ { symbol: [ "std::remove_reference<Defer &>::type", private, "\"cmConfigure.h\"", public ] },
# Wrappers for 3rd-party libraries
{ include: [ "@<.*curl/curlver.h>", private, "<cm3p/curl/curl.h>", public ] },
diff --git a/bootstrap b/bootstrap
index 3d5ef40..a006aee 100755
--- a/bootstrap
+++ b/bootstrap
@@ -338,6 +338,7 @@ CMAKE_CXX_SOURCES="\
cmELF \
cmEnableLanguageCommand \
cmEnableTestingCommand \
+ cmEvaluatedTargetProperty \
cmExecProgramCommand \
cmExecuteProcessCommand \
cmExpandedCommandArgument \