qt6_wrap_cpp: Add .moc generation
When a `.moc` file is included in a source file and that source passed to `qt_wrap_cpp`, Users should add the generated `.moc`s path to the target's include path. Since we don't share anything about the output path of generated files by `qt_wrap_cpp`, it makes sense to add in inside `qt_wrap_cpp`. And also, the generated `.moc` file is added to target's source to complete the dependency graph. Otherwise, Users need to get output variable and pass it to target's sources. * Update docs * Add test [ChangeLog][Build System] qt_wrap_cpp will accept .cpp files from now on. When .cpp a file is passed to qt_wrap_cpp, TARGET parameter becomes required. Generated .moc files are added to target's sources inside qt_wrap_cpp. That's why the output parameter will not contain generated .moc files. Fixes: QTBUG-113402 Change-Id: I54dd2b1ff8e5c9ba457b1eb4f73b0a8190d9c659 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io> Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This commit is contained in:
parent
bcdd51cfae
commit
dc4159286b
@ -200,7 +200,49 @@ function(qt6_wrap_cpp outfiles )
|
|||||||
|
|
||||||
foreach(it ${moc_files})
|
foreach(it ${moc_files})
|
||||||
get_filename_component(it ${it} ABSOLUTE)
|
get_filename_component(it ${it} ABSOLUTE)
|
||||||
_qt_internal_make_output_file(${it} moc_ cpp outfile)
|
get_filename_component(it_ext ${it} EXT)
|
||||||
|
# remove the dot
|
||||||
|
string(SUBSTRING ${it_ext} 1 -1 it_ext)
|
||||||
|
set(HEADER_REGEX "(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$")
|
||||||
|
|
||||||
|
if(it_ext MATCHES "${HEADER_REGEX}")
|
||||||
|
_qt_internal_make_output_file("${it}" moc_ cpp outfile)
|
||||||
|
set(is_header_file TRUE)
|
||||||
|
else()
|
||||||
|
set(found_source_extension FALSE)
|
||||||
|
foreach(LANG C CXX OBJC OBJCXX CUDA)
|
||||||
|
list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${it_ext}"
|
||||||
|
index)
|
||||||
|
if(${index} GREATER -1)
|
||||||
|
set(found_extension TRUE)
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
if(found_extension)
|
||||||
|
if(TARGET ${moc_target})
|
||||||
|
_qt_internal_make_output_file(${it} "" moc outfile)
|
||||||
|
target_sources(${moc_target} PRIVATE "${outfile}")
|
||||||
|
target_include_directories("${moc_target}" PRIVATE
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
else()
|
||||||
|
if("${moc_target}" STREQUAL "")
|
||||||
|
string(JOIN "" err_msg
|
||||||
|
"qt6_wrap_cpp: TARGET parameter is empty. "
|
||||||
|
"Since the file ${it} is a source file, "
|
||||||
|
"the TARGET option must be specified.")
|
||||||
|
else()
|
||||||
|
string(JOIN "" err_msg
|
||||||
|
"qt6_wrap_cpp: TARGET \"${moc_target}\" "
|
||||||
|
"not found.")
|
||||||
|
endif()
|
||||||
|
message(FATAL_ERROR "${err_msg}")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
string(JOIN "" err_msg "qt6_wrap_cpp: Unknown file extension: "
|
||||||
|
"\"\.${it_ext}\".")
|
||||||
|
message(FATAL_ERROR "${err_msg}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
set(out_json_file_var "")
|
set(out_json_file_var "")
|
||||||
if(_WRAP_CPP___QT_INTERNAL_OUTPUT_MOC_JSON_FILES)
|
if(_WRAP_CPP___QT_INTERNAL_OUTPUT_MOC_JSON_FILES)
|
||||||
@ -215,7 +257,10 @@ function(qt6_wrap_cpp outfiles )
|
|||||||
list(APPEND metatypes_json_list "${${out_json_file_var}}")
|
list(APPEND metatypes_json_list "${${out_json_file_var}}")
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
set(${outfiles} ${${outfiles}} PARENT_SCOPE)
|
|
||||||
|
if(is_header_file)
|
||||||
|
set(${outfiles} "${${outfiles}}" PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(metatypes_json_list)
|
if(metatypes_json_list)
|
||||||
set(${_WRAP_CPP___QT_INTERNAL_OUTPUT_MOC_JSON_FILES}
|
set(${_WRAP_CPP___QT_INTERNAL_OUTPUT_MOC_JSON_FILES}
|
||||||
|
@ -28,6 +28,11 @@ target_compile_definitions(myapp PRIVATE "$<$<CONFIG:Debug>:MY_OPTION_FOR_DEBUG>
|
|||||||
"$<$<BOOL:TRUE>:DEFINE_CMDLINE_SIGNAL_IN_GENEX=void cmdlineSignal(const QMap<int$<COMMA> int$<ANGLE-R> &i)>")
|
"$<$<BOOL:TRUE>:DEFINE_CMDLINE_SIGNAL_IN_GENEX=void cmdlineSignal(const QMap<int$<COMMA> int$<ANGLE-R> &i)>")
|
||||||
#! [qt_wrap_cpp_3]
|
#! [qt_wrap_cpp_3]
|
||||||
|
|
||||||
|
#! [qt_wrap_cpp_4]
|
||||||
|
qt_add_executable(myapp myapp.cpp main.cpp)
|
||||||
|
qt_wrap_cpp("" myapp.cpp TARGET myapp)
|
||||||
|
#! [qt_wrap_cpp_4]
|
||||||
|
|
||||||
#! [qt_add_resources]
|
#! [qt_add_resources]
|
||||||
set(SOURCES main.cpp)
|
set(SOURCES main.cpp)
|
||||||
qt_add_resources(SOURCES example.qrc)
|
qt_add_resources(SOURCES example.qrc)
|
||||||
|
16
src/corelib/doc/snippets/cmake-macros/examples.cpp
Normal file
16
src/corelib/doc/snippets/cmake-macros/examples.cpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||||
|
|
||||||
|
//! [qt_wrap_cpp_4]
|
||||||
|
// myapp.cpp
|
||||||
|
#include "myapp.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class MyApp : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
MyApp() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "myapp.moc"
|
||||||
|
//! [qt_wrap_cpp_4]
|
@ -40,6 +40,12 @@ You can set an explicit \c{TARGET}. This will make sure that the target
|
|||||||
properties \c{INCLUDE_DIRECTORIES} and \c{COMPILE_DEFINITIONS} are also used
|
properties \c{INCLUDE_DIRECTORIES} and \c{COMPILE_DEFINITIONS} are also used
|
||||||
when scanning the source files with \c{moc}.
|
when scanning the source files with \c{moc}.
|
||||||
|
|
||||||
|
Since Qt 6.8, when a source file is passed to \c{qt_wrap_cpp} instead of a
|
||||||
|
header file to generate a \c{.moc} file for a target, the \c{TARGET} parameter
|
||||||
|
is needed to set the correct include path for the generated \c{.moc} file in
|
||||||
|
the source file. As generated \c{.moc} files are added to the target's
|
||||||
|
sources by \c{qt_wrap_cpp}, they are not added to \c{<VAR>}.
|
||||||
|
|
||||||
You can set additional \c{OPTIONS} that should be added to the \c{moc} calls.
|
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}.
|
You can find possible options in the \l{moc}{moc documentation}.
|
||||||
|
|
||||||
@ -69,5 +75,16 @@ avoid syntax errors in the generator expressions.
|
|||||||
The following example uses \l{https://cmake.org/cmake/help/latest/command/target_compile_definitions.html}{target_compile_definitions}
|
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
|
to set \l{https://cmake.org/cmake/help/latest/prop_tgt/COMPILE_DEFINITIONS.html}{COMPILE_DEFINITIONS} which will be added to
|
||||||
\c{OPTIONS}.
|
\c{OPTIONS}.
|
||||||
\snippet cmake-macros/examples.cmake qt_wrap_cpp_3
|
|
||||||
|
\snippet cmake-macros/examples.cmake qt_wrap_cpp_4
|
||||||
|
|
||||||
|
\snippet cmake-macros/examples.cpp qt_wrap_cpp_4
|
||||||
|
|
||||||
|
In the above file, \c{myapp.moc} is included in \c{myapp.cpp}.
|
||||||
|
To generate the \c{myapp.moc} file, the \c{qt_wrap_cpp} macro is used with the
|
||||||
|
\c{TARGET} parameter. The first parameter is empty because the \c{.moc} file
|
||||||
|
and its path will be added to the target's sources and include directories by
|
||||||
|
the \c{qt_wrap_cpp} macro.
|
||||||
|
|
||||||
|
\snippet cmake-macros/examples.cmake qt_wrap_cpp_4
|
||||||
*/
|
*/
|
||||||
|
@ -197,6 +197,7 @@ endif()
|
|||||||
_qt_internal_test_expect_pass(test_add_resource_prefix BINARY test_add_resource_prefix)
|
_qt_internal_test_expect_pass(test_add_resource_prefix BINARY test_add_resource_prefix)
|
||||||
_qt_internal_test_expect_build_fail(test_add_resource_options)
|
_qt_internal_test_expect_build_fail(test_add_resource_options)
|
||||||
_qt_internal_test_expect_build_fail(test_wrap_cpp_options)
|
_qt_internal_test_expect_build_fail(test_wrap_cpp_options)
|
||||||
|
_qt_internal_test_expect_pass(test_wrap_cpp_moc)
|
||||||
_qt_internal_test_expect_pass(test_platform_defs_include)
|
_qt_internal_test_expect_pass(test_platform_defs_include)
|
||||||
_qt_internal_test_expect_pass(test_qtmainwin_library)
|
_qt_internal_test_expect_pass(test_qtmainwin_library)
|
||||||
|
|
||||||
|
19
tests/auto/cmake/test_wrap_cpp_moc/CMakeLists.txt
Normal file
19
tests/auto/cmake/test_wrap_cpp_moc/CMakeLists.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
project(test_wrap_cpp_and_resources)
|
||||||
|
|
||||||
|
find_package(Qt6Core REQUIRED)
|
||||||
|
|
||||||
|
add_executable(example main.cpp)
|
||||||
|
|
||||||
|
qt_wrap_cpp(moc_files main.cpp TARGET example)
|
||||||
|
|
||||||
|
# expect the generated moc files to be empty when a source file is passed
|
||||||
|
if (NOT moc_files STREQUAL "")
|
||||||
|
message(FATAL_ERROR "test_qt_wrap_cpp_moc: moc_files should be empty")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(example PRIVATE Qt::Core)
|
17
tests/auto/cmake/test_wrap_cpp_moc/main.cpp
Normal file
17
tests/auto/cmake/test_wrap_cpp_moc/main.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class MyObject2 : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
MyObject2() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "main.moc"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user