summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Copyright.txt1
-rw-r--r--Help/manual/cmake-modules.7.rst1
-rw-r--r--Help/manual/cmake-qt.7.rst18
-rw-r--r--Help/module/FindPatch.rst1
-rw-r--r--Help/release/dev/FindEXPAT-importedtargets.rst4
-rw-r--r--Help/release/dev/FindFreetype-importedtargets.rst4
-rw-r--r--Help/release/dev/find-patch.rst5
-rw-r--r--Modules/AutogenInfo.cmake.in7
-rw-r--r--Modules/CMakeCSharpInformation.cmake2
-rw-r--r--Modules/Compiler/MSVC-CXX.cmake5
-rw-r--r--Modules/ExternalProject.cmake8
-rw-r--r--Modules/FindBoost.cmake64
-rw-r--r--Modules/FindEXPAT.cmake35
-rw-r--r--Modules/FindFreetype.cmake71
-rw-r--r--Modules/FindOpenMP.cmake2
-rw-r--r--Modules/FindPackageHandleStandardArgs.cmake59
-rw-r--r--Modules/FindPatch.cmake68
-rw-r--r--Modules/InstallRequiredSystemLibraries.cmake35
-rw-r--r--Modules/Platform/Android/Determine-Compiler-NDK.cmake2
-rw-r--r--Source/CMakeLists.txt5
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx6
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx2
-rw-r--r--Source/cmGlobalGenerator.cxx74
-rw-r--r--Source/cmGlobalGenerator.h4
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx13
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h3
-rw-r--r--Source/cmLoadCommandCommand.cxx2
-rw-r--r--Source/cmQtAutoGen.cxx (renamed from Source/cmQtAutoGeneratorCommon.cxx)140
-rw-r--r--Source/cmQtAutoGen.h (renamed from Source/cmQtAutoGeneratorCommon.h)28
-rw-r--r--Source/cmQtAutoGenDigest.h64
-rw-r--r--Source/cmQtAutoGeneratorInitializer.cxx948
-rw-r--r--Source/cmQtAutoGeneratorInitializer.h13
-rw-r--r--Source/cmQtAutoGenerators.cxx1410
-rw-r--r--Source/cmQtAutoGenerators.h92
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx7
-rw-r--r--Source/cmakemain.cxx2
-rw-r--r--Source/kwsys/CMakeLists.txt1
-rw-r--r--Source/kwsys/Directory.cxx4
-rw-r--r--Source/kwsys/SystemTools.cxx8
-rw-r--r--Source/kwsys/testDirectory.cxx79
-rw-r--r--Tests/CMakeLists.txt12
-rw-r--r--Tests/CSharpLinkToCxx/CMakeLists.txt6
-rw-r--r--Tests/CSharpLinkToCxx/cpp_native.cpp10
-rw-r--r--Tests/CSharpLinkToCxx/cpp_native.hpp9
-rw-r--r--Tests/FindEXPAT/CMakeLists.txt10
-rw-r--r--Tests/FindEXPAT/Test/CMakeLists.txt16
-rw-r--r--Tests/FindEXPAT/Test/main.c21
-rw-r--r--Tests/FindFreetype/CMakeLists.txt10
-rw-r--r--Tests/FindFreetype/Test/CMakeLists.txt16
-rw-r--r--Tests/FindFreetype/Test/main.c34
-rw-r--r--Tests/FindPatch/CMakeLists.txt8
-rw-r--r--Tests/FindPatch/Test/CMakeLists.txt77
-rw-r--r--Tests/QtAutogen/mocDepends/CMakeLists.txt140
-rw-r--r--Tests/QtAutogen/mocDepends/object_invalid.hpp.in (renamed from Tests/QtAutogen/mocDepends/invalid.hpp.in)0
-rw-r--r--Tests/QtAutogen/mocDepends/object_valid.hpp.in (renamed from Tests/QtAutogen/mocDepends/object.hpp.in)0
-rw-r--r--Tests/QtAutogen/mocDepends/test2.cpp9
-rw-r--r--Tests/QtAutogen/mocDepends/testATDFile.cpp9
-rw-r--r--Tests/QtAutogen/mocDepends/testATDTarget.cpp9
-rw-r--r--Tests/QtAutogen/mocDepends/testGenFile.cpp (renamed from Tests/QtAutogen/mocDepends/test1.cpp)2
-rw-r--r--Tests/QtAutogen/mocDepends/testGenLib.cpp (renamed from Tests/QtAutogen/mocDepends/test3.cpp)4
-rw-r--r--Tests/QtAutogen/mocDepends/testGenLib.hpp (renamed from Tests/QtAutogen/mocDepends/test3.hpp)0
-rw-r--r--Tests/QtAutogen/mocDepends/testGenTarget.cpp9
-rw-r--r--Tests/RunCMake/ExternalProject/MultiCommand-build-stdout.txt15
-rw-r--r--Tests/RunCMake/ExternalProject/MultiCommand.cmake30
-rw-r--r--Tests/RunCMake/ExternalProject/RunCMakeTest.cmake10
-rw-r--r--Tests/RunCMake/FPHSA/FindPseudoNoVersionVar.cmake6
-rw-r--r--Tests/RunCMake/FPHSA/RunCMakeTest.cmake11
-rw-r--r--Tests/RunCMake/FPHSA/any_version_VERSION_cache_variable-stdout.txt2
-rw-r--r--Tests/RunCMake/FPHSA/any_version_VERSION_cache_variable.cmake1
-rw-r--r--Tests/RunCMake/FPHSA/any_version_find_0-stdout.txt2
-rw-r--r--Tests/RunCMake/FPHSA/any_version_find_0.cmake1
72 files changed, 2298 insertions, 1490 deletions
diff --git a/Copyright.txt b/Copyright.txt
index b7af4c5..978be0a 100644
--- a/Copyright.txt
+++ b/Copyright.txt
@@ -69,6 +69,7 @@ The following individuals and institutions are among the Contributors:
* Matthaeus G. Chajdas
* Matthias Kretz <kretz@kde.org>
* Matthias Maennich <matthias@maennich.net>
+* Michael Stürmer
* Miguel A. Figueroa-Villanueva
* Mike Jackson
* Mike McQuaid <mike@mikemcquaid.com>
diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst
index fa6144c..fdc3597 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -182,6 +182,7 @@ All Modules
/module/FindosgWidget
/module/FindPackageHandleStandardArgs
/module/FindPackageMessage
+ /module/FindPatch
/module/FindPerlLibs
/module/FindPerl
/module/FindPHP4
diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst
index 55121df..7052e0a 100644
--- a/Help/manual/cmake-qt.7.rst
+++ b/Help/manual/cmake-qt.7.rst
@@ -214,6 +214,24 @@ overrides options from the :prop_tgt:`AUTORCC_OPTIONS` target property.
Source files can be excluded from :prop_tgt:`AUTORCC` processing by
enabling :prop_sf:`SKIP_AUTORCC` or the broader :prop_sf:`SKIP_AUTOGEN`.
+Visual Studio Generators
+========================
+
+When using the :manual:`Visual Studio generators <cmake-generators(7)>`
+CMake tries to use a ``PRE_BUILD``
+:command:`custom command <add_custom_command>` instead
+of a :command:`custom target <add_custom_target>` for autogen.
+``PRE_BUILD`` can't be used when the autogen target depends on files.
+This happens when
+
+- :prop_tgt:`AUTOMOC` or :prop_tgt:`AUTOUIC` is enabled and the origin target
+ depends on :prop_sf:`GENERATED` files which aren't excluded from autogen by
+ :prop_sf:`SKIP_AUTOMOC`, :prop_sf:`SKIP_AUTOUIC`, :prop_sf:`SKIP_AUTOGEN`
+ or :policy:`CMP0071`
+- :prop_tgt:`AUTORCC` is enabled and a ``.qrc`` file is listed in
+ the origin target sources
+- :prop_tgt:`AUTOGEN_TARGET_DEPENDS` lists a source file
+
qtmain.lib on Windows
=====================
diff --git a/Help/module/FindPatch.rst b/Help/module/FindPatch.rst
new file mode 100644
index 0000000..ba5e910
--- /dev/null
+++ b/Help/module/FindPatch.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/FindPatch.cmake
diff --git a/Help/release/dev/FindEXPAT-importedtargets.rst b/Help/release/dev/FindEXPAT-importedtargets.rst
new file mode 100644
index 0000000..ea73551
--- /dev/null
+++ b/Help/release/dev/FindEXPAT-importedtargets.rst
@@ -0,0 +1,4 @@
+FindEXPAT-importedtargets
+-------------------------
+
+* The :module:`FindEXPAT` module now provides imported targets.
diff --git a/Help/release/dev/FindFreetype-importedtargets.rst b/Help/release/dev/FindFreetype-importedtargets.rst
new file mode 100644
index 0000000..a895883
--- /dev/null
+++ b/Help/release/dev/FindFreetype-importedtargets.rst
@@ -0,0 +1,4 @@
+FindFreetype-importedtargets
+----------------------------
+
+* The :module:`FindFreetype` module now provides imported targets.
diff --git a/Help/release/dev/find-patch.rst b/Help/release/dev/find-patch.rst
new file mode 100644
index 0000000..d720c81
--- /dev/null
+++ b/Help/release/dev/find-patch.rst
@@ -0,0 +1,5 @@
+find-patch
+----------
+
+* A :module:`FindPatch` module was added to find the ``patch``
+ command-line executable.
diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in
index 60ceebc..484dc93 100644
--- a/Modules/AutogenInfo.cmake.in
+++ b/Modules/AutogenInfo.cmake.in
@@ -9,6 +9,7 @@ set(AM_SOURCES @_sources@)
set(AM_HEADERS @_headers@)
# Qt environment
set(AM_QT_VERSION_MAJOR @_qt_version_major@)
+set(AM_QT_VERSION_MINOR @_qt_version_minor@)
set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@)
set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@)
set(AM_QT_RCC_EXECUTABLE @_qt_rcc_executable@)
@@ -28,7 +29,7 @@ set(AM_UIC_OPTIONS_FILES @_qt_uic_options_files@)
set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@)
set(AM_UIC_SEARCH_PATHS @_uic_search_paths@)
# RCC settings
-set(AM_RCC_SOURCES @_rcc_files@ )
+set(AM_RCC_SOURCES @_rcc_files@)
+set(AM_RCC_BUILDS @_rcc_builds@)
+set(AM_RCC_OPTIONS @_rcc_options@)
set(AM_RCC_INPUTS @_rcc_inputs@)
-set(AM_RCC_OPTIONS_FILES @_rcc_options_files@)
-set(AM_RCC_OPTIONS_OPTIONS @_rcc_options_options@)
diff --git a/Modules/CMakeCSharpInformation.cmake b/Modules/CMakeCSharpInformation.cmake
index d474c29..25f869c 100644
--- a/Modules/CMakeCSharpInformation.cmake
+++ b/Modules/CMakeCSharpInformation.cmake
@@ -43,7 +43,7 @@ endif()
# on the initial values computed in the platform/*.cmake files
# use _INIT variables so that this only happens the first time
# and you can set these flags in the cmake cache
-set(CMAKE_CSharp_FLAGS_INIT "$ENV{CSharpFLAGS} ${CMAKE_CSharp_FLAGS_INIT}")
+set(CMAKE_CSharp_FLAGS_INIT "$ENV{CSFLAGS} ${CMAKE_CSharp_FLAGS_INIT}")
# avoid just having a space as the initial value for the cache
if(CMAKE_CSharp_FLAGS_INIT STREQUAL " ")
set(CMAKE_CSharp_FLAGS_INIT)
diff --git a/Modules/Compiler/MSVC-CXX.cmake b/Modules/Compiler/MSVC-CXX.cmake
index f478b85..3a63e3f 100644
--- a/Modules/Compiler/MSVC-CXX.cmake
+++ b/Modules/Compiler/MSVC-CXX.cmake
@@ -3,7 +3,10 @@
include(Compiler/CMakeCommonCompilerMacros)
-if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.10.25017)
+if ((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.0.24215.1 AND
+ CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) OR
+ CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.10.25017)
+
# VS 2015 Update 3 and above support language standard level flags,
# with the default and minimum level being C++14.
set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "")
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index d92eb5f..912c5ac 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -870,6 +870,14 @@ foreach(line IN LISTS lines)
set(_ep_keyword_sep)
elseif("${line}" MATCHES "^ +``([A-Z0-9_]+) [^`]*``$")
set(_ep_key "${CMAKE_MATCH_1}")
+ # COMMAND should never be included as a keyword,
+ # for ExternalProject_Add(), as it is treated as a
+ # special case by argument parsing as an extension
+ # of a previous ..._COMMAND
+ if("x${_ep_key}x" STREQUAL "xCOMMANDx" AND
+ "x${_ep_func}x" STREQUAL "xExternalProject_Addx")
+ continue()
+ endif()
#message(" keyword [${_ep_key}]")
string(APPEND _ep_keywords_${_ep_func}
"${_ep_keyword_sep}${_ep_key}")
diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake
index b28f2b8..614a7ca 100644
--- a/Modules/FindBoost.cmake
+++ b/Modules/FindBoost.cmake
@@ -107,6 +107,10 @@
# Users or projects may tell this module which variant to find by
# setting variables::
#
+# Boost_USE_DEBUG_LIBS - Set to ON or OFF to specify whether to search
+# and use the debug libraries. Default is ON.
+# Boost_USE_RELEASE_LIBS - Set to ON or OFF to specify whether to search
+# and use the release libraries. Default is ON.
# Boost_USE_MULTITHREADED - Set to OFF to use the non-multithreaded
# libraries ('mt' tag). Default is ON.
# Boost_USE_STATIC_LIBS - Set to ON to force the use of the static
@@ -183,9 +187,11 @@
# target_link_libraries(foo Boost::date_time Boost::filesystem
# Boost::iostreams)
#
-# Example to find Boost headers and some *static* libraries::
+# Example to find Boost headers and some *static* (release only) libraries::
#
-# set(Boost_USE_STATIC_LIBS ON) # only find static libs
+# set(Boost_USE_STATIC_LIBS ON) # only find static libs
+# set(Boost_USE_DEBUG_LIBS OFF) # ignore debug libs and
+# set(Boost_USE_RELEASE_LIBS ON) # only find release libs
# set(Boost_USE_MULTITHREADED ON)
# set(Boost_USE_STATIC_RUNTIME OFF)
# find_package(Boost 1.36.0 COMPONENTS date_time filesystem system ...)
@@ -208,10 +214,6 @@
#
# Set Boost_NO_BOOST_CMAKE to ON to disable the search for boost-cmake.
-# Save project's policies
-cmake_policy(PUSH)
-cmake_policy(SET CMP0057 NEW) # if IN_LIST
-
#-------------------------------------------------------------------------------
# Before we go searching, check whether boost-cmake is available, unless the
# user specifically asked NOT to search for boost-cmake.
@@ -298,7 +300,7 @@ macro(_Boost_ADJUST_LIB_VARS basename)
endif()
# If the debug & release library ends up being the same, omit the keywords
- if(${Boost_${basename}_LIBRARY_RELEASE} STREQUAL ${Boost_${basename}_LIBRARY_DEBUG})
+ if("${Boost_${basename}_LIBRARY_RELEASE}" STREQUAL "${Boost_${basename}_LIBRARY_DEBUG}")
set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} )
set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE} )
endif()
@@ -899,7 +901,9 @@ function(_Boost_MISSING_DEPENDENCIES componentvar extravar)
set(_Boost_${uppercomponent}_DEPENDENCIES ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE)
set(_Boost_IMPORTED_TARGETS ${_Boost_IMPORTED_TARGETS} PARENT_SCOPE)
foreach(componentdep ${_Boost_${uppercomponent}_DEPENDENCIES})
- if (NOT ("${componentdep}" IN_LIST _boost_processed_components OR "${componentdep}" IN_LIST _boost_new_components))
+ list(FIND _boost_processed_components "${componentdep}" _boost_component_found)
+ list(FIND _boost_new_components "${componentdep}" _boost_component_new)
+ if (_boost_component_found EQUAL -1 AND _boost_component_new EQUAL -1)
list(APPEND _boost_new_components ${componentdep})
endif()
endforeach()
@@ -996,8 +1000,14 @@ if(NOT Boost_LIBRARY_DIR_DEBUG AND Boost_LIBRARY_DIR)
set(Boost_LIBRARY_DIR_DEBUG "${Boost_LIBRARY_DIR}")
endif()
+if(NOT DEFINED Boost_USE_DEBUG_LIBS)
+ set(Boost_USE_DEBUG_LIBS TRUE)
+endif()
+if(NOT DEFINED Boost_USE_RELEASE_LIBS)
+ set(Boost_USE_RELEASE_LIBS TRUE)
+endif()
if(NOT DEFINED Boost_USE_MULTITHREADED)
- set(Boost_USE_MULTITHREADED TRUE)
+ set(Boost_USE_MULTITHREADED TRUE)
endif()
if(NOT DEFINED Boost_USE_DEBUG_RUNTIME)
set(Boost_USE_DEBUG_RUNTIME TRUE)
@@ -1023,7 +1033,7 @@ else()
# _Boost_COMPONENT_HEADERS. See the instructions at the top of
# _Boost_COMPONENT_DEPENDENCIES.
set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS}
- "1.65.0" "1.65"
+ "1.65.1" "1.65.0" "1.65"
"1.64.0" "1.64" "1.63.0" "1.63" "1.62.0" "1.62" "1.61.0" "1.61" "1.60.0" "1.60"
"1.59.0" "1.59" "1.58.0" "1.58" "1.57.0" "1.57" "1.56.0" "1.56" "1.55.0" "1.55"
"1.54.0" "1.54" "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51"
@@ -1527,7 +1537,8 @@ endif()
_Boost_MISSING_DEPENDENCIES(Boost_FIND_COMPONENTS _Boost_EXTRA_FIND_COMPONENTS)
# If thread is required, get the thread libs as a dependency
-if("thread" IN_LIST Boost_FIND_COMPONENTS)
+list(FIND Boost_FIND_COMPONENTS thread _Boost_THREAD_DEPENDENCY_LIBS)
+if(NOT _Boost_THREAD_DEPENDENCY_LIBS EQUAL -1)
include(CMakeFindDependencyMacro)
find_dependency(Threads)
endif()
@@ -1631,12 +1642,14 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS})
# Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing.
string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS_RELEASE}")
- _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE RELEASE
- NAMES ${_boost_RELEASE_NAMES}
- HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp}
- NAMES_PER_DIR
- DOC "${_boost_docstring_release}"
- )
+ if(Boost_USE_RELEASE_LIBS)
+ _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE RELEASE
+ NAMES ${_boost_RELEASE_NAMES}
+ HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp}
+ NAMES_PER_DIR
+ DOC "${_boost_docstring_release}"
+ )
+ endif()
#
# Find DEBUG libraries
@@ -1680,12 +1693,14 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS})
# Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing.
string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS_DEBUG}")
- _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG DEBUG
- NAMES ${_boost_DEBUG_NAMES}
- HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp}
- NAMES_PER_DIR
- DOC "${_boost_docstring_debug}"
- )
+ if(Boost_USE_DEBUG_LIBS)
+ _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG DEBUG
+ NAMES ${_boost_DEBUG_NAMES}
+ HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp}
+ NAMES_PER_DIR
+ DOC "${_boost_docstring_debug}"
+ )
+ endif ()
if(Boost_REALPATH)
_Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE "${_boost_docstring_release}")
@@ -1952,6 +1967,3 @@ list(REMOVE_DUPLICATES _Boost_COMPONENTS_SEARCHED)
list(SORT _Boost_COMPONENTS_SEARCHED)
set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}"
CACHE INTERNAL "Components requested for this build tree.")
-
-# Restore project's policies
-cmake_policy(POP)
diff --git a/Modules/FindEXPAT.cmake b/Modules/FindEXPAT.cmake
index 09963fc..39086e4 100644
--- a/Modules/FindEXPAT.cmake
+++ b/Modules/FindEXPAT.cmake
@@ -5,15 +5,28 @@
# FindEXPAT
# ---------
#
-# Find expat
+# Find the native Expat headers and library.
#
-# Find the native EXPAT headers and libraries.
+# Imported Targets
+# ^^^^^^^^^^^^^^^^
#
-# ::
+# This module defines the following :prop_tgt:`IMPORTED` targets:
+#
+# ``EXPAT::EXPAT``
+# The Expat ``expat`` library, if found.
+#
+# Result Variables
+# ^^^^^^^^^^^^^^^^
+#
+# This module will set the following variables in your project:
+#
+# ``EXPAT_INCLUDE_DIRS``
+# where to find expat.h, etc.
+# ``EXPAT_LIBRARIES``
+# the libraries to link against to use Expat.
+# ``EXPAT_FOUND``
+# true if the Expat headers and libraries were found.
#
-# EXPAT_INCLUDE_DIRS - where to find expat.h, etc.
-# EXPAT_LIBRARIES - List of libraries when using expat.
-# EXPAT_FOUND - True if expat found.
find_package(PkgConfig QUIET)
@@ -49,10 +62,18 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(EXPAT
REQUIRED_VARS EXPAT_LIBRARY EXPAT_INCLUDE_DIR
VERSION_VAR EXPAT_VERSION_STRING)
-# Copy the results to the output variables.
+# Copy the results to the output variables and target.
if(EXPAT_FOUND)
set(EXPAT_LIBRARIES ${EXPAT_LIBRARY})
set(EXPAT_INCLUDE_DIRS ${EXPAT_INCLUDE_DIR})
+
+ if(NOT TARGET EXPAT::EXPAT)
+ add_library(EXPAT::EXPAT UNKNOWN IMPORTED)
+ set_target_properties(EXPAT::EXPAT PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+ IMPORTED_LOCATION "${EXPAT_LIBRARY}"
+ INTERFACE_INCLUDE_DIRECTORIES "${EXPAT_INCLUDE_DIRS}")
+ endif()
endif()
mark_as_advanced(EXPAT_INCLUDE_DIR EXPAT_LIBRARY)
diff --git a/Modules/FindFreetype.cmake b/Modules/FindFreetype.cmake
index 9ea77df..0e6d336 100644
--- a/Modules/FindFreetype.cmake
+++ b/Modules/FindFreetype.cmake
@@ -5,24 +5,41 @@
# FindFreetype
# ------------
#
-# Locate FreeType library
+# Find the FreeType font renderer includes and library.
#
-# This module defines
+# Imported Targets
+# ^^^^^^^^^^^^^^^^
#
-# ::
+# This module defines the following :prop_tgt:`IMPORTED` target:
#
-# FREETYPE_LIBRARIES, the library to link against
-# FREETYPE_FOUND, if false, do not try to link to FREETYPE
-# FREETYPE_INCLUDE_DIRS, where to find headers.
-# FREETYPE_VERSION_STRING, the version of freetype found (since CMake 2.8.8)
-# This is the concatenation of the paths:
-# FREETYPE_INCLUDE_DIR_ft2build
-# FREETYPE_INCLUDE_DIR_freetype2
+# ``Freetype::Freetype``
+# The Freetype ``freetype`` library, if found
#
+# Result Variables
+# ^^^^^^^^^^^^^^^^
#
+# This module will set the following variables in your project:
#
-# $FREETYPE_DIR is an environment variable that would correspond to the
-# ./configure --prefix=$FREETYPE_DIR used in building FREETYPE.
+# ``FREETYPE_FOUND``
+# true if the Freetype headers and libraries were found
+# ``FREETYPE_INCLUDE_DIRS``
+# directories containing the Freetype headers. This is the
+# concatenation of the variables:
+#
+# ``FREETYPE_INCLUDE_DIR_ft2build``
+# directory holding the main Freetype API configuration header
+# ``FREETYPE_INCLUDE_DIR_freetype2``
+# directory holding Freetype public headers
+# ``FREETYPE_LIBRARIES``
+# the library to link against
+# ``FREETYPE_VERSION_STRING``
+# the version of freetype found (since CMake 2.8.8)
+#
+# Hints
+# ^^^^^
+#
+# The user may set the environment variable ``FREETYPE_DIR`` to the root
+# directory of a Freetype installation.
# Created by Eric Wing.
# Modifications by Alexander Neundorf.
@@ -150,3 +167,33 @@ mark_as_advanced(
FREETYPE_INCLUDE_DIR_freetype2
FREETYPE_INCLUDE_DIR_ft2build
)
+
+if(Freetype_FOUND)
+ if(NOT TARGET Freetype::Freetype)
+ add_library(Freetype::Freetype UNKNOWN IMPORTED)
+ set_target_properties(Freetype::Freetype PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${FREETYPE_INCLUDE_DIRS}")
+
+ if(FREETYPE_LIBRARY_RELEASE)
+ set_property(TARGET Freetype::Freetype APPEND PROPERTY
+ IMPORTED_CONFIGURATIONS RELEASE)
+ set_target_properties(Freetype::Freetype PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
+ IMPORTED_LOCATION_RELEASE "${FREETYPE_LIBRARY_RELEASE}")
+ endif()
+
+ if(FREETYPE_LIBRARY_DEBUG)
+ set_property(TARGET Freetype::Freetype APPEND PROPERTY
+ IMPORTED_CONFIGURATIONS DEBUG)
+ set_target_properties(Freetype::Freetype PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
+ IMPORTED_LOCATION_DEBUG "${FREETYPE_LIBRARY_DEBUG}")
+ endif()
+
+ if(NOT FREETYPE_LIBRARY_RELEASE AND NOT FREETYPE_LIBRARY_DEBUG)
+ set_target_properties(Freetype::Freetype PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+ IMPORTED_LOCATION "${FREETYPE_LIBRARY}")
+ endif()
+ endif()
+endif()
diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake
index 7566e4a..8e9ce7a 100644
--- a/Modules/FindOpenMP.cmake
+++ b/Modules/FindOpenMP.cmake
@@ -430,6 +430,8 @@ foreach(LANG IN ITEMS C CXX Fortran)
endif()
endforeach()
+set(OpenMP_FOUND ${OPENMP_FOUND})
+
if(CMAKE_Fortran_COMPILER_LOADED AND OpenMP_Fortran_FOUND)
if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
set(OpenMP_Fortran_HAVE_OMPLIB_MODULE FALSE CACHE BOOL INTERNAL "")
diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake
index b851a90..7b08bea 100644
--- a/Modules/FindPackageHandleStandardArgs.cmake
+++ b/Modules/FindPackageHandleStandardArgs.cmake
@@ -175,11 +175,12 @@ endmacro()
function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
-# set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in
-# new extended or in the "old" mode:
+# Set up the arguments for `cmake_parse_arguments`.
set(options CONFIG_MODE HANDLE_COMPONENTS)
set(oneValueArgs FAIL_MESSAGE VERSION_VAR FOUND_VAR)
set(multiValueArgs REQUIRED_VARS)
+
+# Check whether we are in 'simple' or 'extended' mode:
set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} )
list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)
@@ -188,8 +189,7 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
set(FPHSA_REQUIRED_VARS ${ARGN})
set(FPHSA_VERSION_VAR)
else()
-
- CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN})
+ cmake_parse_arguments(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN})
if(FPHSA_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"")
@@ -198,6 +198,18 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
if(NOT FPHSA_FAIL_MESSAGE)
set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG")
endif()
+
+ # In config-mode, we rely on the variable <package>_CONFIG, which is set by find_package()
+ # when it successfully found the config-file, including version checking:
+ if(FPHSA_CONFIG_MODE)
+ list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
+ list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS)
+ set(FPHSA_VERSION_VAR ${_NAME}_VERSION)
+ endif()
+
+ if(NOT FPHSA_REQUIRED_VARS)
+ message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
+ endif()
endif()
# now that we collected all arguments, process them
@@ -206,18 +218,6 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}")
endif()
- # In config-mode, we rely on the variable <package>_CONFIG, which is set by find_package()
- # when it successfully found the config-file, including version checking:
- if(FPHSA_CONFIG_MODE)
- list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
- list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS)
- set(FPHSA_VERSION_VAR ${_NAME}_VERSION)
- endif()
-
- if(NOT FPHSA_REQUIRED_VARS)
- message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
- endif()
-
list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
string(TOUPPER ${_NAME} _NAME_UPPER)
@@ -289,15 +289,15 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
# version handling:
set(VERSION_MSG "")
set(VERSION_OK TRUE)
- set(VERSION ${${FPHSA_VERSION_VAR}})
# check with DEFINED here as the requested or found version may be "0"
if (DEFINED ${_NAME}_FIND_VERSION)
if(DEFINED ${FPHSA_VERSION_VAR})
+ set(_FOUND_VERSION ${${FPHSA_VERSION_VAR}})
if(${_NAME}_FIND_VERSION_EXACT) # exact version required
# count the dots in the version string
- string(REGEX REPLACE "[^.]" "" _VERSION_DOTS "${VERSION}")
+ string(REGEX REPLACE "[^.]" "" _VERSION_DOTS "${_FOUND_VERSION}")
# add one dot because there is one dot more than there are components
string(LENGTH "${_VERSION_DOTS}." _VERSION_DOTS)
if (_VERSION_DOTS GREATER ${_NAME}_FIND_VERSION_COUNT)
@@ -312,31 +312,31 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
else ()
set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*")
endif ()
- string(REGEX REPLACE "^(${_VERSION_REGEX})\\..*" "\\1" _VERSION_HEAD "${VERSION}")
+ string(REGEX REPLACE "^(${_VERSION_REGEX})\\..*" "\\1" _VERSION_HEAD "${_FOUND_VERSION}")
unset(_VERSION_REGEX)
if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _VERSION_HEAD)
- set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
+ set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
set(VERSION_OK FALSE)
else ()
- set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
+ set(VERSION_MSG "(found suitable exact version \"${_FOUND_VERSION}\")")
endif ()
unset(_VERSION_HEAD)
else ()
if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL VERSION)
- set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
+ set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
set(VERSION_OK FALSE)
else ()
- set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
+ set(VERSION_MSG "(found suitable exact version \"${_FOUND_VERSION}\")")
endif ()
endif ()
unset(_VERSION_DOTS)
else() # minimum version specified:
- if (${_NAME}_FIND_VERSION VERSION_GREATER VERSION)
- set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"")
+ if (${_NAME}_FIND_VERSION VERSION_GREATER _FOUND_VERSION)
+ set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"")
set(VERSION_OK FALSE)
else ()
- set(VERSION_MSG "(found suitable version \"${VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")")
+ set(VERSION_MSG "(found suitable version \"${_FOUND_VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")")
endif ()
endif()
@@ -351,13 +351,14 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
endif()
else ()
- if(VERSION)
- set(VERSION_MSG "(found version \"${VERSION}\")")
+ # Check with DEFINED as the found version may be 0.
+ if(DEFINED ${FPHSA_VERSION_VAR})
+ set(VERSION_MSG "(found version \"${${FPHSA_VERSION_VAR}}\")")
endif()
endif ()
if(VERSION_OK)
- string(APPEND DETAILS "[v${VERSION}(${${_NAME}_FIND_VERSION})]")
+ string(APPEND DETAILS "[v${${FPHSA_VERSION_VAR}}(${${_NAME}_FIND_VERSION})]")
else()
set(${_NAME}_FOUND FALSE)
endif()
diff --git a/Modules/FindPatch.cmake b/Modules/FindPatch.cmake
new file mode 100644
index 0000000..3ebcae9
--- /dev/null
+++ b/Modules/FindPatch.cmake
@@ -0,0 +1,68 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#.rst:
+# FindPatch
+# ---------
+#
+# The module defines the following variables:
+#
+# ``Patch_EXECUTABLE``
+# Path to patch command-line executable.
+# ``Patch_FOUND``
+# True if the patch command-line executable was found.
+#
+# The following :prop_tgt:`IMPORTED` targets are also defined:
+#
+# ``Patch::patch``
+# The command-line executable.
+#
+# Example usage:
+#
+# .. code-block:: cmake
+#
+# find_package(Patch)
+# if(Patch_FOUND)
+# message("Patch found: ${Patch_EXECUTABLE}")
+# endif()
+
+set(_doc "Patch command line executable")
+set(_patch_path )
+
+if(CMAKE_HOST_WIN32)
+ set(_patch_path
+ "$ENV{LOCALAPPDATA}/Programs/Git/bin"
+ "$ENV{LOCALAPPDATA}/Programs/Git/usr/bin"
+ "$ENV{APPDATA}/Programs/Git/bin"
+ "$ENV{APPDATA}/Programs/Git/usr/bin"
+ )
+endif()
+
+# First search the PATH
+find_program(Patch_EXECUTABLE
+ NAME patch
+ PATHS ${_patch_path}
+ DOC ${_doc}
+ )
+
+if(CMAKE_HOST_WIN32)
+ # Now look for installations in Git/ directories under typical installation
+ # prefixes on Windows.
+ find_program(Patch_EXECUTABLE
+ NAMES patch
+ PATH_SUFFIXES Git/usr/bin Git/bin GnuWin32/bin
+ DOC ${_doc}
+ )
+endif()
+
+if(Patch_EXECUTABLE AND NOT TARGET Patch::patch)
+ add_executable(Patch::patch IMPORTED)
+ set_property(TARGET Patch::patch PROPERTY IMPORTED_LOCATION ${Patch_EXECUTABLE})
+endif()
+
+unset(_patch_path)
+unset(_doc)
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(Patch
+ REQUIRED_VARS Patch_EXECUTABLE)
diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake
index bbbc9eb..ac8c20b 100644
--- a/Modules/InstallRequiredSystemLibraries.cmake
+++ b/Modules/InstallRequiredSystemLibraries.cmake
@@ -205,7 +205,12 @@ if(MSVC)
endif()
endif()
- if(MSVC_VERSION EQUAL 1911)
+ set(MSVC_REDIST_NAME "")
+ set(_MSVCRT_DLL_VERSION "")
+ set(_MSVCRT_IDE_VERSION "")
+ if(MSVC_VERSION GREATER_EQUAL 2000)
+ message(WARNING "MSVC ${MSVC_VERSION} not yet supported.")
+ elseif(MSVC_VERSION GREATER_EQUAL 1911)
set(MSVC_REDIST_NAME VC141)
set(_MSVCRT_DLL_VERSION 140)
set(_MSVCRT_IDE_VERSION 15)
@@ -229,10 +234,6 @@ if(MSVC)
set(MSVC_REDIST_NAME VC100)
set(_MSVCRT_DLL_VERSION 100)
set(_MSVCRT_IDE_VERSION 10)
- else()
- set(MSVC_REDIST_NAME "")
- set(_MSVCRT_DLL_VERSION "")
- set(_MSVCRT_IDE_VERSION "")
endif()
if(_MSVCRT_DLL_VERSION)
@@ -427,10 +428,11 @@ if(MSVC)
)
endif()
- if(MSVC_VERSION EQUAL 1911)
- set(_MFC_DLL_VERSION 140)
- set(_MFC_IDE_VERSION 15)
- elseif(MSVC_VERSION EQUAL 1910)
+ set(_MFC_DLL_VERSION "")
+ set(_MFC_IDE_VERSION "")
+ if(MSVC_VERSION GREATER_EQUAL 2000)
+ # Version not yet supported.
+ elseif(MSVC_VERSION GREATER_EQUAL 1910)
set(_MFC_DLL_VERSION 140)
set(_MFC_IDE_VERSION 15)
elseif(MSVC_VERSION EQUAL 1900)
@@ -445,9 +447,6 @@ if(MSVC)
elseif(MSVC_VERSION EQUAL 1600)
set(_MFC_DLL_VERSION 100)
set(_MFC_IDE_VERSION 10)
- else()
- set(_MFC_DLL_VERSION "")
- set(_MFC_IDE_VERSION "")
endif()
if(_MFC_DLL_VERSION)
@@ -518,10 +517,11 @@ if(MSVC)
# MSVC 8 was the first version with OpenMP
# Furthermore, there is no debug version of this
if(CMAKE_INSTALL_OPENMP_LIBRARIES AND _IRSL_HAVE_MSVC)
- if(MSVC_VERSION EQUAL 1911)
- set(_MSOMP_DLL_VERSION 140)
- set(_MSOMP_IDE_VERSION 15)
- elseif(MSVC_VERSION EQUAL 1910)
+ set(_MSOMP_DLL_VERSION "")
+ set(_MSOMP_IDE_VERSION "")
+ if(MSVC_VERSION GREATER_EQUAL 2000)
+ # Version not yet supported.
+ elseif(MSVC_VERSION GREATER_EQUAL 1910)
set(_MSOMP_DLL_VERSION 140)
set(_MSOMP_IDE_VERSION 15)
elseif(MSVC_VERSION EQUAL 1900)
@@ -542,9 +542,6 @@ if(MSVC)
elseif(MSVC_VERSION EQUAL 1400)
set(_MSOMP_DLL_VERSION 80)
set(_MSOMP_IDE_VERSION 8)
- else()
- set(_MSOMP_DLL_VERSION "")
- set(_MSOMP_IDE_VERSION "")
endif()
if(_MSOMP_DLL_VERSION)
diff --git a/Modules/Platform/Android/Determine-Compiler-NDK.cmake b/Modules/Platform/Android/Determine-Compiler-NDK.cmake
index d983dd6..0649925 100644
--- a/Modules/Platform/Android/Determine-Compiler-NDK.cmake
+++ b/Modules/Platform/Android/Determine-Compiler-NDK.cmake
@@ -124,7 +124,7 @@ file(STRINGS "${_ANDROID_TOOL_SETUP_MK}" _ANDROID_TOOL_SETUP REGEX "^(LLVM|TOOLC
unset(_ANDROID_TOOL_SETUP_MK)
set(_ANDROID_TOOL_PREFIX "")
set(_ANDROID_TOOL_NAME_ONLY "")
-set(_ANDROID_TOOL_LLVM_NAME "")
+set(_ANDROID_TOOL_LLVM_NAME "llvm")
set(_ANDROID_TOOL_LLVM_VERS "")
foreach(line IN LISTS _ANDROID_TOOL_SETUP)
if(CMAKE_ANDROID_NDK_TOOLCHAIN_DEBUG)
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index bcc3437..9cd7b84 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -307,8 +307,9 @@ set(SRCS
cmPropertyDefinitionMap.h
cmPropertyMap.cxx
cmPropertyMap.h
- cmQtAutoGeneratorCommon.cxx
- cmQtAutoGeneratorCommon.h
+ cmQtAutoGen.cxx
+ cmQtAutoGen.h
+ cmQtAutoGenDigest.h
cmQtAutoGeneratorInitializer.cxx
cmQtAutoGeneratorInitializer.h
cmQtAutoGenerators.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 701f1b0..971b451 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 9)
-set(CMake_VERSION_PATCH 20170905)
+set(CMake_VERSION_PATCH 20170911)
#set(CMake_VERSION_RC 1)
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index b6c25b8..f9ff2d7 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -115,21 +115,21 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring,
void CMakeMessageCallback(const char* m, const char* /*unused*/,
bool& /*unused*/, void* s)
{
- std::string* out = reinterpret_cast<std::string*>(s);
+ std::string* out = static_cast<std::string*>(s);
*out += m;
*out += "\n";
}
void CMakeProgressCallback(const char* msg, float /*unused*/, void* s)
{
- std::string* out = reinterpret_cast<std::string*>(s);
+ std::string* out = static_cast<std::string*>(s);
*out += msg;
*out += "\n";
}
void CMakeOutputCallback(const char* m, size_t len, void* s)
{
- std::string* out = reinterpret_cast<std::string*>(s);
+ std::string* out = static_cast<std::string*>(s);
out->append(m, len);
}
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 7d11550..3f11543 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -33,7 +33,7 @@ static CatToErrorType cmCTestMemCheckBoundsChecker[] = {
static void xmlReportError(int line, const char* msg, void* data)
{
- cmCTest* ctest = reinterpret_cast<cmCTest*>(data);
+ cmCTest* ctest = static_cast<cmCTest*>(data);
cmCTestLog(ctest, ERROR_MESSAGE, "Error parsing XML in stream at line "
<< line << ": " << msg << std::endl);
}
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index ab35593..39c181a 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1263,8 +1263,7 @@ bool cmGlobalGenerator::Compute()
#ifdef CMAKE_BUILD_WITH_CMAKE
// Iterate through all targets and set up automoc for those which have
// the AUTOMOC, AUTOUIC or AUTORCC property set
- std::vector<cmGeneratorTarget const*> autogenTargets =
- this->CreateQtAutoGeneratorsTargets();
+ cmQtAutoGenDigestUPV autogenDigests = this->CreateQtAutoGeneratorsTargets();
#endif
unsigned int i;
@@ -1287,11 +1286,10 @@ bool cmGlobalGenerator::Compute()
}
#ifdef CMAKE_BUILD_WITH_CMAKE
- for (std::vector<cmGeneratorTarget const*>::iterator it =
- autogenTargets.begin();
- it != autogenTargets.end(); ++it) {
- cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(*it);
+ for (const cmQtAutoGenDigestUP& digest : autogenDigests) {
+ cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(*digest);
}
+ autogenDigests.clear();
#endif
for (i = 0; i < this->LocalGenerators.size(); ++i) {
@@ -1427,24 +1425,16 @@ bool cmGlobalGenerator::ComputeTargetDepends()
return true;
}
-std::vector<const cmGeneratorTarget*>
-cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
+cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
{
- std::vector<const cmGeneratorTarget*> autogenTargets;
+ cmQtAutoGenDigestUPV autogenDigests;
#ifdef CMAKE_BUILD_WITH_CMAKE
- for (std::vector<cmLocalGenerator*>::const_iterator lgit =
- this->LocalGenerators.begin();
- lgit != this->LocalGenerators.end(); ++lgit) {
- cmLocalGenerator* localGen = *lgit;
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
const std::vector<cmGeneratorTarget*>& targets =
localGen->GetGeneratorTargets();
// Find targets that require AUTOGEN processing
- std::vector<cmGeneratorTarget*> filteredTargets;
- filteredTargets.reserve(targets.size());
- for (std::vector<cmGeneratorTarget*>::const_iterator ti = targets.begin();
- ti != targets.end(); ++ti) {
- cmGeneratorTarget* target = *ti;
+ for (cmGeneratorTarget* target : targets) {
if (target->GetType() == cmStateEnums::GLOBAL_TARGET) {
continue;
}
@@ -1455,33 +1445,43 @@ cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
target->GetType() != cmStateEnums::OBJECT_LIBRARY) {
continue;
}
- if ((!target->GetPropertyAsBool("AUTOMOC") &&
- !target->GetPropertyAsBool("AUTOUIC") &&
- !target->GetPropertyAsBool("AUTORCC")) ||
- target->IsImported()) {
+ if (target->IsImported()) {
continue;
}
- // don't do anything if there is no Qt4 or Qt5Core (which contains moc)
- cmMakefile* mf = target->Target->GetMakefile();
- std::string qtMajorVersion = mf->GetSafeDefinition("QT_VERSION_MAJOR");
- if (qtMajorVersion == "") {
- qtMajorVersion = mf->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
+
+ const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC");
+ const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC");
+ const bool rccEnabled = target->GetPropertyAsBool("AUTORCC");
+ if (!mocEnabled && !uicEnabled && !rccEnabled) {
+ continue;
}
- if (qtMajorVersion != "4" && qtMajorVersion != "5") {
+
+ std::string qtVersionMajor =
+ cmQtAutoGeneratorInitializer::GetQtMajorVersion(target);
+ // don't do anything if there is no Qt4 or Qt5Core (which contains moc)
+ if (qtVersionMajor != "4" && qtVersionMajor != "5") {
continue;
}
- filteredTargets.push_back(target);
- }
- // Initialize AUTOGEN targets
- for (std::vector<cmGeneratorTarget*>::iterator ti =
- filteredTargets.begin();
- ti != filteredTargets.end(); ++ti) {
- cmQtAutoGeneratorInitializer::InitializeAutogenTarget(localGen, *ti);
- autogenTargets.push_back(*ti);
+
+ {
+ cmQtAutoGenDigestUP digest(new cmQtAutoGenDigest(target));
+ digest->QtVersionMajor = std::move(qtVersionMajor);
+ digest->QtVersionMinor =
+ cmQtAutoGeneratorInitializer::GetQtMinorVersion(
+ target, digest->QtVersionMajor);
+ digest->MocEnabled = mocEnabled;
+ digest->UicEnabled = uicEnabled;
+ digest->RccEnabled = rccEnabled;
+ autogenDigests.emplace_back(std::move(digest));
+ }
}
}
+ // Initialize autogen targets
+ for (const cmQtAutoGenDigestUP& digest : autogenDigests) {
+ cmQtAutoGeneratorInitializer::InitializeAutogenTarget(*digest);
+ }
#endif
- return autogenTargets;
+ return autogenDigests;
}
cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer(
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 3931ab8..18ca682 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -15,6 +15,7 @@
#include "cmCustomCommandLines.h"
#include "cmExportSetMap.h"
+#include "cmQtAutoGenDigest.h"
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
@@ -422,7 +423,8 @@ protected:
virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
- std::vector<const cmGeneratorTarget*> CreateQtAutoGeneratorsTargets();
+ // Qt auto generators
+ cmQtAutoGenDigestUPV CreateQtAutoGeneratorsTargets();
std::string SelectMakeProgram(const std::string& makeProgram,
const std::string& makeDefault = "") const;
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index d7ea35a..ece2a77 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -782,6 +782,19 @@ bool cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(
return false;
}
+bool cmGlobalVisualStudioGenerator::TargetCanBeReferenced(
+ cmGeneratorTarget const* gt)
+{
+ if (this->TargetIsCSharpOnly(gt)) {
+ return true;
+ }
+ if (gt->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ gt->GetType() != cmStateEnums::EXECUTABLE) {
+ return false;
+ }
+ return true;
+}
+
bool cmGlobalVisualStudioGenerator::TargetCompare::operator()(
cmGeneratorTarget const* l, cmGeneratorTarget const* r) const
{
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index 04d97c5..399b6e0 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -85,6 +85,9 @@ public:
// return true if target is C# only
static bool TargetIsCSharpOnly(cmGeneratorTarget const* gt);
+ // return true if target can be referenced by C# targets
+ bool TargetCanBeReferenced(cmGeneratorTarget const* gt);
+
/** Get the top-level registry key for this VS version. */
std::string GetRegistryBase();
diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx
index 5ce48e3..a871df9 100644
--- a/Source/cmLoadCommandCommand.cxx
+++ b/Source/cmLoadCommandCommand.cxx
@@ -120,7 +120,7 @@ bool cmLoadedCommand::InitialPass(std::vector<std::string> const& args,
int argc = static_cast<int>(args.size());
char** argv = nullptr;
if (argc) {
- argv = reinterpret_cast<char**>(malloc(argc * sizeof(char*)));
+ argv = static_cast<char**>(malloc(argc * sizeof(char*)));
}
int i;
for (i = 0; i < argc; ++i) {
diff --git a/Source/cmQtAutoGeneratorCommon.cxx b/Source/cmQtAutoGen.cxx
index a8e6b96..95cd122 100644
--- a/Source/cmQtAutoGeneratorCommon.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -1,17 +1,79 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmQtAutoGeneratorCommon.h"
+#include "cmQtAutoGen.h"
#include "cmAlgorithms.h"
#include "cmSystemTools.h"
#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
#include <sstream>
#include <stddef.h>
+// - Static variables
+
+const std::string genNameGen = "AutoGen";
+const std::string genNameMoc = "AutoMoc";
+const std::string genNameUic = "AutoUic";
+const std::string genNameRcc = "AutoRcc";
+
// - Static functions
+/// @brief Merges newOpts into baseOpts
+/// @arg valueOpts list of options that accept a value
+void MergeOptions(std::vector<std::string>& baseOpts,
+ const std::vector<std::string>& newOpts,
+ const std::vector<std::string>& valueOpts, bool isQt5)
+{
+ typedef std::vector<std::string>::iterator Iter;
+ typedef std::vector<std::string>::const_iterator CIter;
+ if (newOpts.empty()) {
+ return;
+ }
+ if (baseOpts.empty()) {
+ baseOpts = newOpts;
+ return;
+ }
+
+ std::vector<std::string> extraOpts;
+ for (CIter fit = newOpts.begin(), fitEnd = newOpts.end(); fit != fitEnd;
+ ++fit) {
+ const std::string& newOpt = *fit;
+ Iter existIt = std::find(baseOpts.begin(), baseOpts.end(), newOpt);
+ if (existIt != baseOpts.end()) {
+ if (newOpt.size() >= 2) {
+ // Acquire the option name
+ std::string optName;
+ {
+ auto oit = newOpt.begin();
+ if (*oit == '-') {
+ ++oit;
+ if (isQt5 && (*oit == '-')) {
+ ++oit;
+ }
+ optName.assign(oit, newOpt.end());
+ }
+ }
+ // Test if this is a value option and change the existing value
+ if (!optName.empty() && (std::find(valueOpts.begin(), valueOpts.end(),
+ optName) != valueOpts.end())) {
+ const Iter existItNext(existIt + 1);
+ const CIter fitNext(fit + 1);
+ if ((existItNext != baseOpts.end()) && (fitNext != fitEnd)) {
+ *existItNext = *fitNext;
+ ++fit;
+ }
+ }
+ }
+ } else {
+ extraOpts.push_back(newOpt);
+ }
+ }
+ // Append options
+ baseOpts.insert(baseOpts.end(), extraOpts.begin(), extraOpts.end());
+}
+
static std::string utilStripCR(std::string const& line)
{
// Strip CR characters rcc may have printed (possibly more than one!).
@@ -40,8 +102,8 @@ static bool RccListInputsQt4(const std::string& fileName,
} else {
if (errorMessage != nullptr) {
std::ostringstream ost;
- ost << "AutoRcc: Error: Rcc file not readable:\n"
- << cmQtAutoGeneratorCommon::Quoted(fileName) << "\n";
+ ost << "rcc file not readable:\n"
+ << " " << cmQtAutoGen::Quoted(fileName) << "\n";
*errorMessage = ost.str();
}
allGood = false;
@@ -49,7 +111,7 @@ static bool RccListInputsQt4(const std::string& fileName,
}
if (allGood) {
// qrc file directory
- std::string qrcDir(cmsys::SystemTools::GetFilenamePath(fileName));
+ std::string qrcDir(cmSystemTools::GetFilenamePath(fileName));
if (!qrcDir.empty()) {
qrcDir += '/';
}
@@ -83,7 +145,7 @@ static bool RccListInputsQt5(const std::string& rccCommand,
std::string* errorMessage)
{
if (rccCommand.empty()) {
- cmSystemTools::Error("AutoRcc: Error: rcc executable not available\n");
+ cmSystemTools::Error("rcc executable not available");
return false;
}
@@ -122,7 +184,7 @@ static bool RccListInputsQt5(const std::string& rccCommand,
if (!result || retVal) {
if (errorMessage != nullptr) {
std::ostringstream ost;
- ost << "AutoRcc: Error: Rcc list process for " << fileName
+ ost << "rcc list process for " << cmQtAutoGen::Quoted(fileName)
<< " failed:\n"
<< rccStdOut << "\n"
<< rccStdErr << "\n";
@@ -155,8 +217,8 @@ static bool RccListInputsQt5(const std::string& rccCommand,
if (pos == std::string::npos) {
if (errorMessage != nullptr) {
std::ostringstream ost;
- ost << "AutoRcc: Error: Rcc lists unparsable output:\n"
- << cmQtAutoGeneratorCommon::Quoted(eline) << "\n";
+ ost << "rcc lists unparsable output:\n"
+ << cmQtAutoGen::Quoted(eline) << "\n";
*errorMessage = ost.str();
}
return false;
@@ -173,9 +235,29 @@ static bool RccListInputsQt5(const std::string& rccCommand,
// - Class definitions
-const char* cmQtAutoGeneratorCommon::listSep = "@LSEP@";
+const std::string cmQtAutoGen::listSep = "@LSEP@";
+
+const std::string& cmQtAutoGen::GeneratorName(GeneratorType type)
+{
+ switch (type) {
+ case GeneratorType::GEN:
+ return genNameGen;
+ case GeneratorType::MOC:
+ return genNameMoc;
+ case GeneratorType::UIC:
+ return genNameUic;
+ case GeneratorType::RCC:
+ return genNameRcc;
+ }
+ return genNameGen;
+}
+
+std::string cmQtAutoGen::GeneratorNameUpper(GeneratorType genType)
+{
+ return cmSystemTools::UpperCase(cmQtAutoGen::GeneratorName(genType));
+}
-std::string cmQtAutoGeneratorCommon::Quoted(const std::string& text)
+std::string cmQtAutoGen::Quoted(const std::string& text)
{
static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a",
"\b", "\\b", "\f", "\\f", "\n", "\\n",
@@ -191,14 +273,36 @@ std::string cmQtAutoGeneratorCommon::Quoted(const std::string& text)
return res;
}
-bool cmQtAutoGeneratorCommon::RccListInputs(const std::string& qtMajorVersion,
- const std::string& rccCommand,
- const std::string& fileName,
- std::vector<std::string>& files,
- std::string* errorMessage)
+void cmQtAutoGen::UicMergeOptions(std::vector<std::string>& baseOpts,
+ const std::vector<std::string>& newOpts,
+ bool isQt5)
+{
+ static const std::vector<std::string> valueOpts = {
+ "tr", "translate", "postfix", "generator",
+ "include", // Since Qt 5.3
+ "g"
+ };
+ MergeOptions(baseOpts, newOpts, valueOpts, isQt5);
+}
+
+void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts,
+ const std::vector<std::string>& newOpts,
+ bool isQt5)
+{
+ static const std::vector<std::string> valueOpts = { "name", "root",
+ "compress",
+ "threshold" };
+ MergeOptions(baseOpts, newOpts, valueOpts, isQt5);
+}
+
+bool cmQtAutoGen::RccListInputs(const std::string& qtMajorVersion,
+ const std::string& rccCommand,
+ const std::string& fileName,
+ std::vector<std::string>& files,
+ std::string* errorMessage)
{
bool allGood = false;
- if (cmsys::SystemTools::FileExists(fileName.c_str())) {
+ if (cmSystemTools::FileExists(fileName.c_str())) {
if (qtMajorVersion == "4") {
allGood = RccListInputsQt4(fileName, files, errorMessage);
} else {
@@ -207,8 +311,8 @@ bool cmQtAutoGeneratorCommon::RccListInputs(const std::string& qtMajorVersion,
} else {
if (errorMessage != nullptr) {
std::ostringstream ost;
- ost << "AutoRcc: Error: Rcc file does not exist:\n"
- << cmQtAutoGeneratorCommon::Quoted(fileName) << "\n";
+ ost << "rcc file does not exist:\n"
+ << " " << cmQtAutoGen::Quoted(fileName) << "\n";
*errorMessage = ost.str();
}
}
diff --git a/Source/cmQtAutoGeneratorCommon.h b/Source/cmQtAutoGen.h
index 23a882a..4cd5e32 100644
--- a/Source/cmQtAutoGeneratorCommon.h
+++ b/Source/cmQtAutoGen.h
@@ -1,31 +1,49 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmQtAutoGeneratorCommon_h
-#define cmQtAutoGeneratorCommon_h
+#ifndef cmQtAutoGen_h
+#define cmQtAutoGen_h
#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-class cmQtAutoGeneratorCommon
+/** \class cmQtAutoGen
+ * \brief Class used as namespace for QtAutogen related types and functions
+ */
+class cmQtAutoGen
{
- // - Types and statics
public:
- static const char* listSep;
+ static const std::string listSep;
enum GeneratorType
{
+ GEN, // General
MOC,
UIC,
RCC
};
public:
+ /// @brief Returns the generator name
+ static const std::string& GeneratorName(GeneratorType genType);
+ /// @brief Returns the generator name in upper case
+ static std::string GeneratorNameUpper(GeneratorType genType);
+
/// @brief Returns a the string escaped and enclosed in quotes
///
static std::string Quoted(const std::string& text);
+ /// @brief Merges newOpts into baseOpts
+ static void UicMergeOptions(std::vector<std::string>& baseOpts,
+ const std::vector<std::string>& newOpts,
+ bool isQt5);
+
+ /// @brief Merges newOpts into baseOpts
+ static void RccMergeOptions(std::vector<std::string>& baseOpts,
+ const std::vector<std::string>& newOpts,
+ bool isQt5);
+
/// @brief Reads the resource files list from from a .qrc file
/// @arg fileName Must be the absolute path of the .qrc file
/// @return True if the rcc file was successfully parsed
diff --git a/Source/cmQtAutoGenDigest.h b/Source/cmQtAutoGenDigest.h
new file mode 100644
index 0000000..677c397
--- /dev/null
+++ b/Source/cmQtAutoGenDigest.h
@@ -0,0 +1,64 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmQtAutoGenDigest_h
+#define cmQtAutoGenDigest_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <memory>
+#include <string>
+#include <vector>
+
+class cmGeneratorTarget;
+
+class cmQtAutoGenDigestQrc
+{
+public:
+ cmQtAutoGenDigestQrc()
+ : Generated(false)
+ , Unique(false)
+ {
+ }
+
+public:
+ std::string QrcFile;
+ std::string QrcName;
+ std::string PathChecksum;
+ std::string RccFile;
+ bool Generated;
+ bool Unique;
+ std::vector<std::string> Options;
+ std::vector<std::string> Resources;
+};
+
+/** \class cmQtAutoGenDigest
+ * \brief Filtered set of QtAutogen variables for a specific target
+ */
+class cmQtAutoGenDigest
+{
+public:
+ cmQtAutoGenDigest(cmGeneratorTarget* target)
+ : Target(target)
+ , MocEnabled(false)
+ , UicEnabled(false)
+ , RccEnabled(false)
+ {
+ }
+
+public:
+ cmGeneratorTarget* Target;
+ std::string QtVersionMajor;
+ std::string QtVersionMinor;
+ bool MocEnabled;
+ bool UicEnabled;
+ bool RccEnabled;
+ std::vector<std::string> Headers;
+ std::vector<std::string> Sources;
+ std::vector<cmQtAutoGenDigestQrc> Qrcs;
+};
+
+// Utility types
+typedef std::unique_ptr<cmQtAutoGenDigest> cmQtAutoGenDigestUP;
+typedef std::vector<cmQtAutoGenDigestUP> cmQtAutoGenDigestUPV;
+
+#endif
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index ebfb6f0..22ac9d2 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -1,7 +1,7 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmQtAutoGen.h"
#include "cmQtAutoGeneratorInitializer.h"
-#include "cmQtAutoGeneratorCommon.h"
#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
@@ -23,6 +23,7 @@
#include "cmsys/FStream.hxx"
#include <algorithm>
+#include <array>
#include <map>
#include <set>
#include <sstream>
@@ -35,12 +36,18 @@ inline static const char* SafeString(const char* value)
return (value != nullptr) ? value : "";
}
-static std::string GetSafeProperty(cmGeneratorTarget const* target,
- const char* key)
+inline static std::string GetSafeProperty(cmGeneratorTarget const* target,
+ const char* key)
{
return std::string(SafeString(target->GetProperty(key)));
}
+inline static std::string GetSafeProperty(cmSourceFile const* sf,
+ const char* key)
+{
+ return std::string(SafeString(sf->GetProperty(key)));
+}
+
inline static bool AutogenMultiConfig(cmGlobalGenerator* globalGen)
{
return globalGen->IsMultiConfig();
@@ -76,39 +83,40 @@ static std::string GetAutogenTargetBuildDir(cmGeneratorTarget const* target)
return targetDir;
}
-static std::string GetQtMajorVersion(cmGeneratorTarget const* target)
+std::string cmQtAutoGeneratorInitializer::GetQtMajorVersion(
+ cmGeneratorTarget const* target)
{
cmMakefile* makefile = target->Target->GetMakefile();
- std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
- if (qtMajorVersion.empty()) {
- qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
+ std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
+ if (qtMajor.empty()) {
+ qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
}
const char* targetQtVersion =
target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");
if (targetQtVersion != nullptr) {
- qtMajorVersion = targetQtVersion;
+ qtMajor = targetQtVersion;
}
- return qtMajorVersion;
+ return qtMajor;
}
-static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
- const std::string& qtMajorVersion)
+std::string cmQtAutoGeneratorInitializer::GetQtMinorVersion(
+ cmGeneratorTarget const* target, const std::string& qtVersionMajor)
{
cmMakefile* makefile = target->Target->GetMakefile();
- std::string qtMinorVersion;
- if (qtMajorVersion == "5") {
- qtMinorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
+ std::string qtMinor;
+ if (qtVersionMajor == "5") {
+ qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
}
- if (qtMinorVersion.empty()) {
- qtMinorVersion = makefile->GetSafeDefinition("QT_VERSION_MINOR");
+ if (qtMinor.empty()) {
+ qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR");
}
const char* targetQtVersion =
target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", "");
if (targetQtVersion != nullptr) {
- qtMinorVersion = targetQtVersion;
+ qtMinor = targetQtVersion;
}
- return qtMinorVersion;
+ return qtMinor;
}
static bool QtVersionGreaterOrEqual(const std::string& major,
@@ -126,26 +134,6 @@ static bool QtVersionGreaterOrEqual(const std::string& major,
return false;
}
-static void GetCompileDefinitionsAndDirectories(
- cmGeneratorTarget const* target, const std::string& config,
- std::string& incs, std::string& defs)
-{
- cmLocalGenerator* localGen = target->GetLocalGenerator();
- {
- std::vector<std::string> includeDirs;
- // Get the include dirs for this target, without stripping the implicit
- // include dirs off, see
- // https://gitlab.kitware.com/cmake/cmake/issues/13667
- localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false);
- incs = cmJoin(includeDirs, ";");
- }
- {
- std::set<std::string> defines;
- localGen->AddCompileDefinitions(defines, target, config, "CXX");
- defs += cmJoin(defines, ";");
- }
-}
-
static std::vector<std::string> GetConfigurations(
cmMakefile* makefile, std::string* config = nullptr)
{
@@ -168,9 +156,8 @@ static std::vector<std::string> GetConfigurationSuffixes(cmMakefile* makefile)
std::vector<std::string> suffixes;
if (AutogenMultiConfig(makefile->GetGlobalGenerator())) {
makefile->GetConfigurations(suffixes);
- for (std::vector<std::string>::iterator it = suffixes.begin();
- it != suffixes.end(); ++it) {
- it->insert(0, "_");
+ for (std::string& suffix : suffixes) {
+ suffix.insert(0, "_");
}
}
if (suffixes.empty()) {
@@ -200,33 +187,56 @@ static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());
}
+static void AddDefinitionEscaped(
+ cmMakefile* makefile, const char* key,
+ const std::vector<std::vector<std::string>>& lists)
+{
+ std::vector<std::string> seplist;
+ for (const std::vector<std::string>& list : lists) {
+ std::string blist = "{";
+ blist += cmJoin(list, ";");
+ blist += "}";
+ seplist.push_back(std::move(blist));
+ }
+ makefile->AddDefinition(key, cmOutputConverter::EscapeForCMake(
+ cmJoin(seplist, cmQtAutoGen::listSep))
+ .c_str());
+}
+
static bool AddToSourceGroup(cmMakefile* makefile, const std::string& fileName,
- cmQtAutoGeneratorCommon::GeneratorType genType)
+ cmQtAutoGen::GeneratorType genType)
{
cmSourceGroup* sourceGroup = nullptr;
// Acquire source group
{
- const char* groupName = nullptr;
- // Use generator specific group name
- switch (genType) {
- case cmQtAutoGeneratorCommon::MOC:
- groupName =
- makefile->GetState()->GetGlobalProperty("AUTOMOC_SOURCE_GROUP");
- break;
- case cmQtAutoGeneratorCommon::RCC:
- groupName =
- makefile->GetState()->GetGlobalProperty("AUTORCC_SOURCE_GROUP");
- break;
- default:
- break;
- }
- // Use default group name on demand
- if ((groupName == nullptr) || (*groupName == 0)) {
- groupName =
- makefile->GetState()->GetGlobalProperty("AUTOGEN_SOURCE_GROUP");
+ std::string property;
+ std::string groupName;
+ {
+ std::array<std::string, 2> props;
+ // Use generator specific group name
+ switch (genType) {
+ case cmQtAutoGen::MOC:
+ props[0] = "AUTOMOC_SOURCE_GROUP";
+ break;
+ case cmQtAutoGen::RCC:
+ props[0] = "AUTORCC_SOURCE_GROUP";
+ break;
+ default:
+ props[0] = "AUTOGEN_SOURCE_GROUP";
+ break;
+ }
+ props[1] = "AUTOGEN_SOURCE_GROUP";
+ for (std::string& prop : props) {
+ const char* propName = makefile->GetState()->GetGlobalProperty(prop);
+ if ((propName != nullptr) && (*propName != '\0')) {
+ groupName = propName;
+ property = std::move(prop);
+ break;
+ }
+ }
}
// Generate a source group on demand
- if ((groupName != nullptr) && (*groupName != 0)) {
+ if (!groupName.empty()) {
{
const char* delimiter =
makefile->GetDefinition("SOURCE_GROUP_DELIMITER");
@@ -242,9 +252,12 @@ static bool AddToSourceGroup(cmMakefile* makefile, const std::string& fileName,
}
}
if (sourceGroup == nullptr) {
- cmSystemTools::Error(
- "Autogen: Could not create or find source group: ",
- cmQtAutoGeneratorCommon::Quoted(groupName).c_str());
+ std::ostringstream ost;
+ ost << cmQtAutoGen::GeneratorNameUpper(genType);
+ ost << ": " << property;
+ ost << ": Could not find or create the source group ";
+ ost << cmQtAutoGen::Quoted(groupName);
+ cmSystemTools::Error(ost.str().c_str());
return false;
}
}
@@ -263,7 +276,7 @@ static void AddCleanFile(cmMakefile* makefile, const std::string& fileName)
static void AddGeneratedSource(cmGeneratorTarget* target,
const std::string& filename,
- cmQtAutoGeneratorCommon::GeneratorType genType)
+ cmQtAutoGen::GeneratorType genType)
{
cmMakefile* makefile = target->Target->GetMakefile();
{
@@ -276,32 +289,24 @@ static void AddGeneratedSource(cmGeneratorTarget* target,
AddToSourceGroup(makefile, filename, genType);
}
-struct AutogenSetup
+struct cmQtAutoGenSetup
{
- std::vector<std::string> sources;
- std::vector<std::string> headers;
+ std::set<std::string> MocSkip;
+ std::set<std::string> UicSkip;
- std::set<std::string> mocSkip;
- std::set<std::string> uicSkip;
-
- std::map<std::string, std::string> configSuffix;
- std::map<std::string, std::string> configMocIncludes;
- std::map<std::string, std::string> configMocDefines;
- std::map<std::string, std::string> configUicOptions;
+ std::map<std::string, std::string> ConfigMocIncludes;
+ std::map<std::string, std::string> ConfigMocDefines;
+ std::map<std::string, std::string> ConfigUicOptions;
};
-static void SetupAcquireScanFiles(cmGeneratorTarget const* target,
- bool mocEnabled, bool uicEnabled,
- const std::vector<cmSourceFile*>& srcFiles,
- AutogenSetup& setup)
+static void SetupAcquireSkipFiles(cmQtAutoGenDigest const& digest,
+ cmQtAutoGenSetup& setup)
{
// Read skip files from makefile sources
{
const std::vector<cmSourceFile*>& allSources =
- target->Makefile->GetSourceFiles();
- for (std::vector<cmSourceFile*>::const_iterator fit = allSources.begin();
- fit != allSources.end(); ++fit) {
- cmSourceFile* sf = *fit;
+ digest.Target->Makefile->GetSourceFiles();
+ for (cmSourceFile* sf : allSources) {
// sf->GetExtension() is only valid after sf->GetFullPath() ...
const std::string& fPath = sf->GetFullPath();
const cmSystemTools::FileFormat fileType =
@@ -311,95 +316,33 @@ static void SetupAcquireScanFiles(cmGeneratorTarget const* target,
continue;
}
const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN");
- const bool mocSkip =
- mocEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
- const bool uicSkip =
- uicEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
+ const bool mocSkip = digest.MocEnabled &&
+ (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
+ const bool uicSkip = digest.UicEnabled &&
+ (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
if (mocSkip || uicSkip) {
- const std::string absFile = cmsys::SystemTools::GetRealPath(fPath);
+ const std::string absFile = cmSystemTools::GetRealPath(fPath);
if (mocSkip) {
- setup.mocSkip.insert(absFile);
+ setup.MocSkip.insert(absFile);
}
if (uicSkip) {
- setup.uicSkip.insert(absFile);
+ setup.UicSkip.insert(absFile);
}
}
}
}
-
- const cmPolicies::PolicyStatus CMP0071_status =
- target->Makefile->GetPolicyStatus(cmPolicies::CMP0071);
- for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
- fileIt != srcFiles.end(); ++fileIt) {
- cmSourceFile* sf = *fileIt;
- // sf->GetExtension() is only valid after sf->GetFullPath() ...
- const std::string& fPath = sf->GetFullPath();
- const cmSystemTools::FileFormat fileType =
- cmSystemTools::GetFileFormat(sf->GetExtension().c_str());
- if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) &&
- !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
- continue;
- }
- // Real file path
- const std::string absFile = cmsys::SystemTools::GetRealPath(fPath);
- // Skip test
- const bool mocSkip = !mocEnabled || (setup.mocSkip.count(absFile) != 0);
- const bool uicSkip = !uicEnabled || (setup.uicSkip.count(absFile) != 0);
- if (mocSkip && uicSkip) {
- continue;
- }
-
- // For GENERATED files check status of policy CMP0071
- if (sf->GetPropertyAsBool("GENERATED")) {
- bool policyAccept = false;
- switch (CMP0071_status) {
- case cmPolicies::WARN: {
- std::ostringstream ost;
- ost << cmPolicies::GetPolicyWarning(cmPolicies::CMP0071) << "\n";
- ost << "AUTOMOC/AUTOUIC: Ignoring GENERATED source file:\n";
- ost << " " << cmQtAutoGeneratorCommon::Quoted(absFile) << "\n";
- target->Makefile->IssueMessage(cmake::AUTHOR_WARNING, ost.str());
- }
- CM_FALLTHROUGH;
- case cmPolicies::OLD:
- // Ignore GENERATED file
- break;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::NEW:
- // Process GENERATED file
- policyAccept = true;
- break;
- }
- if (!policyAccept) {
- continue;
- }
- }
-
- // Add file name to sources or headers list
- switch (fileType) {
- case cmSystemTools::CXX_FILE_FORMAT:
- setup.sources.push_back(absFile);
- break;
- case cmSystemTools::HEADER_FILE_FORMAT:
- setup.headers.push_back(absFile);
- break;
- default:
- break;
- }
- }
}
-static void SetupAutoTargetMoc(cmGeneratorTarget const* target,
- std::string const& qtMajorVersion,
+static void SetupAutoTargetMoc(const cmQtAutoGenDigest& digest,
std::string const& config,
std::vector<std::string> const& configs,
- AutogenSetup& setup)
+ cmQtAutoGenSetup& setup)
{
+ cmGeneratorTarget const* target = digest.Target;
cmLocalGenerator* localGen = target->GetLocalGenerator();
cmMakefile* makefile = target->Target->GetMakefile();
- AddDefinitionEscaped(makefile, "_moc_skip", setup.mocSkip);
+ AddDefinitionEscaped(makefile, "_moc_skip", setup.MocSkip);
AddDefinitionEscaped(makefile, "_moc_options",
GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS"));
AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
@@ -410,33 +353,49 @@ static void SetupAutoTargetMoc(cmGeneratorTarget const* target,
AddDefinitionEscaped(makefile, "_moc_depend_filters",
GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS"));
- if (QtVersionGreaterOrEqual(
- qtMajorVersion, GetQtMinorVersion(target, qtMajorVersion), 5, 8)) {
+ if (QtVersionGreaterOrEqual(digest.QtVersionMajor, digest.QtVersionMinor, 5,
+ 8)) {
AddDefinitionEscaped(
makefile, "_moc_predefs_cmd",
makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
}
// Moc includes and compile definitions
{
+ auto GetCompileDefinitionsAndDirectories = [target, localGen](
+ const std::string& cfg, std::string& incs, std::string& defs) {
+ {
+ std::vector<std::string> includeDirs;
+ // Get the include dirs for this target, without stripping the implicit
+ // include dirs off, see
+ // https://gitlab.kitware.com/cmake/cmake/issues/13667
+ localGen->GetIncludeDirectories(includeDirs, target, "CXX", cfg,
+ false);
+ incs = cmJoin(includeDirs, ";");
+ }
+ {
+ std::set<std::string> defines;
+ localGen->AddCompileDefinitions(defines, target, cfg, "CXX");
+ defs += cmJoin(defines, ";");
+ }
+ };
+
// Default settings
std::string incs;
std::string compileDefs;
- GetCompileDefinitionsAndDirectories(target, config, incs, compileDefs);
+ GetCompileDefinitionsAndDirectories(config, incs, compileDefs);
AddDefinitionEscaped(makefile, "_moc_incs", incs);
AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
// Configuration specific settings
- for (std::vector<std::string>::const_iterator li = configs.begin();
- li != configs.end(); ++li) {
+ for (const std::string& cfg : configs) {
std::string configIncs;
std::string configCompileDefs;
- GetCompileDefinitionsAndDirectories(target, *li, configIncs,
- configCompileDefs);
+ GetCompileDefinitionsAndDirectories(cfg, configIncs, configCompileDefs);
if (configIncs != incs) {
- setup.configMocIncludes[*li] = configIncs;
+ setup.ConfigMocIncludes[cfg] = configIncs;
}
if (configCompileDefs != compileDefs) {
- setup.configMocDefines[*li] = configCompileDefs;
+ setup.ConfigMocDefines[cfg] = configCompileDefs;
}
}
}
@@ -446,14 +405,14 @@ static void SetupAutoTargetMoc(cmGeneratorTarget const* target,
std::string mocExec;
std::string err;
- if (qtMajorVersion == "5") {
+ if (digest.QtVersionMajor == "5") {
cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc");
if (tgt != nullptr) {
mocExec = SafeString(tgt->ImportedGetLocation(""));
} else {
err = "AUTOMOC: Qt5::moc target not found";
}
- } else if (qtMajorVersion == "4") {
+ } else if (digest.QtVersionMajor == "4") {
cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc");
if (tgt != nullptr) {
mocExec = SafeString(tgt->ImportedGetLocation(""));
@@ -473,24 +432,15 @@ static void SetupAutoTargetMoc(cmGeneratorTarget const* target,
}
}
-static void UicGetOpts(cmGeneratorTarget const* target,
- const std::string& config, std::string& optString)
-{
- std::vector<std::string> opts;
- target->GetAutoUicOptions(opts, config);
- optString = cmJoin(opts, ";");
-}
-
-static void SetupAutoTargetUic(cmGeneratorTarget const* target,
- std::string const& qtMajorVersion,
+static void SetupAutoTargetUic(const cmQtAutoGenDigest& digest,
std::string const& config,
std::vector<std::string> const& configs,
- AutogenSetup& setup)
+ cmQtAutoGenSetup& setup)
{
- cmLocalGenerator* localGen = target->GetLocalGenerator();
+ cmGeneratorTarget const* target = digest.Target;
cmMakefile* makefile = target->Target->GetMakefile();
- AddDefinitionEscaped(makefile, "_uic_skip", setup.uicSkip);
+ AddDefinitionEscaped(makefile, "_uic_skip", setup.UicSkip);
// Uic search paths
{
@@ -500,9 +450,8 @@ static void SetupAutoTargetUic(cmGeneratorTarget const* target,
if (!usp.empty()) {
cmSystemTools::ExpandListArgument(usp, uicSearchPaths);
const std::string srcDir = makefile->GetCurrentSourceDirectory();
- for (std::vector<std::string>::iterator it = uicSearchPaths.begin();
- it != uicSearchPaths.end(); ++it) {
- *it = cmSystemTools::CollapseFullPath(*it, srcDir);
+ for (std::string& path : uicSearchPaths) {
+ path = cmSystemTools::CollapseFullPath(path, srcDir);
}
}
}
@@ -510,44 +459,45 @@ static void SetupAutoTargetUic(cmGeneratorTarget const* target,
}
// Uic target options
{
+ auto UicGetOpts = [target](const std::string& cfg) -> std::string {
+ std::vector<std::string> opts;
+ target->GetAutoUicOptions(opts, cfg);
+ return cmJoin(opts, ";");
+ };
+
// Default settings
- std::string uicOpts;
- UicGetOpts(target, config, uicOpts);
+ const std::string uicOpts = UicGetOpts(config);
AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);
// Configuration specific settings
- for (std::vector<std::string>::const_iterator li = configs.begin();
- li != configs.end(); ++li) {
- std::string configUicOpts;
- UicGetOpts(target, *li, configUicOpts);
+ for (const std::string& cfg : configs) {
+ const std::string configUicOpts = UicGetOpts(cfg);
if (configUicOpts != uicOpts) {
- setup.configUicOptions[*li] = configUicOpts;
+ setup.ConfigUicOptions[cfg] = configUicOpts;
}
}
}
// Uic files options
{
std::vector<std::string> uiFileFiles;
- std::vector<std::string> uiFileOptions;
+ std::vector<std::vector<std::string>> uiFileOptions;
{
const std::string uiExt = "ui";
const std::vector<cmSourceFile*>& srcFiles = makefile->GetSourceFiles();
- for (std::vector<cmSourceFile*>::const_iterator fit = srcFiles.begin();
- fit != srcFiles.end(); ++fit) {
- cmSourceFile* sf = *fit;
+ for (cmSourceFile* sf : srcFiles) {
// sf->GetExtension() is only valid after sf->GetFullPath() ...
const std::string& fPath = sf->GetFullPath();
if (sf->GetExtension() == uiExt) {
// Check if the files has uic options
- std::string uicOpts = sf->GetProperty("AUTOUIC_OPTIONS");
+ const std::string uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
if (!uicOpts.empty()) {
- const std::string absFile = cmsys::SystemTools::GetRealPath(fPath);
+ const std::string absFile = cmSystemTools::GetRealPath(fPath);
// Check if file isn't skipped
- if (setup.uicSkip.count(absFile) == 0) {
+ if (setup.UicSkip.count(absFile) == 0) {
uiFileFiles.push_back(absFile);
- cmSystemTools::ReplaceString(uicOpts, ";",
- cmQtAutoGeneratorCommon::listSep);
- uiFileOptions.push_back(uicOpts);
+ std::vector<std::string> optsVec;
+ cmSystemTools::ExpandListArgument(uicOpts, optsVec);
+ uiFileOptions.push_back(std::move(optsVec));
}
}
}
@@ -562,14 +512,15 @@ static void SetupAutoTargetUic(cmGeneratorTarget const* target,
std::string err;
std::string uicExec;
- if (qtMajorVersion == "5") {
+ cmLocalGenerator* localGen = target->GetLocalGenerator();
+ if (digest.QtVersionMajor == "5") {
cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic");
if (tgt != nullptr) {
uicExec = SafeString(tgt->ImportedGetLocation(""));
} else {
// Project does not use Qt5Widgets, but has AUTOUIC ON anyway
}
- } else if (qtMajorVersion == "4") {
+ } else if (digest.QtVersionMajor == "4") {
cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic");
if (tgt != nullptr) {
uicExec = SafeString(tgt->ImportedGetLocation(""));
@@ -621,141 +572,48 @@ static std::string RccGetExecutable(cmGeneratorTarget const* target,
return rccExec;
}
-static void RccMergeOptions(std::vector<std::string>& opts,
- const std::vector<std::string>& fileOpts,
- bool isQt5)
+static void SetupAutoTargetRcc(const cmQtAutoGenDigest& digest)
{
- static const char* valueOptions[] = { "name", "root", "compress",
- "threshold" };
- std::vector<std::string> extraOpts;
- for (std::vector<std::string>::const_iterator fit = fileOpts.begin();
- fit != fileOpts.end(); ++fit) {
- std::vector<std::string>::iterator existingIt =
- std::find(opts.begin(), opts.end(), *fit);
- if (existingIt != opts.end()) {
- const char* optName = fit->c_str();
- if (*optName == '-') {
- ++optName;
- if (isQt5 && *optName == '-') {
- ++optName;
- }
- }
- // Test if this is a value option and change the existing value
- if ((optName != fit->c_str()) &&
- std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions),
- cmStrCmp(optName)) != cmArrayEnd(valueOptions)) {
- const std::vector<std::string>::iterator existValueIt(existingIt + 1);
- const std::vector<std::string>::const_iterator fileValueIt(fit + 1);
- if ((existValueIt != opts.end()) && (fileValueIt != fileOpts.end())) {
- *existValueIt = *fileValueIt;
- ++fit;
- }
- }
- } else {
- extraOpts.push_back(*fit);
- }
- }
- opts.insert(opts.end(), extraOpts.begin(), extraOpts.end());
-}
-
-static void SetupAutoTargetRcc(cmGeneratorTarget const* target,
- const std::string& qtMajorVersion,
- const std::vector<cmSourceFile*>& srcFiles)
-{
- cmMakefile* makefile = target->Target->GetMakefile();
- const bool qtMajorVersion5 = (qtMajorVersion == "5");
- const std::string rccCommand = RccGetExecutable(target, qtMajorVersion);
std::vector<std::string> rccFiles;
- std::vector<std::string> rccInputs;
- std::vector<std::string> rccFileFiles;
- std::vector<std::string> rccFileOptions;
- std::vector<std::string> rccOptionsTarget;
-
- cmSystemTools::ExpandListArgument(GetSafeProperty(target, "AUTORCC_OPTIONS"),
- rccOptionsTarget);
-
- for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
- fileIt != srcFiles.end(); ++fileIt) {
- cmSourceFile* sf = *fileIt;
- // sf->GetExtension() is only valid after sf->GetFullPath() ...
- const std::string& fPath = sf->GetFullPath();
- if ((sf->GetExtension() == "qrc") &&
- !sf->GetPropertyAsBool("SKIP_AUTOGEN") &&
- !sf->GetPropertyAsBool("SKIP_AUTORCC")) {
- const std::string absFile = cmsys::SystemTools::GetRealPath(fPath);
- // qrc file
- rccFiles.push_back(absFile);
- // qrc file entries
- {
- std::string entriesList = "{";
- // Read input file list only for non generated .qrc files.
- if (!sf->GetPropertyAsBool("GENERATED")) {
- std::string error;
- std::vector<std::string> files;
- if (cmQtAutoGeneratorCommon::RccListInputs(
- qtMajorVersion, rccCommand, absFile, files, &error)) {
- entriesList += cmJoin(files, cmQtAutoGeneratorCommon::listSep);
- } else {
- cmSystemTools::Error(error.c_str());
- }
- }
- entriesList += "}";
- rccInputs.push_back(entriesList);
- }
- // rcc options for this qrc file
- {
- // Merged target and file options
- std::vector<std::string> rccOptions(rccOptionsTarget);
- if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) {
- std::vector<std::string> optsVec;
- cmSystemTools::ExpandListArgument(prop, optsVec);
- RccMergeOptions(rccOptions, optsVec, qtMajorVersion5);
- }
- // Only store non empty options lists
- if (!rccOptions.empty()) {
- rccFileFiles.push_back(absFile);
- rccFileOptions.push_back(
- cmJoin(rccOptions, cmQtAutoGeneratorCommon::listSep));
- }
- }
- }
+ std::vector<std::string> rccBuilds;
+ std::vector<std::vector<std::string>> rccOptions;
+ std::vector<std::vector<std::string>> rccInputs;
+
+ for (const cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
+ rccFiles.push_back(qrcDigest.QrcFile);
+ rccBuilds.push_back(qrcDigest.RccFile);
+ rccOptions.push_back(qrcDigest.Options);
+ rccInputs.push_back(qrcDigest.Resources);
}
- AddDefinitionEscaped(makefile, "_qt_rcc_executable", rccCommand);
+ cmMakefile* makefile = digest.Target->Target->GetMakefile();
+ AddDefinitionEscaped(makefile, "_qt_rcc_executable",
+ RccGetExecutable(digest.Target, digest.QtVersionMajor));
AddDefinitionEscaped(makefile, "_rcc_files", rccFiles);
+ AddDefinitionEscaped(makefile, "_rcc_builds", rccBuilds);
+ AddDefinitionEscaped(makefile, "_rcc_options", rccOptions);
AddDefinitionEscaped(makefile, "_rcc_inputs", rccInputs);
- AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles);
- AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions);
}
void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
- cmLocalGenerator* localGen, cmGeneratorTarget* target)
+ cmQtAutoGenDigest& digest)
{
+ cmGeneratorTarget* target = digest.Target;
cmMakefile* makefile = target->Target->GetMakefile();
+ cmLocalGenerator* localGen = target->GetLocalGenerator();
cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
// Create a custom target for running generators at buildtime
- const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC");
- const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC");
- const bool rccEnabled = target->GetPropertyAsBool("AUTORCC");
const bool multiConfig = AutogenMultiConfig(globalGen);
const std::string autogenTargetName = GetAutogenTargetName(target);
const std::string autogenBuildDir = GetAutogenTargetBuildDir(target);
const std::string workingDirectory =
cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory());
const std::vector<std::string> suffixes = GetConfigurationSuffixes(makefile);
- std::set<std::string> autogenDependsSet;
+ std::set<std::string> autogenDependFiles;
+ std::set<std::string> autogenDependTargets;
std::vector<std::string> autogenProvides;
- bool usePRE_BUILD = false;
- if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
- // Under VS use a PRE_BUILD event instead of a separate target to
- // reduce the number of targets loaded into the IDE.
- // This also works around a VS 11 bug that may skip updating the target:
- // https://connect.microsoft.com/VisualStudio/feedback/details/769495
- usePRE_BUILD = true;
- }
-
// Remove build directories on cleanup
AddCleanFile(makefile, autogenBuildDir);
@@ -763,9 +621,8 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
{
std::string base = GetAutogenTargetFilesDir(target);
base += "/AutogenOldSettings";
- for (std::vector<std::string>::const_iterator it = suffixes.begin();
- it != suffixes.end(); ++it) {
- AddCleanFile(makefile, base + *it + ".cmake");
+ for (const std::string& suffix : suffixes) {
+ AddCleanFile(makefile, (base + suffix).append(".cmake"));
}
}
@@ -785,13 +642,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
std::string autogenComment;
{
std::vector<std::string> toolNames;
- if (mocEnabled) {
+ if (digest.MocEnabled) {
toolNames.push_back("MOC");
}
- if (uicEnabled) {
+ if (digest.UicEnabled) {
toolNames.push_back("UIC");
}
- if (rccEnabled) {
+ if (digest.RccEnabled) {
toolNames.push_back("RCC");
}
@@ -808,14 +665,14 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
}
// Add moc compilation to generated files list
- if (mocEnabled) {
+ if (digest.MocEnabled) {
const std::string mocsComp = autogenBuildDir + "/mocs_compilation.cpp";
- AddGeneratedSource(target, mocsComp, cmQtAutoGeneratorCommon::MOC);
+ AddGeneratedSource(target, mocsComp, cmQtAutoGen::MOC);
autogenProvides.push_back(mocsComp);
}
// Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
- if (mocEnabled || uicEnabled) {
+ if (digest.MocEnabled || digest.UicEnabled) {
std::string includeDir = autogenBuildDir + "/include";
if (multiConfig) {
includeDir += "_$<CONFIG>";
@@ -823,49 +680,14 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
target->AddIncludeDirectory(includeDir, true);
}
- // Add user defined autogen target dependencies
- {
- const std::string deps = GetSafeProperty(target, "AUTOGEN_TARGET_DEPENDS");
- if (!deps.empty()) {
- std::vector<std::string> extraDepends;
- cmSystemTools::ExpandListArgument(deps, extraDepends);
- autogenDependsSet.insert(extraDepends.begin(), extraDepends.end());
- }
- }
- // Add utility target dependencies to the autogen dependencies
- {
- const std::set<std::string>& utils = target->Target->GetUtilities();
- for (std::set<std::string>::const_iterator it = utils.begin();
- it != utils.end(); ++it) {
- const std::string& targetName = *it;
- if (makefile->FindTargetToUse(targetName) != nullptr) {
- autogenDependsSet.insert(targetName);
- }
- }
- }
- // Add link library target dependencies to the autogen dependencies
- {
- const cmTarget::LinkLibraryVectorType& libVec =
- target->Target->GetOriginalLinkLibraries();
- for (cmTarget::LinkLibraryVectorType::const_iterator it = libVec.begin();
- it != libVec.end(); ++it) {
- const std::string& libName = it->first;
- if (makefile->FindTargetToUse(libName) != nullptr) {
- autogenDependsSet.insert(libName);
- }
- }
- }
-
// Extract relevant source files
std::vector<std::string> generatedSources;
- std::vector<std::pair<std::string, bool>> qrcSources;
+ std::vector<std::string> generatedHeaders;
{
const std::string qrcExt = "qrc";
std::vector<cmSourceFile*> srcFiles;
target->GetConfigCommonSourceFiles(srcFiles);
- for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
- fileIt != srcFiles.end(); ++fileIt) {
- cmSourceFile* sf = *fileIt;
+ for (cmSourceFile* sf : srcFiles) {
if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
continue;
}
@@ -873,26 +695,51 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
const std::string& fPath = sf->GetFullPath();
const std::string& ext = sf->GetExtension();
// Register generated files that will be scanned by moc or uic
- if (mocEnabled || uicEnabled) {
+ if (digest.MocEnabled || digest.UicEnabled) {
const cmSystemTools::FileFormat fileType =
cmSystemTools::GetFileFormat(ext.c_str());
if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||
(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
- if (sf->GetPropertyAsBool("GENERATED")) {
- if ((mocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
- (uicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {
- generatedSources.push_back(
- cmsys::SystemTools::GetRealPath(fPath));
+ const std::string absPath = cmSystemTools::GetRealPath(fPath);
+ if ((digest.MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
+ (digest.UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {
+ // Register source
+ const bool generated = sf->GetPropertyAsBool("GENERATED");
+ if (fileType == cmSystemTools::HEADER_FILE_FORMAT) {
+ if (generated) {
+ generatedHeaders.push_back(absPath);
+ } else {
+ digest.Headers.push_back(absPath);
+ }
+ } else {
+ if (generated) {
+ generatedSources.push_back(absPath);
+ } else {
+ digest.Sources.push_back(absPath);
+ }
}
}
}
}
// Register rcc enabled files
- if (rccEnabled && (ext == qrcExt) &&
+ if (digest.RccEnabled && (ext == qrcExt) &&
!sf->GetPropertyAsBool("SKIP_AUTORCC")) {
- qrcSources.push_back(
- std::pair<std::string, bool>(cmsys::SystemTools::GetRealPath(fPath),
- sf->GetPropertyAsBool("GENERATED")));
+ // Register qrc file
+ {
+ cmQtAutoGenDigestQrc qrcDigest;
+ qrcDigest.QrcFile = cmSystemTools::GetRealPath(fPath);
+ qrcDigest.QrcName =
+ cmSystemTools::GetFilenameWithoutLastExtension(qrcDigest.QrcFile);
+ qrcDigest.Generated = sf->GetPropertyAsBool("GENERATED");
+ // RCC options
+ {
+ const std::string opts = GetSafeProperty(sf, "AUTORCC_OPTIONS");
+ if (!opts.empty()) {
+ cmSystemTools::ExpandListArgument(opts, qrcDigest.Options);
+ }
+ }
+ digest.Qrcs.push_back(std::move(qrcDigest));
+ }
}
}
// cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's
@@ -902,104 +749,242 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
target->ClearSourcesCache();
}
- if (!generatedSources.empty()) {
- for (std::vector<std::string>::const_iterator it =
- generatedSources.begin();
- it != generatedSources.end(); ++it) {
- autogenDependsSet.insert(*it);
+ // Process GENERATED sources and headers
+ if (!generatedSources.empty() || !generatedHeaders.empty()) {
+ // Check status of policy CMP0071
+ bool policyAccept = false;
+ bool policyWarn = false;
+ const cmPolicies::PolicyStatus CMP0071_status =
+ target->Makefile->GetPolicyStatus(cmPolicies::CMP0071);
+ switch (CMP0071_status) {
+ case cmPolicies::WARN:
+ policyWarn = true;
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // Ignore GENERATED file
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Process GENERATED file
+ policyAccept = true;
+ break;
}
- }
-
- if (!qrcSources.empty()) {
- const std::string qtMajorVersion = GetQtMajorVersion(target);
- const std::string rccCommand = RccGetExecutable(target, qtMajorVersion);
- const cmFilePathChecksum fpathCheckSum(makefile);
- for (std::vector<std::pair<std::string, bool>>::const_iterator it =
- qrcSources.begin();
- it != qrcSources.end(); ++it) {
- const std::string& absFile = it->first;
- // Compose rcc output file name
+ if (policyAccept) {
+ // Accept GENERATED sources
+ for (const std::string& absFile : generatedHeaders) {
+ digest.Headers.push_back(absFile);
+ autogenDependFiles.insert(absFile);
+ }
+ for (const std::string& absFile : generatedSources) {
+ digest.Sources.push_back(absFile);
+ autogenDependFiles.insert(absFile);
+ }
+ } else {
+ if (policyWarn) {
+ std::string msg;
+ msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071);
+ msg += "\n";
+ std::string tools;
+ if (digest.MocEnabled) {
+ tools += "AUTOMOC";
+ }
+ if (digest.UicEnabled) {
+ if (!tools.empty()) {
+ tools += ",";
+ }
+ tools += "AUTOUIC";
+ }
+ if (!generatedHeaders.empty()) {
+ msg.append(tools).append(": Ignoring GENERATED header file(s):\n");
+ for (const std::string& absFile : generatedHeaders) {
+ msg.append(" ").append(cmQtAutoGen::Quoted(absFile)).append("\n");
+ }
+ }
+ if (!generatedSources.empty()) {
+ msg.append(tools).append(": Ignoring GENERATED source file(s):\n");
+ for (const std::string& absFile : generatedSources) {
+ msg.append(" ").append(cmQtAutoGen::Quoted(absFile)).append("\n");
+ }
+ }
+ makefile->IssueMessage(cmake::AUTHOR_WARNING, msg);
+ }
+ }
+ }
+ // Sort headers and sources
+ std::sort(digest.Headers.begin(), digest.Headers.end());
+ std::sort(digest.Sources.begin(), digest.Sources.end());
+
+ // Process qrc files
+ if (!digest.Qrcs.empty()) {
+ const bool QtV5 = (digest.QtVersionMajor == "5");
+ const std::string rcc = RccGetExecutable(target, digest.QtVersionMajor);
+ // Target rcc options
+ std::vector<std::string> optionsTarget;
+ cmSystemTools::ExpandListArgument(
+ GetSafeProperty(target, "AUTORCC_OPTIONS"), optionsTarget);
+
+ // Check if file name is unique
+ for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
+ qrcDigest.Unique = true;
+ for (const cmQtAutoGenDigestQrc& qrcDig2 : digest.Qrcs) {
+ if ((&qrcDigest != &qrcDig2) &&
+ (qrcDigest.QrcName == qrcDig2.QrcName)) {
+ qrcDigest.Unique = false;
+ break;
+ }
+ }
+ }
+ // Path checksum
+ {
+ const cmFilePathChecksum fpathCheckSum(makefile);
+ for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
+ qrcDigest.PathChecksum = fpathCheckSum.getPart(qrcDigest.QrcFile);
+ // RCC output file name
+ std::string rccFile = autogenBuildDir + "/";
+ rccFile += qrcDigest.PathChecksum;
+ rccFile += "/qrc_";
+ rccFile += qrcDigest.QrcName;
+ rccFile += ".cpp";
+ qrcDigest.RccFile = std::move(rccFile);
+ }
+ }
+ // RCC options
+ for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
+ // Target options
+ std::vector<std::string> opts = optionsTarget;
+ // Merge computed "-name XYZ" option
{
- std::string rccBuildFile = autogenBuildDir + "/";
- rccBuildFile += fpathCheckSum.getPart(absFile);
- rccBuildFile += "/qrc_";
- rccBuildFile +=
- cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile);
- rccBuildFile += ".cpp";
-
- // Register rcc ouput file as generated
- AddGeneratedSource(target, rccBuildFile, cmQtAutoGeneratorCommon::RCC);
- // Register rcc ouput file as generated by the _autogen target
- autogenProvides.push_back(rccBuildFile);
+ std::string name = qrcDigest.QrcName;
+ // Replace '-' with '_'. The former is not valid for symbol names.
+ std::replace(name.begin(), name.end(), '-', '_');
+ if (!qrcDigest.Unique) {
+ name += "_";
+ name += qrcDigest.PathChecksum;
+ }
+ std::vector<std::string> nameOpts;
+ nameOpts.emplace_back("-name");
+ nameOpts.emplace_back(std::move(name));
+ cmQtAutoGen::RccMergeOptions(opts, nameOpts, QtV5);
}
-
- if (it->second) {
- // Add generated qrc file to the dependencies
- autogenDependsSet.insert(absFile);
+ // Merge file option
+ cmQtAutoGen::RccMergeOptions(opts, qrcDigest.Options, QtV5);
+ qrcDigest.Options = std::move(opts);
+ }
+ for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
+ // Register file at target
+ AddGeneratedSource(target, qrcDigest.RccFile, cmQtAutoGen::RCC);
+ autogenProvides.push_back(qrcDigest.RccFile);
+ // Dependencies
+ if (qrcDigest.Generated) {
+ // Add the GENERATED .qrc file to the dependencies
+ autogenDependFiles.insert(qrcDigest.QrcFile);
} else {
- // Run cmake again when .qrc file changes
- makefile->AddCMakeDependFile(absFile);
- // Add the qrc input files to the dependencies
+ // Add the resource files to the dependencies
{
std::string error;
- std::vector<std::string> extraDepends;
- if (cmQtAutoGeneratorCommon::RccListInputs(
- qtMajorVersion, rccCommand, absFile, extraDepends, &error)) {
- autogenDependsSet.insert(extraDepends.begin(), extraDepends.end());
+ if (cmQtAutoGen::RccListInputs(digest.QtVersionMajor, rcc,
+ qrcDigest.QrcFile,
+ qrcDigest.Resources, &error)) {
+ for (const std::string& fileName : qrcDigest.Resources) {
+ autogenDependFiles.insert(fileName);
+ }
} else {
cmSystemTools::Error(error.c_str());
}
}
+ // Run cmake again when .qrc file changes
+ makefile->AddCMakeDependFile(qrcDigest.QrcFile);
}
}
}
- // Convert std::set to std::vector
- const std::vector<std::string> autogenDepends(autogenDependsSet.begin(),
- autogenDependsSet.end());
- // Disable PRE_BUILD on demand
- if (usePRE_BUILD) {
- if (!generatedSources.empty() || !qrcSources.empty()) {
- // - Cannot use PRE_BUILD with generated files
- // - Cannot use PRE_BUILD because the resource files themselves
- // may not be sources within the target so VS may not know the
- // target needs to re-build at all.
- usePRE_BUILD = false;
- }
- if (usePRE_BUILD) {
- // If the autogen target depends on an other target don't use PRE_BUILD
- for (std::vector<std::string>::const_iterator it =
- autogenDepends.begin();
- it != autogenDepends.end(); ++it) {
- if (makefile->FindTargetToUse(*it) != nullptr) {
- usePRE_BUILD = false;
- break;
+ // Add user defined autogen target dependencies
+ {
+ const std::string deps = GetSafeProperty(target, "AUTOGEN_TARGET_DEPENDS");
+ if (!deps.empty()) {
+ std::vector<std::string> extraDeps;
+ cmSystemTools::ExpandListArgument(deps, extraDeps);
+ for (const std::string& depName : extraDeps) {
+ // Allow target and file dependencies
+ auto* depTarget = makefile->FindTargetToUse(depName);
+ if (depTarget != nullptr) {
+ autogenDependTargets.insert(depTarget->GetName());
+ } else {
+ autogenDependFiles.insert(depName);
}
}
}
}
+
+ // Use PRE_BUILD on demand
+ bool usePRE_BUILD = false;
+ if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
+ // Under VS use a PRE_BUILD event instead of a separate target to
+ // reduce the number of targets loaded into the IDE.
+ // This also works around a VS 11 bug that may skip updating the target:
+ // https://connect.microsoft.com/VisualStudio/feedback/details/769495
+ usePRE_BUILD = true;
+ }
+ // Disable PRE_BUILD in some cases
if (usePRE_BUILD) {
+ // Cannot use PRE_BUILD with file depends
+ if (!autogenDependFiles.empty()) {
+ usePRE_BUILD = false;
+ }
+ }
+ // Create the autogen target/command
+ if (usePRE_BUILD) {
+ // Add additional autogen target dependencies to origin target
+ for (const std::string& depTarget : autogenDependTargets) {
+ target->Target->AddUtility(depTarget, makefile);
+ }
+
// Add the pre-build command directly to bypass the OBJECT_LIBRARY
// rejection in cmMakefile::AddCustomCommandToTarget because we know
// PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
- std::vector<std::string> no_output;
- cmCustomCommand cc(makefile, no_output, autogenProvides, autogenDepends,
+ //
+ // PRE_BUILD does not support file dependencies!
+ const std::vector<std::string> no_output;
+ const std::vector<std::string> no_deps;
+ cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps,
commandLines, autogenComment.c_str(),
workingDirectory.c_str());
cc.SetEscapeOldStyle(false);
cc.SetEscapeAllowMakeVars(true);
target->Target->AddPreBuildCommand(cc);
} else {
+
+ // Add utility target dependencies to the autogen target dependencies
+ for (const std::string& depTarget : target->Target->GetUtilities()) {
+ autogenDependTargets.insert(depTarget);
+ }
+ // Add link library target dependencies to the autogen target dependencies
+ for (const auto& item : target->Target->GetOriginalLinkLibraries()) {
+ if (makefile->FindTargetToUse(item.first) != nullptr) {
+ autogenDependTargets.insert(item.first);
+ }
+ }
+
+ // Convert file dependencies std::set to std::vector
+ const std::vector<std::string> autogenDepends(autogenDependFiles.begin(),
+ autogenDependFiles.end());
+ // Create autogen target
cmTarget* autogenTarget = makefile->AddUtilityCommand(
autogenTargetName, true, workingDirectory.c_str(),
/*byproducts=*/autogenProvides, autogenDepends, commandLines, false,
autogenComment.c_str());
-
+ // Create autogen generator target
localGen->AddGeneratorTarget(
new cmGeneratorTarget(autogenTarget, localGen));
- // Set autogen target FOLDER
+ // Add additional autogen target dependencies to autogen target
+ for (const std::string& depTarget : autogenDependTargets) {
+ autogenTarget->AddUtility(depTarget, makefile);
+ }
+
+ // Set FOLDER property in autogen target
{
const char* autogenFolder =
makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
@@ -1009,7 +994,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
}
// Inherit FOLDER property from target (#13688)
if (autogenFolder == nullptr) {
- autogenFolder = target->Target->GetProperty("FOLDER");
+ autogenFolder = SafeString(target->Target->GetProperty("FOLDER"));
}
if ((autogenFolder != nullptr) && (*autogenFolder != '\0')) {
autogenTarget->SetProperty("FOLDER", autogenFolder);
@@ -1017,13 +1002,14 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
}
// Add autogen target to the origin target dependencies
- target->Target->AddUtility(autogenTargetName);
+ target->Target->AddUtility(autogenTargetName, makefile);
}
}
void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
- cmGeneratorTarget const* target)
+ const cmQtAutoGenDigest& digest)
{
+ cmGeneratorTarget const* target = digest.Target;
cmMakefile* makefile = target->Target->GetMakefile();
// forget the variables added here afterwards again:
@@ -1037,43 +1023,34 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
// Configuration suffixes
std::map<std::string, std::string> configSuffix;
if (AutogenMultiConfig(target->GetGlobalGenerator())) {
- for (std::vector<std::string>::const_iterator it = configs.begin();
- it != configs.end(); ++it) {
- configSuffix[*it] = "_" + *it;
+ for (const std::string& cfg : configs) {
+ configSuffix[cfg] = "_" + cfg;
}
}
// Configurations settings buffers
- AutogenSetup setup;
+ cmQtAutoGenSetup setup;
// Basic setup
+ AddDefinitionEscaped(makefile, "_build_dir",
+ GetAutogenTargetBuildDir(target));
+ AddDefinitionEscaped(makefile, "_qt_version_major", digest.QtVersionMajor);
+ AddDefinitionEscaped(makefile, "_qt_version_minor", digest.QtVersionMinor);
+ AddDefinitionEscaped(makefile, "_sources", digest.Sources);
+ AddDefinitionEscaped(makefile, "_headers", digest.Headers);
{
- const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC");
- const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC");
- const bool rccEnabled = target->GetPropertyAsBool("AUTORCC");
- const std::string qtMajorVersion = GetQtMajorVersion(target);
- {
- std::vector<cmSourceFile*> srcFiles;
- target->GetConfigCommonSourceFiles(srcFiles);
- if (mocEnabled || uicEnabled) {
- SetupAcquireScanFiles(target, mocEnabled, uicEnabled, srcFiles, setup);
- if (mocEnabled) {
- SetupAutoTargetMoc(target, qtMajorVersion, config, configs, setup);
- }
- if (uicEnabled) {
- SetupAutoTargetUic(target, qtMajorVersion, config, configs, setup);
- }
+ if (digest.MocEnabled || digest.UicEnabled) {
+ SetupAcquireSkipFiles(digest, setup);
+ if (digest.MocEnabled) {
+ SetupAutoTargetMoc(digest, config, configs, setup);
}
- if (rccEnabled) {
- SetupAutoTargetRcc(target, qtMajorVersion, srcFiles);
+ if (digest.UicEnabled) {
+ SetupAutoTargetUic(digest, config, configs, setup);
}
}
-
- AddDefinitionEscaped(makefile, "_build_dir",
- GetAutogenTargetBuildDir(target));
- AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion);
- AddDefinitionEscaped(makefile, "_sources", setup.sources);
- AddDefinitionEscaped(makefile, "_headers", setup.headers);
+ if (digest.RccEnabled) {
+ SetupAutoTargetRcc(digest);
+ }
}
// Generate info file
@@ -1086,8 +1063,8 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
}
// Append custom definitions to info file on demand
- if (!configSuffix.empty() || !setup.configMocDefines.empty() ||
- !setup.configMocIncludes.empty() || !setup.configUicOptions.empty()) {
+ if (!configSuffix.empty() || !setup.ConfigMocDefines.empty() ||
+ !setup.ConfigMocIncludes.empty() || !setup.ConfigUicOptions.empty()) {
// Ensure we have write permission in case .in was read-only.
mode_t perm = 0;
@@ -1104,39 +1081,22 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
// Open and write file
cmsys::ofstream ofs(infoFile.c_str(), std::ios::app);
if (ofs) {
+ auto OfsWriteMap = [&ofs](
+ const char* key, const std::map<std::string, std::string>& map) {
+ for (const auto& item : map) {
+ ofs << "set(" << key << "_" << item.first << " "
+ << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
+ }
+ };
ofs << "# Configuration specific options\n";
- for (std::map<std::string, std::string>::iterator
- it = configSuffix.begin(),
- end = configSuffix.end();
- it != end; ++it) {
- ofs << "set(AM_CONFIG_SUFFIX_" << it->first << " "
- << cmOutputConverter::EscapeForCMake(it->second) << ")\n";
- }
- for (std::map<std::string, std::string>::iterator
- it = setup.configMocDefines.begin(),
- end = setup.configMocDefines.end();
- it != end; ++it) {
- ofs << "set(AM_MOC_DEFINITIONS_" << it->first << " "
- << cmOutputConverter::EscapeForCMake(it->second) << ")\n";
- }
- for (std::map<std::string, std::string>::iterator
- it = setup.configMocIncludes.begin(),
- end = setup.configMocIncludes.end();
- it != end; ++it) {
- ofs << "set(AM_MOC_INCLUDES_" << it->first << " "
- << cmOutputConverter::EscapeForCMake(it->second) << ")\n";
- }
- for (std::map<std::string, std::string>::iterator
- it = setup.configUicOptions.begin(),
- end = setup.configUicOptions.end();
- it != end; ++it) {
- ofs << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " "
- << cmOutputConverter::EscapeForCMake(it->second) << ")\n";
- }
+ OfsWriteMap("AM_CONFIG_SUFFIX", configSuffix);
+ OfsWriteMap("AM_MOC_DEFINITIONS", setup.ConfigMocDefines);
+ OfsWriteMap("AM_MOC_INCLUDES", setup.ConfigMocIncludes);
+ OfsWriteMap("AM_UIC_TARGET_OPTIONS", setup.ConfigUicOptions);
} else {
// File open error
std::string error = "Internal CMake error when trying to open file: ";
- error += cmQtAutoGeneratorCommon::Quoted(infoFile);
+ error += cmQtAutoGen::Quoted(infoFile);
error += " for writing.";
cmSystemTools::Error(error.c_str());
}
diff --git a/Source/cmQtAutoGeneratorInitializer.h b/Source/cmQtAutoGeneratorInitializer.h
index 48ae70e..1264ca5 100644
--- a/Source/cmQtAutoGeneratorInitializer.h
+++ b/Source/cmQtAutoGeneratorInitializer.h
@@ -4,16 +4,21 @@
#define cmQtAutoGeneratorInitializer_h
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmQtAutoGenDigest.h"
+
+#include <string>
class cmGeneratorTarget;
-class cmLocalGenerator;
class cmQtAutoGeneratorInitializer
{
public:
- static void InitializeAutogenTarget(cmLocalGenerator* localGen,
- cmGeneratorTarget* target);
- static void SetupAutoGenerateTarget(cmGeneratorTarget const* target);
+ static std::string GetQtMajorVersion(cmGeneratorTarget const* target);
+ static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
+ const std::string& qtVersionMajor);
+
+ static void InitializeAutogenTarget(cmQtAutoGenDigest& digest);
+ static void SetupAutoGenerateTarget(cmQtAutoGenDigest const& digest);
};
#endif
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index d7f1ea7..5ede9d5 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -1,15 +1,14 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmQtAutoGen.h"
#include "cmQtAutoGenerators.h"
-#include "cmQtAutoGeneratorCommon.h"
#include "cmsys/FStream.hxx"
#include "cmsys/Terminal.h"
#include <algorithm>
-#include <assert.h>
+#include <array>
#include <list>
#include <sstream>
-#include <stdlib.h>
#include <string.h>
#include <utility>
@@ -22,7 +21,6 @@
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
#if defined(__APPLE__)
@@ -37,117 +35,33 @@ static const char* SettingsKeyRcc = "AM_RCC_SETTINGS_HASH";
// -- Static functions
-inline static std::string Quoted(const std::string& text)
-{
- return cmQtAutoGeneratorCommon::Quoted(text);
-}
-
static std::string QuotedCommand(const std::vector<std::string>& command)
{
std::string res;
- for (std::vector<std::string>::const_iterator cit = command.begin();
- cit != command.end(); ++cit) {
+ for (const std::string& item : command) {
if (!res.empty()) {
res.push_back(' ');
}
- const std::string cesc = Quoted(*cit);
- if (cit->empty() || (cesc.size() > (cit->size() + 2)) ||
+ const std::string cesc = cmQtAutoGen::Quoted(item);
+ if (item.empty() || (cesc.size() > (item.size() + 2)) ||
(cesc.find(' ') != std::string::npos)) {
res += cesc;
} else {
- res += *cit;
+ res += item;
}
}
return res;
}
-static void InfoGet(cmMakefile* makefile, const char* key, std::string& value)
-{
- value = makefile->GetSafeDefinition(key);
-}
-
-static void InfoGet(cmMakefile* makefile, const char* key, bool& value)
-{
- value = makefile->IsOn(key);
-}
-
-static void InfoGet(cmMakefile* makefile, const char* key,
- std::vector<std::string>& list)
-{
- cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
-}
-
-static void InfoGetConfig(cmMakefile* makefile, const char* key,
- const std::string& config, std::string& value)
-{
- const char* valueConf = nullptr;
- {
- std::string keyConf = key;
- if (!config.empty()) {
- keyConf += "_";
- keyConf += config;
- }
- valueConf = makefile->GetDefinition(keyConf);
- }
- if (valueConf == nullptr) {
- valueConf = makefile->GetSafeDefinition(key);
- }
- value = valueConf;
-}
-
-static void InfoGetConfig(cmMakefile* makefile, const char* key,
- const std::string& config,
- std::vector<std::string>& list)
-{
- std::string value;
- InfoGetConfig(makefile, key, config, value);
- cmSystemTools::ExpandListArgument(value, list);
-}
-
-inline static bool SettingsMatch(cmMakefile* makefile, const char* key,
- const std::string& value)
-{
- return (value == makefile->GetSafeDefinition(key));
-}
-
-static void SettingAppend(std::string& str, const char* key,
- const std::string& value)
-{
- if (!value.empty()) {
- str += "set(";
- str += key;
- str += " ";
- str += cmOutputConverter::EscapeForCMake(value);
- str += ")\n";
- }
-}
-
static std::string SubDirPrefix(const std::string& fileName)
{
- std::string res(cmsys::SystemTools::GetFilenamePath(fileName));
+ std::string res(cmSystemTools::GetFilenamePath(fileName));
if (!res.empty()) {
res += '/';
}
return res;
}
-static bool FileNameIsUnique(const std::string& filePath,
- const std::map<std::string, std::string>& fileMap)
-{
- size_t count(0);
- const std::string fileName = cmsys::SystemTools::GetFilenameName(filePath);
- for (std::map<std::string, std::string>::const_iterator si = fileMap.begin();
- si != fileMap.end(); ++si) {
- if (cmsys::SystemTools::GetFilenameName(si->first) == fileName) {
- ++count;
- if (count > 1) {
- return false;
- }
- }
- }
- return true;
-}
-
static bool ReadAll(std::string& content, const std::string& filename)
{
bool success = false;
@@ -172,7 +86,7 @@ static bool FileAbsentOrOlder(const std::string& buildFile,
{
int result = 0;
bool success =
- cmsys::SystemTools::FileTimeCompare(buildFile, sourceFile, &result);
+ cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result);
return (!success || (result <= 0));
}
@@ -182,82 +96,10 @@ static bool ListContains(const std::vector<std::string>& list,
return (std::find(list.begin(), list.end(), entry) != list.end());
}
-static std::string JoinOptionsList(const std::vector<std::string>& opts)
-{
- return cmOutputConverter::EscapeForCMake(cmJoin(opts, ";"));
-}
-
-static std::string JoinOptionsMap(
- const std::map<std::string, std::string>& opts)
-{
- std::string result;
- for (std::map<std::string, std::string>::const_iterator it = opts.begin();
- it != opts.end(); ++it) {
- if (it != opts.begin()) {
- result += cmQtAutoGeneratorCommon::listSep;
- }
- result += it->first;
- result += "===";
- result += it->second;
- }
- return result;
-}
-
-static std::string JoinExts(const std::vector<std::string>& lst)
-{
- std::string result;
- if (!lst.empty()) {
- const std::string separator = ",";
- for (std::vector<std::string>::const_iterator it = lst.begin();
- it != lst.end(); ++it) {
- if (it != lst.begin()) {
- result += separator;
- }
- result += '.';
- result += *it;
- }
- }
- return result;
-}
-
-static void UicMergeOptions(std::vector<std::string>& opts,
- const std::vector<std::string>& fileOpts,
- bool isQt5)
-{
- static const char* valueOptions[] = { "tr", "translate",
- "postfix", "generator",
- "include", // Since Qt 5.3
- "g" };
- std::vector<std::string> extraOpts;
- for (std::vector<std::string>::const_iterator it = fileOpts.begin();
- it != fileOpts.end(); ++it) {
- std::vector<std::string>::iterator existingIt =
- std::find(opts.begin(), opts.end(), *it);
- if (existingIt != opts.end()) {
- const char* o = it->c_str();
- if (*o == '-') {
- ++o;
- }
- if (isQt5 && *o == '-') {
- ++o;
- }
- if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions),
- cmStrCmp(*it)) != cmArrayEnd(valueOptions)) {
- assert(existingIt + 1 != opts.end());
- *(existingIt + 1) = *(it + 1);
- ++it;
- }
- } else {
- extraOpts.push_back(*it);
- }
- }
- opts.insert(opts.end(), extraOpts.begin(), extraOpts.end());
-}
-
// -- Class methods
cmQtAutoGenerators::cmQtAutoGenerators()
- : Verbose(cmsys::SystemTools::HasEnv("VERBOSE"))
+ : Verbose(cmSystemTools::HasEnv("VERBOSE"))
, ColorOutput(true)
, MocSettingsChanged(false)
, MocPredefsChanged(false)
@@ -269,7 +111,7 @@ cmQtAutoGenerators::cmQtAutoGenerators()
{
std::string colorEnv;
- cmsys::SystemTools::GetEnv("COLOR", colorEnv);
+ cmSystemTools::GetEnv("COLOR", colorEnv);
if (!colorEnv.empty()) {
if (cmSystemTools::IsOn(colorEnv.c_str())) {
this->ColorOutput = true;
@@ -279,10 +121,10 @@ cmQtAutoGenerators::cmQtAutoGenerators()
}
// Moc macro filters
- this->MocMacroFilters.push_back(
- MocMacroFilter("Q_OBJECT", "[\n][ \t]*{?[ \t]*Q_OBJECT[^a-zA-Z0-9_]"));
- this->MocMacroFilters.push_back(
- MocMacroFilter("Q_GADGET", "[\n][ \t]*{?[ \t]*Q_GADGET[^a-zA-Z0-9_]"));
+ this->MocMacroFilters.emplace_back(
+ "Q_OBJECT", "[\n][ \t]*{?[ \t]*Q_OBJECT[^a-zA-Z0-9_]");
+ this->MocMacroFilters.emplace_back(
+ "Q_GADGET", "[\n][ \t]*{?[ \t]*Q_GADGET[^a-zA-Z0-9_]");
// Precompile regular expressions
this->MocRegExpInclude.compile(
@@ -305,15 +147,15 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory,
snapshot.GetDirectory().SetCurrentBinary(targetDirectory);
snapshot.GetDirectory().SetCurrentSource(targetDirectory);
- CM_AUTO_PTR<cmMakefile> mf(new cmMakefile(&gg, snapshot));
- gg.SetCurrentMakefile(mf.get());
+ std::unique_ptr<cmMakefile> makefile(new cmMakefile(&gg, snapshot));
+ gg.SetCurrentMakefile(makefile.get());
bool success = false;
- if (this->ReadAutogenInfoFile(mf.get(), targetDirectory, config)) {
+ if (this->ReadAutogenInfoFile(makefile.get(), targetDirectory, config)) {
// Read old settings
- this->SettingsFileRead(mf.get());
+ this->SettingsFileRead(makefile.get());
// Init and run
- this->Init(mf.get());
+ this->Init(makefile.get());
if (this->RunAutogen()) {
// Write current settings
if (this->SettingsFileWrite()) {
@@ -327,44 +169,114 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory,
bool cmQtAutoGenerators::MocDependFilterPush(const std::string& key,
const std::string& regExp)
{
- bool success = false;
+ std::string error;
if (!key.empty()) {
if (!regExp.empty()) {
- MocDependFilter filter;
- filter.key = key;
- if (filter.regExp.compile(regExp)) {
- this->MocDependFilters.push_back(filter);
- success = true;
+ KeyRegExp filter;
+ filter.Key = key;
+ if (filter.RegExp.compile(regExp)) {
+ this->MocDependFilters.push_back(std::move(filter));
} else {
- this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Compiling "
- "regular expression failed.\nKey: " +
- Quoted(key) + "\nExp.: " + Quoted(regExp));
+ error = "Regular expression compiling failed";
}
} else {
- this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Regular "
- "expression is empty");
+ error = "Regular expression is empty";
}
} else {
- this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Key is empty");
+ error = "Key is empty";
}
- return success;
+ if (!error.empty()) {
+ std::string emsg = "AUTOMOC_DEPEND_FILTERS: ";
+ emsg += error;
+ emsg += "\n";
+ emsg += " Key: ";
+ emsg += cmQtAutoGen::Quoted(key);
+ emsg += "\n";
+ emsg += " RegExp: ";
+ emsg += cmQtAutoGen::Quoted(regExp);
+ emsg += "\n";
+ this->LogError(cmQtAutoGen::MOC, emsg);
+ return false;
+ }
+ return true;
}
bool cmQtAutoGenerators::ReadAutogenInfoFile(
cmMakefile* makefile, const std::string& targetDirectory,
const std::string& config)
{
+ // Lambdas
+ auto InfoGet = [makefile](const char* key) {
+ return makefile->GetSafeDefinition(key);
+ };
+ auto InfoGetBool = [makefile](const char* key) {
+ return makefile->IsOn(key);
+ };
+ auto InfoGetList = [makefile](const char* key) -> std::vector<std::string> {
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
+ return list;
+ };
+ auto InfoGetLists =
+ [makefile](const char* key) -> std::vector<std::vector<std::string>> {
+ std::vector<std::vector<std::string>> lists;
+ {
+ const std::string value = makefile->GetSafeDefinition(key);
+ std::string::size_type pos = 0;
+ while (pos < value.size()) {
+ std::string::size_type next = value.find(cmQtAutoGen::listSep, pos);
+ std::string::size_type length =
+ (next != std::string::npos) ? next - pos : value.size() - pos;
+ // Remove enclosing braces
+ if (length >= 2) {
+ std::string::const_iterator itBeg = value.begin() + (pos + 1);
+ std::string::const_iterator itEnd = itBeg + (length - 2);
+ {
+ std::string subValue(itBeg, itEnd);
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(subValue, list);
+ lists.push_back(std::move(list));
+ }
+ }
+ pos += length;
+ pos += cmQtAutoGen::listSep.size();
+ }
+ }
+ return lists;
+ };
+ auto InfoGetConfig = [makefile, &config](const char* key) -> std::string {
+ const char* valueConf = nullptr;
+ {
+ std::string keyConf = key;
+ if (!config.empty()) {
+ keyConf += '_';
+ keyConf += config;
+ }
+ valueConf = makefile->GetDefinition(keyConf);
+ }
+ if (valueConf == nullptr) {
+ valueConf = makefile->GetSafeDefinition(key);
+ }
+ return std::string(valueConf);
+ };
+ auto InfoGetConfigList =
+ [&InfoGetConfig](const char* key) -> std::vector<std::string> {
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(InfoGetConfig(key), list);
+ return list;
+ };
+
std::string filename(cmSystemTools::CollapseFullPath(targetDirectory));
cmSystemTools::ConvertToUnixSlashes(filename);
filename += "/AutogenInfo.cmake";
if (!makefile->ReadListFile(filename.c_str())) {
- this->LogError("AutoGen: Error processing file: " + filename);
+ this->LogFileError(cmQtAutoGen::GEN, filename, "File processing failed");
return false;
}
// -- Meta
- InfoGetConfig(makefile, "AM_CONFIG_SUFFIX", config, this->ConfigSuffix);
+ this->ConfigSuffix = InfoGetConfig("AM_CONFIG_SUFFIX");
// - Old settings file
{
@@ -376,41 +288,39 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
}
// - Files and directories
- InfoGet(makefile, "AM_CMAKE_SOURCE_DIR", this->ProjectSourceDir);
- InfoGet(makefile, "AM_CMAKE_BINARY_DIR", this->ProjectBinaryDir);
- InfoGet(makefile, "AM_CMAKE_CURRENT_SOURCE_DIR", this->CurrentSourceDir);
- InfoGet(makefile, "AM_CMAKE_CURRENT_BINARY_DIR", this->CurrentBinaryDir);
- InfoGet(makefile, "AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE",
- this->IncludeProjectDirsBefore);
- InfoGet(makefile, "AM_BUILD_DIR", this->AutogenBuildDir);
+ this->ProjectSourceDir = InfoGet("AM_CMAKE_SOURCE_DIR");
+ this->ProjectBinaryDir = InfoGet("AM_CMAKE_BINARY_DIR");
+ this->CurrentSourceDir = InfoGet("AM_CMAKE_CURRENT_SOURCE_DIR");
+ this->CurrentBinaryDir = InfoGet("AM_CMAKE_CURRENT_BINARY_DIR");
+ this->IncludeProjectDirsBefore =
+ InfoGetBool("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
+ this->AutogenBuildDir = InfoGet("AM_BUILD_DIR");
if (this->AutogenBuildDir.empty()) {
- this->LogError("AutoGen: Error: Missing autogen build directory ");
+ this->LogFileError(cmQtAutoGen::GEN, filename,
+ "Autogen build directory missing");
return false;
}
- InfoGet(makefile, "AM_SOURCES", this->Sources);
- InfoGet(makefile, "AM_HEADERS", this->Headers);
+ this->Sources = InfoGetList("AM_SOURCES");
+ this->Headers = InfoGetList("AM_HEADERS");
// - Qt environment
- InfoGet(makefile, "AM_QT_VERSION_MAJOR", this->QtMajorVersion);
- if (this->QtMajorVersion.empty()) {
- InfoGet(makefile, "AM_Qt5Core_VERSION_MAJOR", this->QtMajorVersion);
- }
- InfoGet(makefile, "AM_QT_MOC_EXECUTABLE", this->MocExecutable);
- InfoGet(makefile, "AM_QT_UIC_EXECUTABLE", this->UicExecutable);
- InfoGet(makefile, "AM_QT_RCC_EXECUTABLE", this->RccExecutable);
+ this->QtMajorVersion = InfoGet("AM_QT_VERSION_MAJOR");
+ this->QtMinorVersion = InfoGet("AM_QT_VERSION_MINOR");
+ this->MocExecutable = InfoGet("AM_QT_MOC_EXECUTABLE");
+ this->UicExecutable = InfoGet("AM_QT_UIC_EXECUTABLE");
+ this->RccExecutable = InfoGet("AM_QT_RCC_EXECUTABLE");
// Check Qt version
if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) {
- this->LogError("AutoGen: Error: Unsupported Qt version: " +
- Quoted(this->QtMajorVersion));
+ this->LogFileError(cmQtAutoGen::GEN, filename, "Unsupported Qt version: " +
+ cmQtAutoGen::Quoted(this->QtMajorVersion));
return false;
}
// - Moc
if (this->MocEnabled()) {
- InfoGet(makefile, "AM_MOC_SKIP", this->MocSkipList);
- InfoGetConfig(makefile, "AM_MOC_DEFINITIONS", config,
- this->MocDefinitions);
+ this->MocSkipList = InfoGetList("AM_MOC_SKIP");
+ this->MocDefinitions = InfoGetConfigList("AM_MOC_DEFINITIONS");
#ifdef _WIN32
{
const std::string win32("WIN32");
@@ -419,22 +329,20 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
}
}
#endif
- InfoGetConfig(makefile, "AM_MOC_INCLUDES", config, this->MocIncludePaths);
- InfoGet(makefile, "AM_MOC_OPTIONS", this->MocOptions);
- InfoGet(makefile, "AM_MOC_RELAXED_MODE", this->MocRelaxedMode);
+ this->MocIncludePaths = InfoGetConfigList("AM_MOC_INCLUDES");
+ this->MocOptions = InfoGetList("AM_MOC_OPTIONS");
+ this->MocRelaxedMode = InfoGetBool("AM_MOC_RELAXED_MODE");
{
- std::vector<std::string> MocMacroNames;
- InfoGet(makefile, "AM_MOC_MACRO_NAMES", MocMacroNames);
- for (std::vector<std::string>::const_iterator dit =
- MocMacroNames.begin();
- dit != MocMacroNames.end(); ++dit) {
- this->MocMacroFilters.push_back(
- MocMacroFilter(*dit, "[^a-zA-Z0-9_]" + *dit + "[^a-zA-Z0-9_]"));
+ const std::vector<std::string> MocMacroNames =
+ InfoGetList("AM_MOC_MACRO_NAMES");
+ for (const std::string& item : MocMacroNames) {
+ this->MocMacroFilters.emplace_back(
+ item, ("[^a-zA-Z0-9_]" + item).append("[^a-zA-Z0-9_]"));
}
}
{
- std::vector<std::string> mocDependFilters;
- InfoGet(makefile, "AM_MOC_DEPEND_FILTERS", mocDependFilters);
+ const std::vector<std::string> mocDependFilters =
+ InfoGetList("AM_MOC_DEPEND_FILTERS");
// Insert Q_PLUGIN_METADATA dependency filter
if (this->QtMajorVersion != "4") {
this->MocDependFilterPush("Q_PLUGIN_METADATA",
@@ -443,49 +351,47 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
}
// Insert user defined dependency filters
if ((mocDependFilters.size() % 2) == 0) {
- for (std::vector<std::string>::const_iterator dit =
- mocDependFilters.begin();
- dit != mocDependFilters.end(); dit += 2) {
+ for (std::vector<std::string>::const_iterator
+ dit = mocDependFilters.begin(),
+ ditEnd = mocDependFilters.end();
+ dit != ditEnd; dit += 2) {
if (!this->MocDependFilterPush(*dit, *(dit + 1))) {
return false;
}
}
} else {
- this->LogError(
- "AutoMoc: Error: AUTOMOC_DEPEND_FILTERS list size is not "
- "a multiple of 2 in:\n" +
- Quoted(filename));
+ this->LogFileError(
+ cmQtAutoGen::MOC, filename,
+ "AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2");
return false;
}
}
- InfoGet(makefile, "AM_MOC_PREDEFS_CMD", this->MocPredefsCmd);
+ this->MocPredefsCmd = InfoGetList("AM_MOC_PREDEFS_CMD");
}
// - Uic
if (this->UicEnabled()) {
- InfoGet(makefile, "AM_UIC_SKIP", this->UicSkipList);
- InfoGet(makefile, "AM_UIC_SEARCH_PATHS", this->UicSearchPaths);
- InfoGetConfig(makefile, "AM_UIC_TARGET_OPTIONS", config,
- this->UicTargetOptions);
+ this->UicSkipList = InfoGetList("AM_UIC_SKIP");
+ this->UicSearchPaths = InfoGetList("AM_UIC_SEARCH_PATHS");
+ this->UicTargetOptions = InfoGetConfigList("AM_UIC_TARGET_OPTIONS");
{
- std::vector<std::string> uicFilesVec;
- std::vector<std::string> uicOptionsVec;
- InfoGet(makefile, "AM_UIC_OPTIONS_FILES", uicFilesVec);
- InfoGet(makefile, "AM_UIC_OPTIONS_OPTIONS", uicOptionsVec);
+ auto sources = InfoGetList("AM_UIC_OPTIONS_FILES");
+ auto options = InfoGetLists("AM_UIC_OPTIONS_OPTIONS");
// Compare list sizes
- if (uicFilesVec.size() == uicOptionsVec.size()) {
- for (std::vector<std::string>::iterator
- fileIt = uicFilesVec.begin(),
- optionIt = uicOptionsVec.begin();
- fileIt != uicFilesVec.end(); ++fileIt, ++optionIt) {
- cmSystemTools::ReplaceString(*optionIt,
- cmQtAutoGeneratorCommon::listSep, ";");
- this->UicOptions[*fileIt] = *optionIt;
+ if (sources.size() == options.size()) {
+ auto fitEnd = sources.cend();
+ auto fit = sources.begin();
+ auto oit = options.begin();
+ while (fit != fitEnd) {
+ this->UicOptions[*fit] = std::move(*oit);
+ ++fit;
+ ++oit;
}
} else {
- this->LogError(
- "AutoGen: Error: Uic files/options lists size missmatch in:\n" +
- Quoted(filename));
+ std::ostringstream ost;
+ ost << "files/options lists sizes missmatch (" << sources.size() << "/"
+ << options.size() << ")";
+ this->LogFileError(cmQtAutoGen::UIC, filename, ost.str());
return false;
}
}
@@ -493,53 +399,48 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
// - Rcc
if (this->RccEnabled()) {
- InfoGet(makefile, "AM_RCC_SOURCES", this->RccSources);
- // File options
- {
- std::vector<std::string> rccFilesVec;
- std::vector<std::string> rccOptionsVec;
- InfoGet(makefile, "AM_RCC_OPTIONS_FILES", rccFilesVec);
- InfoGet(makefile, "AM_RCC_OPTIONS_OPTIONS", rccOptionsVec);
- if (rccFilesVec.size() == rccOptionsVec.size()) {
- for (std::vector<std::string>::iterator
- fileIt = rccFilesVec.begin(),
- optionIt = rccOptionsVec.begin();
- fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) {
- // Replace item separator
- cmSystemTools::ReplaceString(*optionIt,
- cmQtAutoGeneratorCommon::listSep, ";");
- this->RccOptions[*fileIt] = *optionIt;
- }
- } else {
- this->LogError(
- "AutoGen: Error: RCC files/options lists size missmatch in:\n" +
- Quoted(filename));
- return false;
- }
- }
// File lists
+ auto sources = InfoGetList("AM_RCC_SOURCES");
+ auto builds = InfoGetList("AM_RCC_BUILDS");
+ auto options = InfoGetLists("AM_RCC_OPTIONS");
+ auto inputs = InfoGetLists("AM_RCC_INPUTS");
+
+ if (sources.size() != builds.size()) {
+ std::ostringstream ost;
+ ost << "sources, builds lists sizes missmatch (" << sources.size() << "/"
+ << builds.size() << ")";
+ this->LogFileError(cmQtAutoGen::RCC, filename, ost.str());
+ return false;
+ }
+ if (sources.size() != options.size()) {
+ std::ostringstream ost;
+ ost << "sources, options lists sizes missmatch (" << sources.size()
+ << "/" << options.size() << ")";
+ this->LogFileError(cmQtAutoGen::RCC, filename, ost.str());
+ return false;
+ }
+ if (sources.size() != inputs.size()) {
+ std::ostringstream ost;
+ ost << "sources, inputs lists sizes missmatch (" << sources.size() << "/"
+ << inputs.size() << ")";
+ this->LogFileError(cmQtAutoGen::RCC, filename, ost.str());
+ return false;
+ }
+
{
- std::vector<std::string> rccInputLists;
- InfoGet(makefile, "AM_RCC_INPUTS", rccInputLists);
- if (this->RccSources.size() == rccInputLists.size()) {
- for (std::vector<std::string>::iterator
- fileIt = this->RccSources.begin(),
- inputIt = rccInputLists.begin();
- fileIt != this->RccSources.end(); ++fileIt, ++inputIt) {
- // Remove braces
- *inputIt = inputIt->substr(1, inputIt->size() - 2);
- // Replace item separator
- cmSystemTools::ReplaceString(*inputIt,
- cmQtAutoGeneratorCommon::listSep, ";");
- std::vector<std::string> rccInputFiles;
- cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles);
- this->RccInputs[*fileIt] = rccInputFiles;
- }
- } else {
- this->LogError(
- "AutoGen: Error: RCC sources/inputs lists size missmatch in:\n" +
- Quoted(filename));
- return false;
+ auto srcItEnd = sources.end();
+ auto srcIt = sources.begin();
+ auto bldIt = builds.begin();
+ auto optIt = options.begin();
+ auto inpIt = inputs.begin();
+ while (srcIt != srcItEnd) {
+ this->RccJobs.push_back(RccJob{ std::move(*srcIt), std::move(*bldIt),
+ std::move(*optIt),
+ std::move(*inpIt) });
+ ++srcIt;
+ ++bldIt;
+ ++optIt;
+ ++inpIt;
}
}
}
@@ -557,15 +458,15 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
std::string str;
str += this->MocExecutable;
str += sep;
- str += JoinOptionsList(this->MocDefinitions);
+ str += cmJoin(this->MocDefinitions, ";");
str += sep;
- str += JoinOptionsList(this->MocIncludePaths);
+ str += cmJoin(this->MocIncludePaths, ";");
str += sep;
- str += JoinOptionsList(this->MocOptions);
+ str += cmJoin(this->MocOptions, ";");
str += sep;
str += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE";
str += sep;
- str += JoinOptionsList(this->MocPredefsCmd);
+ str += cmJoin(this->MocPredefsCmd, ";");
str += sep;
this->SettingsStringMoc = crypt.HashString(str);
}
@@ -573,17 +474,27 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
std::string str;
str += this->UicExecutable;
str += sep;
- str += JoinOptionsList(this->UicTargetOptions);
- str += sep;
- str += JoinOptionsMap(this->UicOptions);
+ str += cmJoin(this->UicTargetOptions, ";");
+ for (const auto& item : this->UicOptions) {
+ str += sep;
+ str += item.first;
+ str += sep;
+ str += cmJoin(item.second, ";");
+ }
str += sep;
this->SettingsStringUic = crypt.HashString(str);
}
if (this->RccEnabled()) {
std::string str;
str += this->RccExecutable;
- str += sep;
- str += JoinOptionsMap(this->RccOptions);
+ for (const RccJob& rccJob : this->RccJobs) {
+ str += sep;
+ str += rccJob.QrcFile;
+ str += sep;
+ str += rccJob.RccFile;
+ str += sep;
+ str += cmJoin(rccJob.Options, ";");
+ }
str += sep;
this->SettingsStringRcc = crypt.HashString(str);
}
@@ -591,14 +502,19 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
// Read old settings
if (makefile->ReadListFile(this->SettingsFile.c_str())) {
- if (!SettingsMatch(makefile, SettingsKeyMoc, this->SettingsStringMoc)) {
- this->MocSettingsChanged = true;
- }
- if (!SettingsMatch(makefile, SettingsKeyUic, this->SettingsStringUic)) {
- this->UicSettingsChanged = true;
- }
- if (!SettingsMatch(makefile, SettingsKeyRcc, this->SettingsStringRcc)) {
- this->RccSettingsChanged = true;
+ {
+ auto SMatch = [makefile](const char* key, const std::string& value) {
+ return (value == makefile->GetSafeDefinition(key));
+ };
+ if (!SMatch(SettingsKeyMoc, this->SettingsStringMoc)) {
+ this->MocSettingsChanged = true;
+ }
+ if (!SMatch(SettingsKeyUic, this->SettingsStringUic)) {
+ this->UicSettingsChanged = true;
+ }
+ if (!SMatch(SettingsKeyRcc, this->SettingsStringRcc)) {
+ this->RccSettingsChanged = true;
+ }
}
// In case any setting changed remove the old settings file.
// This triggers a full rebuild on the next run if the current
@@ -620,18 +536,28 @@ bool cmQtAutoGenerators::SettingsFileWrite()
// Only write if any setting changed
if (this->AnySettingsChanged()) {
if (this->Verbose) {
- this->LogInfo("AutoGen: Writing settings file " +
- Quoted(this->SettingsFile));
+ this->LogInfo(cmQtAutoGen::GEN, "Writing settings file " +
+ cmQtAutoGen::Quoted(this->SettingsFile));
}
// Compose settings file content
std::string settings;
- SettingAppend(settings, SettingsKeyMoc, this->SettingsStringMoc);
- SettingAppend(settings, SettingsKeyUic, this->SettingsStringUic);
- SettingAppend(settings, SettingsKeyRcc, this->SettingsStringRcc);
+ {
+ auto SettingAppend = [&settings](const char* key,
+ const std::string& value) {
+ settings += "set(";
+ settings += key;
+ settings += " ";
+ settings += cmOutputConverter::EscapeForCMake(value);
+ settings += ")\n";
+ };
+ SettingAppend(SettingsKeyMoc, this->SettingsStringMoc);
+ SettingAppend(SettingsKeyUic, this->SettingsStringUic);
+ SettingAppend(SettingsKeyRcc, this->SettingsStringRcc);
+ }
// Write settings file
- if (!this->FileWrite("AutoGen", this->SettingsFile, settings)) {
- this->LogError("AutoGen: Error: Could not write old settings file " +
- Quoted(this->SettingsFile));
+ if (!this->FileWrite(cmQtAutoGen::GEN, this->SettingsFile, settings)) {
+ this->LogFileError(cmQtAutoGen::GEN, this->SettingsFile,
+ "File writing failed");
// Remove old settings file to trigger a full rebuild on the next run
cmSystemTools::RemoveFile(this->SettingsFile);
success = false;
@@ -679,14 +605,14 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile)
this->MocIncludePaths.reserve(includes.size());
// Append project directories only
{
- const char* movePaths[2] = { this->ProjectBinaryDir.c_str(),
- this->ProjectSourceDir.c_str() };
- for (const char* const* mpit = cmArrayBegin(movePaths);
- mpit != cmArrayEnd(movePaths); ++mpit) {
+ const std::array<const std::string*, 2> movePaths = {
+ { &this->ProjectBinaryDir, &this->ProjectSourceDir }
+ };
+ for (const std::string* ppath : movePaths) {
std::list<std::string>::iterator it = includes.begin();
while (it != includes.end()) {
const std::string& path = *it;
- if (cmsys::SystemTools::StringStartsWith(path, *mpit)) {
+ if (cmSystemTools::StringStartsWith(path, ppath->c_str())) {
this->MocIncludePaths.push_back(path);
it = includes.erase(it);
} else {
@@ -702,26 +628,22 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile)
// Compose moc includes list
{
std::set<std::string> frameworkPaths;
- for (std::vector<std::string>::const_iterator it =
- this->MocIncludePaths.begin();
- it != this->MocIncludePaths.end(); ++it) {
- const std::string& path = *it;
+ for (const std::string& path : this->MocIncludePaths) {
this->MocIncludes.push_back("-I" + path);
// Extract framework path
if (cmHasLiteralSuffix(path, ".framework/Headers")) {
// Go up twice to get to the framework root
std::vector<std::string> pathComponents;
- cmsys::SystemTools::SplitPath(path, pathComponents);
- std::string frameworkPath = cmsys::SystemTools::JoinPath(
+ cmSystemTools::SplitPath(path, pathComponents);
+ std::string frameworkPath = cmSystemTools::JoinPath(
pathComponents.begin(), pathComponents.end() - 2);
frameworkPaths.insert(frameworkPath);
}
}
// Append framework includes
- for (std::set<std::string>::const_iterator it = frameworkPaths.begin();
- it != frameworkPaths.end(); ++it) {
+ for (const std::string& path : frameworkPaths) {
this->MocIncludes.push_back("-F");
- this->MocIncludes.push_back(*it);
+ this->MocIncludes.push_back(path);
}
}
}
@@ -740,9 +662,9 @@ bool cmQtAutoGenerators::RunAutogen()
{
const std::string incDirAbs = cmSystemTools::CollapseCombinedPath(
this->AutogenBuildDir, this->AutogenIncludeDir);
- if (!cmsys::SystemTools::MakeDirectory(incDirAbs)) {
- this->LogError("AutoGen: Error: Could not create include directory " +
- Quoted(incDirAbs));
+ if (!cmSystemTools::MakeDirectory(incDirAbs)) {
+ this->LogFileError(cmQtAutoGen::GEN, incDirAbs,
+ "Could not create directory");
return false;
}
}
@@ -757,28 +679,23 @@ bool cmQtAutoGenerators::RunAutogen()
std::set<std::string> uicHeaderFiles;
// Parse sources
- for (std::vector<std::string>::const_iterator it = this->Sources.begin();
- it != this->Sources.end(); ++it) {
- const std::string& absFilename = cmsys::SystemTools::GetRealPath(*it);
+ for (const std::string& src : this->Sources) {
// Parse source file for MOC/UIC
- if (!this->ParseSourceFile(absFilename, mocsIncluded, mocDepends,
- uisIncluded, this->MocRelaxedMode)) {
+ if (!this->ParseSourceFile(src, mocsIncluded, mocDepends, uisIncluded,
+ this->MocRelaxedMode)) {
return false;
}
// Find additional headers
- this->SearchHeadersForSourceFile(absFilename, mocHeaderFiles,
- uicHeaderFiles);
+ this->SearchHeadersForSourceFile(src, mocHeaderFiles, uicHeaderFiles);
}
// Parse headers
- for (std::vector<std::string>::const_iterator it = this->Headers.begin();
- it != this->Headers.end(); ++it) {
- const std::string& headerName = cmsys::SystemTools::GetRealPath(*it);
- if (!this->MocSkip(headerName)) {
- mocHeaderFiles.insert(headerName);
+ for (const std::string& hdr : this->Headers) {
+ if (!this->MocSkip(hdr)) {
+ mocHeaderFiles.insert(hdr);
}
- if (!this->UicSkip(headerName)) {
- uicHeaderFiles.insert(headerName);
+ if (!this->UicSkip(hdr)) {
+ uicHeaderFiles.insert(hdr);
}
}
if (!this->ParseHeaders(mocHeaderFiles, uicHeaderFiles, mocsIncluded,
@@ -807,17 +724,14 @@ bool cmQtAutoGenerators::RunAutogen()
bool cmQtAutoGenerators::MocRequired(const std::string& contentText,
std::string* macroName)
{
- for (std::vector<MocMacroFilter>::iterator fit =
- this->MocMacroFilters.begin();
- fit != this->MocMacroFilters.end(); ++fit) {
- MocMacroFilter& filter = *fit;
+ for (KeyRegExp& filter : this->MocMacroFilters) {
// Run a simple find string operation before the expensive
// regular expression check
- if (contentText.find(filter.first) != std::string::npos) {
- if (filter.second.find(contentText)) {
+ if (contentText.find(filter.Key) != std::string::npos) {
+ if (filter.RegExp.find(contentText)) {
// Return macro name on demand
if (macroName != nullptr) {
- *macroName = filter.first;
+ *macroName = filter.Key;
}
return true;
}
@@ -830,35 +744,33 @@ void cmQtAutoGenerators::MocFindDepends(
const std::string& absFilename, const std::string& contentText,
std::map<std::string, std::set<std::string>>& mocDepends)
{
- for (std::vector<MocDependFilter>::iterator fit =
- this->MocDependFilters.begin();
- fit != this->MocDependFilters.end(); ++fit) {
- MocDependFilter& filter = *fit;
+ for (KeyRegExp& filter : this->MocDependFilters) {
// Run a simple find string operation before the expensive
// regular expression check
- if (contentText.find(filter.key) != std::string::npos) {
+ if (contentText.find(filter.Key) != std::string::npos) {
// Run regular expression check loop
const std::string sourcePath = SubDirPrefix(absFilename);
const char* contentChars = contentText.c_str();
- while (filter.regExp.find(contentChars)) {
+ while (filter.RegExp.find(contentChars)) {
// Evaluate match
- const std::string match = filter.regExp.match(1);
+ const std::string match = filter.RegExp.match(1);
if (!match.empty()) {
// Find the dependency file
std::string incFile;
if (this->MocFindIncludedFile(incFile, sourcePath, match)) {
mocDepends[absFilename].insert(incFile);
if (this->Verbose) {
- this->LogInfo("AutoMoc: Found dependency:\n " +
- Quoted(absFilename) + "\n " + Quoted(incFile));
+ this->LogInfo(cmQtAutoGen::MOC, "Found dependency:\n " +
+ cmQtAutoGen::Quoted(absFilename) + "\n " +
+ cmQtAutoGen::Quoted(incFile));
}
} else {
- this->LogWarning("AutoMoc: Warning: " + Quoted(absFilename) +
- "\n" + "Could not find dependency file " +
- Quoted(match));
+ this->LogFileWarning(cmQtAutoGen::MOC, absFilename,
+ "Could not find dependency file " +
+ cmQtAutoGen::Quoted(match));
}
}
- contentChars += filter.regExp.end();
+ contentChars += filter.RegExp.end();
}
}
}
@@ -916,15 +828,10 @@ bool cmQtAutoGenerators::ParseSourceFile(
this->UicParseContent(absFilename, contentText, uisIncluded);
}
} else {
- std::ostringstream ost;
- ost << "AutoGen: Warning: The file is empty:\n"
- << Quoted(absFilename) << "\n";
- this->LogWarning(ost.str());
+ this->LogFileWarning(cmQtAutoGen::GEN, absFilename, "The file is empty");
}
} else {
- std::ostringstream ost;
- ost << "AutoGen: Error: Could not read file:\n" << Quoted(absFilename);
- this->LogError(ost.str());
+ this->LogFileError(cmQtAutoGen::GEN, absFilename, "Could not read file");
}
return success;
}
@@ -934,7 +841,7 @@ void cmQtAutoGenerators::UicParseContent(
std::map<std::string, std::vector<std::string>>& uisIncluded)
{
if (this->Verbose) {
- this->LogInfo("AutoUic: Checking " + absFilename);
+ this->LogInfo(cmQtAutoGen::UIC, "Checking " + absFilename);
}
const char* contentChars = contentText.c_str();
@@ -946,6 +853,36 @@ void cmQtAutoGenerators::UicParseContent(
}
}
+std::string cmQtAutoGenerators::MocMacroNamesString() const
+{
+ std::string res;
+ const auto itB = this->MocMacroFilters.cbegin();
+ const auto itE = this->MocMacroFilters.cend();
+ const auto itL = itE - 1;
+ auto itC = itB;
+ for (; itC != itE; ++itC) {
+ // Separator
+ if (itC != itB) {
+ if (itC != itL) {
+ res += ", ";
+ } else {
+ res += " or ";
+ }
+ }
+ // Key
+ res += itC->Key;
+ }
+ return res;
+}
+
+std::string cmQtAutoGenerators::MocHeaderSuffixesString() const
+{
+ std::string res = ".{";
+ res += cmJoin(this->HeaderExtensions, ",");
+ res += "}";
+ return res;
+}
+
/**
* @return True on success
*/
@@ -955,15 +892,15 @@ bool cmQtAutoGenerators::MocParseSourceContent(
std::map<std::string, std::set<std::string>>& mocDepends, bool relaxed)
{
if (this->Verbose) {
- this->LogInfo("AutoMoc: Checking " + absFilename);
+ this->LogInfo(cmQtAutoGen::MOC, "Checking " + absFilename);
}
- const std::string scannedFileAbsPath = SubDirPrefix(absFilename);
- const std::string scannedFileBasename =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
+ const std::string scanFileDir = SubDirPrefix(absFilename);
+ const std::string scanFileBase =
+ cmSystemTools::GetFilenameWithoutLastExtension(absFilename);
- std::string macroName;
- const bool requiresMoc = this->MocRequired(contentText, &macroName);
+ std::string selfMacroName;
+ const bool selfRequiresMoc = this->MocRequired(contentText, &selfMacroName);
bool ownDotMocIncluded = false;
std::string ownMocUnderscoreInclude;
std::string ownMocUnderscoreHeader;
@@ -977,120 +914,132 @@ bool cmQtAutoGenerators::MocParseSourceContent(
while (this->MocRegExpInclude.find(contentChars)) {
const std::string incString = this->MocRegExpInclude.match(1);
// Basename of the moc include
- const std::string incSubDir(SubDirPrefix(incString));
- const std::string incBasename =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(incString);
+ const std::string incDir(SubDirPrefix(incString));
+ const std::string incBase =
+ cmSystemTools::GetFilenameWithoutLastExtension(incString);
// If the moc include is of the moc_foo.cpp style we expect
// the Q_OBJECT class declaration in a header file.
// If the moc include is of the foo.moc style we need to look for
// a Q_OBJECT macro in the current source file, if it contains the
// macro we generate the moc file from the source file.
- if (cmHasLiteralPrefix(incBasename, "moc_")) {
+ if (cmHasLiteralPrefix(incBase, "moc_")) {
// Include: moc_FOO.cxx
// Remove the moc_ part
- const std::string incRealBasename = incBasename.substr(4);
+ const std::string incRealBase = incBase.substr(4);
const std::string headerToMoc =
- this->MocFindHeader(scannedFileAbsPath, incSubDir + incRealBasename);
+ this->MocFindHeader(scanFileDir, incDir + incRealBase);
if (!headerToMoc.empty()) {
if (!this->MocSkip(headerToMoc)) {
// Register moc job
mocsIncluded[headerToMoc] = incString;
this->MocFindDepends(headerToMoc, contentText, mocDepends);
// Store meta information for relaxed mode
- if (relaxed && (incRealBasename == scannedFileBasename)) {
+ if (relaxed && (incRealBase == scanFileBase)) {
ownMocUnderscoreInclude = incString;
ownMocUnderscoreHeader = headerToMoc;
}
}
} else {
std::ostringstream ost;
- ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
- << "The file includes the moc file " << Quoted(incString)
- << ", but could not find header "
- << Quoted(incRealBasename + "{" +
- JoinExts(this->HeaderExtensions) + "}");
- ;
- this->LogError(ost.str());
+ ost << "The file includes the moc file "
+ << cmQtAutoGen::Quoted(incString)
+ << ", but could not find header ";
+ ost << cmQtAutoGen::Quoted(incRealBase +
+ this->MocHeaderSuffixesString());
+ this->LogFileError(cmQtAutoGen::MOC, absFilename, ost.str());
return false;
}
} else {
// Include: FOO.moc
+ bool ownDotMoc = (incBase == scanFileBase);
std::string fileToMoc;
if (relaxed) {
// Mode: Relaxed
- if (requiresMoc && (incBasename == scannedFileBasename)) {
+ if (selfRequiresMoc && ownDotMoc) {
// Include self
fileToMoc = absFilename;
ownDotMocIncluded = true;
} else {
// In relaxed mode try to find a header instead but issue a warning
const std::string headerToMoc =
- this->MocFindHeader(scannedFileAbsPath, incSubDir + incBasename);
+ this->MocFindHeader(scanFileDir, incDir + incBase);
if (!headerToMoc.empty()) {
if (!this->MocSkip(headerToMoc)) {
// This is for KDE4 compatibility:
fileToMoc = headerToMoc;
- if (!requiresMoc && (incBasename == scannedFileBasename)) {
- std::ostringstream ost;
- ost
- << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
- << "The file includes the moc file " << Quoted(incString)
- << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n"
- << "Running moc on " << Quoted(headerToMoc) << "!\n"
- << "Include " << Quoted("moc_" + incBasename + ".cpp")
- << " for a compatibility with strict mode (see "
- "CMAKE_AUTOMOC_RELAXED_MODE).\n";
- this->LogWarning(ost.str());
+
+ auto quoted_inc = cmQtAutoGen::Quoted(incString);
+ auto quoted_header = cmQtAutoGen::Quoted(headerToMoc);
+ auto quoted_base =
+ cmQtAutoGen::Quoted("moc_" + incBase + ".cpp");
+ if (!selfRequiresMoc) {
+ if (ownDotMoc) {
+ std::ostringstream ost;
+ ost << "The file includes the moc file " << quoted_inc
+ << ", but does not contain a "
+ << this->MocMacroNamesString() << " macro.\n"
+ << "Running moc on\n"
+ << " " << quoted_header << "!\n"
+ << "Better include " << quoted_base
+ << " for a compatibility with strict mode.\n"
+ "(CMAKE_AUTOMOC_RELAXED_MODE warning)\n";
+ this->LogFileWarning(cmQtAutoGen::MOC, absFilename,
+ ost.str());
+ } else if (!ownDotMoc) {
+ std::ostringstream ost;
+ ost << "The file includes the moc file " << quoted_inc
+ << " instead of " << quoted_base << ".\n";
+ ost << "Running moc on\n"
+ << " " << quoted_header << "!\n"
+ << "Better include " << quoted_base
+ << " for compatibility with strict mode.\n"
+ "(CMAKE_AUTOMOC_RELAXED_MODE warning)\n";
+ this->LogFileWarning(cmQtAutoGen::MOC, absFilename,
+ ost.str());
+ }
} else {
- std::ostringstream ost;
- ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
- << "The file includes the moc file " << Quoted(incString)
- << " instead of "
- << Quoted("moc_" + incBasename + ".cpp") << ".\n"
- << "Running moc on " << Quoted(headerToMoc) << "!\n"
- << "Include " << Quoted("moc_" + incBasename + ".cpp")
- << " for compatibility with strict mode (see "
- "CMAKE_AUTOMOC_RELAXED_MODE).\n";
- this->LogWarning(ost.str());
+ if (!ownDotMoc) {
+ // Handled further down
+ }
}
}
} else {
std::ostringstream ost;
- ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
- << "The file includes the moc file " << Quoted(incString)
+ ost << "The file includes the moc file "
+ << cmQtAutoGen::Quoted(incString)
<< ", which seems to be the moc file from a different "
"source file. CMake also could not find a matching "
"header.";
- this->LogError(ost.str());
+ this->LogFileError(cmQtAutoGen::MOC, absFilename, ost.str());
return false;
}
}
} else {
// Mode: Strict
- if (incBasename == scannedFileBasename) {
+ if (ownDotMoc) {
// Include self
fileToMoc = absFilename;
ownDotMocIncluded = true;
// Accept but issue a warning if moc isn't required
- if (!requiresMoc) {
+ if (!selfRequiresMoc) {
std::ostringstream ost;
- ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
- << "The file includes the moc file " << Quoted(incString)
- << ", but does not contain a Q_OBJECT or Q_GADGET "
- "macro.";
- this->LogWarning(ost.str());
+ ost << "The file includes the moc file "
+ << cmQtAutoGen::Quoted(incString)
+ << ", but does not contain a " << this->MocMacroNamesString()
+ << " macro.";
+ this->LogFileWarning(cmQtAutoGen::MOC, absFilename, ost.str());
}
} else {
// Don't allow FOO.moc include other than self in strict mode
std::ostringstream ost;
- ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
- << "The file includes the moc file " << Quoted(incString)
+ ost << "The file includes the moc file "
+ << cmQtAutoGen::Quoted(incString)
<< ", which seems to be the moc file from a different "
"source file. This is not supported. Include "
- << Quoted(scannedFileBasename + ".moc")
+ << cmQtAutoGen::Quoted(scanFileBase + ".moc")
<< " to run moc on this source file.";
- this->LogError(ost.str());
+ this->LogFileError(cmQtAutoGen::MOC, absFilename, ost.str());
return false;
}
}
@@ -1104,24 +1053,26 @@ bool cmQtAutoGenerators::MocParseSourceContent(
}
}
- if (requiresMoc && !ownDotMocIncluded) {
- // In this case, check whether the scanned file itself contains a Q_OBJECT.
+ if (selfRequiresMoc && !ownDotMocIncluded) {
+ // In this case, check whether the scanned file itself contains a
+ // Q_OBJECT.
// If this is the case, the moc_foo.cpp should probably be generated from
// foo.cpp instead of foo.h, because otherwise it won't build.
// But warn, since this is not how it is supposed to be used.
if (relaxed && !ownMocUnderscoreInclude.empty()) {
// This is for KDE4 compatibility:
std::ostringstream ost;
- ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
- << "The file contains a " << macroName
+ ost << "The file contains a " << selfMacroName
<< " macro, but does not include "
- << Quoted(scannedFileBasename + ".moc") << ", but instead includes "
- << Quoted(ownMocUnderscoreInclude) << ".\n"
- << "Running moc on " << Quoted(absFilename) << "!\n"
- << "Better include " << Quoted(scannedFileBasename + ".moc")
- << " for compatibility with strict mode (see "
- "CMAKE_AUTOMOC_RELAXED_MODE).";
- this->LogWarning(ost.str());
+ << cmQtAutoGen::Quoted(scanFileBase + ".moc")
+ << ". Instead it includes "
+ << cmQtAutoGen::Quoted(ownMocUnderscoreInclude) << ".\n"
+ << "Running moc on\n"
+ << " " << cmQtAutoGen::Quoted(absFilename) << "!\n"
+ << "Better include " << cmQtAutoGen::Quoted(scanFileBase + ".moc")
+ << " for compatibility with strict mode.\n"
+ "(CMAKE_AUTOMOC_RELAXED_MODE warning)";
+ this->LogFileWarning(cmQtAutoGen::MOC, absFilename, ost.str());
// Use scanned source file instead of scanned header file as moc source
mocsIncluded[absFilename] = ownMocUnderscoreInclude;
@@ -1131,13 +1082,12 @@ bool cmQtAutoGenerators::MocParseSourceContent(
} else {
// Otherwise always error out since it will not compile:
std::ostringstream ost;
- ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
- << "The file contains a " << macroName
+ ost << "The file contains a " << selfMacroName
<< " macro, but does not include "
- << Quoted(scannedFileBasename + ".moc") << "!\n"
+ << cmQtAutoGen::Quoted(scanFileBase + ".moc") << "!\n"
<< "Consider adding the include or enabling SKIP_AUTOMOC for this "
"file.";
- this->LogError(ost.str());
+ this->LogFileError(cmQtAutoGen::MOC, absFilename, ost.str());
return false;
}
}
@@ -1152,7 +1102,7 @@ void cmQtAutoGenerators::MocParseHeaderContent(
{
// Log
if (this->Verbose) {
- this->LogInfo("AutoMoc: Checking " + absFilename);
+ this->LogInfo(cmQtAutoGen::MOC, "Checking " + absFilename);
}
if (this->MocRequired(contentText)) {
// Register moc job
@@ -1166,19 +1116,19 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile(
const std::string& absFilename, std::set<std::string>& mocHeaderFiles,
std::set<std::string>& uicHeaderFiles) const
{
- std::string basepaths[2];
+ std::array<std::string, 2> basepaths;
{
std::string bpath = SubDirPrefix(absFilename);
- bpath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
+ bpath += cmSystemTools::GetFilenameWithoutLastExtension(absFilename);
// search for default header files and private header files
basepaths[0] = bpath;
- basepaths[1] = bpath + "_p";
+ basepaths[1] = bpath;
+ basepaths[1] += "_p";
}
- for (const std::string* bpit = cmArrayBegin(basepaths);
- bpit != cmArrayEnd(basepaths); ++bpit) {
+ for (const std::string& bPath : basepaths) {
std::string headerName;
- if (this->FindHeader(headerName, *bpit)) {
+ if (this->FindHeader(headerName, bPath)) {
// Moc headers
if (!this->MocSkip(absFilename) && !this->MocSkip(headerName)) {
mocHeaderFiles.insert(headerName);
@@ -1205,9 +1155,7 @@ bool cmQtAutoGenerators::ParseHeaders(
headerFiles.insert(mocHeaderFiles.begin(), mocHeaderFiles.end());
headerFiles.insert(uicHeaderFiles.begin(), uicHeaderFiles.end());
- for (std::set<std::string>::const_iterator hIt = headerFiles.begin();
- hIt != headerFiles.end(); ++hIt) {
- const std::string& headerName = *hIt;
+ for (const std::string& headerName : headerFiles) {
std::string contentText;
if (ReadAll(contentText, headerName)) {
// Parse header content for MOC
@@ -1221,10 +1169,8 @@ bool cmQtAutoGenerators::ParseHeaders(
this->UicParseContent(headerName, contentText, uisIncluded);
}
} else {
- std::ostringstream ost;
- ost << "AutoGen: Error: Could not read header file:\n"
- << Quoted(headerName);
- this->LogError(ost.str());
+ this->LogFileError(cmQtAutoGen::GEN, headerName,
+ "Could not read header file");
success = false;
break;
}
@@ -1248,14 +1194,12 @@ bool cmQtAutoGenerators::MocGenerateAll(
std::map<std::string, std::string> mergedMocs(mocsIncluded);
mergedMocs.insert(mocsNotIncluded.begin(), mocsNotIncluded.end());
if (this->NameCollisionTest(mergedMocs, collisions)) {
- std::ostringstream ost;
- ost << "AutoMoc: Error: "
- "The same moc file will be generated "
- "from different sources.\n"
- "To avoid this error either\n"
- "- rename the source files or\n"
- "- do not include the (moc_NAME.cpp|NAME.moc) file";
- this->LogErrorNameCollision(ost.str(), collisions);
+ std::string msg = "The same moc file will be generated "
+ "from different sources.\n"
+ "To avoid this error either\n"
+ " - rename the source files or\n"
+ " - do not include the (moc_NAME.cpp|NAME.moc) file";
+ this->LogNameCollisionError(cmQtAutoGen::MOC, msg, collisions);
return false;
}
}
@@ -1276,33 +1220,35 @@ bool cmQtAutoGenerators::MocGenerateAll(
cmd.insert(cmd.end(), this->MocIncludes.begin(),
this->MocIncludes.end());
// Add definitions
- for (std::vector<std::string>::const_iterator it =
- this->MocDefinitions.begin();
- it != this->MocDefinitions.end(); ++it) {
- cmd.push_back("-D" + (*it));
+ for (const std::string& def : this->MocDefinitions) {
+ cmd.push_back("-D" + def);
}
// Add options
cmd.insert(cmd.end(), this->MocOptions.begin(),
this->MocOptions.end());
// Execute command
- if (!this->RunCommand(cmd, output, false)) {
- {
- std::ostringstream ost;
- ost << "AutoMoc: Error: moc predefs generation command failed\n";
- ost << "AutoMoc: Command:\n" << QuotedCommand(cmd) << "\n";
- ost << "AutoMoc: Command output:\n" << output << "\n";
- this->LogError(ost.str());
- }
+ if (!this->RunCommand(cmd, output)) {
+ this->LogCommandError(cmQtAutoGen::MOC,
+ "moc_predefs generation failed", cmd, output);
return false;
}
}
+
// (Re)write predefs file only on demand
if (this->FileDiffers(this->MocPredefsFileAbs, output)) {
- if (this->FileWrite("AutoMoc", this->MocPredefsFileAbs, output)) {
+ if (this->FileWrite(cmQtAutoGen::MOC, this->MocPredefsFileAbs,
+ output)) {
this->MocPredefsChanged = true;
} else {
return false;
}
+ } else {
+ // Touch to update the time stamp
+ if (this->Verbose) {
+ this->LogInfo(cmQtAutoGen::MOC,
+ "Touching moc_predefs " + this->MocPredefsFileRel);
+ }
+ cmSystemTools::Touch(this->MocPredefsFileAbs, false);
}
}
}
@@ -1356,13 +1302,15 @@ bool cmQtAutoGenerators::MocGenerateAll(
if (this->Verbose) {
this->LogBold("Generating MOC compilation " + this->MocCompFileRel);
}
- if (!this->FileWrite("AutoMoc", this->MocCompFileAbs, automocSource)) {
+ if (!this->FileWrite(cmQtAutoGen::MOC, this->MocCompFileAbs,
+ automocSource)) {
return false;
}
} else if (mocCompFileGenerated) {
// Only touch mocs compilation file
if (this->Verbose) {
- this->LogInfo("Touching MOC compilation " + this->MocCompFileRel);
+ this->LogInfo(cmQtAutoGen::MOC,
+ "Touching mocs compilation " + this->MocCompFileRel);
}
cmSystemTools::Touch(this->MocCompFileAbs, false);
}
@@ -1411,7 +1359,7 @@ bool cmQtAutoGenerators::MocGenerateFile(
}
// Make sure the parent directory exists
- if (this->MakeParentDirectory("AutoMoc", mocFileAbs)) {
+ if (this->MakeParentDirectory(cmQtAutoGen::MOC, mocFileAbs)) {
// Compose moc command
std::vector<std::string> cmd;
cmd.push_back(this->MocExecutable);
@@ -1419,10 +1367,8 @@ bool cmQtAutoGenerators::MocGenerateFile(
cmd.insert(cmd.end(), this->MocIncludes.begin(),
this->MocIncludes.end());
// Add definitions
- for (std::vector<std::string>::const_iterator it =
- this->MocDefinitions.begin();
- it != this->MocDefinitions.end(); ++it) {
- cmd.push_back("-D" + (*it));
+ for (const std::string& def : this->MocDefinitions) {
+ cmd.push_back("-D" + def);
}
// Add options
cmd.insert(cmd.end(), this->MocOptions.begin(), this->MocOptions.end());
@@ -1441,15 +1387,9 @@ bool cmQtAutoGenerators::MocGenerateFile(
// Success
mocGenerated = true;
} else {
- // Command failed
- {
- std::ostringstream ost;
- ost << "AutoMoc: Error: moc process failed for\n";
- ost << Quoted(mocFileRel) << "\n";
- ost << "AutoMoc: Command:\n" << QuotedCommand(cmd) << "\n";
- ost << "AutoMoc: Command output:\n" << output << "\n";
- this->LogError(ost.str());
- }
+ this->LogCommandError(cmQtAutoGen::MOC, "moc failed for\n " +
+ cmQtAutoGen::Quoted(sourceFile),
+ cmd, output);
cmSystemTools::RemoveFile(mocFileAbs);
this->MocRunFailed = true;
}
@@ -1470,7 +1410,11 @@ bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile,
std::vector<std::string> testFiles;
// Collect search paths list
{
- const std::string searchFileFull = searchPath + searchFile;
+ std::string searchFileFull;
+ if (!searchPath.empty()) {
+ searchFileFull = searchPath;
+ searchFileFull += searchFile;
+ }
// Vicinity of the source
{
const std::string sourcePath = SubDirPrefix(sourceFile);
@@ -1481,27 +1425,21 @@ bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile,
}
// AUTOUIC search paths
if (!this->UicSearchPaths.empty()) {
- for (std::vector<std::string>::const_iterator iit =
- this->UicSearchPaths.begin();
- iit != this->UicSearchPaths.end(); ++iit) {
- testFiles.push_back(*iit + "/" + searchFile);
+ for (const std::string& sPath : this->UicSearchPaths) {
+ testFiles.push_back((sPath + "/").append(searchFile));
}
if (!searchPath.empty()) {
- for (std::vector<std::string>::const_iterator iit =
- this->UicSearchPaths.begin();
- iit != this->UicSearchPaths.end(); ++iit) {
- testFiles.push_back(*iit + "/" + searchFileFull);
+ for (const std::string& sPath : this->UicSearchPaths) {
+ testFiles.push_back((sPath + "/").append(searchFileFull));
}
}
}
}
// Search for the .ui file!
- for (std::vector<std::string>::const_iterator iit = testFiles.begin();
- iit != testFiles.end(); ++iit) {
- const std::string& testFile = *iit;
- if (cmsys::SystemTools::FileExists(testFile.c_str())) {
- absFile = cmsys::SystemTools::GetRealPath(testFile);
+ for (const std::string& testFile : testFiles) {
+ if (cmSystemTools::FileExists(testFile.c_str())) {
+ absFile = cmSystemTools::GetRealPath(testFile);
success = true;
break;
}
@@ -1510,13 +1448,11 @@ bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile,
// Log error
if (!success) {
std::ostringstream ost;
- ost << "AutoUic: Error: " << Quoted(sourceFile) << "\n";
- ost << "Could not find " << Quoted(searchFile) << " in\n";
- for (std::vector<std::string>::const_iterator iit = testFiles.begin();
- iit != testFiles.end(); ++iit) {
- ost << " " << Quoted(*iit) << "\n";
+ ost << "Could not find " << cmQtAutoGen::Quoted(searchFile) << " in\n";
+ for (const std::string& testFile : testFiles) {
+ ost << " " << cmQtAutoGen::Quoted(testFile) << "\n";
}
- this->LogError(ost.str());
+ this->LogFileError(cmQtAutoGen::UIC, sourceFile, ost.str());
}
return success;
@@ -1542,16 +1478,18 @@ bool cmQtAutoGenerators::UicGenerateAll(
const std::vector<std::string>& sourceIncs(sit->second);
// insert new source/destination map
std::map<std::string, std::string>& uiGenMap = sourceGenMap[source];
- for (std::vector<std::string>::const_iterator uit = sourceIncs.begin();
- uit != sourceIncs.end(); ++uit) {
+ for (const std::string& inc : sourceIncs) {
// Remove ui_ from the begin filename by substr()
- const std::string uiBasePath = SubDirPrefix(*uit);
+ const std::string uiBasePath = SubDirPrefix(inc);
const std::string uiBaseName =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(*uit).substr(3);
+ cmSystemTools::GetFilenameWithoutLastExtension(inc).substr(3);
const std::string uiFileName = uiBaseName + ".ui";
std::string uiInputFile;
if (UicFindIncludedFile(uiInputFile, source, uiBasePath, uiFileName)) {
- std::string uiOutputFile = uiBasePath + "ui_" + uiBaseName + ".h";
+ std::string uiOutputFile = uiBasePath;
+ uiOutputFile += "ui_";
+ uiOutputFile += uiBaseName;
+ uiOutputFile += ".h";
cmSystemTools::ReplaceString(uiOutputFile, "..", "__");
uiGenMap[uiInputFile] = uiOutputFile;
testMap[uiInputFile] = uiOutputFile;
@@ -1564,25 +1502,19 @@ bool cmQtAutoGenerators::UicGenerateAll(
{
std::multimap<std::string, std::string> collisions;
if (this->NameCollisionTest(testMap, collisions)) {
- std::ostringstream ost;
- ost << "AutoUic: Error: The same ui_NAME.h file will be generated "
- "from different sources.\n"
- "To avoid this error rename the source files.\n";
- this->LogErrorNameCollision(ost.str(), collisions);
+ std::string msg = "The same ui_NAME.h file will be generated "
+ "from different sources.\n"
+ "To avoid this error rename the source files.\n";
+ this->LogNameCollisionError(cmQtAutoGen::UIC, msg, collisions);
return false;
}
}
}
// generate ui files
- for (std::map<std::string,
- std::map<std::string, std::string>>::const_iterator it =
- sourceGenMap.begin();
- it != sourceGenMap.end(); ++it) {
- for (std::map<std::string, std::string>::const_iterator sit =
- it->second.begin();
- sit != it->second.end(); ++sit) {
- if (!this->UicGenerateFile(it->first, sit->first, sit->second)) {
+ for (const auto& srcItem : sourceGenMap) {
+ for (const auto& item : srcItem.second) {
+ if (!this->UicGenerateFile(srcItem.first, item.first, item.second)) {
if (this->UicRunFailed) {
return false;
}
@@ -1618,18 +1550,16 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName,
}
// Make sure the parent directory exists
- if (this->MakeParentDirectory("AutoUic", uicFileAbs)) {
+ if (this->MakeParentDirectory(cmQtAutoGen::UIC, uicFileAbs)) {
// Compose uic command
std::vector<std::string> cmd;
cmd.push_back(this->UicExecutable);
{
std::vector<std::string> allOpts = this->UicTargetOptions;
- std::map<std::string, std::string>::const_iterator optionIt =
- this->UicOptions.find(uiInputFile);
+ auto optionIt = this->UicOptions.find(uiInputFile);
if (optionIt != this->UicOptions.end()) {
- std::vector<std::string> fileOpts;
- cmSystemTools::ExpandListArgument(optionIt->second, fileOpts);
- UicMergeOptions(allOpts, fileOpts, (this->QtMajorVersion == "5"));
+ cmQtAutoGen::UicMergeOptions(allOpts, optionIt->second,
+ (this->QtMajorVersion == "5"));
}
cmd.insert(cmd.end(), allOpts.begin(), allOpts.end());
}
@@ -1645,12 +1575,11 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName,
// Command failed
{
std::ostringstream ost;
- ost << "AutoUic: Error: uic process failed for\n";
- ost << Quoted(uicFileRel) << " needed by\n";
- ost << Quoted(realName) << "\n";
- ost << "AutoUic: Command:\n" << QuotedCommand(cmd) << "\n";
- ost << "AutoUic: Command output:\n" << output << "\n";
- this->LogError(ost.str());
+ ost << "uic failed for\n"
+ << " " << cmQtAutoGen::Quoted(uiInputFile) << "\n"
+ << "needed by\n"
+ << " " << cmQtAutoGen::Quoted(realName);
+ this->LogCommandError(cmQtAutoGen::UIC, ost.str(), cmd, output);
}
cmSystemTools::RemoveFile(uicFileAbs);
this->UicRunFailed = true;
@@ -1669,41 +1598,9 @@ bool cmQtAutoGenerators::RccGenerateAll()
return true;
}
- // generate single map with input / output names
- std::map<std::string, std::string> qrcGenMap;
- {
- const std::string qrcPrefix = "qrc_";
- const std::string qrcSuffix = this->ConfigSuffix + ".cpp";
- for (std::vector<std::string>::const_iterator si =
- this->RccSources.begin();
- si != this->RccSources.end(); ++si) {
- const std::string ext =
- cmsys::SystemTools::GetFilenameLastExtension(*si);
- if (ext == ".qrc") {
- qrcGenMap[*si] = this->ChecksumedPath(*si, qrcPrefix, qrcSuffix);
- }
- }
- }
-
- // look for name collisions
- {
- std::multimap<std::string, std::string> collisions;
- if (this->NameCollisionTest(qrcGenMap, collisions)) {
- std::ostringstream ost;
- ost << "AutoRcc: Error: The same qrc_NAME.cpp file"
- " will be generated from different sources.\n"
- "To avoid this error rename the source .qrc files.\n";
- this->LogErrorNameCollision(ost.str(), collisions);
- return false;
- }
- }
-
- // generate qrc files
- for (std::map<std::string, std::string>::const_iterator si =
- qrcGenMap.begin();
- si != qrcGenMap.end(); ++si) {
- bool unique = FileNameIsUnique(si->first, qrcGenMap);
- if (!this->RccGenerateFile(si->first, si->second, unique)) {
+ // Generate qrc files
+ for (const RccJob& rccJob : this->RccJobs) {
+ if (!this->RccGenerateFile(rccJob)) {
if (this->RccRunFailed) {
return false;
}
@@ -1715,41 +1612,49 @@ bool cmQtAutoGenerators::RccGenerateAll()
/**
* @return True if a rcc file was created. False may indicate an error.
*/
-bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
- const std::string& rccOutputFile,
- bool unique_n)
+bool cmQtAutoGenerators::RccGenerateFile(const RccJob& rccJob)
{
bool rccGenerated = false;
bool generateRcc = this->RccSettingsChanged;
- const std::string rccBuildFile =
- cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, rccOutputFile);
+
+ std::string rccFileAbs;
+ if (this->ConfigSuffix.empty()) {
+ rccFileAbs = rccJob.RccFile;
+ } else {
+ rccFileAbs = SubDirPrefix(rccJob.RccFile);
+ rccFileAbs +=
+ cmSystemTools::GetFilenameWithoutLastExtension(rccJob.RccFile);
+ rccFileAbs += this->ConfigSuffix;
+ rccFileAbs += cmSystemTools::GetFilenameLastExtension(rccJob.RccFile);
+ }
+ const std::string rccFileRel = cmSystemTools::RelativePath(
+ this->AutogenBuildDir.c_str(), rccFileAbs.c_str());
// Check if regeneration is required
if (!generateRcc) {
// Test if the resources list file is newer than build file
- generateRcc = FileAbsentOrOlder(rccBuildFile, rccInputFile);
+ generateRcc = FileAbsentOrOlder(rccFileAbs, rccJob.QrcFile);
if (!generateRcc) {
// Acquire input file list
std::vector<std::string> readFiles;
- const std::vector<std::string>* files = &this->RccInputs[rccInputFile];
+ const std::vector<std::string>* files = &rccJob.Inputs;
if (files->empty()) {
// Read input file list from qrc file
std::string error;
- if (cmQtAutoGeneratorCommon::RccListInputs(
- this->QtMajorVersion, this->RccExecutable, rccInputFile,
- readFiles, &error)) {
+ if (cmQtAutoGen::RccListInputs(this->QtMajorVersion,
+ this->RccExecutable, rccJob.QrcFile,
+ readFiles, &error)) {
files = &readFiles;
} else {
files = nullptr;
- this->LogError(error);
+ this->LogFileError(cmQtAutoGen::RCC, rccJob.QrcFile, error);
this->RccRunFailed = true;
}
}
// Test if any input file is newer than the build file
if (files != nullptr) {
- for (std::vector<std::string>::const_iterator it = files->begin();
- it != files->end(); ++it) {
- if (FileAbsentOrOlder(rccBuildFile, *it)) {
+ for (const std::string& file : *files) {
+ if (FileAbsentOrOlder(rccFileAbs, file)) {
generateRcc = true;
break;
}
@@ -1761,53 +1666,28 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
if (generateRcc) {
// Log
if (this->Verbose) {
- this->LogBold("Generating RCC source " + rccOutputFile);
+ this->LogBold("Generating RCC source " + rccFileRel);
}
// Make sure the parent directory exists
- if (this->MakeParentDirectory("AutoRcc", rccBuildFile)) {
- // Compose symbol name
- std::string symbolName =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(rccInputFile);
- if (!unique_n) {
- symbolName += "_";
- symbolName += FPathChecksum.getPart(rccInputFile);
- }
- // Replace '-' with '_'. The former is valid for
- // file names but not for symbol names.
- std::replace(symbolName.begin(), symbolName.end(), '-', '_');
-
+ if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccFileAbs)) {
// Compose rcc command
std::vector<std::string> cmd;
cmd.push_back(this->RccExecutable);
- {
- std::map<std::string, std::string>::const_iterator optionIt =
- this->RccOptions.find(rccInputFile);
- if (optionIt != this->RccOptions.end()) {
- cmSystemTools::ExpandListArgument(optionIt->second, cmd);
- }
- }
- cmd.push_back("-name");
- cmd.push_back(symbolName);
+ cmd.insert(cmd.end(), rccJob.Options.begin(), rccJob.Options.end());
cmd.push_back("-o");
- cmd.push_back(rccBuildFile);
- cmd.push_back(rccInputFile);
+ cmd.push_back(rccFileAbs);
+ cmd.push_back(rccJob.QrcFile);
std::string output;
if (this->RunCommand(cmd, output)) {
// Success
rccGenerated = true;
} else {
- // Command failed
- {
- std::ostringstream ost;
- ost << "AutoRcc: Error: rcc process failed for\n";
- ost << Quoted(rccOutputFile) << "\n";
- ost << "AutoRcc: Command:\n" << QuotedCommand(cmd) << "\n";
- ost << "AutoRcc: Command output:\n" << output << "\n";
- this->LogError(ost.str());
- }
- cmSystemTools::RemoveFile(rccBuildFile);
+ this->LogCommandError(cmQtAutoGen::RCC, "rcc failed for\n " +
+ cmQtAutoGen::Quoted(rccJob.QrcFile),
+ cmd, output);
+ cmSystemTools::RemoveFile(rccFileAbs);
this->RccRunFailed = true;
}
} else {
@@ -1818,17 +1698,14 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
// For a multi configuration generator generate a wrapper file
if (!this->ConfigSuffix.empty() && !this->RccRunFailed) {
// Wrapper file name
- const std::string cppSuffix = ".cpp";
- const size_t suffixLength = this->ConfigSuffix.size() + cppSuffix.size();
- const std::string wrapperFileRel =
- rccOutputFile.substr(0, rccOutputFile.size() - suffixLength) + cppSuffix;
- const std::string wrapperFileAbs = cmSystemTools::CollapseCombinedPath(
- this->AutogenBuildDir, wrapperFileRel);
+ const std::string& wrapperFileAbs = rccJob.RccFile;
+ const std::string wrapperFileRel = cmSystemTools::RelativePath(
+ this->AutogenBuildDir.c_str(), wrapperFileAbs.c_str());
// Wrapper file content
- std::string content =
- "// This is an autogenerated configuration wrapper file. Do not edit.\n"
- "#include \"";
- content += cmsys::SystemTools::GetFilenameName(rccBuildFile);
+ std::string content = "// This is an autogenerated configuration "
+ "wrapper file. Do not edit.\n"
+ "#include \"";
+ content += cmSystemTools::GetFilenameName(rccFileRel);
content += "\"\n";
// Write content to file
if (this->FileDiffers(wrapperFileAbs, content)) {
@@ -1836,7 +1713,7 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
if (this->Verbose) {
this->LogBold("Generating RCC wrapper " + wrapperFileRel);
}
- if (!this->FileWrite("AutoRcc", wrapperFileAbs, content)) {
+ if (!this->FileWrite(cmQtAutoGen::RCC, wrapperFileAbs, content)) {
// Error
rccGenerated = false;
this->RccRunFailed = true;
@@ -1844,7 +1721,8 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
} else if (rccGenerated) {
// Only touch wrapper file if the content matches
if (this->Verbose) {
- this->LogInfo("Touching RCC wrapper " + wrapperFileRel);
+ this->LogInfo(cmQtAutoGen::RCC,
+ "Touching RCC wrapper " + wrapperFileRel);
}
cmSystemTools::Touch(wrapperFileAbs, false);
}
@@ -1853,69 +1731,144 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
return rccGenerated;
}
-void cmQtAutoGenerators::LogErrorNameCollision(
- const std::string& message,
- const std::multimap<std::string, std::string>& collisions) const
+void cmQtAutoGenerators::LogBold(const std::string& message) const
{
- typedef std::multimap<std::string, std::string>::const_iterator Iter;
+ cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
+ cmsysTerminal_Color_ForegroundBold,
+ message.c_str(), true, this->ColorOutput);
+}
- std::ostringstream ost;
- // Add message
- if (!message.empty()) {
- ost << message;
- if (message[message.size() - 1] != '\n') {
- ost << '\n';
- }
+void cmQtAutoGenerators::LogInfo(cmQtAutoGen::GeneratorType genType,
+ const std::string& message) const
+{
+ std::string msg = cmQtAutoGen::GeneratorName(genType);
+ msg += ": ";
+ msg += message;
+ if (msg.back() != '\n') {
+ msg.push_back('\n');
}
- // Append collision list
- for (Iter it = collisions.begin(); it != collisions.end(); ++it) {
- ost << it->first << " : " << it->second << '\n';
+ cmSystemTools::Stdout(msg.c_str(), msg.size());
+}
+
+void cmQtAutoGenerators::LogWarning(cmQtAutoGen::GeneratorType genType,
+ const std::string& message) const
+{
+ std::string msg = cmQtAutoGen::GeneratorName(genType);
+ msg += " warning:";
+ if (message.find('\n') == std::string::npos) {
+ // Single line message
+ msg.push_back(' ');
+ } else {
+ // Multi line message
+ msg.push_back('\n');
+ }
+ // Message
+ msg += message;
+ if (msg.back() != '\n') {
+ msg.push_back('\n');
}
- this->LogError(ost.str());
+ msg += "\n";
+ cmSystemTools::Stdout(msg.c_str(), msg.size());
}
-void cmQtAutoGenerators::LogBold(const std::string& message) const
+void cmQtAutoGenerators::LogFileWarning(cmQtAutoGen::GeneratorType genType,
+ const std::string& filename,
+ const std::string& message) const
{
- cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
- cmsysTerminal_Color_ForegroundBold,
- message.c_str(), true, this->ColorOutput);
+ std::string emsg = " ";
+ emsg += cmQtAutoGen::Quoted(filename);
+ emsg += "\n";
+ // Message
+ emsg += message;
+ this->LogWarning(genType, emsg);
}
-void cmQtAutoGenerators::LogInfo(const std::string& message) const
+void cmQtAutoGenerators::LogError(cmQtAutoGen::GeneratorType genType,
+ const std::string& message) const
{
- std::string msg(message);
- if (!msg.empty()) {
- if (msg[msg.size() - 1] != '\n') {
- msg.push_back('\n');
- }
- cmSystemTools::Stdout(msg.c_str(), msg.size());
+ std::string msg;
+ msg.push_back('\n');
+ msg = cmQtAutoGen::GeneratorName(genType);
+ msg += " error:";
+ if (message.find('\n') == std::string::npos) {
+ // Single line message
+ msg.push_back(' ');
+ } else {
+ // Multi line message
+ msg.push_back('\n');
+ }
+ // Message
+ msg += message;
+ if (msg.back() != '\n') {
+ msg.push_back('\n');
}
+ msg += "\n";
+ cmSystemTools::Stderr(msg.c_str(), msg.size());
}
-void cmQtAutoGenerators::LogWarning(const std::string& message) const
+void cmQtAutoGenerators::LogFileError(cmQtAutoGen::GeneratorType genType,
+ const std::string& filename,
+ const std::string& message) const
{
- std::string msg(message);
- if (!msg.empty()) {
- if (msg[msg.size() - 1] != '\n') {
- msg.push_back('\n');
+ std::string emsg = " ";
+ emsg += cmQtAutoGen::Quoted(filename);
+ emsg += "\n";
+ // Message
+ emsg += message;
+ this->LogError(genType, emsg);
+}
+
+void cmQtAutoGenerators::LogNameCollisionError(
+ cmQtAutoGen::GeneratorType genType, const std::string& message,
+ const std::multimap<std::string, std::string>& collisions) const
+{
+ std::string emsg;
+ // Add message
+ if (!message.empty()) {
+ emsg += message;
+ if (emsg.back() != '\n') {
+ emsg.push_back('\n');
}
- // Append empty line
- msg.push_back('\n');
- cmSystemTools::Stdout(msg.c_str(), msg.size());
}
+ // Append collision list
+ for (const auto& item : collisions) {
+ emsg += " ";
+ emsg += item.first;
+ emsg += " -> ";
+ emsg += item.second;
+ emsg += "\n";
+ }
+ this->LogError(genType, emsg);
}
-void cmQtAutoGenerators::LogError(const std::string& message) const
+void cmQtAutoGenerators::LogCommandError(
+ cmQtAutoGen::GeneratorType genType, const std::string& message,
+ const std::vector<std::string>& command, const std::string& output) const
{
- std::string msg(message);
- if (!msg.empty()) {
- if (msg[msg.size() - 1] != '\n') {
- msg.push_back('\n');
- }
- // Append empty line
+ std::string msg;
+ msg.push_back('\n');
+ msg += cmQtAutoGen::GeneratorName(genType);
+ msg += " subprocess error: ";
+ msg += message;
+ if (msg.back() != '\n') {
+ msg.push_back('\n');
+ }
+ msg.push_back('\n');
+ msg += "Command\n";
+ msg += "-------\n";
+ msg += QuotedCommand(command);
+ if (msg.back() != '\n') {
+ msg.push_back('\n');
+ }
+ msg.push_back('\n');
+ msg += "Output\n";
+ msg += "------\n";
+ msg += output;
+ if (msg.back() != '\n') {
msg.push_back('\n');
- cmSystemTools::Stderr(msg.c_str(), msg.size());
}
+ msg += "\n";
+ cmSystemTools::Stderr(msg.c_str(), msg.size());
}
/**
@@ -1959,7 +1912,7 @@ std::string cmQtAutoGenerators::ChecksumedPath(
std::string res = FPathChecksum.getPart(sourceFile);
res += "/";
res += basePrefix;
- res += cmsys::SystemTools::GetFilenameWithoutLastExtension(sourceFile);
+ res += cmSystemTools::GetFilenameWithoutLastExtension(sourceFile);
res += baseSuffix;
return res;
}
@@ -1968,18 +1921,16 @@ std::string cmQtAutoGenerators::ChecksumedPath(
* @brief Generates the parent directory of the given file on demand
* @return True on success
*/
-bool cmQtAutoGenerators::MakeParentDirectory(const char* logPrefix,
- const std::string& filename) const
+bool cmQtAutoGenerators::MakeParentDirectory(
+ cmQtAutoGen::GeneratorType genType, const std::string& filename) const
{
bool success = true;
const std::string dirName = cmSystemTools::GetFilenamePath(filename);
if (!dirName.empty()) {
- success = cmsys::SystemTools::MakeDirectory(dirName);
+ success = cmSystemTools::MakeDirectory(dirName);
if (!success) {
- std::string error = logPrefix;
- error += ": Error: Parent directory creation failed for ";
- error += Quoted(filename);
- this->LogError(error);
+ this->LogFileError(genType, filename,
+ "Could not create parent directory");
}
}
return success;
@@ -1998,31 +1949,27 @@ bool cmQtAutoGenerators::FileDiffers(const std::string& filename,
return differs;
}
-bool cmQtAutoGenerators::FileWrite(const char* logPrefix,
+bool cmQtAutoGenerators::FileWrite(cmQtAutoGen::GeneratorType genType,
const std::string& filename,
const std::string& content)
{
std::string error;
// Make sure the parent directory exists
- if (this->MakeParentDirectory(logPrefix, filename)) {
+ if (this->MakeParentDirectory(genType, filename)) {
cmsys::ofstream outfile;
outfile.open(filename.c_str(), std::ios::trunc);
if (outfile) {
outfile << content;
// Check for write errors
if (!outfile.good()) {
- error = logPrefix;
- error += ": Error writing ";
- error += Quoted(filename);
+ error = "File writing failed";
}
} else {
- error = logPrefix;
- error = ": Error opening ";
- error += Quoted(filename);
+ error = "Opening file for writing failed";
}
}
if (!error.empty()) {
- this->LogError(error);
+ this->LogFileError(genType, filename, error);
return false;
}
return true;
@@ -2033,17 +1980,18 @@ bool cmQtAutoGenerators::FileWrite(const char* logPrefix,
* @return True on success
*/
bool cmQtAutoGenerators::RunCommand(const std::vector<std::string>& command,
- std::string& output, bool verbose) const
+ std::string& output) const
{
// Log command
if (this->Verbose) {
- this->LogInfo(QuotedCommand(command));
+ std::string qcmd = QuotedCommand(command);
+ qcmd.push_back('\n');
+ cmSystemTools::Stdout(qcmd.c_str(), qcmd.size());
}
// Execute command
int retVal = 0;
bool res = cmSystemTools::RunSingleCommand(
- command, &output, &output, &retVal, nullptr,
- verbose ? cmSystemTools::OUTPUT_MERGE : cmSystemTools::OUTPUT_NONE);
+ command, &output, &output, &retVal, nullptr, cmSystemTools::OUTPUT_NONE);
return (res && (retVal == 0));
}
@@ -2055,13 +2003,11 @@ bool cmQtAutoGenerators::RunCommand(const std::vector<std::string>& command,
bool cmQtAutoGenerators::FindHeader(std::string& header,
const std::string& testBasePath) const
{
- for (std::vector<std::string>::const_iterator ext =
- this->HeaderExtensions.begin();
- ext != this->HeaderExtensions.end(); ++ext) {
+ for (const std::string& ext : this->HeaderExtensions) {
std::string testFilePath(testBasePath);
- testFilePath += '.';
- testFilePath += (*ext);
- if (cmsys::SystemTools::FileExists(testFilePath.c_str())) {
+ testFilePath.push_back('.');
+ testFilePath += ext;
+ if (cmSystemTools::FileExists(testFilePath.c_str())) {
header = testFilePath;
return true;
}
@@ -2076,10 +2022,10 @@ std::string cmQtAutoGenerators::MocFindHeader(
// Search in vicinity of the source
if (!this->FindHeader(header, sourcePath + includeBase)) {
// Search in include directories
- for (std::vector<std::string>::const_iterator iit =
- this->MocIncludePaths.begin();
- iit != this->MocIncludePaths.end(); ++iit) {
- const std::string fullPath = ((*iit) + '/' + includeBase);
+ for (const std::string& path : this->MocIncludePaths) {
+ std::string fullPath = path;
+ fullPath.push_back('/');
+ fullPath += includeBase;
if (FindHeader(header, fullPath)) {
break;
}
@@ -2087,7 +2033,7 @@ std::string cmQtAutoGenerators::MocFindHeader(
}
// Sanitize
if (!header.empty()) {
- header = cmsys::SystemTools::GetRealPath(header);
+ header = cmSystemTools::GetRealPath(header);
}
return header;
}
@@ -2101,19 +2047,19 @@ bool cmQtAutoGenerators::MocFindIncludedFile(
{
std::string testPath = sourcePath;
testPath += includeString;
- if (cmsys::SystemTools::FileExists(testPath.c_str())) {
- absFile = cmsys::SystemTools::GetRealPath(testPath);
+ if (cmSystemTools::FileExists(testPath.c_str())) {
+ absFile = cmSystemTools::GetRealPath(testPath);
success = true;
}
}
// Search in include directories
if (!success) {
- for (std::vector<std::string>::const_iterator iit =
- this->MocIncludePaths.begin();
- iit != this->MocIncludePaths.end(); ++iit) {
- const std::string fullPath = ((*iit) + '/' + includeString);
- if (cmsys::SystemTools::FileExists(fullPath.c_str())) {
- absFile = cmsys::SystemTools::GetRealPath(fullPath);
+ for (const std::string& path : this->MocIncludePaths) {
+ std::string fullPath = path;
+ fullPath.push_back('/');
+ fullPath += includeString;
+ if (cmSystemTools::FileExists(fullPath.c_str())) {
+ absFile = cmSystemTools::GetRealPath(fullPath);
success = true;
break;
}
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index 5cb3d9f..5d3ad74 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -6,18 +6,19 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmFilePathChecksum.h"
+#include "cmQtAutoGen.h"
#include "cmsys/RegularExpression.hxx"
#include <map>
#include <set>
#include <string>
-#include <utility>
#include <vector>
class cmMakefile;
class cmQtAutoGenerators
{
+ CM_DISABLE_COPY(cmQtAutoGenerators)
public:
cmQtAutoGenerators();
bool Run(const std::string& targetDirectory, const std::string& config);
@@ -25,13 +26,35 @@ public:
private:
// -- Types
- /// @brief Used to extract additional dependencies from content text
- struct MocDependFilter
+ /// @brief Search key plus regular expression pair
+ struct KeyRegExp
{
- std::string key;
- cmsys::RegularExpression regExp;
+ KeyRegExp() = default;
+
+ KeyRegExp(const char* key, const char* regExp)
+ : Key(key)
+ , RegExp(regExp)
+ {
+ }
+
+ KeyRegExp(const std::string& key, const std::string& regExp)
+ : Key(key)
+ , RegExp(regExp)
+ {
+ }
+
+ std::string Key;
+ cmsys::RegularExpression RegExp;
+ };
+
+ /// @brief RCC job
+ struct RccJob
+ {
+ std::string QrcFile;
+ std::string RccFile;
+ std::vector<std::string> Options;
+ std::vector<std::string> Inputs;
};
- typedef std::pair<std::string, cmsys::RegularExpression> MocMacroFilter;
// -- Configuration
bool MocDependFilterPush(const std::string& key, const std::string& regExp);
@@ -90,6 +113,9 @@ private:
const std::string& fileName, const std::string& contentText,
std::map<std::string, std::vector<std::string>>& includedUis);
+ std::string MocMacroNamesString() const;
+ std::string MocHeaderSuffixesString() const;
+
bool MocParseSourceContent(
const std::string& absFilename, const std::string& contentText,
std::map<std::string, std::string>& mocsIncluded,
@@ -122,18 +148,31 @@ private:
// -- Rcc file generation
bool RccGenerateAll();
- bool RccGenerateFile(const std::string& qrcInputFile,
- const std::string& qrcOutputFile, bool unique_n);
+ bool RccGenerateFile(const RccJob& rccJob);
- // -- Logging
- void LogErrorNameCollision(
- const std::string& message,
- const std::multimap<std::string, std::string>& collisions) const;
+ // -- Log info
void LogBold(const std::string& message) const;
- void LogInfo(const std::string& message) const;
- void LogWarning(const std::string& message) const;
- void LogError(const std::string& message) const;
- void LogCommand(const std::vector<std::string>& command) const;
+ void LogInfo(cmQtAutoGen::GeneratorType genType,
+ const std::string& message) const;
+ // -- Log warning
+ void LogWarning(cmQtAutoGen::GeneratorType genType,
+ const std::string& message) const;
+ void LogFileWarning(cmQtAutoGen::GeneratorType genType,
+ const std::string& filename,
+ const std::string& message) const;
+ // -- Log error
+ void LogError(cmQtAutoGen::GeneratorType genType,
+ const std::string& message) const;
+ void LogFileError(cmQtAutoGen::GeneratorType genType,
+ const std::string& filename,
+ const std::string& message) const;
+ void LogCommandError(cmQtAutoGen::GeneratorType genType,
+ const std::string& message,
+ const std::vector<std::string>& command,
+ const std::string& output) const;
+ void LogNameCollisionError(
+ cmQtAutoGen::GeneratorType genType, const std::string& message,
+ const std::multimap<std::string, std::string>& collisions) const;
// -- Utility
bool NameCollisionTest(
@@ -142,14 +181,14 @@ private:
std::string ChecksumedPath(const std::string& sourceFile,
const std::string& basePrefix,
const std::string& baseSuffix) const;
- bool MakeParentDirectory(const char* logPrefix,
+ bool MakeParentDirectory(cmQtAutoGen::GeneratorType genType,
const std::string& filename) const;
bool FileDiffers(const std::string& filename, const std::string& content);
- bool FileWrite(const char* logPrefix, const std::string& filename,
- const std::string& content);
+ bool FileWrite(cmQtAutoGen::GeneratorType genType,
+ const std::string& filename, const std::string& content);
- bool RunCommand(const std::vector<std::string>& command, std::string& output,
- bool verbose = true) const;
+ bool RunCommand(const std::vector<std::string>& command,
+ std::string& output) const;
bool FindHeader(std::string& header, const std::string& testBasePath) const;
@@ -169,6 +208,7 @@ private:
std::string AutogenIncludeDir;
// -- Qt environment
std::string QtMajorVersion;
+ std::string QtMinorVersion;
std::string MocExecutable;
std::string UicExecutable;
std::string RccExecutable;
@@ -200,23 +240,21 @@ private:
std::vector<std::string> MocDefinitions;
std::vector<std::string> MocOptions;
std::vector<std::string> MocPredefsCmd;
- std::vector<MocDependFilter> MocDependFilters;
- std::vector<MocMacroFilter> MocMacroFilters;
+ std::vector<KeyRegExp> MocDependFilters;
+ std::vector<KeyRegExp> MocMacroFilters;
cmsys::RegularExpression MocRegExpInclude;
// -- Uic
bool UicSettingsChanged;
bool UicRunFailed;
std::vector<std::string> UicSkipList;
std::vector<std::string> UicTargetOptions;
- std::map<std::string, std::string> UicOptions;
+ std::map<std::string, std::vector<std::string>> UicOptions;
std::vector<std::string> UicSearchPaths;
cmsys::RegularExpression UicRegExpInclude;
// -- Rcc
bool RccSettingsChanged;
bool RccRunFailed;
- std::vector<std::string> RccSources;
- std::map<std::string, std::string> RccOptions;
- std::map<std::string, std::vector<std::string>> RccInputs;
+ std::vector<RccJob> RccJobs;
};
#endif
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 86099eb..7fe2f2a 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -3607,6 +3607,13 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
this->WriteString("<Name>", 3);
(*this->BuildFileStream) << name << "</Name>\n";
this->WriteDotNetReferenceCustomTags(name);
+ if (csproj == this->ProjectType) {
+ if (!static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
+ ->TargetCanBeReferenced(dt)) {
+ this->WriteString(
+ "<ReferenceOutputAssembly>false</ReferenceOutputAssembly>\n", 3);
+ }
+ }
this->WriteString("</ProjectReference>\n", 2);
}
this->WriteString("</ItemGroup>\n", 1);
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index e6f88a7..a60b2b2 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -102,7 +102,7 @@ static int do_build(int ac, char const* const* av);
static cmMakefile* cmakemainGetMakefile(void* clientdata)
{
- cmake* cm = reinterpret_cast<cmake*>(clientdata);
+ cmake* cm = static_cast<cmake*>(clientdata);
if (cm && cm->GetDebugOutput()) {
cmGlobalGenerator* gg = cm->GetGlobalGenerator();
if (gg) {
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index d7d0c51..5b8ce00 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -1032,6 +1032,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
testSystemTools
testCommandLineArguments
testCommandLineArguments1
+ testDirectory
)
IF(KWSYS_STL_HAS_WSTRING)
SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index 5141d45..69068aa 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -118,8 +118,8 @@ bool Directory::Load(const std::string& name)
struct _wfinddata_t data; // data of current file
// Now put them into the file array
- srchHandle =
- _wfindfirst_func((wchar_t*)Encoding::ToWide(buf).c_str(), &data);
+ srchHandle = _wfindfirst_func(
+ (wchar_t*)Encoding::ToWindowsExtendedPath(buf).c_str(), &data);
delete[] buf;
if (srchHandle == -1) {
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 11f3b81..560c19c 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -2269,11 +2269,7 @@ bool SystemTools::CopyADirectory(const std::string& source,
const std::string& destination, bool always)
{
Directory dir;
-#ifdef _WIN32
- dir.Load(Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)));
-#else
dir.Load(source);
-#endif
size_t fileNum;
if (!SystemTools::MakeDirectory(destination)) {
return false;
@@ -2626,11 +2622,7 @@ bool SystemTools::RemoveADirectory(const std::string& source)
}
Directory dir;
-#ifdef _WIN32
- dir.Load(Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)));
-#else
dir.Load(source);
-#endif
size_t fileNum;
for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") &&
diff --git a/Source/kwsys/testDirectory.cxx b/Source/kwsys/testDirectory.cxx
new file mode 100644
index 0000000..983f2c6
--- /dev/null
+++ b/Source/kwsys/testDirectory.cxx
@@ -0,0 +1,79 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#include "kwsysPrivate.h"
+#include KWSYS_HEADER(Directory.hxx)
+#include KWSYS_HEADER(Encoding.hxx)
+#include KWSYS_HEADER(SystemTools.hxx)
+
+// Work-around CMake dependency scanning limitation. This must
+// duplicate the above list of headers.
+#if 0
+#include "Directory.hxx.in"
+#include "Encoding.hxx.in"
+#include "SystemTools.hxx.in"
+#endif
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+
+#include <testSystemTools.h>
+
+int _doLongPathTest()
+{
+ using namespace kwsys;
+ static const int LONG_PATH_THRESHOLD = 512;
+ int res = 0;
+ std::string topdir(TEST_SYSTEMTOOLS_BINARY_DIR "/directory_testing/");
+ std::stringstream testpathstrm;
+ std::string testdirpath;
+ std::string extendedtestdirpath;
+
+ testpathstrm << topdir;
+ size_t pathlen = testpathstrm.str().length();
+ testpathstrm.seekp(0, std::ios_base::end);
+ while (pathlen < LONG_PATH_THRESHOLD) {
+ testpathstrm << "0123456789/";
+ pathlen = testpathstrm.str().length();
+ }
+
+ testdirpath = testpathstrm.str();
+#ifdef _WIN32
+ extendedtestdirpath =
+ Encoding::ToNarrow(SystemTools::ConvertToWindowsExtendedPath(testdirpath));
+#else
+ extendedtestdirpath = testdirpath;
+#endif
+
+ if (SystemTools::MakeDirectory(extendedtestdirpath)) {
+ std::ofstream testfile1(
+ (extendedtestdirpath + "longfilepathtest1.txt").c_str());
+ std::ofstream testfile2(
+ (extendedtestdirpath + "longfilepathtest2.txt").c_str());
+ testfile1 << "foo";
+ testfile2 << "bar";
+ testfile1.close();
+ testfile2.close();
+
+ Directory testdir;
+ // Set res to failure if the directory doesn't load
+ res += !testdir.Load(testdirpath);
+ // Increment res failure if the directory appears empty
+ res += testdir.GetNumberOfFiles() == 0;
+ // Increment res failures if the path has changed from
+ // what was provided.
+ res += testdirpath != testdir.GetPath();
+
+ SystemTools::RemoveADirectory(topdir);
+ } else {
+ std::cerr << "Failed to create directory with long path: "
+ << extendedtestdirpath << std::endl;
+ res += 1;
+ }
+ return res;
+}
+
+int testDirectory(int, char* [])
+{
+ return _doLongPathTest();
+}
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 516bc89..640b542 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1431,6 +1431,14 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
add_subdirectory(FindDoxygen)
endif()
+ if(CMake_TEST_FindEXPAT)
+ add_subdirectory(FindEXPAT)
+ endif()
+
+ if(CMake_TEST_FindFreetype)
+ add_subdirectory(FindFreetype)
+ endif()
+
if(CMake_TEST_FindGSL)
add_subdirectory(FindGSL)
endif()
@@ -1484,6 +1492,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
add_subdirectory(FindPNG)
endif()
+ if(CMake_TEST_FindPatch)
+ add_subdirectory(FindPatch)
+ endif()
+
if(CMake_TEST_FindProtobuf)
add_subdirectory(FindProtobuf)
endif()
diff --git a/Tests/CSharpLinkToCxx/CMakeLists.txt b/Tests/CSharpLinkToCxx/CMakeLists.txt
index c4269e0..153c57c 100644
--- a/Tests/CSharpLinkToCxx/CMakeLists.txt
+++ b/Tests/CSharpLinkToCxx/CMakeLists.txt
@@ -15,3 +15,9 @@ target_compile_options(CLIApp PRIVATE "/clr")
add_executable(CSharpLinkToCxx csharp.cs)
target_link_libraries(CSharpLinkToCxx CLIApp)
+
+# this unmanaged C++ library will be added to the C#/.NET
+# references of CSharpLinkToCxx but it will show a warning
+# because it is unmanaged
+add_library(CppNativeApp SHARED cpp_native.hpp cpp_native.cpp)
+target_link_libraries(CSharpLinkToCxx CppNativeApp)
diff --git a/Tests/CSharpLinkToCxx/cpp_native.cpp b/Tests/CSharpLinkToCxx/cpp_native.cpp
new file mode 100644
index 0000000..dc7670f
--- /dev/null
+++ b/Tests/CSharpLinkToCxx/cpp_native.cpp
@@ -0,0 +1,10 @@
+#include "cpp_native.hpp"
+
+#include <iostream>
+
+namespace CppApp {
+void MyCpp::testMyCpp()
+{
+ std::cout << "#message from CppApp" << std::endl;
+}
+}
diff --git a/Tests/CSharpLinkToCxx/cpp_native.hpp b/Tests/CSharpLinkToCxx/cpp_native.hpp
new file mode 100644
index 0000000..0fa1a3b
--- /dev/null
+++ b/Tests/CSharpLinkToCxx/cpp_native.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+namespace CppApp {
+class MyCpp
+{
+public:
+ void testMyCpp();
+};
+}
diff --git a/Tests/FindEXPAT/CMakeLists.txt b/Tests/FindEXPAT/CMakeLists.txt
new file mode 100644
index 0000000..a74174a
--- /dev/null
+++ b/Tests/FindEXPAT/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindEXPAT.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindEXPAT/Test"
+ "${CMake_BINARY_DIR}/Tests/FindEXPAT/Test"
+ ${build_generator_args}
+ --build-project TestFindEXPAT
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
diff --git a/Tests/FindEXPAT/Test/CMakeLists.txt b/Tests/FindEXPAT/Test/CMakeLists.txt
new file mode 100644
index 0000000..5681f74
--- /dev/null
+++ b/Tests/FindEXPAT/Test/CMakeLists.txt
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 3.9)
+project(TestFindEXPAT C)
+include(CTest)
+
+find_package(EXPAT REQUIRED)
+
+add_definitions(-DCMAKE_EXPECTED_EXPAT_VERSION="${EXPAT_VERSION_STRING}")
+
+add_executable(testexpat_tgt main.c)
+target_link_libraries(testexpat_tgt EXPAT::EXPAT)
+add_test(NAME testexpat_tgt COMMAND testexpat_tgt)
+
+add_executable(testexpat_var main.c)
+target_include_directories(testexpat_var PRIVATE ${EXPAT_INCLUDE_DIRS})
+target_link_libraries(testexpat_var PRIVATE ${EXPAT_LIBRARIES})
+add_test(NAME testexpat_var COMMAND testexpat_var)
diff --git a/Tests/FindEXPAT/Test/main.c b/Tests/FindEXPAT/Test/main.c
new file mode 100644
index 0000000..94ee3ef
--- /dev/null
+++ b/Tests/FindEXPAT/Test/main.c
@@ -0,0 +1,21 @@
+#include <expat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main()
+{
+ XML_Expat_Version expat_version;
+ char expat_version_string[16];
+
+ expat_version = XML_ExpatVersionInfo();
+
+ snprintf(expat_version_string, 16, "%i.%i.%i", expat_version.major,
+ expat_version.minor, expat_version.micro);
+
+ if (strcmp(expat_version_string, CMAKE_EXPECTED_EXPAT_VERSION) != 0) {
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/Tests/FindFreetype/CMakeLists.txt b/Tests/FindFreetype/CMakeLists.txt
new file mode 100644
index 0000000..490c25b
--- /dev/null
+++ b/Tests/FindFreetype/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindFreetype.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindFreetype/Test"
+ "${CMake_BINARY_DIR}/Tests/FindFreetype/Test"
+ ${build_generator_args}
+ --build-project TestFindFreetype
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
diff --git a/Tests/FindFreetype/Test/CMakeLists.txt b/Tests/FindFreetype/Test/CMakeLists.txt
new file mode 100644
index 0000000..bc869a1
--- /dev/null
+++ b/Tests/FindFreetype/Test/CMakeLists.txt
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 3.9)
+project(TestFindFreetype C)
+include(CTest)
+
+find_package(Freetype REQUIRED)
+
+add_definitions(-DCMAKE_EXPECTED_FREETYPE_VERSION="${FREETYPE_VERSION_STRING}")
+
+add_executable(testfreetype_tgt main.c)
+target_link_libraries(testfreetype_tgt Freetype::Freetype)
+add_test(NAME testfreetype_tgt COMMAND testfreetype_tgt)
+
+add_executable(testfreetype_var main.c)
+target_include_directories(testfreetype_var PRIVATE ${FREETYPE_INCLUDE_DIRS})
+target_link_libraries(testfreetype_var PRIVATE ${FREETYPE_LIBRARIES})
+add_test(NAME testfreetype_var COMMAND testfreetype_var)
diff --git a/Tests/FindFreetype/Test/main.c b/Tests/FindFreetype/Test/main.c
new file mode 100644
index 0000000..bb838a5
--- /dev/null
+++ b/Tests/FindFreetype/Test/main.c
@@ -0,0 +1,34 @@
+#include <ft2build.h>
+#include <stdlib.h>
+#include FT_FREETYPE_H
+#include <string.h>
+
+int main()
+{
+ FT_Library library;
+ FT_Error error;
+
+ error = FT_Init_FreeType(&library);
+ if (error) {
+ return EXIT_FAILURE;
+ }
+
+ FT_Int major = 0;
+ FT_Int minor = 0;
+ FT_Int patch = 0;
+ FT_Library_Version(library, &major, &minor, &patch);
+
+ char ft_version_string[16];
+ snprintf(ft_version_string, 16, "%i.%i.%i", major, minor, patch);
+
+ if (strcmp(ft_version_string, CMAKE_EXPECTED_FREETYPE_VERSION) != 0) {
+ return EXIT_FAILURE;
+ }
+
+ error = FT_Done_FreeType(library);
+ if (error) {
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/Tests/FindPatch/CMakeLists.txt b/Tests/FindPatch/CMakeLists.txt
new file mode 100644
index 0000000..541f5bd
--- /dev/null
+++ b/Tests/FindPatch/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_test(NAME FindPatch.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindPatch/Test"
+ "${CMake_BINARY_DIR}/Tests/FindPatch/Test"
+ ${build_generator_args}
+ --build-options ${build_options}
+)
diff --git a/Tests/FindPatch/Test/CMakeLists.txt b/Tests/FindPatch/Test/CMakeLists.txt
new file mode 100644
index 0000000..f4cd621
--- /dev/null
+++ b/Tests/FindPatch/Test/CMakeLists.txt
@@ -0,0 +1,77 @@
+cmake_minimum_required(VERSION 3.8)
+project(TestFindPatch VERSION 1.0 LANGUAGES NONE)
+
+macro(_check)
+ if(NOT EXISTS "${Patch_EXECUTABLE}")
+ message(FATAL_ERROR "Failed to lookup Patch_EXECUTABLE [${Patch_EXECUTABLE}]")
+ endif()
+
+ if(NOT DEFINED PATCH_FOUND)
+ message(FATAL_ERROR "Variable PATCH_FOUND is not defined")
+ endif()
+
+ # Is import target available ?
+ if(NOT TARGET Patch::patch)
+ message(FATAL_ERROR "Target Patch::patch is not defined")
+ endif()
+
+ # Check Patch::patch imported location
+ get_property(_imported_location TARGET Patch::patch PROPERTY IMPORTED_LOCATION)
+ if(NOT "${Patch_EXECUTABLE}" STREQUAL "${_imported_location}")
+ message(FATAL_ERROR "\
+Patch_EXECUTABLE is expected to be equal to Patch::patch IMPORTED_LOCATION
+ Patch_EXECUTABLE [${Patch_EXECUTABLE}]
+ Patch::patch IMPORTED_LOCATION [${_imported_location}]
+")
+ endif()
+
+endmacro()
+
+find_package(Patch REQUIRED)
+_check()
+
+# Calling twice should not fail
+find_package(Patch REQUIRED)
+_check()
+
+add_custom_target(TestPatchVersion ALL
+ COMMAND ${Patch_EXECUTABLE} -v
+ )
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/QUOTE.txt.baseline"
+[=[Because it's there.
+- George Mallory, 1923
+]=]
+)
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/QUOTE.txt" "Because it's there.\n")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/quote-add-author.patch"
+[=[diff --git a/QUOTE.txt b/QUOTE.txt
+index b36681d..68059b3 100644
+--- a/QUOTE.txt
++++ b/QUOTE.txt
+@@ -1 +1,2 @@
+ Because it's there.
++- George Mallory
+]=]
+)
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/quote-add-date.patch"
+[=[diff --git a/QUOTE.txt b/QUOTE.txt
+index 68059b3..c6f30c2 100644
+--- a/QUOTE.txt
++++ b/QUOTE.txt
+@@ -1,2 +1,2 @@
+ Because it's there.
+-- George Mallory
++- George Mallory, 1923
+]=]
+)
+
+add_custom_target(TestPatch ALL
+ COMMAND ${Patch_EXECUTABLE} -p1 -i quote-add-author.patch
+ COMMAND Patch::patch -p1 -i quote-add-date.patch
+ COMMAND ${CMAKE_COMMAND} -E compare_files QUOTE.txt QUOTE.txt.baseline
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ )
diff --git a/Tests/QtAutogen/mocDepends/CMakeLists.txt b/Tests/QtAutogen/mocDepends/CMakeLists.txt
index d71d740..8217b8d 100644
--- a/Tests/QtAutogen/mocDepends/CMakeLists.txt
+++ b/Tests/QtAutogen/mocDepends/CMakeLists.txt
@@ -15,81 +15,137 @@ else()
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR})
+set(CSD ${CMAKE_CURRENT_SOURCE_DIR})
+set(CBD ${CMAKE_CURRENT_BINARY_DIR})
-# -- Test 1: Depend on generated header
+# -- Test dependency on header generated by a custom command
+#
# The ORIGIN_autogen target must depend on the same *GENERATED* source files as
# the ORIGIN target. This is a requirement to ensure that all files for the
# ORIGIN target are generated before the ORIGIN_autogen target is built.
#
-# This tests the dependency of the mocDepends1_autogen target of mocDepends1
-# to the source file test1_object.hpp, which is *GENERATED* by a custom command.
-# If mocDepends1_autogen gets built *before* or in *parallel* to the
-# custom command, the build will fail. That's because test1_object.hpp,
-# which is required by mocDepends1_autogen, is only valid after the
+# This tests the dependency of the mocDepGenFile_autogen target of
+# mocDepGenFile to the source file GenFile.hpp, which is *GENERATED*
+# by a custom command.
+# If mocDepGenFile_autogen gets built *before* or in *parallel* to the
+# custom command, the build will fail. That's because GenFile.hpp,
+# which is required by mocDepGenFile_autogen, is only valid after the
# custom command has been completed.
#
# The sleep seconds artificially increase the build time of the custom command
# to simulate a slow file generation process that takes longer to run than
-# the build of the mocDepends1_autogen target.
+# the build of the mocDepGenFile_autogen target.
add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/test1_object.hpp
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/test1_object.hpp
+ OUTPUT ${CBD}/GenFile.hpp
+ COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_invalid.hpp.in ${CBD}/GenFile.hpp
COMMAND ${CMAKE_COMMAND} -E sleep 3
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/object.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/test1_object.hpp)
+ COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_valid.hpp.in ${CBD}/GenFile.hpp)
+
+add_executable(mocDepGenFile testGenFile.cpp ${CBD}/GenFile.hpp)
+target_link_libraries(mocDepGenFile ${QT_CORE_TARGET})
+set_target_properties(mocDepGenFile PROPERTIES AUTOMOC TRUE)
-add_executable(mocDepends1 test1.cpp ${CMAKE_CURRENT_BINARY_DIR}/test1_object.hpp)
-target_link_libraries(mocDepends1 ${QT_CORE_TARGET})
-set_target_properties(mocDepends1 PROPERTIES AUTOMOC TRUE)
-# -- Test 2: Depend on header generating target
+# -- Test dependency on header generating custom target
+#
# The ORIGIN_autogen target must depend on the same user defined targets
# as the ORIGIN target. This is a requirement to ensure that all files for the
# ORIGIN target are generated before the ORIGIN_autogen target is built.
#
-# This tests the dependency of the mocDepends2_autogen target of mocDepends2
-# to the utility target mocDepends2Object. If mocDepends2_autogen gets built
-# *before* or in *parallel* to mocDepends2Object, the build will fail. That's
-# because test2_object.hpp, which is required by mocDepends2_autogen,
-# is only valid after the mocDepends2Object build has been completed.
+# This tests the dependency of the mocDepTarget_autogen target of
+# mocDepTarget to the utility target mocDepTargetUtil.
+# If mocDepTarget_autogen gets built *before* or in *parallel* to
+# mocDepTargetUtil, the build will fail. That's
+# because GenTarget.hpp, which is required by mocDepTarget_autogen,
+# is only valid after the mocDepTargetUtil build has been completed.
#
-# The sleep seconds artificially increase the build time of mocDepends2Object
+# The sleep seconds artificially increase the build time of mocDepTargetUtil
# to simulate a slow utility target build that takes longer to run than
-# the build of the mocDepends2_autogen target.
-add_custom_target(mocDepends2Object
- BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/test2_object.hpp
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/test2_object.hpp
+# the build of the mocDepTarget_autogen target.
+add_custom_target(mocDepTargetUtil
+ BYPRODUCTS ${CBD}/GenTarget.hpp
+ COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_invalid.hpp.in ${CBD}/GenTarget.hpp
COMMAND ${CMAKE_COMMAND} -E sleep 3
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/object.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/test2_object.hpp)
+ COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_valid.hpp.in ${CBD}/GenTarget.hpp)
+
+add_executable(mocDepTarget testGenTarget.cpp)
+target_link_libraries(mocDepTarget ${QT_CORE_TARGET})
+set_target_properties(mocDepTarget PROPERTIES AUTOMOC TRUE)
+add_dependencies(mocDepTarget mocDepTargetUtil)
-add_executable(mocDepends2 test2.cpp)
-target_link_libraries(mocDepends2 ${QT_CORE_TARGET})
-set_target_properties(mocDepends2 PROPERTIES AUTOMOC TRUE)
-add_dependencies(mocDepends2 mocDepends2Object)
# -- Test 3: Depend on generated linked library
# The ORIGIN_autogen target must depend on the same linked libraries
# as the ORIGIN target. This is a requirement to ensure that all files for the
# ORIGIN target are generated before the ORIGIN_autogen target is built.
#
-# This tests the dependency of the mocDepends3_autogen target of mocDepends3
-# to the user generated library SimpleLib, which mocDepends3 links to.
-# If mocDepends3_autogen gets built *before* or in *parallel* to SimpleLib,
+# This tests the dependency of the mocDepGenLib_autogen target of mocDepGenLib
+# to the user generated library SimpleLib, which mocDepGenLib links to.
+# If mocDepGenLib_autogen gets built *before* or in *parallel* to SimpleLib,
# the build will fail. That's because simpleLib.hpp, which is required by
-# mocDepends3_autogen, is only valid after the SimpleLib build has been
+# mocDepGenLib_autogen, is only valid after the SimpleLib build has been
# completed.
#
# The sleep seconds artificially increase the build time of SimpleLib
# to simulate a slow utility library build that takes longer to run than
-# the build of the mocDepends3_autogen target.
+# the build of the mocDepGenLib_autogen target.
add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.cpp
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp
+ OUTPUT ${CBD}/simpleLib.hpp ${CBD}/simpleLib.cpp
+ COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_invalid.hpp.in ${CBD}/simpleLib.hpp
COMMAND ${CMAKE_COMMAND} -E sleep 3
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/simpleLib.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/simpleLib.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.cpp)
-add_library(SimpleLib STATIC ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.cpp)
+ COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/simpleLib.hpp.in ${CBD}/simpleLib.hpp
+ COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/simpleLib.cpp.in ${CBD}/simpleLib.cpp)
+add_library(SimpleLib STATIC ${CBD}/simpleLib.hpp ${CBD}/simpleLib.cpp)
target_link_libraries(SimpleLib ${QT_CORE_TARGET})
-add_executable(mocDepends3 test3.cpp)
-target_link_libraries(mocDepends3 SimpleLib ${QT_CORE_TARGET})
-set_target_properties(mocDepends3 PROPERTIES AUTOMOC TRUE)
+add_executable(mocDepGenLib testGenLib.cpp)
+target_link_libraries(mocDepGenLib SimpleLib ${QT_CORE_TARGET})
+set_target_properties(mocDepGenLib PROPERTIES AUTOMOC TRUE)
+
+
+# -- Test AUTOGEN_TARGET_DEPENDS with GENERATED file dependency
+#
+# This tests the dependency of the mocDepATDFile_autogen target of
+# mocDepATDTarget to the utility target mocDepATDFileUtil.
+# If mocDepATDFile_autogen gets built *before* or in *parallel* to
+# mocDepATDFileUtil, the build will fail. That's
+# because ATDFile.hpp, which is required by mocDepATDFile_autogen,
+# is only valid after the mocDepATDFileUtil build has been completed.
+#
+# The sleep seconds artificially increase the build time of
+# mocDepATDFileUtil to simulate a slow utility target build that takes
+# longer to run than the build of the mocDepATDFile_autogen target.
+add_custom_command(
+ OUTPUT ${CBD}/ATDFile.hpp
+ COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_invalid.hpp.in ${CBD}/ATDFile.hpp
+ COMMAND ${CMAKE_COMMAND} -E sleep 3
+ COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_valid.hpp.in ${CBD}/ATDFile.hpp)
+
+add_executable(mocDepATDFile testATDFile.cpp)
+target_link_libraries(mocDepATDFile ${QT_CORE_TARGET})
+set_target_properties(mocDepATDFile PROPERTIES AUTOMOC TRUE)
+set_target_properties(mocDepATDFile PROPERTIES AUTOGEN_TARGET_DEPENDS ${CBD}/ATDFile.hpp)
+
+
+# -- Test AUTOGEN_TARGET_DEPENDS with target dependency
+#
+# This tests the dependency of the mocDepATDTarget_autogen target of
+# mocDepATDTarget to the utility target mocDepATDTargetUtil.
+# If mocDepATDTarget_autogen gets built *before* or in *parallel* to
+# mocDepATDTargetUtil, the build will fail. That's
+# because ATDTarget.hpp, which is required by mocDepATDTarget_autogen,
+# is only valid after the mocDepATDTargetUtil build has been completed.
+#
+# The sleep seconds artificially increase the build time of
+# mocDepATDTargetUtil to simulate a slow utility target build that takes
+# longer to run than the build of the mocDepATDTarget_autogen target.
+add_custom_target(mocDepATDTargetUtil
+ BYPRODUCTS ${CBD}/ATDTarget.hpp
+ COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_invalid.hpp.in ${CBD}/ATDTarget.hpp
+ COMMAND ${CMAKE_COMMAND} -E sleep 3
+ COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_valid.hpp.in ${CBD}/ATDTarget.hpp)
+
+add_executable(mocDepATDTarget testATDTarget.cpp)
+target_link_libraries(mocDepATDTarget ${QT_CORE_TARGET})
+set_target_properties(mocDepATDTarget PROPERTIES AUTOMOC TRUE)
+set_target_properties(mocDepATDTarget PROPERTIES AUTOGEN_TARGET_DEPENDS mocDepATDTargetUtil)
diff --git a/Tests/QtAutogen/mocDepends/invalid.hpp.in b/Tests/QtAutogen/mocDepends/object_invalid.hpp.in
index 854d9a1..854d9a1 100644
--- a/Tests/QtAutogen/mocDepends/invalid.hpp.in
+++ b/Tests/QtAutogen/mocDepends/object_invalid.hpp.in
diff --git a/Tests/QtAutogen/mocDepends/object.hpp.in b/Tests/QtAutogen/mocDepends/object_valid.hpp.in
index f364f7c..f364f7c 100644
--- a/Tests/QtAutogen/mocDepends/object.hpp.in
+++ b/Tests/QtAutogen/mocDepends/object_valid.hpp.in
diff --git a/Tests/QtAutogen/mocDepends/test2.cpp b/Tests/QtAutogen/mocDepends/test2.cpp
deleted file mode 100644
index 3fd845e..0000000
--- a/Tests/QtAutogen/mocDepends/test2.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-
-#include "moc_test2_object.cpp"
-#include "test2_object.hpp"
-
-int main()
-{
- Object obj;
- return 0;
-}
diff --git a/Tests/QtAutogen/mocDepends/testATDFile.cpp b/Tests/QtAutogen/mocDepends/testATDFile.cpp
new file mode 100644
index 0000000..6bddfcd
--- /dev/null
+++ b/Tests/QtAutogen/mocDepends/testATDFile.cpp
@@ -0,0 +1,9 @@
+
+#include "ATDFile.hpp"
+#include "moc_ATDFile.cpp"
+
+int main()
+{
+ Object obj;
+ return 0;
+}
diff --git a/Tests/QtAutogen/mocDepends/testATDTarget.cpp b/Tests/QtAutogen/mocDepends/testATDTarget.cpp
new file mode 100644
index 0000000..831fc26
--- /dev/null
+++ b/Tests/QtAutogen/mocDepends/testATDTarget.cpp
@@ -0,0 +1,9 @@
+
+#include "ATDTarget.hpp"
+#include "moc_ATDTarget.cpp"
+
+int main()
+{
+ Object obj;
+ return 0;
+}
diff --git a/Tests/QtAutogen/mocDepends/test1.cpp b/Tests/QtAutogen/mocDepends/testGenFile.cpp
index 002dfd8..7df6e13 100644
--- a/Tests/QtAutogen/mocDepends/test1.cpp
+++ b/Tests/QtAutogen/mocDepends/testGenFile.cpp
@@ -1,5 +1,5 @@
-#include "test1_object.hpp"
+#include "GenFile.hpp"
int main()
{
diff --git a/Tests/QtAutogen/mocDepends/test3.cpp b/Tests/QtAutogen/mocDepends/testGenLib.cpp
index a009598..c14e159 100644
--- a/Tests/QtAutogen/mocDepends/test3.cpp
+++ b/Tests/QtAutogen/mocDepends/testGenLib.cpp
@@ -1,5 +1,5 @@
-#include "test3.hpp"
+#include "testGenLib.hpp"
int main()
{
@@ -8,5 +8,5 @@ int main()
return 0;
}
-// AUTOMOC the SimpleLib header simpleLib.hpp
+// Depend on and AUTOMOC the SimpleLib header simpleLib.hpp
#include "moc_simpleLib.cpp"
diff --git a/Tests/QtAutogen/mocDepends/test3.hpp b/Tests/QtAutogen/mocDepends/testGenLib.hpp
index 408335b..408335b 100644
--- a/Tests/QtAutogen/mocDepends/test3.hpp
+++ b/Tests/QtAutogen/mocDepends/testGenLib.hpp
diff --git a/Tests/QtAutogen/mocDepends/testGenTarget.cpp b/Tests/QtAutogen/mocDepends/testGenTarget.cpp
new file mode 100644
index 0000000..911076e
--- /dev/null
+++ b/Tests/QtAutogen/mocDepends/testGenTarget.cpp
@@ -0,0 +1,9 @@
+
+#include "GenTarget.hpp"
+#include "moc_GenTarget.cpp"
+
+int main()
+{
+ Object obj;
+ return 0;
+}
diff --git a/Tests/RunCMake/ExternalProject/MultiCommand-build-stdout.txt b/Tests/RunCMake/ExternalProject/MultiCommand-build-stdout.txt
new file mode 100644
index 0000000..30ebc7d
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/MultiCommand-build-stdout.txt
@@ -0,0 +1,15 @@
+.* *download 1
+.* *download 2
+.* *update 1
+.* *update 2
+.* *patch 1
+.* *patch 2
+.* *configure 1
+.* *configure 2
+.* *build 1
+.* *build 2
+.* *install 1
+.* *install 2
+.* *test 1
+.* *test 2
+.*
diff --git a/Tests/RunCMake/ExternalProject/MultiCommand.cmake b/Tests/RunCMake/ExternalProject/MultiCommand.cmake
new file mode 100644
index 0000000..a8dbfea
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/MultiCommand.cmake
@@ -0,0 +1,30 @@
+cmake_minimum_required(VERSION 3.9)
+
+include(ExternalProject)
+
+# Verify COMMAND keyword is recognised after various *_COMMAND options
+ExternalProject_Add(multiCommand
+ DOWNLOAD_COMMAND "${CMAKE_COMMAND}" -E echo "download 1"
+ COMMAND "${CMAKE_COMMAND}" -E echo "download 2"
+ UPDATE_COMMAND "${CMAKE_COMMAND}" -E echo "update 1"
+ COMMAND "${CMAKE_COMMAND}" -E echo "update 2"
+ PATCH_COMMAND "${CMAKE_COMMAND}" -E echo "patch 1"
+ COMMAND "${CMAKE_COMMAND}" -E echo "patch 2"
+ CONFIGURE_COMMAND "${CMAKE_COMMAND}" -E echo "configure 1"
+ COMMAND "${CMAKE_COMMAND}" -E echo "configure 2"
+ BUILD_COMMAND "${CMAKE_COMMAND}" -E echo "build 1"
+ COMMAND "${CMAKE_COMMAND}" -E echo "build 2"
+ TEST_COMMAND "${CMAKE_COMMAND}" -E echo "test 1"
+ COMMAND "${CMAKE_COMMAND}" -E echo "test 2"
+ INSTALL_COMMAND "${CMAKE_COMMAND}" -E echo "install 1"
+ COMMAND "${CMAKE_COMMAND}" -E echo "install 2"
+)
+
+# Workaround for issue 17229 (missing dependency between update and patch steps)
+ExternalProject_Add_StepTargets(multiCommand NO_DEPENDS update)
+ExternalProject_Add_StepDependencies(multiCommand patch multiCommand-update)
+
+# Force all steps to be re-run by removing timestamps from any previous run
+ExternalProject_Get_Property(multiCommand STAMP_DIR)
+file(REMOVE_RECURSE "${STAMP_DIR}")
+file(MAKE_DIRECTORY "${STAMP_DIR}")
diff --git a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
index 47d6129..994e2aa 100644
--- a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
@@ -12,3 +12,13 @@ run_cmake(Add_StepDependencies_iface)
run_cmake(Add_StepDependencies_iface_step)
run_cmake(Add_StepDependencies_no_target)
run_cmake(UsesTerminal)
+
+# Run both cmake and build steps. We always do a clean before the
+# build to ensure that the download step re-runs each time.
+set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/MultiCommand-build)
+set(RunCMake_TEST_NO_CLEAN 1)
+file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+run_cmake(MultiCommand)
+run_cmake_command(MultiCommand-clean ${CMAKE_COMMAND} --build . --target clean)
+run_cmake_command(MultiCommand-build ${CMAKE_COMMAND} --build .)
diff --git a/Tests/RunCMake/FPHSA/FindPseudoNoVersionVar.cmake b/Tests/RunCMake/FPHSA/FindPseudoNoVersionVar.cmake
new file mode 100644
index 0000000..d961c64
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/FindPseudoNoVersionVar.cmake
@@ -0,0 +1,6 @@
+# pseudo find_module without specifying VERSION_VAR
+
+set(FOOBAR TRUE)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(PseudoNoVersionVar REQUIRED_VARS FOOBAR)
diff --git a/Tests/RunCMake/FPHSA/RunCMakeTest.cmake b/Tests/RunCMake/FPHSA/RunCMakeTest.cmake
index e9b2a7a..1b71a31 100644
--- a/Tests/RunCMake/FPHSA/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FPHSA/RunCMakeTest.cmake
@@ -4,6 +4,17 @@ run_cmake(BadFoundVar)
# The pseudo module will "find" a package with the given version. Check if the
# version selection code in FPHSA works correctly.
+
+# Find a package with version 0.
+set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DPseudo_VERSION=0")
+run_cmake(any_version_find_0)
+
+# Find a package with more customary version number, without requestion a specific version and in
+# the presence of a cache variable VERSION.
+set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DPseudoNoVersionVar_VERSION=1.2.3.4.5_SHOULD_BE_IGNORED" "-DVERSION=BAD_VERSION")
+run_cmake(any_version_VERSION_cache_variable)
+
+# Find a package with a more customary version number, without requestion a specific version.
set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DPseudo_VERSION=1.2.3.4.5")
run_cmake(any_version)
diff --git a/Tests/RunCMake/FPHSA/any_version_VERSION_cache_variable-stdout.txt b/Tests/RunCMake/FPHSA/any_version_VERSION_cache_variable-stdout.txt
new file mode 100644
index 0000000..f9acece
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/any_version_VERSION_cache_variable-stdout.txt
@@ -0,0 +1,2 @@
+Found PseudoNoVersionVar: TRUE *
++
diff --git a/Tests/RunCMake/FPHSA/any_version_VERSION_cache_variable.cmake b/Tests/RunCMake/FPHSA/any_version_VERSION_cache_variable.cmake
new file mode 100644
index 0000000..9f27897
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/any_version_VERSION_cache_variable.cmake
@@ -0,0 +1 @@
+find_package(PseudoNoVersionVar REQUIRED)
diff --git a/Tests/RunCMake/FPHSA/any_version_find_0-stdout.txt b/Tests/RunCMake/FPHSA/any_version_find_0-stdout.txt
new file mode 100644
index 0000000..861a339
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/any_version_find_0-stdout.txt
@@ -0,0 +1,2 @@
+Found Pseudo: [^
+]*\(found version "0\"\)
diff --git a/Tests/RunCMake/FPHSA/any_version_find_0.cmake b/Tests/RunCMake/FPHSA/any_version_find_0.cmake
new file mode 100644
index 0000000..b34a540
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/any_version_find_0.cmake
@@ -0,0 +1 @@
+find_package(Pseudo REQUIRED)