summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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/cmExportBuildFileGenerator.cxx3
-rw-r--r--Source/cmExportInstallFileGenerator.cxx3
-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
15 files changed, 274 insertions, 2 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/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/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)