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})
|
||||
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 "")
|
||||
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}}")
|
||||
endif()
|
||||
endforeach()
|
||||
set(${outfiles} ${${outfiles}} PARENT_SCOPE)
|
||||
|
||||
if(is_header_file)
|
||||
set(${outfiles} "${${outfiles}}" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if(metatypes_json_list)
|
||||
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)>")
|
||||
#! [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]
|
||||
set(SOURCES main.cpp)
|
||||
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
|
||||
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 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}
|
||||
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
|
||||
|
||||
\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_build_fail(test_add_resource_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_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