Add the support for custom definitions to the qt_manual_moc function

The function now support two new arguments:
 - DEFINITIONS, which allows specifying the custom definitions
 - TARGETS, the list of targets thart will be used to collect
   the [INTERFACE_]INCLUDE_DIRECTORIES and COMPILE_DEFINITIONS.

Task-number: QTBUG-104898
Change-Id: I3f67537057f91a97597788f1bd4db6904bac6d9c
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
bb10
Alexey Edelev 2024-02-20 16:43:42 +01:00
parent 4148fcced6
commit 2c0120d35b
7 changed files with 173 additions and 5 deletions

View File

@ -78,14 +78,23 @@ endfunction()
# Complete manual moc invocation with full control.
# Use AUTOMOC whenever possible.
# INCLUDE_DIRECTORIES specifies a list of include directories used by 'moc'.
# INCLUDE_DIRECTORY_TARGETS specifies a list of targets to extract the INTERFACE_INCLUDE_DIRECTORIES
# property and use it as the 'moc' include directories.
# Multi-value Arguments:
# INCLUDE_DIRECTORIES
# Specifies a list of include directories used by 'moc'.
# INCLUDE_DIRECTORY_TARGETS
# Specifies a list of targets to extract the INTERFACE_INCLUDE_DIRECTORIES
# property and use it as the 'moc' include directories.(Deprecated use TARGETS instead)
# DEFINITIONS
# List of the definitions that should be added to the moc command line arguments.
# Supports the syntax both with and without the prepending '-D'.
# TARGETS
# The list of targets that will be used to collect the INTERFACE_INCLUDE_DIRECTORIES,
# INCLUDE_DIRECTORIES, and COMPILE_DEFINITIONS properties.
function(qt_manual_moc result)
cmake_parse_arguments(arg
""
"OUTPUT_MOC_JSON_FILES"
"FLAGS;INCLUDE_DIRECTORIES;INCLUDE_DIRECTORY_TARGETS"
"FLAGS;INCLUDE_DIRECTORIES;INCLUDE_DIRECTORY_TARGETS;DEFINITIONS;TARGETS"
${ARGN})
set(moc_files)
set(metatypes_json_list)
@ -102,7 +111,7 @@ function(qt_manual_moc result)
"-I\n${dir}")
endforeach()
foreach(dep IN ITEMS ${arg_INCLUDE_DIRECTORY_TARGETS})
foreach(dep IN LISTS arg_INCLUDE_DIRECTORY_TARGETS arg_TARGETS)
set(include_expr "$<TARGET_PROPERTY:${dep},INTERFACE_INCLUDE_DIRECTORIES>")
list(APPEND moc_parameters
"$<$<BOOL:${include_expr}>:-I\n$<JOIN:${include_expr},\n-I\n>>")
@ -128,6 +137,30 @@ function(qt_manual_moc result)
endif()
endforeach()
foreach(dep IN LISTS arg_TARGETS)
set(include_property_expr
"$<TARGET_GENEX_EVAL:${dep},$<TARGET_PROPERTY:${dep},INCLUDE_DIRECTORIES>>")
list(APPEND moc_parameters
"$<$<BOOL:${include_property_expr}>:-I\n$<JOIN:${include_property_expr},\n-I\n>>")
set(defines_property_expr
"$<TARGET_GENEX_EVAL:${dep},$<TARGET_PROPERTY:${dep},COMPILE_DEFINITIONS>>")
set(defines_with_d "$<FILTER:${defines_property_expr},INCLUDE,^-D>")
set(defines_without_d "$<FILTER:${defines_property_expr},EXCLUDE,^-D>")
list(APPEND moc_parameters
"$<$<BOOL:${defines_with_d}>:$<JOIN:${defines_with_d},\n>>")
list(APPEND moc_parameters
"$<$<BOOL:${defines_without_d}>:-D\n$<JOIN:${defines_without_d},\n-D\n>>")
endforeach()
foreach(def IN LISTS arg_DEFINITIONS)
if(NOT def MATCHES "^-D")
list(APPEND moc_parameters "-D\n${def}")
else()
list(APPEND moc_parameters "${def}")
endif()
endforeach()
set(metatypes_byproducts)
if (arg_OUTPUT_MOC_JSON_FILES)
set(moc_json_file "${outfile}.json")

View File

@ -402,3 +402,5 @@ _qt_internal_test_expect_pass(test_QTP0003)
if(NOT NO_GUI)
_qt_internal_test_expect_pass(test_collecting_plugins)
endif()
_qt_internal_test_expect_pass(test_qt_manual_moc)

View File

@ -0,0 +1,61 @@
# Copyright (C) 2024 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals Core)
set(CMAKE_AUTOMOC FALSE)
qt_manual_moc(moc_files testclass.h
DEFINITIONS
-DMY_FIRST_DEF
MY_SECOND_DEF
-DMY_THIRD_DEF=1
MY_FOURTH_DEF=1
)
add_custom_target(verify_testclass ALL COMMAND ${CMAKE_COMMAND}
"-DMOC_ARGS=moc_testclass.cpp_parameters$<$<BOOL:$<CONFIG>>:_$<CONFIG>>"
"-DDEFINITIONS=MY_FIRST_DEF;MY_SECOND_DEF;MY_THIRD_DEF=1;MY_FOURTH_DEF=1"
-P "${CMAKE_CURRENT_SOURCE_DIR}/VerifyDefines.cmake"
VERBATIM
)
add_library(MyInterfaceLib INTERFACE)
target_compile_definitions(MyInterfaceLib INTERFACE -DMY_TRANSITIVE_DEF=1)
add_library(MyLib SHARED testclass1.h testclass.cpp)
target_link_libraries(MyLib PRIVATE Qt6::Core MyInterfaceLib)
target_compile_definitions(MyLib PRIVATE
-DMY_FIRST_DEF
MY_SECOND_DEF
-DMY_THIRD_DEF=1
MY_FOURTH_DEF=1
)
add_library(MyLib2 SHARED testclass1.h testclass.cpp)
target_link_libraries(MyLib2 PRIVATE Qt6::Core)
target_compile_definitions(MyLib2 PRIVATE
-DMY_FOREIGN_DEF
)
qt_manual_moc(moc_files testclass1.h TARGETS MyLib MyLib2)
target_sources(MyLib PRIVATE ${moc_files})
target_sources(MyLib2 PRIVATE ${moc_files})
string(JOIN ";" expected
"MY_FIRST_DEF"
"MY_SECOND_DEF"
"MY_THIRD_DEF=1"
"MY_FOURTH_DEF=1"
"MY_TRANSITIVE_DEF=1"
"MY_FOREIGN_DEF"
)
add_custom_target(verify_testclass1 ALL COMMAND ${CMAKE_COMMAND}
"-DMOC_ARGS=moc_testclass1.cpp_parameters$<$<BOOL:$<CONFIG>>:_$<CONFIG>>"
"-DDEFINITIONS=${expected}"
-P "${CMAKE_CURRENT_SOURCE_DIR}/VerifyDefines.cmake"
VERBATIM
)

View File

@ -0,0 +1,30 @@
# Copyright (C) 2024 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
if(NOT DEFINITIONS)
message(FATAL_ERROR "No definitions are provided to test")
endif()
if(NOT MOC_ARGS)
message(FATAL_ERROR "The moc RSP file is not specified")
endif()
file(READ "${MOC_ARGS}" moc_args_data)
string(REPLACE "\n" ";" moc_args_data "${moc_args_data}")
foreach(def IN LISTS DEFINITIONS)
set(found FALSE)
foreach(data IN LISTS moc_args_data)
if(data MATCHES "^(-D)?${def}")
set(found TRUE)
break()
endif()
endforeach()
if(NOT found)
message(FATAL_ERROR "The ${def} is missing in the moc argument list:\n${moc_args_data}")
endif()
endforeach()

View File

@ -0,0 +1,8 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testclass.h"
TestClass::TestClass(QObject *parent) : QObject(parent)
{
}

View File

@ -0,0 +1,17 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTCLASS_H
#define TESTCLASS_H
#include <QObject>
class TestClass : public QObject
{
Q_OBJECT
public:
TestClass(QObject *parent = nullptr);
};
#endif // TESTCLASS_H

View File

@ -0,0 +1,17 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTCLASS_H
#define TESTCLASS_H
#include <QObject>
class TestClass : public QObject
{
Q_OBJECT
public:
TestClass(QObject *parent = nullptr);
};
#endif // TESTCLASS_H