_qt_internal_create_moc_command: Fix genex parse

The function was replacing the `>` character in generator expressions coming from `add_compile_definitions`. This was creating generator expression syntax errors. Discard generator expressions from character replacing.
Add tests for the three cases.

Amends 5bb745f62ba1aa63e4bbd107b279d96bd06dffda

Fixes: QTBUG-111717
Fixes: QTBUG-119716
Change-Id: I694d2908738085fdf15112834f20183a9f393422
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
(cherry picked from commit bc0c44d4cd634c574307920968f0ab1bf6cd8305)
Reviewed-by: Orkun Tokdemir <orkun.tokdemir@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
This commit is contained in:
Orkun Tokdemir 2023-07-13 15:30:09 +02:00 committed by Alexandru Croitor
parent dc86b61d77
commit e4c396f254
5 changed files with 93 additions and 5 deletions

View File

@ -101,11 +101,22 @@ function(_qt_internal_create_moc_command infile outfile moc_flags moc_options
set(targetincludes "$<$<BOOL:${targetincludes}>:-I$<JOIN:${targetincludes},;-I>>")
set(targetdefines "$<$<BOOL:${targetdefines}>:-D$<JOIN:${targetdefines},;-D>>")
string(REPLACE ">" "$<ANGLE-R>" _moc_escaped_parameters "${_moc_parameters}")
string(REPLACE "," "$<COMMA>" _moc_escaped_parameters "${_moc_escaped_parameters}")
set(_moc_parameters_list_without_genex)
set(_moc_parameters_list_with_genex)
foreach(_moc_parameter ${_moc_parameters})
if(_moc_parameter MATCHES "\\\$<")
list(APPEND _moc_parameters_list_with_genex ${_moc_parameter})
else()
list(APPEND _moc_parameters_list_without_genex ${_moc_parameter})
endif()
endforeach()
string(REPLACE ">" "$<ANGLE-R>" _moc_escaped_parameters "${_moc_parameters_list_without_genex}")
string(REPLACE "," "$<COMMA>" _moc_escaped_parameters "${_moc_escaped_parameters}")
string(REPLACE ";" "$<SEMICOLON>" _moc_escaped_parameters "${_moc_escaped_parameters}")
set(concatenated "$<$<BOOL:${targetincludes}>:${targetincludes};>$<$<BOOL:${targetdefines}>:${targetdefines};>$<$<BOOL:${_moc_escaped_parameters}>:${_moc_escaped_parameters};>")
list(APPEND concatenated ${_moc_parameters_list_with_genex})
set(concatenated "$<FILTER:$<REMOVE_DUPLICATES:${concatenated}>,EXCLUDE,^-[DI]$>")
set(concatenated "$<JOIN:${concatenated},\n>")

View File

@ -1,11 +1,32 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#! [qt_wrap_cpp]
#! [qt_wrap_cpp_1]
set(SOURCES myapp.cpp main.cpp)
qt_wrap_cpp(SOURCES myapp.h)
qt_add_executable(myapp ${SOURCES})
#! [qt_wrap_cpp]
#! [qt_wrap_cpp_1]
#! [qt_wrap_cpp_2]
set(SOURCES myapp.cpp main.cpp)
qt_wrap_cpp(SOURCES myapp.h
TARGET myapp
OPTIONS
"$<$<CONFIG:Debug>:-DMY_OPTION_FOR_DEBUG>"
"-DDEFINE_CMDLINE_SIGNAL=void cmdlineSignal(const QMap<int, int> &i)"
"$<$<CONFIG:Debug>:-DDEFINE_CMDLINE_SIGNAL_IN_GENEX=void cmdlineSignal(const QMap<int$<COMMA> int$<ANGLE-R> &i)>")
qt_add_executable(myapp ${SOURCES})
#! [qt_wrap_cpp_2]
#! [qt_wrap_cpp_3]
set(SOURCES myapp.cpp main.cpp)
qt_wrap_cpp(SOURCES myapp.h
TARGET myapp)
qt_add_executable(myapp ${SOURCES})
target_compile_definitions(myapp PRIVATE "$<$<CONFIG:Debug>:MY_OPTION_FOR_DEBUG>"
"DEFINE_CMDLINE_SIGNAL=void cmdlineSignal(const QMap<int, int> &i)"
"$<$<BOOL:TRUE>:DEFINE_CMDLINE_SIGNAL_IN_GENEX=void cmdlineSignal(const QMap<int$<COMMA> int$<ANGLE-R> &i)>")
#! [qt_wrap_cpp_3]
#! [qt_add_resources]
set(SOURCES main.cpp)

View File

@ -43,6 +43,14 @@ when scanning the source files with \c{moc}.
You can set additional \c{OPTIONS} that should be added to the \c{moc} calls.
You can find possible options in the \l{moc}{moc documentation}.
The \c{OPTIONS} can evaluate generator expressions when \c{TARGET} is set.
\note If the \c{OPTIONS} include both generator expressions and special
characters, use variables to implement them. For example, use \c{$<ANGLE-R>},
\c{$<COMMA>} and \c{$<SEMICOLON>} instead of \c{>}, \c{,} and \c{:}. Otherwise,
the generator expression will not be evaluated correctly. \c {OPTIONS} are
wrapped in generator expressions, so you must escape special characters in
them.
\c{DEPENDS} allows you to add additional dependencies for recreation of the
generated files. This is useful when the sources have implicit dependencies,
like code for a Qt plugin that includes a \c{.json} file using the
@ -50,5 +58,16 @@ Q_PLUGIN_METADATA() macro.
\section1 Examples
\snippet cmake-macros/examples.cmake qt_wrap_cpp
\snippet cmake-macros/examples.cmake qt_wrap_cpp_1
In the following example, the generator expressions passed to \c{OPTIONS}
will be evaluated since \c{TARGET} is set. The argument is specified this way to
avoid syntax errors in the generator expressions.
\snippet cmake-macros/examples.cmake qt_wrap_cpp_2
The following example uses \l{https://cmake.org/cmake/help/latest/command/target_compile_definitions.html}{target_compile_definitions}
to set \l{https://cmake.org/cmake/help/latest/prop_tgt/COMPILE_DEFINITIONS.html}{COMPILE_DEFINITIONS} which will be added to
\c{OPTIONS}.
\snippet cmake-macros/examples.cmake qt_wrap_cpp_3
*/

View File

@ -24,3 +24,25 @@ qt_wrap_cpp(moc_file mywrapobject.h
add_executable(QtWrapMacroTest main_wrap_test.cpp ${moc_file})
target_include_directories(QtWrapMacroTest PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/interface")
target_link_libraries(QtWrapMacroTest PRIVATE Qt::Core)
target_compile_definitions(QtWrapMacroTest PRIVATE "$<$<BOOL:TRUE>:MY_OPTION>"
"$<$<BOOL:TRUE>:DEFINE_CMDLINE_SIGNAL=void cmdlineSignal(const QMap<int$<COMMA> int$<ANGLE-R> &i)>"
"DEFINE_CMDLINE_SIGNAL=void cmdlineSignal(const QMap<int, int> &i)")
set(parameters_file_base "${CMAKE_CURRENT_BINARY_DIR}/moc_mywrapobject.cpp_parameters")
# check if generator is multi-config
if(CMAKE_CONFIGURATION_TYPES)
set(parameters_file "${parameters_file_base}_$<CONFIG>")
else()
if(NOT CMAKE_BUILD_TYPE STREQUAL "")
set(parameters_file "${parameters_file_base}_${CMAKE_BUILD_TYPE}")
else()
set(parameters_file "${parameters_file_base}")
endif()
endif()
add_custom_command(TARGET QtWrapMacroTest
POST_BUILD
COMMAND ${CMAKE_COMMAND} "-DPARAMETERS_FILE_PATH=${parameters_file}" -P check_moc_parameters.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@ -0,0 +1,15 @@
function(check_parameters file_path)
file(READ ${file_path} file_content)
foreach(compile_option IN ITEMS "-DDEFINE_CMDLINE_SIGNAL" "-DMY_OPTION")
string(REGEX MATCHALL "${compile_option}" matches ${file_content})
list(LENGTH matches matches_length)
if(matches_length GREATER 1)
message(FATAL_ERROR "${compile_option} is defined multiple times in ${file_path}")
elseif(matches_length EQUAL 0)
message(FATAL_ERROR "${compile_option} is not defined in ${file_path}")
endif()
endforeach()
endfunction()
check_parameters(${PARAMETERS_FILE_PATH})