CMake: Use AUTOMOC/AUTOUIC/AUTORCC

Change-Id: I0235ca4f227623e5937348b4b010637921dbf154
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
Tobias Hunger 2018-12-12 10:55:20 +01:00 committed by Simon Hausmann
parent 07dfa3013c
commit e57a94cbd8
26 changed files with 101 additions and 1026 deletions

View File

@ -222,43 +222,6 @@ function(qt_internal_add_linker_version_script target)
endif()
endfunction()
# Generates the necessary rules to run moc on the sources specified after the MOC parameter.
# The resulting moc files are added to the target.
function(qt_internal_wrap_cpp target)
# get include dirs
qt_get_moc_flags(moc_flags)
qt_parse_all_arguments(arg "qt_internal_wrap_cpp" "" "HEADER_FILE_ONLY" "OPTIONS;DEPENDS;MOC" ${ARGN})
set(outfiles)
get_target_property(binary_dir "${target}" BINARY_DIR)
get_target_property(source_dir "${target}" SOURCE_DIR)
foreach(it ${arg_MOC})
get_filename_component(moc_file_extension ${it} EXT)
if("x${moc_file_extension}" STREQUAL "x.h")
set(file_prefix "moc_")
set(file_extension ".cpp")
else()
set(file_prefix "")
set(file_extension ".moc")
endif()
qt_make_output_file("${it}" "${file_prefix}" "${file_extension}" "${source_dir}" "${binary_dir}" outfile)
qt_create_moc_command("${target}" "${source_dir}" "${it}" "${outfile}" "${moc_flags}" "${arg_OPTIONS}" "${arg_DEPENDS}")
set_source_files_properties("${outfile}" PROPERTIES HEADER_FILE_ONLY ${arg_HEADER_FILE_ONLY})
if (arg_HEADER_FILE_ONLY)
get_filename_component(directory "${outfile}" DIRECTORY)
target_include_directories("${target}" PRIVATE "${directory}")
endif()
list(APPEND outfiles "${outfile}")
endforeach()
target_sources("${target}" PRIVATE "${outfiles}")
endfunction()
# Get a set of Qt module related values based on the target name.
# When doing qt_internal_module_info(foo Core) this method will set
@ -280,157 +243,6 @@ function(qt_internal_module_info result target)
endfunction()
# This function takes a target as a parameter, followed by a list of sources.
# The sources are scanned for Q_OBJECT/Q_GADGET use as well as the inclusion of
# moc_*.cpp/*.moc. Rules are created to call moc accordingly at build time and
# add the generated sources to the target, if the generated code is not
# directly included otherwise.
function(qt_internal_automoc target)
if ("x${ARGN}" STREQUAL "x")
return()
endif()
if(NOT DEFINED QT_MOCSCANNER)
get_target_property(mocPath "Qt::moc" LOCATION)
get_filename_component(binDirectory "${mocPath}" DIRECTORY)
set(QT_MOCSCANNER "${binDirectory}/qmocscanner${CMAKE_EXECUTABLE_SUFFIX}")
endif()
string(REPLACE ";" "\n" sources "${ARGN}")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/moc_sources_and_headers.txt" ${sources})
execute_process(COMMAND "${QT_MOCSCANNER}"
"${CMAKE_CURRENT_BINARY_DIR}/moc_sources_and_headers.txt"
"${CMAKE_CURRENT_BINARY_DIR}/moc_files_included.txt"
"${CMAKE_CURRENT_BINARY_DIR}/moc_files_to_build.txt"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/moc_files_included.txt" moc_files_included)
file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/moc_files_to_build.txt" moc_files_to_build)
file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/moc_sources_and_headers.txt")
file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/moc_files_included.txt")
file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/moc_files_to_build.txt")
qt_internal_wrap_cpp("${target}" MOC ${moc_files_included} HEADER_FILE_ONLY ON)
qt_internal_wrap_cpp("${target}" MOC ${moc_files_to_build} HEADER_FILE_ONLY OFF)
endfunction()
# This function takes a target as a parameter, followed by a list of sources.
# Any sources with the .ui extension are passed on to uic and the generated output
# is added to the target sources.
function(qt_internal_autouic target)
set(outfiles "")
get_target_property(source_dir "${target}" SOURCE_DIR)
get_target_property(binary_dir "${target}" BINARY_DIR)
foreach(infile ${ARGN})
get_filename_component(ext "${infile}" EXT)
if("${ext}" STREQUAL ".ui")
qt_make_output_file("${infile}" "ui_" ".h" "${source_dir}" "${binary_dir}" outfile)
qt_create_uic_command("${infile}" "${source_dir}" "${outfile}")
list(APPEND outfiles "${outfile}")
get_filename_component(outfile_path "${outfile}" PATH)
target_include_directories("${target}" PRIVATE "${outfile_path}")
endif()
endforeach()
target_sources("${target}" PRIVATE "${outfiles}")
endfunction()
# This function attempts to (poorly) parse the given resourceFile (.qrc) and
# determine the dependencies, i.e. which files are intended for inclusion into
# the Qt resource.
function(qt_extract_qrc_dependencies resourceFile out_depends_ rc_depends_)
get_filename_component(rc_path ${resourceFile} PATH)
if(EXISTS "${infile}")
# parse file for dependencies
# all files are absolute paths or relative to the location of the qrc file
file(READ "${infile}" RC_FILE_CONTENTS)
string(REGEX MATCHALL "<file[^<]+" RC_FILES "${RC_FILE_CONTENTS}")
set(RC_DEPENDS "")
foreach(RC_FILE ${RC_FILES})
string(REGEX REPLACE "^<file[^>]*>" "" RC_FILE "${RC_FILE}")
if(NOT IS_ABSOLUTE "${RC_FILE}")
set(RC_FILE "${rc_path}/${RC_FILE}")
endif()
set(RC_DEPENDS ${RC_DEPENDS} "${RC_FILE}")
endforeach()
# Since this cmake function is doing the dependency scanning for these files,
# let's make a configured file and add it as a dependency so cmake is run
# again when dependencies need to be recomputed.
qt_make_output_file("${infile}" "" ".qrc.depends" "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" out_depends)
configure_file("${infile}" "${out_depends}" COPYONLY)
else()
# The .qrc file does not exist (yet). Let's add a dependency and hope
# that it will be generated later
set(out_depends)
endif()
set(${out_depends_} ${out_depends} PARENT_SCOPE)
set(${rc_depends_} ${RC_DEPENDS} PARENT_SCOPE)
endfunction()
# This function creates the necessary rule to call rcc on the given
# resource file and stores the name of the to-be generated C++ source
# file (created by rcc) in the outCppFile variable.
function(qt_create_rcc_command resourceFile source_dir binary_dir outfile)
qt_extract_qrc_dependencies("${infile}" out_depends rc_depends "${source_dir}" "${binary_dir}")
set_source_files_properties("${infile}" PROPERTIES SKIP_AUTORCC ON)
get_filename_component(outfilename "${resourceFile}" NAME_WE)
add_custom_command(OUTPUT "${outfile}"
COMMAND "Qt::rcc" --name "${outfilename}" --output "${outfile}" "${resourceFile}"
MAIN_DEPENDENCY "${infile}"
DEPENDS "${rc_depends}" "${out_depends}"
WORKING_DIRECTORY "${source_dir}" VERBATIM)
set_source_files_properties("${outfile}" PROPERTIES SKIP_AUTOMOC ON)
set_source_files_properties("${outfile}" PROPERTIES SKIP_AUTOUIC ON)
endfunction()
# This function takes a target as a parameter, followed by a list of sources.
# Any sources ending with the .qrc extension are treated as Qt resources and rules
# to call rcc are generated. The source files rcc generates are added to the target.
function(qt_internal_autorcc target)
get_target_property(binary_dir "${target}" BINARY_DIR)
get_target_property(source_dir "${target}" SOURCE_DIR)
set(qrc_outfiles "")
foreach(infile ${ARGN})
get_filename_component(ext "${infile}" EXT)
if("${ext}" STREQUAL ".qrc")
qt_make_output_file("${infile}" "qrc_" ".cpp" "${source_dir}" "${binary_dir}" outfile)
list(FIND all_sources "${outfile}" known_result)
if (known_result GREATER -1)
continue()
endif()
qt_create_rcc_command("${infile}" "${source_dir}" "${binary_dir}" "${outfile}")
list(APPEND qrc_outfiles "${outfile}")
endif()
endforeach()
target_sources("${target}" PRIVATE "${qrc_outfiles}")
endfunction()
# This function takes a target as a parameter, followed by a list of sources.
# The sources are scanned for .ui and .qrc as well as Q_OBJECT/Q_GADGET use
# and rules to call uic/rcc/moc are created. Any generated sources are added
# as private sources to the specified target.
function(qt_internal_process_automatic_sources target)
qt_internal_automoc("${target}" ${ARGN})
qt_internal_autouic("${target}" ${ARGN})
qt_internal_autorcc("${target}" ${ARGN})
endfunction()
set(__default_private_args "SOURCES;LIBRARIES;INCLUDE_DIRECTORIES;DEFINES;DBUS_ADAPTOR_FLAGS;DBUS_ADAPTOR_SOURCES;DBUS_INTERFACE_FLAGS;DBUS_INTERFACE_SOURCES;FEATURE_DEPENDENCIES")
set(__default_public_args "PUBLIC_LIBRARIES;PUBLIC_INCLUDE_DIRECTORIES;PUBLIC_DEFINES")
@ -459,7 +271,6 @@ function(extend_target target)
qt_create_qdbusxml2cpp_command("${target}" "${interface}" INTERFACE FLAGS "${arg_DBUS_INTERFACE_FLAGS}")
list(APPEND dbus_sources "${sources}")
endforeach()
qt_internal_process_automatic_sources("${target}" "${arg_SOURCES}")
# Import features
if(NOT "${target}" STREQUAL "Core")
@ -487,6 +298,15 @@ function(extend_target target)
endif()
endforeach()
set_target_properties("${target}" PROPERTIES
AUTOMOC ON
AUTOMOC_EXECUTABLE "$<TARGET_FILE:Qt::moc>"
AUTORCC ON
AUTORCC_EXECUTABLE "$<TARGET_FILE:Qt::rcc>"
AUTOUIC ON
AUTOUIC_EXECUTABLE "$<TARGET_FILE:Qt::uic>"
)
target_sources("${target}" PRIVATE ${arg_SOURCES} ${dbus_sources})
if (arg_COMPILE_FLAGS)
set_source_files_properties(${arg_SOURCES} PROPERTIES COMPILE_FLAGS "${arg_COMPILE_FLAGS}")
@ -882,19 +702,14 @@ function(add_qt_tool name)
endif()
add_qt_executable("${name}" OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${INSTALL_BINDIR}"
# Do not pass sources here: They may not get processed when BOOTSTRAP is set!
SOURCES ${arg_SOURCES}
INCLUDE_DIRECTORIES
${arg_INCLUDE_DIRECTORIES}
DEFINES ${arg_DEFINES}
LIBRARIES ${corelib} ${arg_LIBRARIES}
)
target_sources("${name}" PRIVATE "${arg_SOURCES}")
qt_internal_add_target_aliases("${name}")
if (NOT arg_BOOTSTRAP)
qt_internal_process_automatic_sources("${name}" ${arg_SOURCES})
endif()
install(TARGETS "${name}" EXPORT "Qt${PROJECT_VERSION_MAJOR}ToolsTargets" DESTINATION ${INSTALL_TARGETS_DEFAULT_ARGS})
qt_push_features_into_parent_scope()
endfunction()
@ -968,75 +783,28 @@ function(qt_make_output_file infile prefix suffix source_dir binary_dir result)
endfunction()
macro(qt_get_moc_flags moc_flags)
set(${moc_flags})
get_directory_property(inc_DIRS INCLUDE_DIRECTORIES)
# Complete manual moc invocation with full control.
# Use AUTOMOC whenever possible.
function(qt_manual_moc result)
cmake_parse_arguments(arg "" "" "FLAGS" ${ARGN})
set(moc_files)
foreach(infile ${arg_UNPARSED_ARGUMENTS})
qt_make_output_file("${infile}" "moc_" ".cpp"
"${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" outfile)
list(APPEND moc_files "${outfile}")
if(CMAKE_INCLUDE_CURRENT_DIR)
list(APPEND inc_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
endif()
foreach(current ${inc_DIRS})
if("${current}" MATCHES "\\.framework/?$")
string(REGEX REPLACE "/[^/]+\\.framework" "" framework_path "${current}")
set(${moc_flags} ${${moc_flags}} "-F${framework_path}")
else()
set(${moc_flags} ${${moc_flags}} "-I${current}")
endif()
endforeach()
get_directory_property(defines COMPILE_DEFINITIONS)
foreach(current ${defines})
set(${moc_flags} ${${moc_flags}} "-D${current}")
endforeach()
if(WIN32)
set(${moc_flags} ${${moc_flags}} -DWIN32)
endif()
if (MSVC)
set(${moc_flags} ${${moc_flags}} --compiler-flavor=msvc)
endif()
endmacro()
# helper to set up a moc rule
function(qt_create_moc_command target source_dir infile outfile moc_flags moc_options moc_depends)
# Pass the parameters in a file. Set the working directory to
# be that containing the parameters file and reference it by
# just the file name. This is necessary because the moc tool on
# MinGW builds does not seem to handle spaces in the path to the
# file given with the @ syntax.
set (moc_parameters_file "${outfile}_parameters")
set (moc_parameters ${moc_flags} ${moc_options} -o "${outfile}" "${infile}")
set(moc_parameters_file "${outfile}_parameters$<$<BOOL:$<CONFIGURATION>>:_$<CONFIGURATION>>")
set(moc_parameters ${arg_FLAGS} -o "${outfile}" "${infile}")
string (REPLACE ";" "\n" moc_parameters "${moc_parameters}")
set(moc_parameters_file "${moc_parameters_file}$<$<BOOL:$<CONFIGURATION>>:_$<CONFIGURATION>>")
set(targetincludes "$<TARGET_PROPERTY:${target},INCLUDE_DIRECTORIES>")
set(targetdefines "$<TARGET_PROPERTY:${target},COMPILE_DEFINITIONS>")
set(targetincludes "$<$<BOOL:${targetincludes}>:-I$<JOIN:${targetincludes},\n-I>\n>")
set(targetdefines "$<$<BOOL:${targetdefines}>:-D$<JOIN:${targetdefines},\n-D>\n>")
file(GENERATE OUTPUT "${moc_parameters_file}" CONTENT "${moc_parameters}\n")
file (GENERATE
OUTPUT "${moc_parameters_file}"
CONTENT "${targetdefines}${targetincludes}${moc_parameters}\n"
)
set(moc_extra_parameters_file @${moc_parameters_file})
add_custom_command(OUTPUT "${outfile}"
COMMAND "Qt::moc" "${moc_extra_parameters_file}"
DEPENDS "${infile}" ${moc_depends}
WORKING_DIRECTORY "${source_dir}" VERBATIM)
endfunction()
# helper to set up a uic rule
function(qt_create_uic_command infile source_dir outfile)
add_custom_command(OUTPUT "${outfile}"
COMMAND "Qt::uic" "${infile}" -o "${outfile}"
DEPENDS "${infile}"
COMMENT "Running UIC on ${infile}."
WORKING_DIRECTORY "${source_dir}" VERBATIM)
set_source_files_properties("${outfile}" PROPERTIES HEADER_FILE_ONLY ON)
COMMAND Qt::moc "@${moc_parameters_file}"
DEPENDS "${infile}" ${moc_depends} Qt::moc
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" VERBATIM)
endforeach()
set("${result}" ${moc_files} PARENT_SCOPE)
endfunction()
@ -1066,10 +834,7 @@ function(qt_create_qdbusxml2cpp_command target infile)
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
VERBATIM)
# Moc the header:
qt_internal_wrap_cpp("${target}" MOC "${header_file}" HEADER_FILE_ONLY OFF)
target_sources("${target}" PRIVATE "${header_file}" "${source_file}" "${moc_sources}")
target_sources("${target}" PRIVATE "${header_file}" "${source_file}")
endfunction()

View File

@ -4,6 +4,8 @@ Initial port is on-going. Some modules of QtBase are ported, incl. some of the p
Basic functionality is there (moc, uic, etc.), but documentation, translations, qdbusxml2cpp, etc. are missing.
NOTE: YOU WILL NEED CMAKE 3.14 or later (if that is not released yet you will need to have
https://gitlab.kitware.com/cmake/cmake/merge_requests/2679 applied).
# Intro

View File

@ -45,7 +45,4 @@ macro(add_cmake_test_generate name)
endmacro()
add_cmake_test_generate(features)
add_cmake_test_generate(moc)
add_cmake_test_generate(qrc)
add_cmake_test_generate(qt_make_output_file)
add_cmake_test_generate(uic)

View File

@ -1,34 +0,0 @@
cmake_minimum_required(VERSION 3.12.0)
project(MocTest
VERSION 1.0.0
DESCRIPTION "Moc test"
HOMEPAGE_URL "https://qt.io/"
LANGUAGES CXX
)
## Add some paths to check for cmake modules:
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../;${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/extra-cmake-modules/find-modules;${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/kwin")
## Qt specific setup common for all modules:
include(QtSetup)
include(../test.cmake)
fake_moc_results(MOC foo.cpp sub2/foobar.h MOC_AND_BUILD main.cpp sub/bar.h)
add_qt_executable(test_executable
SOURCES
../main.cpp
sub/bar.h
sub2/foobar.h
foo.cpp
)
test_source_file(test_executable "${CMAKE_CURRENT_BINARY_DIR}/main.moc" BUILD)
test_source_file(test_executable "${CMAKE_CURRENT_BINARY_DIR}/sub/moc_bar.cpp" BUILD)
test_source_file(test_executable "${CMAKE_CURRENT_BINARY_DIR}/sub2/moc_foobar.cpp")
test_source_file(test_executable "${CMAKE_CURRENT_BINARY_DIR}/foo.moc")
test_include_directory(test_executable "${CMAKE_CURRENT_BINARY_DIR}/sub" UNKNOWN)
test_include_directory(test_executable "${CMAKE_CURRENT_BINARY_DIR}/sub2")

View File

@ -1,31 +0,0 @@
cmake_minimum_required(VERSION 3.12.0)
project(QrcTest
VERSION 1.0.0
DESCRIPTION "Qrc test"
HOMEPAGE_URL "https://qt.io/"
LANGUAGES CXX
)
## Add some paths to check for cmake modules:
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../;${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/extra-cmake-modules/find-modules;${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/kwin")
## Qt specific setup common for all modules:
include(QtSetup)
include(../test.cmake)
fake_moc_results()
add_qt_executable(test_executable
SOURCES
../main.cpp
qrc.qrc
)
fake_moc_results()
extend_target(test_executable SOURCES dialog/dialog.qrc)
test_source_file(test_executable "${CMAKE_CURRENT_BINARY_DIR}/qrc_qrc.cpp" BUILD)
test_source_file(test_executable "${CMAKE_CURRENT_BINARY_DIR}/dialog/qrc_dialog.cpp" BUILD)
test_include_directory(test_executable "${CMAKE_CURRENT_BINARY_DIR}/dialog" UNKNOWN)

View File

@ -1,31 +0,0 @@
cmake_minimum_required(VERSION 3.12.0)
project(UicTest
VERSION 1.0.0
DESCRIPTION "Uic test"
HOMEPAGE_URL "https://qt.io/"
LANGUAGES CXX
)
## Add some paths to check for cmake modules:
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../;${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/extra-cmake-modules/find-modules;${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/kwin")
## Qt specific setup common for all modules:
include(QtSetup)
include(../test.cmake)
fake_moc_results()
add_qt_executable(test_executable
SOURCES
../main.cpp
window.ui
)
fake_moc_results()
extend_target(test_executable SOURCES dialog/dialog.ui)
test_source_file(test_executable "${CMAKE_CURRENT_BINARY_DIR}/ui_window.h")
test_source_file(test_executable "${CMAKE_CURRENT_BINARY_DIR}/dialog/ui_dialog.h")
test_include_directory(test_executable "${CMAKE_CURRENT_BINARY_DIR}/dialog")

View File

@ -1,18 +1,6 @@
# Generated from rasterwindow.pro.
#####################################################################
## None Binary:
#####################################################################
set(sources main.cpp
rasterwindow.cpp rasterwindow.h)
add_executable(rasterwindow
${sources}
add_qt_executable(rasterwindow
SOURCES
main.cpp
rasterwindow.cpp rasterwindow.h
LIBRARIES Qt::Core Qt::Test Qt::Gui
)
qt_internal_automoc(rasterwindow ${sources})
target_include_directories(rasterwindow
PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}"
)
target_link_libraries(rasterwindow PRIVATE Qt::Core Qt::Test Qt::Gui)

View File

@ -23,7 +23,6 @@ function(find_or_build_bootstrap_names)
endif()
endfunction()
find_or_build_bootstrap_tool(qmocscanner)
if (_build_tools)
add_subdirectory(tools/bootstrap) # bootstrap library
endif()
@ -32,10 +31,6 @@ function(find_or_build_bootstrap_names)
find_or_build_bootstrap_tool(qfloat16-tables)
find_or_build_bootstrap_tool(tracegen)
# $<TARGET_FILE:Qt::qmocscanner> does not work during configure run, so export into a plain variable:
get_target_property(_mocscanner "Qt::qmocscanner" IMPORTED_LOCATION)
set(QT_MOCSCANNER "${_mocscanner}" CACHE INTERNAL "Qt moc scanner")
if (_build_tools)
install(EXPORT "Qt${PROJECT_VERSION_MAJOR}ToolsTargets" NAMESPACE "Qt::" DESTINATION "${INSTALL_LIBDIR}/cmake/Qt${PROJECT_VERSION_MAJOR}")
endif()
@ -76,4 +71,5 @@ endif()
if (QT_FEATURE_testlib)
add_subdirectory(testlib)
endif()
add_subdirectory(printsupport)
add_subdirectory(plugins)

View File

@ -1,4 +1,3 @@
find_package(Threads)
find_package(WrapDoubleConversion REQUIRED)
@ -51,7 +50,6 @@ add_qt_module(Core
global/qlibraryinfo.cpp global/qlibraryinfo.h
global/qlogging.cpp global/qlogging.h
global/qmalloc.cpp
global/qnamespace.h
global/qnumeric.cpp global/qnumeric.h global/qnumeric_p.h
global/qoperatingsystemversion.cpp global/qoperatingsystemversion.h global/qoperatingsystemversion_p.h
global/qprocessordetection.h
@ -117,7 +115,6 @@ add_qt_module(Core
kernel/qmetatype.cpp kernel/qmetatype.h kernel/qmetatype_p.h
kernel/qmetatypeswitcher_p.h
kernel/qmimedata.cpp kernel/qmimedata.h
kernel/qobject.cpp kernel/qobject.h kernel/qobject_p.h
kernel/qobject_impl.h
kernel/qobjectcleanuphandler.cpp kernel/qobjectcleanuphandler.h
kernel/qobjectdefs.h
@ -229,6 +226,8 @@ add_qt_module(Core
tools/qvector.h
tools/qversionnumber.cpp tools/qversionnumber.h
tools/qvsnprintf.cpp
INCLUDE_DIRECTORIES
${CMAKE_CURRENT_BINARY_DIR}/global # For qconfig.cpp
LIBRARIES
WrapDoubleConversion
WrapRt
@ -240,6 +239,28 @@ add_qt_module(Core
QT_NO_FOREACH
)
# Handle QObject: Automoc does not work for this as it would
# require to spill internals into users:
add_library(Core_qobject OBJECT)
qt_manual_moc(qobject_moc_files kernel/qobject.h global/qnamespace.h)
set_source_files_properties(${qobject_moc_files} PROPERTIES HEADER_FILE_ONLY ON)
target_sources(Core_qobject PRIVATE
global/qnamespace.h
kernel/qobject.cpp kernel/qobject.h kernel/qobject_p.h ${qobject_moc_files})
target_include_directories(Core_qobject PRIVATE
"${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}/global"
"${CMAKE_CURRENT_BINARY_DIR}/kernel"
"${PROJECT_BINARY_DIR}/include"
"${PROJECT_BINARY_DIR}/include/QtCore"
"${PROJECT_BINARY_DIR}/include/QtCore/${PROJECT_VERSION}"
"${PROJECT_BINARY_DIR}/include/QtCore/${PROJECT_VERSION}/QtCore")
target_link_libraries(Core_qobject PRIVATE Qt::Platform)
target_link_libraries(Core PRIVATE Core_qobject)
# Comments trigger moc for these, so skip automoc:
set_source_files_properties( tools/qsharedpointer.cpp PROPERTIES SKIP_AUTOMOC ON)
set_property(TARGET Core APPEND PROPERTY PUBLIC_HEADER "${CMAKE_CURRENT_BINARY_DIR}/global/qconfig.h")
set_property(TARGET Core APPEND PROPERTY PRIVATE_HEADER "${CMAKE_CURRENT_BINARY_DIR}/global/qconfig_p.h")
@ -738,6 +759,7 @@ extend_target(Core CONDITION QT_FEATURE_statemachine
statemachine/qsignaltransition.cpp statemachine/qsignaltransition.h statemachine/qsignaltransition_p.h
statemachine/qstate.cpp statemachine/qstate.h statemachine/qstate_p.h
statemachine/qstatemachine.cpp statemachine/qstatemachine.h statemachine/qstatemachine_p.h
INCLUDE_DIRECTORIES statemachine
)
# qeventtransition:
@ -756,6 +778,7 @@ extend_target(Core CONDITION QT_FEATURE_mimetype
mimetypes/qmimeprovider.cpp mimetypes/qmimeprovider_p.h
mimetypes/qmimetype.cpp mimetypes/qmimetype.h mimetypes/qmimetype_p.h
mimetypes/qmimetypeparser.cpp mimetypes/qmimetypeparser_p.h
INCLUDE_DIRECTORIES mimetypes
)
# Enable Evaluation based on QT_EVAL variable being set from the outside:

View File

@ -4215,8 +4215,8 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
If the QVariant contains a pointer to a type derived from QObject then
\c{T} may be any QObject type. If the pointer stored in the QVariant can be
qobject_cast to T, then that result is returned. Otherwise a null pointer is
returned. Note that this only works for QObject subclasses which use the
Q_OBJECT macro.
returned. Note that this only works for QObject subclasses which use
the Q_OBJECT macro.
If the QVariant contains a sequential container and \c{T} is QVariantList, the
elements of the container will be converted into \l {QVariant}s and returned as a QVariantList.

View File

@ -235,6 +235,14 @@ add_qt_module(Gui
Qt::Core
)
set_source_files_properties(
# Comment triggering moc:
opengl/qopenglfunctions.cpp
PROPERTIES
SKIP_AUTOMOC ON
SKIP_AUTOUIC ON
SKIP_AUTORCC ON)
## Scopes:
#####################################################################

View File

@ -59,7 +59,8 @@ QT_BEGIN_NAMESPACE
namespace QShaderLanguage
{
Q_GUI_EXPORT Q_NAMESPACE
Q_GUI_EXPORT
Q_NAMESPACE
enum StorageQualifier : char {
Const = 1,

View File

@ -58,6 +58,14 @@ add_qt_module(Network
Qt::CorePrivate
)
set_source_files_properties(
# Comment triggering moc:
access/qnetworkaccessdebugpipebackend_p.h
PROPERTIES
SKIP_AUTOMOC ON
SKIP_AUTOUIC ON
SKIP_AUTORCC ON)
## Scopes:
#####################################################################

View File

@ -31,6 +31,12 @@ add_qt_module(OpenGL
Qt::GuiPrivate
Qt::WidgetsPrivate
)
set_source_files_properties(qglfunctions.cpp qgraphicsshadereffect.cpp PROPERTIES
SKIP_AUTOMOC ON
SKIP_AUTOUIC ON
SKIP_AUTORCC ON
)
## Scopes:
#####################################################################

View File

@ -1,6 +1,11 @@
# FIXME Add the rest of the stuff
add_qt_module(PlatformHeaders SOURCES fake.cpp)
set_source_files_properties(fake.cpp PROPERTIES
SKIP_AUTOMOC ON
SKIP_AUTOUIC ON
SKIP_AUTORCC ON
)
extend_target(PlatformHeaders CONDITION APPLE SOURCES cocoafunctions/qcocoawindowfunctions.h)

View File

@ -20,6 +20,11 @@ add_qt_module(FontDatabaseSupport
Qt::CorePrivate
Qt::GuiPrivate
)
set_source_files_properties(fake.cpp PROPERTIES
SKIP_AUTOMOC ON
SKIP_AUTOUIC ON
SKIP_AUTORCC ON
)
extend_target(FontDatabaseSupport CONDITION APPLE
SOURCES

View File

@ -1,10 +0,0 @@
set(_mocscanner "${PROJECT_BINARY_DIR}/${INSTALL_BINDIR}/qmocscanner${CMAKE_EXECUTABLE_SUFFIX}")
try_compile(mocscanner_built "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp" COPY_FILE "${_mocscanner}")
add_executable(qmocscanner IMPORTED GLOBAL)
set_target_properties(qmocscanner PROPERTIES IMPORTED_LOCATION "${_mocscanner}")
install(PROGRAMS "${_mocscanner}" DESTINATION "${INSTALL_BINDIR}")
add_executable("Qt::qmocscanner" ALIAS "qmocscanner")
# FIXME: This should get exported to ToolsTargets!

View File

@ -1,623 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the qmocscanner application of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <set>
#include <unordered_set>
#include <assert.h>
#include <limits.h>
#include <string.h>
#include <stdarg.h>
struct ScanResult
{
std::string fileName;
bool foundMocRelevantMacro = false;
std::vector<std::string> includedMocFiles;
};
struct Option
{
static int debug_level;
};
int Option::debug_level = 0;
static void debug_msg(int level, const char *fmt, ...)
{
if (level < 3)
return;
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
#define qmake_endOfLine(c) (c == '\r' || c == '\n')
static int skipEscapedLineEnds(const char *buffer, int buffer_len, int offset, int *lines)
{
// Join physical lines to make logical lines, as in the C preprocessor
while (offset + 1 < buffer_len
&& buffer[offset] == '\\'
&& qmake_endOfLine(buffer[offset + 1])) {
offset += 2;
++*lines;
if (offset < buffer_len
&& buffer[offset - 1] == '\r'
&& buffer[offset] == '\n') // CRLF
offset++;
}
return offset;
}
static bool matchWhileUnsplitting(const char *buffer, int buffer_len, int start,
const char *needle, int needle_len,
int *matchlen, int *lines)
{
int x = start;
for (int n = 0; n < needle_len;
n++, x = skipEscapedLineEnds(buffer, buffer_len, x + 1, lines)) {
if (x >= buffer_len || buffer[x] != needle[n])
return false;
}
// That also skipped any remaining BSNLs immediately after the match.
// Tell caller how long the match was:
*matchlen = x - start;
return true;
}
/* Advance from an opening quote at buffer[offset] to the matching close quote. */
static int scanPastString(char *buffer, int buffer_len, int offset, int *lines)
{
// http://en.cppreference.com/w/cpp/language/string_literal
// It might be a C++11 raw string.
bool israw = false;
if (buffer[offset] == '"' && offset > 0) {
int explore = offset - 1;
bool prefix = false; // One of L, U, u or u8 may appear before R
bool saw8 = false; // Partial scan of u8
while (explore >= 0) {
// Cope with backslash-newline interruptions of the prefix:
if (explore > 0
&& qmake_endOfLine(buffer[explore])
&& buffer[explore - 1] == '\\') {
explore -= 2;
} else if (explore > 1
&& buffer[explore] == '\n'
&& buffer[explore - 1] == '\r'
&& buffer[explore - 2] == '\\') {
explore -= 3;
// Remaining cases can only decrement explore by one at a time:
} else if (saw8 && buffer[explore] == 'u') {
explore--;
saw8 = false;
prefix = true;
} else if (saw8 || prefix) {
break;
} else if (explore > 1 && buffer[explore] == '8') {
explore--;
saw8 = true;
} else if (buffer[explore] == 'L'
|| buffer[explore] == 'U'
|| buffer[explore] == 'u') {
explore--;
prefix = true;
} else if (buffer[explore] == 'R') {
if (israw)
break;
explore--;
israw = true;
} else {
break;
}
}
// Check the R (with possible prefix) isn't just part of an identifier:
if (israw && explore >= 0
&& (isalnum(buffer[explore]) || buffer[explore] == '_')) {
israw = false;
}
}
if (israw) {
#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), lines)
offset = SKIP_BSNL(offset + 1);
const char *const delim = buffer + offset;
int clean = offset;
while (offset < buffer_len && buffer[offset] != '(') {
if (clean < offset)
buffer[clean++] = buffer[offset];
else
clean++;
offset = SKIP_BSNL(offset + 1);
}
/*
Not checking correctness (trust real compiler to do that):
- no controls, spaces, '(', ')', '\\' or (presumably) '"' in delim;
- at most 16 bytes in delim
Raw strings are surely defined after phase 2, when BSNLs are resolved;
so the delimiter's exclusion of '\\' and space (including newlines)
applies too late to save us the need to cope with BSNLs in it.
*/
const int delimlen = buffer + clean - delim;
int matchlen = delimlen, extralines = 0;
while ((offset = SKIP_BSNL(offset + 1)) < buffer_len
&& (buffer[offset] != ')'
|| (delimlen > 0 &&
!matchWhileUnsplitting(buffer, buffer_len,
offset + 1, delim, delimlen,
&matchlen, &extralines))
|| buffer[offset + 1 + matchlen] != '"')) {
// skip, but keep track of lines
if (qmake_endOfLine(buffer[offset]))
++*lines;
extralines = 0;
}
*lines += extralines; // from the match
// buffer[offset] is ')'
offset += 1 + matchlen; // 1 for ')', then delim
// buffer[offset] is '"'
#undef SKIP_BSNL
} else { // Traditional string or char literal:
const char term = buffer[offset];
while (++offset < buffer_len && buffer[offset] != term) {
if (buffer[offset] == '\\')
++offset;
else if (qmake_endOfLine(buffer[offset]))
++*lines;
}
}
return offset;
}
static std::vector<std::string> findIncludes(const char *fileName, char *buffer, int buffer_len)
{
std::vector<std::string> includes;
int line_count = 1;
enum {
/*
States of C preprocessing (for TYPE_C only), after backslash-newline
elimination and skipping comments and spaces (i.e. in ANSI X3.159-1989
section 2.1.1.2's phase 4). We're about to study buffer[x] to decide
on which transition to do.
*/
AtStart, // start of logical line; a # may start a preprocessor directive
HadHash, // saw a # at start, looking for preprocessor keyword
WantName, // saw #include or #import, waiting for name
InCode // after directive, parsing non-#include directive or in actual code
} cpp_state = AtStart;
int x = 0;
if (buffer_len >= 3) {
const unsigned char *p = (unsigned char *)buffer;
// skip UTF-8 BOM, if present
if (p[0] == 0xEF && p[1] == 0xBB && p[2] == 0xBF)
x += 3;
}
for (; x < buffer_len; ++x) {
bool try_local = true;
char *inc = nullptr;
// We've studied all buffer[i] for i < x
for (; x < buffer_len; ++x) {
// How to handle backslash-newline (BSNL) pairs:
#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count)
// Seek code or directive, skipping comments and space:
for (; (x = SKIP_BSNL(x)) < buffer_len; ++x) {
if (buffer[x] == ' ' || buffer[x] == '\t') {
// keep going
} else if (buffer[x] == '/') {
int extralines = 0;
int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
if (y >= buffer_len) {
x = y;
break;
} else if (buffer[y] == '/') { // C++-style comment
line_count += extralines;
x = SKIP_BSNL(y + 1);
while (x < buffer_len && !qmake_endOfLine(buffer[x]))
x = SKIP_BSNL(x + 1); // skip
cpp_state = AtStart;
++line_count;
} else if (buffer[y] == '*') { // C-style comment
line_count += extralines;
x = y;
while ((x = SKIP_BSNL(++x)) < buffer_len) {
if (buffer[x] == '*') {
extralines = 0;
y = skipEscapedLineEnds(buffer, buffer_len,
x + 1, &extralines);
if (y < buffer_len && buffer[y] == '/') {
line_count += extralines;
x = y; // for loop shall step past this
break;
}
} else if (qmake_endOfLine(buffer[x])) {
++line_count;
}
}
} else {
// buffer[x] is the division operator
break;
}
} else if (qmake_endOfLine(buffer[x])) {
++line_count;
cpp_state = AtStart;
} else {
/* Drop out of phases 1, 2, 3, into phase 4 */
break;
}
}
// Phase 4 study of buffer[x]:
if (x >= buffer_len)
break;
switch (cpp_state) {
case HadHash:
{
// Read keyword; buffer[x] starts first preprocessing token after #
const char *const keyword = buffer + x;
int clean = x;
while (x < buffer_len && buffer[x] >= 'a' && buffer[x] <= 'z') {
// skip over keyword, consolidating it if it contains BSNLs
// (see WantName's similar code consolidating inc, below)
if (clean < x)
buffer[clean++] = buffer[x];
else
clean++;
x = SKIP_BSNL(x + 1);
}
const int keyword_len = buffer + clean - keyword;
x--; // Still need to study buffer[x] next time round for loop.
cpp_state =
((keyword_len == 7 && !strncmp(keyword, "include", 7)) // C & Obj-C
|| (keyword_len == 6 && !strncmp(keyword, "import", 6))) // Obj-C
? WantName : InCode;
break;
}
case WantName:
{
char term = buffer[x];
if (term == '<') {
try_local = false;
term = '>';
} else if (term != '"') {
/*
Possibly malformed, but this may be something like:
#include IDENTIFIER
which does work, if #define IDENTIFIER "filename" is
in effect. This is beyond this noddy preprocessor's
powers of tracking. So give up and resume searching
for a directive. We haven't made sense of buffer[x],
so back up to ensure we do study it (now as code) next
time round the loop.
*/
x--;
cpp_state = InCode;
continue;
}
x = SKIP_BSNL(x + 1);
inc = buffer + x;
int clean = x; // offset if we need to clear \-newlines
for (; x < buffer_len && buffer[x] != term; x = SKIP_BSNL(x + 1)) {
if (qmake_endOfLine(buffer[x])) { // malformed
cpp_state = AtStart;
++line_count;
break;
}
/*
If we do skip any BSNLs, we need to consolidate the
surviving text by copying to lower indices. For that
to be possible, we also have to keep 'clean' advanced
in step with x even when we've yet to see any BSNLs.
*/
if (clean < x)
buffer[clean++] = buffer[x];
else
clean++;
}
if (cpp_state == WantName)
buffer[clean] = '\0';
else // i.e. malformed
inc = nullptr;
cpp_state = InCode; // hereafter
break;
}
case AtStart:
// Preprocessor directive?
if (buffer[x] == '#') {
cpp_state = HadHash;
break;
}
cpp_state = InCode;
// ... and fall through to handle buffer[x] as such.
case InCode:
// matching quotes (string literals and character literals)
if (buffer[x] == '\'' || buffer[x] == '"') {
x = scanPastString(buffer, buffer_len, x, &line_count);
// for loop's ++x shall step over the closing quote.
}
// else: buffer[x] is just some code; move on.
break;
}
if (inc) // We were in WantName and found a name.
break;
#undef SKIP_BSNL
}
if (x >= buffer_len)
break;
if (inc) {
includes.push_back(inc);
}
}
return includes;
}
static bool isCWordChar(char c) {
return c == '_'
|| (c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9');
}
static bool scanBufferForMocRelevantMacros(const char *fileName, char *buffer, int buffer_len)
{
int line_count = 1;
bool ignore[3] = { false, false, false }; // [0] for Q_OBJECT, [1] for Q_GADGET, [2] for Q_NAMESPACE
/* qmake ignore Q_GADGET */
/* qmake ignore Q_OBJECT */
/* qmake ignore Q_NAMESPACE */
for (int x = 0; x < buffer_len; x++) {
#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count)
x = SKIP_BSNL(x);
if (buffer[x] == '/') {
int extralines = 0;
int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
if (buffer_len > y) {
// If comment, advance to the character that ends it:
if (buffer[y] == '/') { // C++-style comment
line_count += extralines;
x = y;
do {
x = SKIP_BSNL(x + 1);
} while (x < buffer_len && !qmake_endOfLine(buffer[x]));
} else if (buffer[y] == '*') { // C-style comment
line_count += extralines;
x = SKIP_BSNL(y + 1);
for (; x < buffer_len; x = SKIP_BSNL(x + 1)) {
if (buffer[x] == 't' || buffer[x] == 'q') { // ignore
if (buffer_len >= (x + 20) &&
!strncmp(buffer + x + 1, "make ignore Q_OBJECT", 20)) {
debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_OBJECT\"",
fileName, line_count);
x += 20;
ignore[0] = true;
} else if (buffer_len >= (x + 20) &&
!strncmp(buffer + x + 1, "make ignore Q_GADGET", 20)) {
debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_GADGET\"",
fileName, line_count);
x += 20;
ignore[1] = true;
} else if (buffer_len >= (x + 23) &&
!strncmp(buffer + x + 1, "make ignore Q_NAMESPACE", 23)) {
debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_NAMESPACE\"",
fileName, line_count);
x += 23;
ignore[2] = true;
}
} else if (buffer[x] == '*') {
extralines = 0;
y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
if (buffer_len > y && buffer[y] == '/') {
line_count += extralines;
x = y;
break;
}
} else if (Option::debug_level && qmake_endOfLine(buffer[x])) {
++line_count;
}
}
}
// else: don't update x, buffer[x] is just the division operator.
}
} else if (buffer[x] == '\'' || buffer[x] == '"') {
x = scanPastString(buffer, buffer_len, x, &line_count);
// Leaves us on closing quote; for loop's x++ steps us past it.
}
if (x < buffer_len && Option::debug_level && qmake_endOfLine(buffer[x]))
++line_count;
if (buffer_len > x + 8 && !isCWordChar(buffer[x])) {
int morelines = 0;
int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &morelines);
if (buffer[y] == 'Q') {
static const char interesting[][12] = { "Q_OBJECT", "Q_GADGET", "Q_NAMESPACE"};
for (int interest = 0; interest < 3; ++interest) {
if (ignore[interest])
continue;
int matchlen = 0, extralines = 0;
size_t needle_len = strlen(interesting[interest]);
assert(needle_len <= INT_MAX);
if (matchWhileUnsplitting(buffer, buffer_len, y,
interesting[interest],
static_cast<int>(needle_len),
&matchlen, &extralines)
&& y + matchlen < buffer_len
&& !isCWordChar(buffer[y + matchlen])) {
if (Option::debug_level) {
buffer[y + matchlen] = '\0';
debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s",
fileName,
line_count + morelines, buffer + y);
}
return true;
}
}
}
}
#undef SKIP_BSNL
}
return false;
}
static bool startsWith(const std::string &str, const char *needle)
{
return str.find(needle) == 0;
}
static bool endsWith(const std::string &str, const char *needle)
{
return str.rfind(needle) == str.size() - strlen(needle);
}
static std::string fileNameFromPath(const std::string &path)
{
int separatorIndex = path.rfind("/");
if (separatorIndex == -1)
return path;
return path.substr(separatorIndex + 1);
}
static ScanResult scanFile(const std::string &fileName)
{
ScanResult result;
result.fileName = fileName;
std::ifstream file(fileName, std::ios::binary);
if (!file.is_open())
return result;
file.seekg(0, std::ios_base::end);
auto size = file.tellg();
if (size == 0)
return result;
file.seekg(0, std::ios_base::beg);
std::vector<char> buffer;
buffer.resize(size);
char *bufferPtr = &(*buffer.begin());
file.read(bufferPtr, size);
file.close();
result.foundMocRelevantMacro = scanBufferForMocRelevantMacros(fileName.c_str(), bufferPtr, size);
for (const auto &include: findIncludes(fileName.c_str(), bufferPtr, size)) {
if (startsWith(include, "moc_") && endsWith(include, ".cpp")) {
std::string mocHeader = include.substr(strlen("moc_"),
include.size() - strlen("moc_") - strlen(".cpp"));
mocHeader.append(".h");
result.includedMocFiles.push_back(mocHeader);
} else if (endsWith(include, ".moc")) {
std::string mocHeader = include.substr(0, include.size() - strlen(".moc"));
mocHeader.append(".cpp");
result.includedMocFiles.push_back(mocHeader);
}
}
return result;
}
static void writeSetToFile(const char *fileName, const std::set<std::string> &content)
{
std::ofstream file(fileName, std::ios::binary);
for (const auto &entry: content) {
const std::string &fileName = entry;
file << fileName << std::endl;
}
}
int main(int argc, char **argv)
{
if (argc != 4) {
fprintf(stderr, "usage: %s <sources file> <included mocs output file> <built mocs output file>\n", argv[0]);
return EXIT_FAILURE;
}
std::vector<std::string> sourcesAndHeaders;
{
std::ifstream file(argv[1]);
if (!file.is_open()) {
std::cerr << "failed to open input file " << argv[1] << std::endl;
return EXIT_FAILURE;
}
for (std::string line; std::getline(file, line);)
sourcesAndHeaders.push_back(line);
}
std::unordered_set<std::string> mocCandidates;
std::unordered_set<std::string> mocFilesInIncludeStatements;
for (const auto &sourceOrHeader: sourcesAndHeaders) {
auto result = scanFile(sourceOrHeader);
if (result.foundMocRelevantMacro)
mocCandidates.insert(result.fileName);
for (const auto &header: result.includedMocFiles)
mocFilesInIncludeStatements.insert(header);
}
std::set<std::string> mocFilesToInclude;
std::set<std::string> mocFilesToBuild;
for (const auto &candidate: mocCandidates) {
std::string fileName = fileNameFromPath(candidate);
if (mocFilesInIncludeStatements.find(fileName) != mocFilesInIncludeStatements.end())
mocFilesToInclude.insert(candidate);
else
mocFilesToBuild.insert(candidate);
}
writeSetToFile(argv[2], mocFilesToInclude);
writeSetToFile(argv[3], mocFilesToBuild);
return EXIT_SUCCESS;
}

View File

@ -49,7 +49,7 @@ if (TARGET Qt::Widgets)
add_subdirectory(widgets)
endif()
if (TARGET Qt::PrintSupport)
# add_subdirectory(printsupport)
add_subdirectory(printsupport)
endif()
# add_subdirectory(cmake) ## FIXME: Does this still make sense in this form?
# add_subdirectory(installed_cmake) ## FIXME: Does this still make sense in this form?