summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/command/enable_language.rst5
-rw-r--r--Help/command/project.rst3
-rw-r--r--Help/manual/cmake-generator-expressions.7.rst28
-rw-r--r--Help/manual/cmake-modules.7.rst6
-rw-r--r--Help/module/CheckOBJCCompilerFlag.rst1
-rw-r--r--Help/module/CheckOBJCSourceCompiles.rst1
-rw-r--r--Help/module/CheckOBJCSourceRuns.rst1
-rw-r--r--Help/module/CheckOBJCXXCompilerFlag.rst1
-rw-r--r--Help/module/CheckOBJCXXSourceCompiles.rst1
-rw-r--r--Help/module/CheckOBJCXXSourceRuns.rst1
-rw-r--r--Help/release/dev/FPHSA-reason-failure-message.rst5
-rw-r--r--Help/release/dev/objective-c-cxx.rst9
-rw-r--r--Modules/CMakeCXXCompiler.cmake.in11
-rw-r--r--Modules/CMakeDetermineOBJCCompiler.cmake189
-rw-r--r--Modules/CMakeDetermineOBJCXXCompiler.cmake197
-rw-r--r--Modules/CMakeOBJCCompiler.cmake.in69
-rw-r--r--Modules/CMakeOBJCCompilerABI.m20
-rw-r--r--Modules/CMakeOBJCCompilerId.m.in63
-rw-r--r--Modules/CMakeOBJCInformation.cmake188
-rw-r--r--Modules/CMakeOBJCXXCompiler.cmake.in79
-rw-r--r--Modules/CMakeOBJCXXCompilerABI.mm20
-rw-r--r--Modules/CMakeOBJCXXCompilerId.mm.in68
-rw-r--r--Modules/CMakeOBJCXXInformation.cmake273
-rw-r--r--Modules/CMakeTestOBJCCompiler.cmake94
-rw-r--r--Modules/CMakeTestOBJCXXCompiler.cmake93
-rw-r--r--Modules/CheckOBJCCompilerFlag.cmake64
-rw-r--r--Modules/CheckOBJCSourceCompiles.cmake145
-rw-r--r--Modules/CheckOBJCSourceRuns.cmake145
-rw-r--r--Modules/CheckOBJCXXCompilerFlag.cmake64
-rw-r--r--Modules/CheckOBJCXXSourceCompiles.cmake146
-rw-r--r--Modules/CheckOBJCXXSourceRuns.cmake145
-rw-r--r--Modules/Compiler/AppleClang-OBJC.cmake17
-rw-r--r--Modules/Compiler/AppleClang-OBJCXX.cmake37
-rw-r--r--Modules/Compiler/Clang-OBJC.cmake18
-rw-r--r--Modules/Compiler/Clang-OBJCXX.cmake70
-rw-r--r--Modules/Compiler/GNU-OBJC.cmake6
-rw-r--r--Modules/Compiler/GNU-OBJCXX.cmake10
-rw-r--r--Modules/FindPackageHandleStandardArgs.cmake27
-rw-r--r--Modules/Platform/Apple-AppleClang-OBJC.cmake6
-rw-r--r--Modules/Platform/Apple-AppleClang-OBJCXX.cmake6
-rw-r--r--Modules/Platform/Apple-Clang-OBJC.cmake2
-rw-r--r--Modules/Platform/Apple-Clang-OBJCXX.cmake2
-rw-r--r--Modules/Platform/Apple-GNU-OBJC.cmake4
-rw-r--r--Modules/Platform/Apple-GNU-OBJCXX.cmake4
-rw-r--r--Modules/Platform/Darwin.cmake10
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CursesDialog/CMakeLists.txt36
-rw-r--r--Source/CursesDialog/cmCursesCacheEntryComposite.cxx81
-rw-r--r--Source/CursesDialog/cmCursesCacheEntryComposite.h17
-rw-r--r--Source/CursesDialog/cmCursesMainForm.cxx174
-rw-r--r--Source/CursesDialog/cmCursesMainForm.h13
-rw-r--r--Source/CursesDialog/cmCursesStringWidget.cxx32
-rw-r--r--Source/CursesDialog/cmCursesStringWidget.h5
-rw-r--r--Source/cmGeneratorExpressionNode.cxx8
-rw-r--r--Source/cmLocalGenerator.cxx12
-rw-r--r--Source/cmMakefile.cxx148
-rw-r--r--Source/cmMakefile.h14
-rw-r--r--Source/cmQtAutoGenerator.cxx266
-rw-r--r--Source/cmQtAutoGenerator.h96
-rw-r--r--Source/cmQtAutoMocUic.cxx856
-rw-r--r--Source/cmQtAutoMocUic.h551
-rw-r--r--Source/cmQtAutoRcc.cxx129
-rw-r--r--Source/cmQtAutoRcc.h72
-rw-r--r--Source/cmTarget.cxx8
-rw-r--r--Source/cmcmd.cxx21
-rw-r--r--Tests/CMakeLists.txt73
-rw-r--r--Tests/CMakeOnly/CMakeLists.txt11
-rw-r--r--Tests/CMakeOnly/CheckLanguage/CMakeLists.txt12
-rw-r--r--Tests/CMakeOnly/CheckOBJCCompilerFlag/CMakeLists.txt17
-rw-r--r--Tests/CMakeOnly/CheckOBJCXXCompilerFlag/CMakeLists.txt17
-rw-r--r--Tests/CMakeOnly/CompilerIdOBJC/CMakeLists.txt14
-rw-r--r--Tests/CMakeOnly/CompilerIdOBJCXX/CMakeLists.txt14
-rw-r--r--Tests/Objective-C++/cxx-file-extension-test/CMakeLists.txt5
-rw-r--r--Tests/Objective-C++/cxx-file-extension-test/main.mm8
-rw-r--r--Tests/Objective-C++/objcxx-file-extension-test/CMakeLists.txt6
-rw-r--r--Tests/Objective-C++/objcxx-file-extension-test/main.mm14
-rw-r--r--Tests/Objective-C++/simple-build-test/CMakeLists.txt11
-rw-r--r--Tests/Objective-C++/simple-build-test/foo.h9
-rw-r--r--Tests/Objective-C++/simple-build-test/foo.mm7
-rw-r--r--Tests/Objective-C++/simple-build-test/main.mm14
-rw-r--r--Tests/Objective-C/c-file-extension-test/CMakeLists.txt5
-rw-r--r--Tests/Objective-C/c-file-extension-test/main.m8
-rw-r--r--Tests/Objective-C/objc-file-extension-test/CMakeLists.txt6
-rw-r--r--Tests/Objective-C/objc-file-extension-test/main.m12
-rw-r--r--Tests/Objective-C/simple-build-test/CMakeLists.txt11
-rw-r--r--Tests/Objective-C/simple-build-test/foo.h9
-rw-r--r--Tests/Objective-C/simple-build-test/foo.m7
-rw-r--r--Tests/Objective-C/simple-build-test/main.m12
-rw-r--r--Tests/RunCMake/FPHSA/CustomMessageConfig.cmake1
-rw-r--r--Tests/RunCMake/FPHSA/CustomMessageConfigVersion.cmake4
-rw-r--r--Tests/RunCMake/FPHSA/FindCustomMessage.cmake17
-rw-r--r--Tests/RunCMake/FPHSA/RunCMakeTest.cmake7
-rw-r--r--Tests/RunCMake/FPHSA/custom_message_1-result.txt1
-rw-r--r--Tests/RunCMake/FPHSA/custom_message_1-stderr.txt7
-rw-r--r--Tests/RunCMake/FPHSA/custom_message_1.cmake4
-rw-r--r--Tests/RunCMake/FPHSA/custom_message_2-result.txt1
-rw-r--r--Tests/RunCMake/FPHSA/custom_message_2-stderr.txt8
-rw-r--r--Tests/RunCMake/FPHSA/custom_message_2.cmake5
-rw-r--r--Tests/RunCMake/FPHSA/custom_message_3-result.txt1
-rw-r--r--Tests/RunCMake/FPHSA/custom_message_3-stderr.txt9
-rw-r--r--Tests/RunCMake/FPHSA/custom_message_3.cmake5
-rw-r--r--Tests/TryCompile/CMakeLists.txt54
103 files changed, 4055 insertions, 1268 deletions
diff --git a/Help/command/enable_language.rst b/Help/command/enable_language.rst
index fb49b44..fdc44f2 100644
--- a/Help/command/enable_language.rst
+++ b/Help/command/enable_language.rst
@@ -1,7 +1,6 @@
enable_language
---------------
-
-Enable a language (CXX/C/Fortran/etc)
+Enable a language (CXX/C/OBJC/OBJCXX/Fortran/etc)
.. code-block:: cmake
@@ -10,7 +9,7 @@ Enable a language (CXX/C/Fortran/etc)
Enables support for the named language in CMake. This is
the same as the :command:`project` command but does not create any of the extra
variables that are created by the project command. Example languages
-are ``CXX``, ``C``, ``CUDA``, ``Fortran``, and ``ASM``.
+are ``CXX``, ``C``, ``CUDA``, ``OBJC``, ``OBJCXX``, ``Fortran``, and ``ASM``.
If enabling ``ASM``, enable it last so that CMake can check whether
compilers for other languages like ``C`` work for assembly too.
diff --git a/Help/command/project.rst b/Help/command/project.rst
index baf18be..3951456 100644
--- a/Help/command/project.rst
+++ b/Help/command/project.rst
@@ -87,7 +87,8 @@ The options are:
Can also be specified without ``LANGUAGES`` keyword per the first, short signature.
Selects which programming languages are needed to build the project.
- Supported languages include ``C``, ``CXX`` (i.e. C++), ``CUDA``, ``Fortran``, and ``ASM``.
+ Supported languages include ``C``, ``CXX`` (i.e. C++), ``CUDA``,
+ ``OBJC`` (i.e. Objective-C), ``OBJCXX``, ``Fortran``, and ``ASM``.
By default ``C`` and ``CXX`` are enabled if no language options are given.
Specify language ``NONE``, or use the ``LANGUAGES`` keyword and list no languages,
to skip enabling any languages.
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index c0449fb..6e7f9b5 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -130,6 +130,16 @@ Variable Queries
``1`` if the CMake's compiler id of the CUDA compiler matches any one
of the entries in ``compiler_ids``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+``$<OBJC_COMPILER_ID:compiler_ids>``
+ where ``compiler_ids`` is a comma-separated list.
+ ``1`` if the CMake's compiler id of the Objective-C compiler matches any one
+ of the entries in ``compiler_ids``, otherwise ``0``.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+``$<OBJCXX_COMPILER_ID:compiler_ids>``
+ where ``compiler_ids`` is a comma-separated list.
+ ``1`` if the CMake's compiler id of the Objective-C++ compiler matches any one
+ of the entries in ``compiler_ids``, otherwise ``0``.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
``$<Fortran_COMPILER_ID:compiler_ids>``
where ``compiler_ids`` is a comma-separated list.
``1`` if the CMake's compiler id of the Fortran compiler matches any one
@@ -144,6 +154,12 @@ Variable Queries
``$<CUDA_COMPILER_VERSION:version>``
``1`` if the version of the CXX compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+``$<OBJC_COMPILER_VERSION:version>``
+ ``1`` if the version of the OBJC compiler matches ``version``, otherwise ``0``.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+``$<OBJCXX_COMPILER_VERSION:version>``
+ ``1`` if the version of the OBJCXX compiler matches ``version``, otherwise ``0``.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
``$<Fortran_COMPILER_VERSION:version>``
``1`` if the version of the Fortran compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
@@ -401,6 +417,12 @@ Variable Queries
``$<CUDA_COMPILER_ID>``
The CMake's compiler id of the CUDA compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+``$<OBJC_COMPILER_ID>``
+ The CMake's compiler id of the OBJC compiler used.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+``$<OBJCXX_COMPILER_ID>``
+ The CMake's compiler id of the OBJCXX compiler used.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
``$<Fortran_COMPILER_ID>``
The CMake's compiler id of the Fortran compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
@@ -413,6 +435,12 @@ Variable Queries
``$<CUDA_COMPILER_VERSION>``
The version of the CUDA compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+``$<OBJC_COMPILER_VERSION>``
+ The version of the OBJC compiler used.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+``$<OBJCXX_COMPILER_VERSION>``
+ The version of the OBJCXX compiler used.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
``$<Fortran_COMPILER_VERSION>``
The version of the Fortran compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst
index fc4bfdc..c60dc40 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -36,6 +36,12 @@ These modules are loaded using the :command:`include` command.
/module/CheckIncludeFiles
/module/CheckLanguage
/module/CheckLibraryExists
+ /module/CheckOBJCCompilerFlag
+ /module/CheckOBJCSourceCompiles
+ /module/CheckOBJCSourceRuns
+ /module/CheckOBJCXXCompilerFlag
+ /module/CheckOBJCXXSourceCompiles
+ /module/CheckOBJCXXSourceRuns
/module/CheckPIESupported
/module/CheckPrototypeDefinition
/module/CheckStructHasMember
diff --git a/Help/module/CheckOBJCCompilerFlag.rst b/Help/module/CheckOBJCCompilerFlag.rst
new file mode 100644
index 0000000..e4bd6fd
--- /dev/null
+++ b/Help/module/CheckOBJCCompilerFlag.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CheckOBJCCompilerFlag.cmake
diff --git a/Help/module/CheckOBJCSourceCompiles.rst b/Help/module/CheckOBJCSourceCompiles.rst
new file mode 100644
index 0000000..d4a1484
--- /dev/null
+++ b/Help/module/CheckOBJCSourceCompiles.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CheckOBJCSourceCompiles.cmake
diff --git a/Help/module/CheckOBJCSourceRuns.rst b/Help/module/CheckOBJCSourceRuns.rst
new file mode 100644
index 0000000..c72f0db
--- /dev/null
+++ b/Help/module/CheckOBJCSourceRuns.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CheckOBJCSourceRuns.cmake
diff --git a/Help/module/CheckOBJCXXCompilerFlag.rst b/Help/module/CheckOBJCXXCompilerFlag.rst
new file mode 100644
index 0000000..1518a48
--- /dev/null
+++ b/Help/module/CheckOBJCXXCompilerFlag.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CheckOBJCXXCompilerFlag.cmake
diff --git a/Help/module/CheckOBJCXXSourceCompiles.rst b/Help/module/CheckOBJCXXSourceCompiles.rst
new file mode 100644
index 0000000..a1c8ae9
--- /dev/null
+++ b/Help/module/CheckOBJCXXSourceCompiles.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CheckOBJCXXSourceCompiles.cmake
diff --git a/Help/module/CheckOBJCXXSourceRuns.rst b/Help/module/CheckOBJCXXSourceRuns.rst
new file mode 100644
index 0000000..5198e1b
--- /dev/null
+++ b/Help/module/CheckOBJCXXSourceRuns.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CheckOBJCXXSourceRuns.cmake
diff --git a/Help/release/dev/FPHSA-reason-failure-message.rst b/Help/release/dev/FPHSA-reason-failure-message.rst
new file mode 100644
index 0000000..419c3ba
--- /dev/null
+++ b/Help/release/dev/FPHSA-reason-failure-message.rst
@@ -0,0 +1,5 @@
+FPHSA-reason-failure-message
+----------------------------
+
+* Modules :module:`FindPackageHandleStandardArgs` gains the capability to
+ specify a message giving the reason for the failure.
diff --git a/Help/release/dev/objective-c-cxx.rst b/Help/release/dev/objective-c-cxx.rst
new file mode 100644
index 0000000..218af4e
--- /dev/null
+++ b/Help/release/dev/objective-c-cxx.rst
@@ -0,0 +1,9 @@
+Objective C/C++
+---------------
+
+* CMake learned to support the Objective C (``OBJC``) and Objective C++
+ (``OBJCXX``) languages. They may be enabled via the :command:`project`
+ and :command:`enable_language` commands. When ``OBJC`` or ``OBJCXX``
+ is enabled, source files with the ``.m`` or ``.mm``, respectively,
+ will be compiled as Objective C or C++. Otherwise they will be treated
+ as plain C++ sources as they were before.
diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in
index e7f0e70..ef65021 100644
--- a/Modules/CMakeCXXCompiler.cmake.in
+++ b/Modules/CMakeCXXCompiler.cmake.in
@@ -42,8 +42,17 @@ if(CMAKE_COMPILER_IS_MINGW)
set(MINGW 1)
endif()
set(CMAKE_CXX_COMPILER_ID_RUN 1)
+set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP)
set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
-set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP)
+
+foreach (lang OBJC OBJCXX)
+ if (CMAKE_${lang}_COMPILER_ID_RUN)
+ foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS)
+ list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension})
+ endforeach()
+ endif()
+endforeach()
+
set(CMAKE_CXX_LINKER_PREFERENCE 30)
set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1)
diff --git a/Modules/CMakeDetermineOBJCCompiler.cmake b/Modules/CMakeDetermineOBJCCompiler.cmake
new file mode 100644
index 0000000..ad13eab
--- /dev/null
+++ b/Modules/CMakeDetermineOBJCCompiler.cmake
@@ -0,0 +1,189 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+# determine the compiler to use for Objective-C programs
+# NOTE, a generator may set CMAKE_OBJC_COMPILER before
+# loading this file to force a compiler.
+# use environment variable OBJC first if defined by user, next use
+# the cmake variable CMAKE_GENERATOR_OBJC which can be defined by a generator
+# as a default compiler
+#
+# Sets the following variables:
+# CMAKE_OBJC_COMPILER
+# CMAKE_AR
+# CMAKE_RANLIB
+# CMAKE_COMPILER_IS_GNUOBJC
+# CMAKE_COMPILER_IS_CLANGOBJC
+#
+# If not already set before, it also sets
+# _CMAKE_TOOLCHAIN_PREFIX
+
+include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
+
+# Load system-specific compiler preferences for this language.
+include(Platform/${CMAKE_SYSTEM_NAME}-Determine-OBJC OPTIONAL)
+include(Platform/${CMAKE_SYSTEM_NAME}-OBJC OPTIONAL)
+if(NOT CMAKE_OBJC_COMPILER_NAMES)
+ set(CMAKE_OBJC_COMPILER_NAMES clang)
+endif()
+
+if("${CMAKE_GENERATOR}" MATCHES "Xcode")
+ set(CMAKE_OBJC_COMPILER_XCODE_TYPE sourcecode.c.objc)
+else()
+ if(NOT CMAKE_OBJC_COMPILER)
+ set(CMAKE_OBJC_COMPILER_INIT NOTFOUND)
+
+ # prefer the environment variable OBJC
+ if($ENV{OBJC} MATCHES ".+")
+ get_filename_component(CMAKE_OBJC_COMPILER_INIT $ENV{OBJC} PROGRAM PROGRAM_ARGS CMAKE_OBJC_FLAGS_ENV_INIT)
+ if(CMAKE_OBJC_FLAGS_ENV_INIT)
+ set(CMAKE_OBJC_COMPILER_ARG1 "${CMAKE_OBJC_FLAGS_ENV_INIT}" CACHE STRING "First argument to Objective-C compiler")
+ endif()
+ if(NOT EXISTS ${CMAKE_OBJC_COMPILER_INIT})
+ message(FATAL_ERROR "Could not find compiler set in environment variable OBJC:\n$ENV{OBJC}.")
+ endif()
+ endif()
+
+ # next try prefer the compiler specified by the generator
+ if(CMAKE_GENERATOR_OBJC)
+ if(NOT CMAKE_OBJC_COMPILER_INIT)
+ set(CMAKE_OBJC_COMPILER_INIT ${CMAKE_GENERATOR_OBJC})
+ endif()
+ endif()
+
+ # finally list compilers to try
+ if(NOT CMAKE_OBJC_COMPILER_INIT)
+ set(CMAKE_OBJC_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}cc ${_CMAKE_TOOLCHAIN_PREFIX}gcc clang)
+ endif()
+
+ _cmake_find_compiler(OBJC)
+
+ else()
+ # we only get here if CMAKE_OBJC_COMPILER was specified using -D or a pre-made CMakeCache.txt
+ # (e.g. via ctest) or set in CMAKE_TOOLCHAIN_FILE
+ # if CMAKE_OBJC_COMPILER is a list of length 2, use the first item as
+ # CMAKE_OBJC_COMPILER and the 2nd one as CMAKE_OBJC_COMPILER_ARG1
+
+ list(LENGTH CMAKE_OBJC_COMPILER _CMAKE_OBJC_COMPILER_LIST_LENGTH)
+ if("${_CMAKE_OBJC_COMPILER_LIST_LENGTH}" EQUAL 2)
+ list(GET CMAKE_OBJC_COMPILER 1 CMAKE_OBJC_COMPILER_ARG1)
+ list(GET CMAKE_OBJC_COMPILER 0 CMAKE_OBJC_COMPILER)
+ endif()
+
+ # if a compiler was specified by the user but without path,
+ # now try to find it with the full path
+ # if it is found, force it into the cache,
+ # if not, don't overwrite the setting (which was given by the user) with "NOTFOUND"
+ # if the C compiler already had a path, reuse it for searching the CXX compiler
+ get_filename_component(_CMAKE_USER_OBJC_COMPILER_PATH "${CMAKE_OBJC_COMPILER}" PATH)
+ if(NOT _CMAKE_USER_OBJC_COMPILER_PATH)
+ find_program(CMAKE_OBJC_COMPILER_WITH_PATH NAMES ${CMAKE_OBJC_COMPILER})
+ if(CMAKE_OBJC_COMPILER_WITH_PATH)
+ set(CMAKE_OBJC_COMPILER ${CMAKE_OBJC_COMPILER_WITH_PATH} CACHE STRING "Objective-C compiler" FORCE)
+ endif()
+ unset(CMAKE_OBJC_COMPILER_WITH_PATH CACHE)
+ endif()
+ endif()
+ mark_as_advanced(CMAKE_OBJC_COMPILER)
+
+ # Each entry in this list is a set of extra flags to try
+ # adding to the compile line to see if it helps produce
+ # a valid identification file.
+ set(CMAKE_OBJC_COMPILER_ID_TEST_FLAGS_FIRST)
+ set(CMAKE_OBJC_COMPILER_ID_TEST_FLAGS
+ # Try compiling to an object file only.
+ "-c"
+
+ )
+endif()
+
+# Build a small source file to identify the compiler.
+if(NOT CMAKE_OBJC_COMPILER_ID_RUN)
+ set(CMAKE_OBJC_COMPILER_ID_RUN 1)
+
+ # Try to identify the compiler.
+ set(CMAKE_OBJC_COMPILER_ID)
+ file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in
+ CMAKE_OBJC_COMPILER_ID_PLATFORM_CONTENT)
+
+ # Match the link line from xcodebuild output of the form
+ # Ld ...
+ # ...
+ # /path/to/cc ...CompilerIdOBJC/...
+ # to extract the compiler front-end for the language.
+ set(CMAKE_OBJC_COMPILER_ID_TOOL_MATCH_REGEX "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerIdOBJC/(\\./)?(CompilerIdOBJC.(framework|xctest)/)?CompilerIdOBJC[ \t\n\\\"]")
+ set(CMAKE_OBJC_COMPILER_ID_TOOL_MATCH_INDEX 2)
+
+ include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
+ CMAKE_DETERMINE_COMPILER_ID(OBJC OBJCCFLAGS CMakeOBJCCompilerId.m)
+
+ # Set old compiler and platform id variables.
+ if(CMAKE_OBJC_COMPILER_ID STREQUAL "GNU")
+ set(CMAKE_COMPILER_IS_GNUOBJC 1)
+ endif()
+ if(CMAKE_OBJC_COMPILER_ID STREQUAL "Clang")
+ set(CMAKE_COMPILER_IS_CLANGOBJC 1)
+ endif()
+endif()
+
+if (NOT _CMAKE_TOOLCHAIN_LOCATION)
+ get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_OBJC_COMPILER}" PATH)
+endif ()
+
+# If we have a gcc cross compiler, they have usually some prefix, like
+# e.g. powerpc-linux-gcc, arm-elf-gcc or i586-mingw32msvc-gcc, optionally
+# with a 3-component version number at the end (e.g. arm-eabi-gcc-4.5.2).
+# The other tools of the toolchain usually have the same prefix
+# NAME_WE cannot be used since then this test will fail for names like
+# "arm-unknown-nto-qnx6.3.0-gcc.exe", where BASENAME would be
+# "arm-unknown-nto-qnx6" instead of the correct "arm-unknown-nto-qnx6.3.0-"
+if (CMAKE_CROSSCOMPILING AND NOT _CMAKE_TOOLCHAIN_PREFIX)
+
+ if(CMAKE_OBJC_COMPILER_ID MATCHES "GNU|Clang|QCC")
+ get_filename_component(COMPILER_BASENAME "${CMAKE_OBJC_COMPILER}" NAME)
+ if (COMPILER_BASENAME MATCHES "^(.+-)(clang|g?cc)(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$")
+ set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
+ set(_CMAKE_COMPILER_SUFFIX ${CMAKE_MATCH_5})
+ elseif(CMAKE_OBJC_COMPILER_ID MATCHES "Clang")
+ if(CMAKE_OBJC_COMPILER_TARGET)
+ set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_OBJC_COMPILER_TARGET}-)
+ endif()
+ elseif(COMPILER_BASENAME MATCHES "qcc(\\.exe)?$")
+ if(CMAKE_OBJC_COMPILER_TARGET MATCHES "gcc_nto([a-z0-9]+_[0-9]+|[^_le]+)(le)?")
+ set(_CMAKE_TOOLCHAIN_PREFIX nto${CMAKE_MATCH_1}-)
+ endif()
+ endif ()
+
+ # if "llvm-" is part of the prefix, remove it, since llvm doesn't have its own binutils
+ # but uses the regular ar, objcopy, etc. (instead of llvm-objcopy etc.)
+ if ("${_CMAKE_TOOLCHAIN_PREFIX}" MATCHES "(.+-)?llvm-$")
+ set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
+ endif ()
+ endif()
+
+endif ()
+
+set(_CMAKE_PROCESSING_LANGUAGE "OBJC")
+include(CMakeFindBinUtils)
+include(Compiler/${CMAKE_OBJC_COMPILER_ID}-FindBinUtils OPTIONAL)
+unset(_CMAKE_PROCESSING_LANGUAGE)
+
+if(CMAKE_OBJC_COMPILER_ARCHITECTURE_ID)
+ set(_SET_CMAKE_OBJC_COMPILER_ARCHITECTURE_ID
+ "set(CMAKE_OBJC_COMPILER_ARCHITECTURE_ID ${CMAKE_OBJC_COMPILER_ARCHITECTURE_ID})")
+else()
+ set(_SET_CMAKE_OBJC_COMPILER_ARCHITECTURE_ID "")
+endif()
+
+if(CMAKE_OBJC_XCODE_ARCHS)
+ set(SET_CMAKE_XCODE_ARCHS
+ "set(CMAKE_XCODE_ARCHS \"${CMAKE_OBJC_XCODE_ARCHS}\")")
+endif()
+
+# configure variables set in this file for fast reload later on
+configure_file(${CMAKE_ROOT}/Modules/CMakeOBJCCompiler.cmake.in
+ ${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCCompiler.cmake
+ @ONLY
+ )
+set(CMAKE_OBJC_COMPILER_ENV_VAR "OBJC")
diff --git a/Modules/CMakeDetermineOBJCXXCompiler.cmake b/Modules/CMakeDetermineOBJCXXCompiler.cmake
new file mode 100644
index 0000000..60fcbb3
--- /dev/null
+++ b/Modules/CMakeDetermineOBJCXXCompiler.cmake
@@ -0,0 +1,197 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+# determine the compiler to use for Objective-C++ programs
+# NOTE, a generator may set CMAKE_OBJCXX_COMPILER before
+# loading this file to force a compiler.
+# use environment variable OBJCXX first if defined by user, next use
+# the cmake variable CMAKE_GENERATOR_OBJCXX which can be defined by a generator
+# as a default compiler
+# If the internal cmake variable _CMAKE_TOOLCHAIN_PREFIX is set, this is used
+# as prefix for the tools (e.g. arm-elf-g++, arm-elf-ar etc.)
+#
+# Sets the following variables:
+# CMAKE_OBJCXX_COMPILER
+# CMAKE_COMPILER_IS_GNUOBJCXX
+# CMAKE_COMPILER_IS_CLANGOBJCXX
+# CMAKE_AR
+# CMAKE_RANLIB
+#
+# If not already set before, it also sets
+# _CMAKE_TOOLCHAIN_PREFIX
+
+include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
+
+# Load system-specific compiler preferences for this language.
+include(Platform/${CMAKE_SYSTEM_NAME}-Determine-OBJCXX OPTIONAL)
+include(Platform/${CMAKE_SYSTEM_NAME}-OBJCXX OPTIONAL)
+if(NOT CMAKE_OBJCXX_COMPILER_NAMES)
+ set(CMAKE_OBJCXX_COMPILER_NAMES clang++)
+endif()
+
+if("${CMAKE_GENERATOR}" MATCHES "Xcode")
+ set(CMAKE_OBJCXX_COMPILER_XCODE_TYPE sourcecode.cpp.objcpp)
+else()
+ if(NOT CMAKE_OBJCXX_COMPILER)
+ set(CMAKE_OBJCXX_COMPILER_INIT NOTFOUND)
+
+ # prefer the environment variable OBJCXX
+ if($ENV{OBJCXX} MATCHES ".+")
+ get_filename_component(CMAKE_OBJCXX_COMPILER_INIT $ENV{OBJCXX} PROGRAM PROGRAM_ARGS CMAKE_OBJCXX_FLAGS_ENV_INIT)
+ if(CMAKE_OBJCXX_FLAGS_ENV_INIT)
+ set(CMAKE_OBJCXX_COMPILER_ARG1 "${CMAKE_OBJCXX_FLAGS_ENV_INIT}" CACHE STRING "First argument to Objective-C++ compiler")
+ endif()
+ if(NOT EXISTS ${CMAKE_OBJCXX_COMPILER_INIT})
+ message(FATAL_ERROR "Could not find compiler set in environment variable OBJCXX:\n$ENV{OBJCXX}.\n${CMAKE_OBJCXX_COMPILER_INIT}")
+ endif()
+ endif()
+
+ # next prefer the generator specified compiler
+ if(CMAKE_GENERATOR_OBJCXX)
+ if(NOT CMAKE_OBJCXX_COMPILER_INIT)
+ set(CMAKE_OBJCXX_COMPILER_INIT ${CMAKE_GENERATOR_OBJCXX})
+ endif()
+ endif()
+
+ # finally list compilers to try
+ if(NOT CMAKE_OBJCXX_COMPILER_INIT)
+ set(CMAKE_OBJCXX_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}c++ ${_CMAKE_TOOLCHAIN_PREFIX}g++ clang++)
+ endif()
+
+ _cmake_find_compiler(OBJCXX)
+
+ else()
+ # we only get here if CMAKE_OBJCXX_COMPILER was specified using -D or a pre-made CMakeCache.txt
+ # (e.g. via ctest) or set in CMAKE_TOOLCHAIN_FILE
+ # if CMAKE_OBJCXX_COMPILER is a list of length 2, use the first item as
+ # CMAKE_OBJCXX_COMPILER and the 2nd one as CMAKE_OBJCXX_COMPILER_ARG1
+
+ list(LENGTH CMAKE_OBJCXX_COMPILER _CMAKE_OBJCXX_COMPILER_LIST_LENGTH)
+ if("${_CMAKE_OBJCXX_COMPILER_LIST_LENGTH}" EQUAL 2)
+ list(GET CMAKE_OBJCXX_COMPILER 1 CMAKE_OBJCXX_COMPILER_ARG1)
+ list(GET CMAKE_OBJCXX_COMPILER 0 CMAKE_OBJCXX_COMPILER)
+ endif()
+
+ # if a compiler was specified by the user but without path,
+ # now try to find it with the full path
+ # if it is found, force it into the cache,
+ # if not, don't overwrite the setting (which was given by the user) with "NOTFOUND"
+ # if the C compiler already had a path, reuse it for searching the CXX compiler
+ get_filename_component(_CMAKE_USER_OBJCXX_COMPILER_PATH "${CMAKE_OBJCXX_COMPILER}" PATH)
+ if(NOT _CMAKE_USER_OBJCXX_COMPILER_PATH)
+ find_program(CMAKE_OBJCXX_COMPILER_WITH_PATH NAMES ${CMAKE_OBJCXX_COMPILER})
+ if(CMAKE_OBJCXX_COMPILER_WITH_PATH)
+ set(CMAKE_OBJCXX_COMPILER ${CMAKE_OBJCXX_COMPILER_WITH_PATH} CACHE STRING "Objective-C++ compiler" FORCE)
+ endif()
+ unset(CMAKE_OBJCXX_COMPILER_WITH_PATH CACHE)
+ endif()
+
+ endif()
+ mark_as_advanced(CMAKE_OBJCXX_COMPILER)
+
+ # Each entry in this list is a set of extra flags to try
+ # adding to the compile line to see if it helps produce
+ # a valid identification file.
+ set(CMAKE_OBJCXX_COMPILER_ID_TEST_FLAGS_FIRST)
+ set(CMAKE_OBJCXX_COMPILER_ID_TEST_FLAGS
+ # Try compiling to an object file only.
+ "-c"
+
+ # ARMClang need target options
+ "--target=arm-arm-none-eabi -mcpu=cortex-m3"
+ )
+endif()
+
+# Build a small source file to identify the compiler.
+if(NOT CMAKE_OBJCXX_COMPILER_ID_RUN)
+ set(CMAKE_OBJCXX_COMPILER_ID_RUN 1)
+
+ # Try to identify the compiler.
+ set(CMAKE_OBJCXX_COMPILER_ID)
+ file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in
+ CMAKE_OBJCXX_COMPILER_ID_PLATFORM_CONTENT)
+
+ # Match the link line from xcodebuild output of the form
+ # Ld ...
+ # ...
+ # /path/to/cc ...CompilerIdOBJCXX/...
+ # to extract the compiler front-end for the language.
+ set(CMAKE_OBJCXX_COMPILER_ID_TOOL_MATCH_REGEX "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerIdOBJCXX/(\\./)?(CompilerIdOBJCXX.(framework|xctest)/)?CompilerIdOBJCXX[ \t\n\\\"]")
+ set(CMAKE_OBJCXX_COMPILER_ID_TOOL_MATCH_INDEX 2)
+
+ include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
+ CMAKE_DETERMINE_COMPILER_ID(OBJCXX OBJCXXFLAGS CMakeOBJCXXCompilerId.mm)
+
+ # Set old compiler and platform id variables.
+ if(CMAKE_OBJCXX_COMPILER_ID MATCHES "GNU")
+ set(CMAKE_COMPILER_IS_GNUOBJCXX 1)
+ endif()
+ if(CMAKE_OBJCXX_COMPILER_ID MATCHES "Clang")
+ set(CMAKE_COMPILER_IS_CLANGOBJCXX 1)
+ endif()
+endif()
+
+if (NOT _CMAKE_TOOLCHAIN_LOCATION)
+ get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_OBJCXX_COMPILER}" PATH)
+endif ()
+
+# if we have a g++ cross compiler, they have usually some prefix, like
+# e.g. powerpc-linux-g++, arm-elf-g++ or i586-mingw32msvc-g++ , optionally
+# with a 3-component version number at the end (e.g. arm-eabi-gcc-4.5.2).
+# The other tools of the toolchain usually have the same prefix
+# NAME_WE cannot be used since then this test will fail for names like
+# "arm-unknown-nto-qnx6.3.0-gcc.exe", where BASENAME would be
+# "arm-unknown-nto-qnx6" instead of the correct "arm-unknown-nto-qnx6.3.0-"
+
+
+if (CMAKE_CROSSCOMPILING AND NOT _CMAKE_TOOLCHAIN_PREFIX)
+
+ if("${CMAKE_OBJCXX_COMPILER_ID}" MATCHES "GNU|Clang|QCC")
+ get_filename_component(COMPILER_BASENAME "${CMAKE_OBJCXX_COMPILER}" NAME)
+ if (COMPILER_BASENAME MATCHES "^(.+-)(clan)?[gc]\\+\\+(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$")
+ set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
+ set(_CMAKE_COMPILER_SUFFIX ${CMAKE_MATCH_5})
+ elseif("${CMAKE_OBJCXX_COMPILER_ID}" MATCHES "Clang")
+ if(CMAKE_OBJCXX_COMPILER_TARGET)
+ set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_OBJCXX_COMPILER_TARGET}-)
+ endif()
+ elseif(COMPILER_BASENAME MATCHES "QCC(\\.exe)?$")
+ if(CMAKE_OBJCXX_COMPILER_TARGET MATCHES "gcc_nto([a-z0-9]+_[0-9]+|[^_le]+)(le)")
+ set(_CMAKE_TOOLCHAIN_PREFIX nto${CMAKE_MATCH_1}-)
+ endif()
+ endif ()
+
+ # if "llvm-" is part of the prefix, remove it, since llvm doesn't have its own binutils
+ # but uses the regular ar, objcopy, etc. (instead of llvm-objcopy etc.)
+ if ("${_CMAKE_TOOLCHAIN_PREFIX}" MATCHES "(.+-)?llvm-$")
+ set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
+ endif ()
+ endif()
+
+endif ()
+
+set(_CMAKE_PROCESSING_LANGUAGE "OBJCXX")
+include(CMakeFindBinUtils)
+include(Compiler/${CMAKE_OBJCXX_COMPILER_ID}-FindBinUtils OPTIONAL)
+unset(_CMAKE_PROCESSING_LANGUAGE)
+
+if(CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID)
+ set(_SET_CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID
+ "set(CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID ${CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID})")
+else()
+ set(_SET_CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID "")
+endif()
+
+if(CMAKE_OBJCXX_XCODE_ARCHS)
+ set(SET_CMAKE_XCODE_ARCHS
+ "set(CMAKE_XCODE_ARCHS \"${CMAKE_OBJCXX_XCODE_ARCHS}\")")
+endif()
+
+# configure all variables set in this file
+configure_file(${CMAKE_ROOT}/Modules/CMakeOBJCXXCompiler.cmake.in
+ ${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCXXCompiler.cmake
+ @ONLY
+ )
+
+set(CMAKE_OBJCXX_COMPILER_ENV_VAR "OBJCXX")
diff --git a/Modules/CMakeOBJCCompiler.cmake.in b/Modules/CMakeOBJCCompiler.cmake.in
new file mode 100644
index 0000000..1555517
--- /dev/null
+++ b/Modules/CMakeOBJCCompiler.cmake.in
@@ -0,0 +1,69 @@
+set(CMAKE_OBJC_COMPILER "@CMAKE_OBJC_COMPILER@")
+set(CMAKE_OBJC_COMPILER_ARG1 "@CMAKE_OBJC_COMPILER_ARG1@")
+set(CMAKE_OBJC_COMPILER_ID "@CMAKE_OBJC_COMPILER_ID@")
+set(CMAKE_OBJC_COMPILER_VERSION "@CMAKE_OBJC_COMPILER_VERSION@")
+set(CMAKE_OBJC_COMPILER_VERSION_INTERNAL "@CMAKE_OBJC_COMPILER_VERSION_INTERNAL@")
+set(CMAKE_OBJC_COMPILER_WRAPPER "@CMAKE_OBJC_COMPILER_WRAPPER@")
+set(CMAKE_OBJC_STANDARD_COMPUTED_DEFAULT "@CMAKE_OBJC_STANDARD_COMPUTED_DEFAULT@")
+set(CMAKE_OBJC_COMPILE_FEATURES "@CMAKE_OBJC_COMPILE_FEATURES@")
+set(CMAKE_OBJC90_COMPILE_FEATURES "@CMAKE_OBJC90_COMPILE_FEATURES@")
+set(CMAKE_OBJC99_COMPILE_FEATURES "@CMAKE_OBJC99_COMPILE_FEATURES@")
+set(CMAKE_OBJC11_COMPILE_FEATURES "@CMAKE_OBJC11_COMPILE_FEATURES@")
+
+set(CMAKE_OBJC_PLATFORM_ID "@CMAKE_OBJC_PLATFORM_ID@")
+set(CMAKE_OBJC_SIMULATE_ID "@CMAKE_OBJC_SIMULATE_ID@")
+set(CMAKE_OBJC_COMPILER_FRONTEND_VARIANT "@CMAKE_OBJC_COMPILER_FRONTEND_VARIANT@")
+set(CMAKE_OBJC_SIMULATE_VERSION "@CMAKE_OBJC_SIMULATE_VERSION@")
+@_SET_CMAKE_OBJC_COMPILER_ARCHITECTURE_ID@
+@SET_CMAKE_XCODE_ARCHS@
+set(CMAKE_AR "@CMAKE_AR@")
+set(CMAKE_OBJC_COMPILER_AR "@CMAKE_OBJC_COMPILER_AR@")
+set(CMAKE_RANLIB "@CMAKE_RANLIB@")
+set(CMAKE_OBJC_COMPILER_RANLIB "@CMAKE_OBJC_COMPILER_RANLIB@")
+set(CMAKE_LINKER "@CMAKE_LINKER@")
+set(CMAKE_MT "@CMAKE_MT@")
+set(CMAKE_COMPILER_IS_GNUOBJC @CMAKE_COMPILER_IS_GNUOBJC@)
+set(CMAKE_OBJC_COMPILER_LOADED 1)
+set(CMAKE_OBJC_COMPILER_WORKS @CMAKE_OBJC_COMPILER_WORKS@)
+set(CMAKE_OBJC_ABI_COMPILED @CMAKE_OBJC_ABI_COMPILED@)
+
+set(CMAKE_OBJC_COMPILER_ENV_VAR "OBJC")
+
+set(CMAKE_OBJC_COMPILER_ID_RUN 1)
+set(CMAKE_OBJC_SOURCE_FILE_EXTENSIONS m)
+set(CMAKE_OBJC_IGNORE_EXTENSIONS h;H;o;O)
+set(CMAKE_OBJC_LINKER_PREFERENCE 5)
+
+foreach (lang C CXX OBJCXX)
+ foreach(extension IN LISTS CMAKE_OBJC_SOURCE_FILE_EXTENSIONS)
+ if (CMAKE_${lang}_COMPILER_ID_RUN)
+ list(REMOVE_ITEM CMAKE_${lang}_SOURCE_FILE_EXTENSIONS ${extension})
+ endif()
+ endforeach()
+endforeach()
+
+# Save compiler ABI information.
+set(CMAKE_OBJC_SIZEOF_DATA_PTR "@CMAKE_OBJC_SIZEOF_DATA_PTR@")
+set(CMAKE_OBJC_COMPILER_ABI "@CMAKE_OBJC_COMPILER_ABI@")
+set(CMAKE_OBJC_LIBRARY_ARCHITECTURE "@CMAKE_OBJC_LIBRARY_ARCHITECTURE@")
+
+if(CMAKE_OBJC_SIZEOF_DATA_PTR)
+ set(CMAKE_SIZEOF_VOID_P "${CMAKE_OBJC_SIZEOF_DATA_PTR}")
+endif()
+
+if(CMAKE_OBJC_COMPILER_ABI)
+ set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_OBJC_COMPILER_ABI}")
+endif()
+
+if(CMAKE_OBJC_LIBRARY_ARCHITECTURE)
+ set(CMAKE_LIBRARY_ARCHITECTURE "@CMAKE_OBJC_LIBRARY_ARCHITECTURE@")
+endif()
+
+@CMAKE_OBJC_COMPILER_CUSTOM_CODE@
+@CMAKE_OBJC_SYSROOT_FLAG_CODE@
+@CMAKE_OBJC_OSX_DEPLOYMENT_TARGET_FLAG_CODE@
+
+set(CMAKE_OBJC_IMPLICIT_INCLUDE_DIRECTORIES "@CMAKE_OBJC_IMPLICIT_INCLUDE_DIRECTORIES@")
+set(CMAKE_OBJC_IMPLICIT_LINK_LIBRARIES "@CMAKE_OBJC_IMPLICIT_LINK_LIBRARIES@")
+set(CMAKE_OBJC_IMPLICIT_LINK_DIRECTORIES "@CMAKE_OBJC_IMPLICIT_LINK_DIRECTORIES@")
+set(CMAKE_OBJC_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_OBJC_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@")
diff --git a/Modules/CMakeOBJCCompilerABI.m b/Modules/CMakeOBJCCompilerABI.m
new file mode 100644
index 0000000..8fa8511
--- /dev/null
+++ b/Modules/CMakeOBJCCompilerABI.m
@@ -0,0 +1,20 @@
+#ifdef __cplusplus
+# error "A C++ compiler has been selected for Objective-C."
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+#include "CMakeCompilerABI.h"
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+ int require = 0;
+ require += info_sizeof_dptr[argc];
+#if defined(ABI_ID)
+ require += info_abi[argc];
+#endif
+ (void)argv;
+ return require;
+}
diff --git a/Modules/CMakeOBJCCompilerId.m.in b/Modules/CMakeOBJCCompilerId.m.in
new file mode 100644
index 0000000..2b8aa30
--- /dev/null
+++ b/Modules/CMakeOBJCCompilerId.m.in
@@ -0,0 +1,63 @@
+#ifdef __cplusplus
+# error "An Objective-C++ compiler has been selected for Objective-C."
+#endif
+
+@CMAKE_OBJC_COMPILER_ID_CONTENT@
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+#ifdef SIMULATE_ID
+char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+#endif
+
+#ifdef __QNXNTO__
+char const* qnxnto = "INFO" ":" "qnxnto[]";
+#endif
+
+@CMAKE_OBJC_COMPILER_ID_PLATFORM_CONTENT@
+@CMAKE_OBJC_COMPILER_ID_ERROR_FOR_TEST@
+
+#if !defined(__STDC__)
+# if (defined(_MSC_VER) && !defined(__clang__)) \
+ || (defined(__ibmxl__) || defined(__IBMC__))
+# define C_DIALECT "90"
+# else
+# define C_DIALECT
+# endif
+#elif __STDC_VERSION__ >= 201000L
+# define C_DIALECT "11"
+#elif __STDC_VERSION__ >= 199901L
+# define C_DIALECT "99"
+#else
+# define C_DIALECT "90"
+#endif
+const char* info_language_dialect_default =
+ "INFO" ":" "dialect_default[" C_DIALECT "]";
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char* argv[])
+{
+ int require = 0;
+ require += info_compiler[argc];
+ require += info_platform[argc];
+ require += info_arch[argc];
+#ifdef COMPILER_VERSION_MAJOR
+ require += info_version[argc];
+#endif
+#ifdef COMPILER_VERSION_INTERNAL
+ require += info_version_internal[argc];
+#endif
+#ifdef SIMULATE_ID
+ require += info_simulate[argc];
+#endif
+#ifdef SIMULATE_VERSION_MAJOR
+ require += info_simulate_version[argc];
+#endif
+ require += info_language_dialect_default[argc];
+ (void)argv;
+ return require;
+}
diff --git a/Modules/CMakeOBJCInformation.cmake b/Modules/CMakeOBJCInformation.cmake
new file mode 100644
index 0000000..2baad4a
--- /dev/null
+++ b/Modules/CMakeOBJCInformation.cmake
@@ -0,0 +1,188 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+# This file sets the basic flags for the Objective-C language in CMake.
+# It also loads the available platform file for the system-compiler
+# if it exists.
+# It also loads a system - compiler - processor (or target hardware)
+# specific file, which is mainly useful for crosscompiling and embedded systems.
+
+include(CMakeLanguageInformation)
+
+# some compilers use different extensions (e.g. sdcc uses .rel)
+# so set the extension here first so it can be overridden by the compiler specific file
+set(CMAKE_OBJC_OUTPUT_EXTENSION .o)
+
+if(NOT CMAKE_INCLUDE_FLAG_OBJC)
+ set(CMAKE_INCLUDE_FLAG_OBJC ${CMAKE_INCLUDE_FLAG_C})
+endif()
+
+set(_INCLUDED_FILE 0)
+
+# Load compiler-specific information.
+if(CMAKE_OBJC_COMPILER_ID)
+ include(Compiler/${CMAKE_OBJC_COMPILER_ID}-OBJC OPTIONAL)
+endif()
+
+set(CMAKE_BASE_NAME)
+get_filename_component(CMAKE_BASE_NAME "${CMAKE_OBJC_COMPILER}" NAME_WE)
+if(CMAKE_COMPILER_IS_GNUOBJC)
+ set(CMAKE_BASE_NAME gcc)
+endif()
+
+
+# load a hardware specific file, mostly useful for embedded compilers
+if(CMAKE_SYSTEM_PROCESSOR)
+ if(CMAKE_OBJC_COMPILER_ID)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_OBJC_COMPILER_ID}-OBJC-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+ endif()
+ if (NOT _INCLUDED_FILE)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
+ endif ()
+endif()
+
+
+# load the system- and compiler specific files
+if(CMAKE_OBJC_COMPILER_ID)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_OBJC_COMPILER_ID}-OBJC
+ OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+endif()
+if (NOT _INCLUDED_FILE)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME}
+ OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+endif ()
+
+# load any compiler-wrapper specific information
+if (CMAKE_OBJC_COMPILER_WRAPPER)
+ __cmake_include_compiler_wrapper(OBJC)
+endif ()
+
+# We specify the compiler information in the system file for some
+# platforms, but this language may not have been enabled when the file
+# was first included. Include it again to get the language info.
+# Remove this when all compiler info is removed from system files.
+if (NOT _INCLUDED_FILE)
+ include(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL)
+endif ()
+
+if(CMAKE_OBJC_SIZEOF_DATA_PTR)
+ foreach(f ${CMAKE_OBJC_ABI_FILES})
+ include(${f})
+ endforeach()
+ unset(CMAKE_OBJC_ABI_FILES)
+endif()
+
+# This should be included before the _INIT variables are
+# used to initialize the cache. Since the rule variables
+# have if blocks on them, users can still define them here.
+# But, it should still be after the platform file so changes can
+# be made to those values.
+
+if(CMAKE_USER_MAKE_RULES_OVERRIDE)
+ # Save the full path of the file so try_compile can use it.
+ include(${CMAKE_USER_MAKE_RULES_OVERRIDE} RESULT_VARIABLE _override)
+ set(CMAKE_USER_MAKE_RULES_OVERRIDE "${_override}")
+endif()
+
+if(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJC)
+ # Save the full path of the file so try_compile can use it.
+ include(${CMAKE_USER_MAKE_RULES_OVERRIDE_OBJC} RESULT_VARIABLE _override)
+ set(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJC "${_override}")
+endif()
+
+
+# for most systems a module is the same as a shared library
+# so unless the variable CMAKE_MODULE_EXISTS is set just
+# copy the values from the LIBRARY variables
+if(NOT CMAKE_MODULE_EXISTS)
+ set(CMAKE_SHARED_MODULE_OBJC_FLAGS ${CMAKE_SHARED_LIBRARY_OBJC_FLAGS})
+ set(CMAKE_SHARED_MODULE_CREATE_OBJC_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS})
+endif()
+
+set(CMAKE_OBJC_FLAGS_INIT "$ENV{OBJCFLAGS} ${CMAKE_OBJC_FLAGS_INIT}")
+
+cmake_initialize_per_config_variable(CMAKE_OBJC_FLAGS "Flags used by the Objective-C compiler")
+
+if(CMAKE_OBJC_STANDARD_LIBRARIES_INIT)
+ set(CMAKE_OBJC_STANDARD_LIBRARIES "${CMAKE_OBJC_STANDARD_LIBRARIES_INIT}"
+ CACHE STRING "Libraries linked by default with all Objective-C applications.")
+ mark_as_advanced(CMAKE_OBJC_STANDARD_LIBRARIES)
+endif()
+
+include(CMakeCommonLanguageInclude)
+
+# now define the following rule variables
+
+# CMAKE_OBJC_CREATE_SHARED_LIBRARY
+# CMAKE_OBJC_CREATE_SHARED_MODULE
+# CMAKE_OBJC_COMPILE_OBJECT
+# CMAKE_OBJC_LINK_EXECUTABLE
+
+# variables supplied by the generator at use time
+# <TARGET>
+# <TARGET_BASE> the target without the suffix
+# <OBJECTS>
+# <OBJECT>
+# <LINK_LIBRARIES>
+# <FLAGS>
+# <LINK_FLAGS>
+
+# Objective-C compiler information
+# <CMAKE_OBJC_COMPILER>
+# <CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS>
+# <CMAKE_SHARED_MODULE_CREATE_OBJC_FLAGS>
+# <CMAKE_OBJC_LINK_FLAGS>
+
+# Static library tools
+# <CMAKE_AR>
+# <CMAKE_RANLIB>
+
+
+# create an Objective-C shared library
+if(NOT CMAKE_OBJC_CREATE_SHARED_LIBRARY)
+ set(CMAKE_OBJC_CREATE_SHARED_LIBRARY
+ "<CMAKE_OBJC_COMPILER> <CMAKE_SHARED_LIBRARY_OBJC_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
+endif()
+
+# create an Objective-C shared module just copy the shared library rule
+if(NOT CMAKE_OBJC_CREATE_SHARED_MODULE)
+ set(CMAKE_OBJC_CREATE_SHARED_MODULE ${CMAKE_OBJC_CREATE_SHARED_LIBRARY})
+endif()
+
+# Create an static archive incrementally for large object file counts.
+# If CMAKE_OBJC_CREATE_STATIC_LIBRARY is set it will override these.
+if(NOT DEFINED CMAKE_OBJC_ARCHIVE_CREATE)
+ set(CMAKE_OBJC_ARCHIVE_CREATE "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>")
+endif()
+if(NOT DEFINED CMAKE_OBJC_ARCHIVE_APPEND)
+ set(CMAKE_OBJC_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>")
+endif()
+if(NOT DEFINED CMAKE_OBJC_ARCHIVE_FINISH)
+ set(CMAKE_OBJC_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
+endif()
+
+# compile an Objective-C file into an object file
+if(NOT CMAKE_OBJC_COMPILE_OBJECT)
+ set(CMAKE_OBJC_COMPILE_OBJECT
+ "<CMAKE_OBJC_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
+endif()
+
+if(NOT CMAKE_OBJC_LINK_EXECUTABLE)
+ set(CMAKE_OBJC_LINK_EXECUTABLE
+ "<CMAKE_OBJC_COMPILER> <FLAGS> <CMAKE_OBJC_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RUNTIME_OBJC_FLAG)
+ set(CMAKE_EXECUTABLE_RUNTIME_OBJC_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJC_FLAG})
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RUNTIME_OBJC_FLAG_SEP)
+ set(CMAKE_EXECUTABLE_RUNTIME_OBJC_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJC_FLAG_SEP})
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RPATH_LINK_OBJC_FLAG)
+ set(CMAKE_EXECUTABLE_RPATH_LINK_OBJC_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJC_FLAG})
+endif()
+
+set(CMAKE_OBJC_INFORMATION_LOADED 1)
diff --git a/Modules/CMakeOBJCXXCompiler.cmake.in b/Modules/CMakeOBJCXXCompiler.cmake.in
new file mode 100644
index 0000000..b6452c4
--- /dev/null
+++ b/Modules/CMakeOBJCXXCompiler.cmake.in
@@ -0,0 +1,79 @@
+set(CMAKE_OBJCXX_COMPILER "@CMAKE_OBJCXX_COMPILER@")
+set(CMAKE_OBJCXX_COMPILER_ARG1 "@CMAKE_OBJCXX_COMPILER_ARG1@")
+set(CMAKE_OBJCXX_COMPILER_ID "@CMAKE_OBJCXX_COMPILER_ID@")
+set(CMAKE_OBJCXX_COMPILER_VERSION "@CMAKE_OBJCXX_COMPILER_VERSION@")
+set(CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL "@CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL@")
+set(CMAKE_OBJCXX_COMPILER_WRAPPER "@CMAKE_OBJCXX_COMPILER_WRAPPER@")
+set(CMAKE_OBJCXX_STANDARD_COMPUTED_DEFAULT "@CMAKE_OBJCXX_STANDARD_COMPUTED_DEFAULT@")
+set(CMAKE_OBJCXX_COMPILE_FEATURES "@CMAKE_OBJCXX_COMPILE_FEATURES@")
+set(CMAKE_OBJCXX98_COMPILE_FEATURES "@CMAKE_OBJCXX98_COMPILE_FEATURES@")
+set(CMAKE_OBJCXX11_COMPILE_FEATURES "@CMAKE_OBJCXX11_COMPILE_FEATURES@")
+set(CMAKE_OBJCXX14_COMPILE_FEATURES "@CMAKE_OBJCXX14_COMPILE_FEATURES@")
+set(CMAKE_OBJCXX17_COMPILE_FEATURES "@CMAKE_OBJCXX17_COMPILE_FEATURES@")
+set(CMAKE_OBJCXX20_COMPILE_FEATURES "@CMAKE_OBJCXX20_COMPILE_FEATURES@")
+
+set(CMAKE_OBJCXX_PLATFORM_ID "@CMAKE_OBJCXX_PLATFORM_ID@")
+set(CMAKE_OBJCXX_SIMULATE_ID "@CMAKE_OBJCXX_SIMULATE_ID@")
+set(CMAKE_OBJCXX_COMPILER_FRONTEND_VARIANT "@CMAKE_OBJCXX_COMPILER_FRONTEND_VARIANT@")
+set(CMAKE_OBJCXX_SIMULATE_VERSION "@CMAKE_OBJCXX_SIMULATE_VERSION@")
+@_SET_CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID@
+@SET_CMAKE_XCODE_ARCHS@
+set(CMAKE_AR "@CMAKE_AR@")
+set(CMAKE_OBJCXX_COMPILER_AR "@CMAKE_OBJCXX_COMPILER_AR@")
+set(CMAKE_RANLIB "@CMAKE_RANLIB@")
+set(CMAKE_OBJCXX_COMPILER_RANLIB "@CMAKE_OBJCXX_COMPILER_RANLIB@")
+set(CMAKE_LINKER "@CMAKE_LINKER@")
+set(CMAKE_MT "@CMAKE_MT@")
+set(CMAKE_COMPILER_IS_GNUOBJCXX @CMAKE_COMPILER_IS_GNUOBJCXX@)
+set(CMAKE_OBJCXX_COMPILER_LOADED 1)
+set(CMAKE_OBJCXX_COMPILER_WORKS @CMAKE_OBJCXX_COMPILER_WORKS@)
+set(CMAKE_OBJCXX_ABI_COMPILED @CMAKE_OBJCXX_ABI_COMPILED@)
+
+set(CMAKE_OBJCXX_COMPILER_ENV_VAR "OBJCXX")
+
+set(CMAKE_OBJCXX_COMPILER_ID_RUN 1)
+set(CMAKE_OBJCXX_SOURCE_FILE_EXTENSIONS M;m;mm)
+set(CMAKE_OBJCXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O)
+
+if (CMAKE_OBJC_COMPILER_ID_RUN)
+ foreach(extension IN LISTS CMAKE_OBJC_SOURCE_FILE_EXTENSIONS)
+ list(REMOVE_ITEM CMAKE_OBJCXX_SOURCE_FILE_EXTENSIONS ${extension})
+ endforeach()
+endif()
+
+foreach (lang C CXX OBJC)
+ foreach(extension IN LISTS CMAKE_OBJCXX_SOURCE_FILE_EXTENSIONS)
+ if (CMAKE_${lang}_COMPILER_ID_RUN)
+ list(REMOVE_ITEM CMAKE_${lang}_SOURCE_FILE_EXTENSIONS ${extension})
+ endif()
+ endforeach()
+endforeach()
+
+set(CMAKE_OBJCXX_LINKER_PREFERENCE 25)
+set(CMAKE_OBJCXX_LINKER_PREFERENCE_PROPAGATES 1)
+
+# Save compiler ABI information.
+set(CMAKE_OBJCXX_SIZEOF_DATA_PTR "@CMAKE_OBJCXX_SIZEOF_DATA_PTR@")
+set(CMAKE_OBJCXX_COMPILER_ABI "@CMAKE_OBJCXX_COMPILER_ABI@")
+set(CMAKE_OBJCXX_LIBRARY_ARCHITECTURE "@CMAKE_OBJCXX_LIBRARY_ARCHITECTURE@")
+
+if(CMAKE_OBJCXX_SIZEOF_DATA_PTR)
+ set(CMAKE_SIZEOF_VOID_P "${CMAKE_OBJCXX_SIZEOF_DATA_PTR}")
+endif()
+
+if(CMAKE_OBJCXX_COMPILER_ABI)
+ set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_OBJCXX_COMPILER_ABI}")
+endif()
+
+if(CMAKE_OBJCXX_LIBRARY_ARCHITECTURE)
+ set(CMAKE_LIBRARY_ARCHITECTURE "@CMAKE_OBJCXX_LIBRARY_ARCHITECTURE@")
+endif()
+
+@CMAKE_OBJCXX_COMPILER_CUSTOM_CODE@
+@CMAKE_OBJCXX_SYSROOT_FLAG_CODE@
+@CMAKE_OBJCXX_OSX_DEPLOYMENT_TARGET_FLAG_CODE@
+
+set(CMAKE_OBJCXX_IMPLICIT_INCLUDE_DIRECTORIES "@CMAKE_OBJCXX_IMPLICIT_INCLUDE_DIRECTORIES@")
+set(CMAKE_OBJCXX_IMPLICIT_LINK_LIBRARIES "@CMAKE_OBJCXX_IMPLICIT_LINK_LIBRARIES@")
+set(CMAKE_OBJCXX_IMPLICIT_LINK_DIRECTORIES "@CMAKE_OBJCXX_IMPLICIT_LINK_DIRECTORIES@")
+set(CMAKE_OBJCXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_OBJCXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@")
diff --git a/Modules/CMakeOBJCXXCompilerABI.mm b/Modules/CMakeOBJCXXCompilerABI.mm
new file mode 100644
index 0000000..288a58c
--- /dev/null
+++ b/Modules/CMakeOBJCXXCompilerABI.mm
@@ -0,0 +1,20 @@
+#ifndef __cplusplus
+# error "A C compiler has been selected for Objective-C++."
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+#include "CMakeCompilerABI.h"
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+ int require = 0;
+ require += info_sizeof_dptr[argc];
+#if defined(ABI_ID)
+ require += info_abi[argc];
+#endif
+ (void)argv;
+ return require;
+}
diff --git a/Modules/CMakeOBJCXXCompilerId.mm.in b/Modules/CMakeOBJCXXCompilerId.mm.in
new file mode 100644
index 0000000..fe04de1
--- /dev/null
+++ b/Modules/CMakeOBJCXXCompilerId.mm.in
@@ -0,0 +1,68 @@
+/* This source file must have a .cpp extension so that all C++ compilers
+ recognize the extension without flags. Borland does not know .cxx for
+ example. */
+#ifndef __cplusplus
+# error "An Objective-C compiler has been selected for Objective-C++."
+#endif
+
+@CMAKE_OBJCXX_COMPILER_ID_CONTENT@
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+#ifdef SIMULATE_ID
+char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+#endif
+
+#ifdef __QNXNTO__
+char const* qnxnto = "INFO" ":" "qnxnto[]";
+#endif
+
+@CMAKE_OBJCXX_COMPILER_ID_PLATFORM_CONTENT@
+@CMAKE_OBJCXX_COMPILER_ID_ERROR_FOR_TEST@
+
+#if defined(_MSC_VER) && defined(_MSVC_LANG)
+#define CXX_STD _MSVC_LANG
+#else
+#define CXX_STD __cplusplus
+#endif
+
+const char* info_language_dialect_default = "INFO" ":" "dialect_default["
+#if CXX_STD > 201703L
+ "20"
+#elif CXX_STD >= 201703L
+ "17"
+#elif CXX_STD >= 201402L
+ "14"
+#elif CXX_STD >= 201103L
+ "11"
+#else
+ "98"
+#endif
+"]";
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char* argv[])
+{
+ int require = 0;
+ require += info_compiler[argc];
+ require += info_platform[argc];
+#ifdef COMPILER_VERSION_MAJOR
+ require += info_version[argc];
+#endif
+#ifdef COMPILER_VERSION_INTERNAL
+ require += info_version_internal[argc];
+#endif
+#ifdef SIMULATE_ID
+ require += info_simulate[argc];
+#endif
+#ifdef SIMULATE_VERSION_MAJOR
+ require += info_simulate_version[argc];
+#endif
+ require += info_language_dialect_default[argc];
+ (void)argv;
+ return require;
+}
diff --git a/Modules/CMakeOBJCXXInformation.cmake b/Modules/CMakeOBJCXXInformation.cmake
new file mode 100644
index 0000000..3f55b01
--- /dev/null
+++ b/Modules/CMakeOBJCXXInformation.cmake
@@ -0,0 +1,273 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+# This file sets the basic flags for the Objective-C++ language in CMake.
+# It also loads the available platform file for the system-compiler
+# if it exists.
+# It also loads a system - compiler - processor (or target hardware)
+# specific file, which is mainly useful for crosscompiling and embedded systems.
+
+include(CMakeLanguageInformation)
+
+# some compilers use different extensions (e.g. sdcc uses .rel)
+# so set the extension here first so it can be overridden by the compiler specific file
+set(CMAKE_OBJCXX_OUTPUT_EXTENSION .o)
+
+set(_INCLUDED_FILE 0)
+
+# Load compiler-specific information.
+if(CMAKE_OBJCXX_COMPILER_ID)
+ include(Compiler/${CMAKE_OBJCXX_COMPILER_ID}-OBJCXX OPTIONAL)
+endif()
+
+set(CMAKE_BASE_NAME)
+get_filename_component(CMAKE_BASE_NAME "${CMAKE_OBJCXX_COMPILER}" NAME_WE)
+# since the gnu compiler has several names force g++
+if(CMAKE_COMPILER_IS_GNUOBJCXX)
+ set(CMAKE_BASE_NAME g++)
+endif()
+
+
+# load a hardware specific file, mostly useful for embedded compilers
+if(CMAKE_SYSTEM_PROCESSOR)
+ if(CMAKE_OBJCXX_COMPILER_ID)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_OBJCXX_COMPILER_ID}-OBJCXX-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+ endif()
+ if (NOT _INCLUDED_FILE)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
+ endif ()
+endif()
+
+# load the system- and compiler specific files
+if(CMAKE_OBJCXX_COMPILER_ID)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_OBJCXX_COMPILER_ID}-OBJCXX OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+endif()
+if (NOT _INCLUDED_FILE)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL
+ RESULT_VARIABLE _INCLUDED_FILE)
+endif ()
+
+# load any compiler-wrapper specific information
+if (CMAKE_OBJCXX_COMPILER_WRAPPER)
+ __cmake_include_compiler_wrapper(OBJCXX)
+endif ()
+
+# We specify the compiler information in the system file for some
+# platforms, but this language may not have been enabled when the file
+# was first included. Include it again to get the language info.
+# Remove this when all compiler info is removed from system files.
+if (NOT _INCLUDED_FILE)
+ include(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL)
+endif ()
+
+if(CMAKE_OBJCXX_SIZEOF_DATA_PTR)
+ foreach(f ${CMAKE_OBJCXX_ABI_FILES})
+ include(${f})
+ endforeach()
+ unset(CMAKE_OBJCXX_ABI_FILES)
+endif()
+
+# This should be included before the _INIT variables are
+# used to initialize the cache. Since the rule variables
+# have if blocks on them, users can still define them here.
+# But, it should still be after the platform file so changes can
+# be made to those values.
+
+if(CMAKE_USER_MAKE_RULES_OVERRIDE)
+ # Save the full path of the file so try_compile can use it.
+ include(${CMAKE_USER_MAKE_RULES_OVERRIDE} RESULT_VARIABLE _override)
+ set(CMAKE_USER_MAKE_RULES_OVERRIDE "${_override}")
+endif()
+
+if(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJCXX)
+ # Save the full path of the file so try_compile can use it.
+ include(${CMAKE_USER_MAKE_RULES_OVERRIDE_OBJCXX} RESULT_VARIABLE _override)
+ set(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJCXX "${_override}")
+endif()
+
+
+# Create a set of shared library variable specific to Objective-C++
+# For 90% of the systems, these are the same flags as the Objective-C versions
+# so if these are not set just copy the flags from the Objective-C version
+if(NOT CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS)
+ set(CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS})
+endif()
+
+if(NOT CMAKE_OBJCXX_COMPILE_OPTIONS_PIC)
+ set(CMAKE_OBJCXX_COMPILE_OPTIONS_PIC ${CMAKE_OBJC_COMPILE_OPTIONS_PIC})
+endif()
+
+if(NOT CMAKE_OBJCXX_COMPILE_OPTIONS_PIE)
+ set(CMAKE_OBJCXX_COMPILE_OPTIONS_PIE ${CMAKE_OBJC_COMPILE_OPTIONS_PIE})
+endif()
+if(NOT CMAKE_OBJCXX_LINK_OPTIONS_PIE)
+ set(CMAKE_OBJCXX_LINK_OPTIONS_PIE ${CMAKE_OBJC_LINK_OPTIONS_PIE})
+endif()
+if(NOT CMAKE_OBJCXX_LINK_OPTIONS_NO_PIE)
+ set(CMAKE_OBJCXX_LINK_OPTIONS_NO_PIE ${CMAKE_OBJC_LINK_OPTIONS_NO_PIE})
+endif()
+
+if(NOT CMAKE_OBJCXX_COMPILE_OPTIONS_DLL)
+ set(CMAKE_OBJCXX_COMPILE_OPTIONS_DLL ${CMAKE_OBJC_COMPILE_OPTIONS_DLL})
+endif()
+
+if(NOT CMAKE_SHARED_LIBRARY_OBJCXX_FLAGS)
+ set(CMAKE_SHARED_LIBRARY_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_OBJC_FLAGS})
+endif()
+
+if(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_OBJCXX_FLAGS)
+ set(CMAKE_SHARED_LIBRARY_LINK_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_LINK_OBJC_FLAGS})
+endif()
+
+if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG)
+ set(CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJC_FLAG})
+endif()
+
+if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG_SEP)
+ set(CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJC_FLAG_SEP})
+endif()
+
+if(NOT CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJCXX_FLAG)
+ set(CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJC_FLAG})
+endif()
+
+if(NOT DEFINED CMAKE_EXE_EXPORTS_OBJCXX_FLAG)
+ set(CMAKE_EXE_EXPORTS_OBJCXX_FLAG ${CMAKE_EXE_EXPORTS_OBJC_FLAG})
+endif()
+
+if(NOT DEFINED CMAKE_SHARED_LIBRARY_SONAME_OBJCXX_FLAG)
+ set(CMAKE_SHARED_LIBRARY_SONAME_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_SONAME_OBJC_FLAG})
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RUNTIME_OBJCXX_FLAG)
+ set(CMAKE_EXECUTABLE_RUNTIME_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG})
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RUNTIME_OBJCXX_FLAG_SEP)
+ set(CMAKE_EXECUTABLE_RUNTIME_OBJCXX_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG_SEP})
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RPATH_LINK_OBJCXX_FLAG)
+ set(CMAKE_EXECUTABLE_RPATH_LINK_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJCXX_FLAG})
+endif()
+
+if(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_OBJCXX_WITH_RUNTIME_PATH)
+ set(CMAKE_SHARED_LIBRARY_LINK_OBJCXX_WITH_RUNTIME_PATH ${CMAKE_SHARED_LIBRARY_LINK_OBJC_WITH_RUNTIME_PATH})
+endif()
+
+if(NOT CMAKE_INCLUDE_FLAG_OBJCXX)
+ set(CMAKE_INCLUDE_FLAG_OBJCXX ${CMAKE_INCLUDE_FLAG_C})
+endif()
+
+# for most systems a module is the same as a shared library
+# so unless the variable CMAKE_MODULE_EXISTS is set just
+# copy the values from the LIBRARY variables
+if(NOT CMAKE_MODULE_EXISTS)
+ set(CMAKE_SHARED_MODULE_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_OBJCXX_FLAGS})
+ set(CMAKE_SHARED_MODULE_CREATE_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS})
+endif()
+
+# repeat for modules
+if(NOT CMAKE_SHARED_MODULE_CREATE_OBJCXX_FLAGS)
+ set(CMAKE_SHARED_MODULE_CREATE_OBJCXX_FLAGS ${CMAKE_SHARED_MODULE_CREATE_OBJC_FLAGS})
+endif()
+
+if(NOT CMAKE_SHARED_MODULE_OBJCXX_FLAGS)
+ set(CMAKE_SHARED_MODULE_OBJCXX_FLAGS ${CMAKE_SHARED_MODULE_OBJC_FLAGS})
+endif()
+
+# Initialize OBJCXX link type selection flags from OBJC versions.
+foreach(type SHARED_LIBRARY SHARED_MODULE EXE)
+ if(NOT CMAKE_${type}_LINK_STATIC_OBJCXX_FLAGS)
+ set(CMAKE_${type}_LINK_STATIC_OBJCXX_FLAGS
+ ${CMAKE_${type}_LINK_STATIC_OBJC_FLAGS})
+ endif()
+ if(NOT CMAKE_${type}_LINK_DYNAMIC_OBJCXX_FLAGS)
+ set(CMAKE_${type}_LINK_DYNAMIC_OBJCXX_FLAGS
+ ${CMAKE_${type}_LINK_DYNAMIC_OBJC_FLAGS})
+ endif()
+endforeach()
+
+# add the flags to the cache based
+# 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_OBJCXX_FLAGS_INIT "$ENV{OBJCXXFLAGS} ${CMAKE_OBJCXX_FLAGS_INIT}")
+
+cmake_initialize_per_config_variable(CMAKE_OBJCXX_FLAGS "Flags used by the Objective-C++ compiler")
+
+if(CMAKE_OBJCXX_STANDARD_LIBRARIES_INIT)
+ set(CMAKE_OBJCXX_STANDARD_LIBRARIES "${CMAKE_OBJCXX_STANDARD_LIBRARIES_INIT}"
+ CACHE STRING "Libraries linked by default with all Objective-C++ applications.")
+ mark_as_advanced(CMAKE_OBJCXX_STANDARD_LIBRARIES)
+endif()
+
+include(CMakeCommonLanguageInclude)
+
+# now define the following rules:
+# CMAKE_OBJCXX_CREATE_SHARED_LIBRARY
+# CMAKE_OBJCXX_CREATE_SHARED_MODULE
+# CMAKE_OBJCXX_COMPILE_OBJECT
+# CMAKE_OBJCXX_LINK_EXECUTABLE
+
+# variables supplied by the generator at use time
+# <TARGET>
+# <TARGET_BASE> the target without the suffix
+# <OBJECTS>
+# <OBJECT>
+# <LINK_LIBRARIES>
+# <FLAGS>
+# <LINK_FLAGS>
+
+# Objective-C++ compiler information
+# <CMAKE_OBJCXX_COMPILER>
+# <CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS>
+# <CMAKE_OBJCXX_SHARED_MODULE_CREATE_FLAGS>
+# <CMAKE_OBJCXX_LINK_FLAGS>
+
+# Static library tools
+# <CMAKE_AR>
+# <CMAKE_RANLIB>
+
+
+# create a shared Objective-C++ library
+if(NOT CMAKE_OBJCXX_CREATE_SHARED_LIBRARY)
+ set(CMAKE_OBJCXX_CREATE_SHARED_LIBRARY
+ "<CMAKE_OBJCXX_COMPILER> <CMAKE_SHARED_LIBRARY_OBJCXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
+endif()
+
+# create an Objective-C++ shared module copy the shared library rule by default
+if(NOT CMAKE_OBJCXX_CREATE_SHARED_MODULE)
+ set(CMAKE_OBJCXX_CREATE_SHARED_MODULE ${CMAKE_OBJCXX_CREATE_SHARED_LIBRARY})
+endif()
+
+
+# Create a static archive incrementally for large object file counts.
+# If CMAKE_OBJCXX_CREATE_STATIC_LIBRARY is set it will override these.
+if(NOT DEFINED CMAKE_OBJCXX_ARCHIVE_CREATE)
+ set(CMAKE_OBJCXX_ARCHIVE_CREATE "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>")
+endif()
+if(NOT DEFINED CMAKE_OBJCXX_ARCHIVE_APPEND)
+ set(CMAKE_OBJCXX_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>")
+endif()
+if(NOT DEFINED CMAKE_OBJCXX_ARCHIVE_FINISH)
+ set(CMAKE_OBJCXX_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
+endif()
+
+# compile an Objective-C++ file into an object file
+if(NOT CMAKE_OBJCXX_COMPILE_OBJECT)
+ set(CMAKE_OBJCXX_COMPILE_OBJECT
+ "<CMAKE_OBJCXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
+endif()
+
+if(NOT CMAKE_OBJCXX_LINK_EXECUTABLE)
+ set(CMAKE_OBJCXX_LINK_EXECUTABLE
+ "<CMAKE_OBJCXX_COMPILER> <FLAGS> <CMAKE_OBJCXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
+endif()
+
+mark_as_advanced(
+CMAKE_VERBOSE_MAKEFILE
+)
+
+set(CMAKE_OBJCXX_INFORMATION_LOADED 1)
diff --git a/Modules/CMakeTestOBJCCompiler.cmake b/Modules/CMakeTestOBJCCompiler.cmake
new file mode 100644
index 0000000..0030683
--- /dev/null
+++ b/Modules/CMakeTestOBJCCompiler.cmake
@@ -0,0 +1,94 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+if(CMAKE_OBJC_COMPILER_FORCED)
+ # The compiler configuration was forced by the user.
+ # Assume the user has configured all compiler information.
+ set(CMAKE_OBJC_COMPILER_WORKS TRUE)
+ return()
+endif()
+
+include(CMakeTestCompilerCommon)
+
+# work around enforced code signing and / or missing exectuable target type
+set(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE ${CMAKE_TRY_COMPILE_TARGET_TYPE})
+if(_CMAKE_FEATURE_DETECTION_TARGET_TYPE)
+ set(CMAKE_TRY_COMPILE_TARGET_TYPE ${_CMAKE_FEATURE_DETECTION_TARGET_TYPE})
+endif()
+
+# Remove any cached result from an older CMake version.
+# We now store this in CMakeCCompiler.cmake.
+unset(CMAKE_OBJC_COMPILER_WORKS CACHE)
+
+# This file is used by EnableLanguage in cmGlobalGenerator to
+# determine that that selected Objective-C compiler can actually compile
+# and link the most basic of programs. If not, a fatal error
+# is set and cmake stops processing commands and will not generate
+# any makefiles or projects.
+if(NOT CMAKE_OBJC_COMPILER_WORKS)
+ PrintTestCompilerStatus("OBJC" "")
+ __TestCompiler_setTryCompileTargetType()
+ file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCCompiler.m
+ "#ifdef __cplusplus\n"
+ "# error \"The CMAKE_OBJC_COMPILER is set to a C++ compiler\"\n"
+ "#endif\n"
+ "#ifndef __OBJC__\n"
+ "# error \"The CMAKE_OBJC_COMPILER is not an Objective-C compiler\"\n"
+ "#endif\n"
+ "int main(int argc, char* argv[])\n"
+ "{ (void)argv; return argc-1;}\n")
+ try_compile(CMAKE_OBJC_COMPILER_WORKS ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCCompiler.m
+ OUTPUT_VARIABLE __CMAKE_OBJC_COMPILER_OUTPUT)
+ # Move result from cache to normal variable.
+ set(CMAKE_OBJC_COMPILER_WORKS ${CMAKE_OBJC_COMPILER_WORKS})
+ unset(CMAKE_OBJC_COMPILER_WORKS CACHE)
+ set(OBJC_TEST_WAS_RUN 1)
+ __TestCompiler_restoreTryCompileTargetType()
+endif()
+
+if(NOT CMAKE_OBJC_COMPILER_WORKS)
+ PrintTestCompilerStatus("OBJC" " -- broken")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Determining if the Objective-C compiler works failed with "
+ "the following output:\n${__CMAKE_OBJC_COMPILER_OUTPUT}\n\n")
+ string(REPLACE "\n" "\n " _output "${__CMAKE_OBJC_COMPILER_OUTPUT}")
+ message(FATAL_ERROR "The Objective-C compiler\n \"${CMAKE_OBJC_COMPILER}\"\n"
+ "is not able to compile a simple test program.\nIt fails "
+ "with the following output:\n ${_output}\n\n"
+ "CMake will not be able to correctly generate this project.")
+else()
+ if(OBJC_TEST_WAS_RUN)
+ PrintTestCompilerStatus("OBJC" " -- works")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determining if the Objective-C compiler works passed with "
+ "the following output:\n${__CMAKE_OBJC_COMPILER_OUTPUT}\n\n")
+ endif()
+
+ # Try to identify the ABI and configure it into CMakeOBJCCompiler.cmake
+ include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
+ CMAKE_DETERMINE_COMPILER_ABI(OBJC ${CMAKE_ROOT}/Modules/CMakeOBJCCompilerABI.m)
+ # Try to identify the compiler features
+ include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake)
+ CMAKE_DETERMINE_COMPILE_FEATURES(OBJC)
+
+ # Re-configure to save learned information.
+ configure_file(
+ ${CMAKE_ROOT}/Modules/CMakeOBJCCompiler.cmake.in
+ ${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCCompiler.cmake
+ @ONLY
+ )
+ include(${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCCompiler.cmake)
+
+ if(CMAKE_OBJC_SIZEOF_DATA_PTR)
+ foreach(f ${CMAKE_OBJC_ABI_FILES})
+ include(${f})
+ endforeach()
+ unset(CMAKE_OBJC_ABI_FILES)
+ endif()
+endif()
+
+set(CMAKE_TRY_COMPILE_TARGET_TYPE ${__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE})
+unset(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE)
+unset(__CMAKE_OBJC_COMPILER_OUTPUT)
diff --git a/Modules/CMakeTestOBJCXXCompiler.cmake b/Modules/CMakeTestOBJCXXCompiler.cmake
new file mode 100644
index 0000000..bcce2f1
--- /dev/null
+++ b/Modules/CMakeTestOBJCXXCompiler.cmake
@@ -0,0 +1,93 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+if(CMAKE_OBJCXX_COMPILER_FORCED)
+ # The compiler configuration was forced by the user.
+ # Assume the user has configured all compiler information.
+ set(CMAKE_OBJCXX_COMPILER_WORKS TRUE)
+ return()
+endif()
+
+include(CMakeTestCompilerCommon)
+
+# work around enforced code signing and / or missing exectuable target type
+set(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE ${CMAKE_TRY_COMPILE_TARGET_TYPE})
+if(_CMAKE_FEATURE_DETECTION_TARGET_TYPE)
+ set(CMAKE_TRY_COMPILE_TARGET_TYPE ${_CMAKE_FEATURE_DETECTION_TARGET_TYPE})
+endif()
+
+# Remove any cached result from an older CMake version.
+# We now store this in CMakeOBJCXXCompiler.cmake.
+unset(CMAKE_OBJCXX_COMPILER_WORKS CACHE)
+
+# This file is used by EnableLanguage in cmGlobalGenerator to
+# determine that the selected Objective-C++ compiler can actually compile
+# and link the most basic of programs. If not, a fatal error
+# is set and cmake stops processing commands and will not generate
+# any makefiles or projects.
+if(NOT CMAKE_OBJCXX_COMPILER_WORKS)
+ PrintTestCompilerStatus("OBJCXX" "")
+ __TestCompiler_setTryCompileTargetType()
+ file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCXXCompiler.mm
+ "#ifndef __cplusplus\n"
+ "# error \"The CMAKE_OBJCXX_COMPILER is set to a C compiler\"\n"
+ "#endif\n"
+ "#ifndef __OBJC__\n"
+ "# error \"The CMAKE_OBJCXX_COMPILER is not an Objective-C++ compiler\"\n"
+ "#endif\n"
+ "int main(){return 0;}\n")
+ try_compile(CMAKE_OBJCXX_COMPILER_WORKS ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCXXCompiler.mm
+ OUTPUT_VARIABLE __CMAKE_OBJCXX_COMPILER_OUTPUT)
+ # Move result from cache to normal variable.
+ set(CMAKE_OBJCXX_COMPILER_WORKS ${CMAKE_OBJCXX_COMPILER_WORKS})
+ unset(CMAKE_OBJCXX_COMPILER_WORKS CACHE)
+ set(OBJCXX_TEST_WAS_RUN 1)
+ __TestCompiler_restoreTryCompileTargetType()
+endif()
+
+if(NOT CMAKE_OBJCXX_COMPILER_WORKS)
+ PrintTestCompilerStatus("OBJCXX" " -- broken")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Determining if the Objective-C++ compiler works failed with "
+ "the following output:\n${__CMAKE_OBJCXX_COMPILER_OUTPUT}\n\n")
+ string(REPLACE "\n" "\n " _output "${__CMAKE_OBJCXX_COMPILER_OUTPUT}")
+ message(FATAL_ERROR "The Objective-C++ compiler\n \"${CMAKE_OBJCXX_COMPILER}\"\n"
+ "is not able to compile a simple test program.\nIt fails "
+ "with the following output:\n ${_output}\n\n"
+ "CMake will not be able to correctly generate this project.")
+else()
+ if(OBJCXX_TEST_WAS_RUN)
+ PrintTestCompilerStatus("OBJCXX" " -- works")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determining if the Objective-C++ compiler works passed with "
+ "the following output:\n${__CMAKE_OBJCXX_COMPILER_OUTPUT}\n\n")
+ endif()
+
+ # Try to identify the ABI and configure it into CMakeOBJCXXCompiler.cmake
+ include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
+ CMAKE_DETERMINE_COMPILER_ABI(OBJCXX ${CMAKE_ROOT}/Modules/CMakeOBJCXXCompilerABI.mm)
+ # Try to identify the compiler features
+ include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake)
+ CMAKE_DETERMINE_COMPILE_FEATURES(OBJCXX)
+
+ # Re-configure to save learned information.
+ configure_file(
+ ${CMAKE_ROOT}/Modules/CMakeOBJCXXCompiler.cmake.in
+ ${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCXXCompiler.cmake
+ @ONLY
+ )
+ include(${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCXXCompiler.cmake)
+
+ if(CMAKE_OBJCXX_SIZEOF_DATA_PTR)
+ foreach(f ${CMAKE_OBJCXX_ABI_FILES})
+ include(${f})
+ endforeach()
+ unset(CMAKE_OBJCXX_ABI_FILES)
+ endif()
+endif()
+
+set(CMAKE_TRY_COMPILE_TARGET_TYPE ${__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE})
+unset(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE)
+unset(__CMAKE_OBJCXX_COMPILER_OUTPUT)
diff --git a/Modules/CheckOBJCCompilerFlag.cmake b/Modules/CheckOBJCCompilerFlag.cmake
new file mode 100644
index 0000000..1d975da
--- /dev/null
+++ b/Modules/CheckOBJCCompilerFlag.cmake
@@ -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.
+
+#[=======================================================================[.rst:
+CheckOBJCCompilerFlag
+---------------------
+
+Check whether the Objective-C compiler supports a given flag.
+
+.. command:: check_objc_compiler_flag
+
+ .. code-block:: cmake
+
+ check_objc_compiler_flag(<flag> <var>)
+
+ Check that the ``<flag>`` is accepted by the compiler without
+ a diagnostic. Stores the result in an internal cache entry
+ named ``<var>``.
+
+This command temporarily sets the ``CMAKE_REQUIRED_DEFINITIONS`` variable
+and calls the ``check_objc_source_compiles`` macro from the
+:module:`CheckOBJCSourceCompiles` module. See documentation of that
+module for a listing of variables that can otherwise modify the build.
+
+A positive result from this check indicates only that the compiler did not
+issue a diagnostic message when given the flag. Whether the flag has any
+effect or even a specific one is beyond the scope of this module.
+
+.. note::
+ Since the :command:`try_compile` command forwards flags from variables
+ like :variable:`CMAKE_OBJC_FLAGS <CMAKE_<LANG>_FLAGS>`, unknown flags
+ in such variables may cause a false negative for this check.
+#]=======================================================================]
+
+include_guard(GLOBAL)
+include(CheckOBJCSourceCompiles)
+include(CMakeCheckCompilerFlagCommonPatterns)
+
+macro (CHECK_OBJC_COMPILER_FLAG _FLAG _RESULT)
+ set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
+ set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
+
+ # Normalize locale during test compilation.
+ set(_CheckOBJCCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG)
+ foreach(v ${_CheckOBJCCompilerFlag_LOCALE_VARS})
+ set(_CheckOBJCCompilerFlag_SAVED_${v} "$ENV{${v}}")
+ set(ENV{${v}} OBJC)
+ endforeach()
+ CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckOBJCCompilerFlag_COMMON_PATTERNS)
+ CHECK_OBJC_SOURCE_COMPILES("#ifndef __OBJC__\n# error \"Not an Objective-C compiler\"\n#endif\nint main(void) { return 0; }" ${_RESULT}
+ # Some compilers do not fail with a bad flag
+ FAIL_REGEX "command line option .* is valid for .* but not for Objective-C" # GNU
+ FAIL_REGEX "argument unused during compilation: .*" # Clang
+ ${_CheckOBJCCompilerFlag_COMMON_PATTERNS}
+ )
+ foreach(v ${_CheckOBJCCompilerFlag_LOCALE_VARS})
+ set(ENV{${v}} ${_CheckOBJCCompilerFlag_SAVED_${v}})
+ unset(_CheckOBJCCompilerFlag_SAVED_${v})
+ endforeach()
+ unset(_CheckOBJCCompilerFlag_LOCALE_VARS)
+ unset(_CheckOBJCCompilerFlag_COMMON_PATTERNS)
+
+ set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
+endmacro ()
diff --git a/Modules/CheckOBJCSourceCompiles.cmake b/Modules/CheckOBJCSourceCompiles.cmake
new file mode 100644
index 0000000..a4676ad
--- /dev/null
+++ b/Modules/CheckOBJCSourceCompiles.cmake
@@ -0,0 +1,145 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CheckOBJCSourceCompiles
+-----------------------
+
+Check if given Objective-C source compiles and links into an executable.
+
+.. command:: check_objc_source_compiles
+
+ .. code-block:: cmake
+
+ check_objc_source_compiles(<code> <resultVar>
+ [FAIL_REGEX <regex1> [<regex2>...]])
+
+ Check that the source supplied in ``<code>`` can be compiled as a Objectie-C source
+ file and linked as an executable (so it must contain at least a ``main()``
+ function). The result will be stored in the internal cache variable specified
+ by ``<resultVar>``, with a boolean true value for success and boolean false
+ for failure. If ``FAIL_REGEX`` is provided, then failure is determined by
+ checking if anything in the output matches any of the specified regular
+ expressions.
+
+ The underlying check is performed by the :command:`try_compile` command. The
+ compile and link commands can be influenced by setting any of the following
+ variables prior to calling ``check_objc_source_compiles()``:
+
+ ``CMAKE_REQUIRED_FLAGS``
+ Additional flags to pass to the compiler. Note that the contents of
+ :variable:`CMAKE_OBJC_FLAGS <CMAKE_<LANG>_FLAGS>` and its associated
+ configuration-specific variable are automatically added to the compiler
+ command before the contents of ``CMAKE_REQUIRED_FLAGS``.
+
+ ``CMAKE_REQUIRED_DEFINITIONS``
+ A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form
+ ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by
+ ``<resultVar>`` will also be added automatically.
+
+ ``CMAKE_REQUIRED_INCLUDES``
+ A :ref:`;-list <CMake Language Lists>` of header search paths to pass to
+ the compiler. These will be the only header search paths used by
+ ``try_compile()``, i.e. the contents of the :prop_dir:`INCLUDE_DIRECTORIES`
+ directory property will be ignored.
+
+ ``CMAKE_REQUIRED_LINK_OPTIONS``
+ A :ref:`;-list <CMake Language Lists>` of options to add to the link
+ command (see :command:`try_compile` for further details).
+
+ ``CMAKE_REQUIRED_LIBRARIES``
+ A :ref:`;-list <CMake Language Lists>` of libraries to add to the link
+ command. These can be the name of system libraries or they can be
+ :ref:`Imported Targets <Imported Targets>` (see :command:`try_compile` for
+ further details).
+
+ ``CMAKE_REQUIRED_QUIET``
+ If this variable evaluates to a boolean true value, all status messages
+ associated with the check will be suppressed.
+
+ The check is only performed once, with the result cached in the variable
+ named by ``<resultVar>``. Every subsequent CMake run will re-use this cached
+ value rather than performing the check again, even if the ``<code>`` changes.
+ In order to force the check to be re-evaluated, the variable named by
+ ``<resultVar>`` must be manually removed from the cache.
+
+#]=======================================================================]
+
+include_guard(GLOBAL)
+
+macro(CHECK_OBJC_SOURCE_COMPILES SOURCE VAR)
+ if(NOT DEFINED "${VAR}")
+ set(_FAIL_REGEX)
+ set(_key)
+ foreach(arg ${ARGN})
+ if("${arg}" MATCHES "^(FAIL_REGEX)$")
+ set(_key "${arg}")
+ elseif(_key)
+ list(APPEND _${_key} "${arg}")
+ else()
+ message(FATAL_ERROR "Unknown argument:\n ${arg}\n")
+ endif()
+ endforeach()
+ set(MACRO_CHECK_FUNCTION_DEFINITIONS
+ "-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
+ if(CMAKE_REQUIRED_LINK_OPTIONS)
+ set(CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS
+ LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS})
+ else()
+ set(CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS)
+ endif()
+ if(CMAKE_REQUIRED_LIBRARIES)
+ set(CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES
+ LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+ else()
+ set(CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES)
+ endif()
+ if(CMAKE_REQUIRED_INCLUDES)
+ set(CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES
+ "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
+ else()
+ set(CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES)
+ endif()
+ file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.m"
+ "${SOURCE}\n")
+
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Performing Test ${VAR}")
+ endif()
+ try_compile(${VAR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.m
+ COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ ${CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS}
+ ${CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES}
+ CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
+ "${CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES}"
+ OUTPUT_VARIABLE OUTPUT)
+
+ foreach(_regex ${_FAIL_REGEX})
+ if("${OUTPUT}" MATCHES "${_regex}")
+ set(${VAR} 0)
+ endif()
+ endforeach()
+
+ if(${VAR})
+ set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Performing Test ${VAR} - Success")
+ endif()
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Performing Objective-C SOURCE FILE Test ${VAR} succeeded with the following output:\n"
+ "${OUTPUT}\n"
+ "Source file was:\n${SOURCE}\n")
+ else()
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Performing Test ${VAR} - Failed")
+ endif()
+ set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Performing Objective-C SOURCE FILE Test ${VAR} failed with the following output:\n"
+ "${OUTPUT}\n"
+ "Source file was:\n${SOURCE}\n")
+ endif()
+ endif()
+endmacro()
diff --git a/Modules/CheckOBJCSourceRuns.cmake b/Modules/CheckOBJCSourceRuns.cmake
new file mode 100644
index 0000000..00a1ebd
--- /dev/null
+++ b/Modules/CheckOBJCSourceRuns.cmake
@@ -0,0 +1,145 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CheckOBJCSourceRuns
+-------------------
+
+Check if given Objective-C source compiles and links into an executable and can
+subsequently be run.
+
+.. command:: check_objc_source_runs
+
+ .. code-block:: cmake
+
+ check_objc_source_runs(<code> <resultVar>)
+
+ Check that the source supplied in ``<code>`` can be compiled as a Objective-C source
+ file, linked as an executable and then run. The ``<code>`` must contain at
+ least a ``main()`` function. If the ``<code>`` could be built and run
+ successfully, the internal cache variable specified by ``<resultVar>`` will
+ be set to 1, otherwise it will be set to an value that evaluates to boolean
+ false (e.g. an empty string or an error message).
+
+ The underlying check is performed by the :command:`try_run` command. The
+ compile and link commands can be influenced by setting any of the following
+ variables prior to calling ``check_objc_source_runs()``:
+
+ ``CMAKE_REQUIRED_FLAGS``
+ Additional flags to pass to the compiler. Note that the contents of
+ :variable:`CMAKE_OBJC_FLAGS <CMAKE_<LANG>_FLAGS>` and its associated
+ configuration-specific variable are automatically added to the compiler
+ command before the contents of ``CMAKE_REQUIRED_FLAGS``.
+
+ ``CMAKE_REQUIRED_DEFINITIONS``
+ A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form
+ ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by
+ ``<resultVar>`` will also be added automatically.
+
+ ``CMAKE_REQUIRED_INCLUDES``
+ A :ref:`;-list <CMake Language Lists>` of header search paths to pass to
+ the compiler. These will be the only header search paths used by
+ ``try_run()``, i.e. the contents of the :prop_dir:`INCLUDE_DIRECTORIES`
+ directory property will be ignored.
+
+ ``CMAKE_REQUIRED_LINK_OPTIONS``
+ A :ref:`;-list <CMake Language Lists>` of options to add to the link
+ command (see :command:`try_run` for further details).
+
+ ``CMAKE_REQUIRED_LIBRARIES``
+ A :ref:`;-list <CMake Language Lists>` of libraries to add to the link
+ command. These can be the name of system libraries or they can be
+ :ref:`Imported Targets <Imported Targets>` (see :command:`try_run` for
+ further details).
+
+ ``CMAKE_REQUIRED_QUIET``
+ If this variable evaluates to a boolean true value, all status messages
+ associated with the check will be suppressed.
+
+ The check is only performed once, with the result cached in the variable
+ named by ``<resultVar>``. Every subsequent CMake run will re-use this cached
+ value rather than performing the check again, even if the ``<code>`` changes.
+ In order to force the check to be re-evaluated, the variable named by
+ ``<resultVar>`` must be manually removed from the cache.
+
+#]=======================================================================]
+
+include_guard(GLOBAL)
+
+macro(CHECK_OBJC_SOURCE_RUNS SOURCE VAR)
+ if(NOT DEFINED "${VAR}")
+ set(MACRO_CHECK_FUNCTION_DEFINITIONS
+ "-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
+ if(CMAKE_REQUIRED_LINK_OPTIONS)
+ set(CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS
+ LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS})
+ else()
+ set(CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS)
+ endif()
+ if(CMAKE_REQUIRED_LIBRARIES)
+ set(CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES
+ LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+ else()
+ set(CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES)
+ endif()
+ if(CMAKE_REQUIRED_INCLUDES)
+ set(CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES
+ "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
+ else()
+ set(CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES)
+ endif()
+ file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.m"
+ "${SOURCE}\n")
+
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Performing Test ${VAR}")
+ endif()
+ try_run(${VAR}_EXITCODE ${VAR}_COMPILED
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.m
+ COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ ${CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS}
+ ${CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES}
+ CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
+ -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
+ "${CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES}"
+ COMPILE_OUTPUT_VARIABLE OUTPUT
+ RUN_OUTPUT_VARIABLE RUN_OUTPUT)
+ # if it did not compile make the return value fail code of 1
+ if(NOT ${VAR}_COMPILED)
+ set(${VAR}_EXITCODE 1)
+ endif()
+ # if the return value was 0 then it worked
+ if("${${VAR}_EXITCODE}" EQUAL 0)
+ set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Performing Test ${VAR} - Success")
+ endif()
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Performing Objective-C SOURCE FILE Test ${VAR} succeeded with the following compile output:\n"
+ "${OUTPUT}\n"
+ "...and run output:\n"
+ "${RUN_OUTPUT}\n"
+ "Return value: ${${VAR}}\n"
+ "Source file was:\n${SOURCE}\n")
+ else()
+ if(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES "FAILED_TO_RUN")
+ set(${VAR} "${${VAR}_EXITCODE}")
+ else()
+ set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
+ endif()
+
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Performing Test ${VAR} - Failed")
+ endif()
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Performing Objective-C SOURCE FILE Test ${VAR} failed with the following compile output:\n"
+ "${OUTPUT}\n"
+ "...and run output:\n"
+ "${RUN_OUTPUT}\n"
+ "Return value: ${${VAR}_EXITCODE}\n"
+ "Source file was:\n${SOURCE}\n")
+
+ endif()
+ endif()
+endmacro()
diff --git a/Modules/CheckOBJCXXCompilerFlag.cmake b/Modules/CheckOBJCXXCompilerFlag.cmake
new file mode 100644
index 0000000..c32741b
--- /dev/null
+++ b/Modules/CheckOBJCXXCompilerFlag.cmake
@@ -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.
+
+#[=======================================================================[.rst:
+CheckOBJCXXCompilerFlag
+-----------------------
+
+Check whether the Objective-C++ compiler supports a given flag.
+
+.. command:: check_objcxx_compiler_flag
+
+ .. code-block:: cmake
+
+ check_objcxx_compiler_flag(<flag> <var>)
+
+ Check that the ``<flag>`` is accepted by the compiler without
+ a diagnostic. Stores the result in an internal cache entry
+ named ``<var>``.
+
+This command temporarily sets the ``CMAKE_REQUIRED_DEFINITIONS`` variable
+and calls the ``check_objcxx_source_compiles`` macro from the
+:module:`CheckOBJCXXSourceCompiles` module. See documentation of that
+module for a listing of variables that can otherwise modify the build.
+
+A positive result from this check indicates only that the compiler did not
+issue a diagnostic message when given the flag. Whether the flag has any
+effect or even a specific one is beyond the scope of this module.
+
+.. note::
+ Since the :command:`try_compile` command forwards flags from variables
+ like :variable:`CMAKE_OBJCXX_FLAGS <CMAKE_<LANG>_FLAGS>`, unknown flags
+ in such variables may cause a false negative for this check.
+#]=======================================================================]
+
+include_guard(GLOBAL)
+include(CheckOBJCXXSourceCompiles)
+include(CMakeCheckCompilerFlagCommonPatterns)
+
+macro (CHECK_OBJCXX_COMPILER_FLAG _FLAG _RESULT)
+ set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
+ set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
+
+ # Normalize locale during test compilation.
+ set(_CheckOBJCXXCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG)
+ foreach(v ${_CheckOBJCXXCompilerFlag_LOCALE_VARS})
+ set(_CheckOBJCXXCompilerFlag_SAVED_${v} "$ENV{${v}}")
+ set(ENV{${v}} OBJCXX)
+ endforeach()
+ CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckOBJCXXCompilerFlag_COMMON_PATTERNS)
+ CHECK_OBJCXX_SOURCE_COMPILES("#ifndef __OBJC__\n# error \"Not an Objective-C++ compiler\"\n#endif\nint main(void) { return 0; }" ${_RESULT}
+ # Some compilers do not fail with a bad flag
+ FAIL_REGEX "command line option .* is valid for .* but not for Objective-C\\\\+\\\\+" # GNU
+ FAIL_REGEX "argument unused during compilation: .*" # Clang
+ ${_CheckOBJCXXCompilerFlag_COMMON_PATTERNS}
+ )
+ foreach(v ${_CheckOBJCXXCompilerFlag_LOCALE_VARS})
+ set(ENV{${v}} ${_CheckOBJCXXCompilerFlag_SAVED_${v}})
+ unset(_CheckOBJCXXCompilerFlag_SAVED_${v})
+ endforeach()
+ unset(_CheckOBJCXXCompilerFlag_LOCALE_VARS)
+ unset(_CheckOBJCXXCompilerFlag_COMMON_PATTERNS)
+
+ set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
+endmacro ()
diff --git a/Modules/CheckOBJCXXSourceCompiles.cmake b/Modules/CheckOBJCXXSourceCompiles.cmake
new file mode 100644
index 0000000..4c0fdd0
--- /dev/null
+++ b/Modules/CheckOBJCXXSourceCompiles.cmake
@@ -0,0 +1,146 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CheckOBJCXXSourceCompiles
+-------------------------
+
+Check if given Objective-C++ source compiles and links into an executable.
+
+.. command:: check_objcxx_source_compiles
+
+ .. code-block:: cmake
+
+ check_objcxx_source_compiles(<code> <resultVar>
+ [FAIL_REGEX <regex1> [<regex2>...]])
+
+ Check that the source supplied in ``<code>`` can be compiled as a Objective-C++ source
+ file and linked as an executable (so it must contain at least a ``main()``
+ function). The result will be stored in the internal cache variable specified
+ by ``<resultVar>``, with a boolean true value for success and boolean false
+ for failure. If ``FAIL_REGEX`` is provided, then failure is determined by
+ checking if anything in the output matches any of the specified regular
+ expressions.
+
+ The underlying check is performed by the :command:`try_compile` command. The
+ compile and link commands can be influenced by setting any of the following
+ variables prior to calling ``check_objcxx_source_compiles()``:
+
+ ``CMAKE_REQUIRED_FLAGS``
+ Additional flags to pass to the compiler. Note that the contents of
+ :variable:`CMAKE_OBJCXX_FLAGS <CMAKE_<LANG>_FLAGS>` and its associated
+ configuration-specific variable are automatically added to the compiler
+ command before the contents of ``CMAKE_REQUIRED_FLAGS``.
+
+ ``CMAKE_REQUIRED_DEFINITIONS``
+ A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form
+ ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by
+ ``<resultVar>`` will also be added automatically.
+
+ ``CMAKE_REQUIRED_INCLUDES``
+ A :ref:`;-list <CMake Language Lists>` of header search paths to pass to
+ the compiler. These will be the only header search paths used by
+ ``try_compile()``, i.e. the contents of the :prop_dir:`INCLUDE_DIRECTORIES`
+ directory property will be ignored.
+
+ ``CMAKE_REQUIRED_LINK_OPTIONS``
+ A :ref:`;-list <CMake Language Lists>` of options to add to the link
+ command (see :command:`try_compile` for further details).
+
+ ``CMAKE_REQUIRED_LIBRARIES``
+ A :ref:`;-list <CMake Language Lists>` of libraries to add to the link
+ command. These can be the name of system libraries or they can be
+ :ref:`Imported Targets <Imported Targets>` (see :command:`try_compile` for
+ further details).
+
+ ``CMAKE_REQUIRED_QUIET``
+ If this variable evaluates to a boolean true value, all status messages
+ associated with the check will be suppressed.
+
+ The check is only performed once, with the result cached in the variable
+ named by ``<resultVar>``. Every subsequent CMake run will re-use this cached
+ value rather than performing the check again, even if the ``<code>`` changes.
+ In order to force the check to be re-evaluated, the variable named by
+ ``<resultVar>`` must be manually removed from the cache.
+
+#]=======================================================================]
+
+include_guard(GLOBAL)
+
+macro(CHECK_OBJCXX_SOURCE_COMPILES SOURCE VAR)
+ if(NOT DEFINED "${VAR}")
+ set(_FAIL_REGEX)
+ set(_key)
+ foreach(arg ${ARGN})
+ if("${arg}" MATCHES "^(FAIL_REGEX)$")
+ set(_key "${arg}")
+ elseif(_key)
+ list(APPEND _${_key} "${arg}")
+ else()
+ message(FATAL_ERROR "Unknown argument:\n ${arg}\n")
+ endif()
+ endforeach()
+
+ set(MACRO_CHECK_FUNCTION_DEFINITIONS
+ "-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
+ if(CMAKE_REQUIRED_LINK_OPTIONS)
+ set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS
+ LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS})
+ else()
+ set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS)
+ endif()
+ if(CMAKE_REQUIRED_LIBRARIES)
+ set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES
+ LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+ else()
+ set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES)
+ endif()
+ if(CMAKE_REQUIRED_INCLUDES)
+ set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES
+ "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
+ else()
+ set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES)
+ endif()
+ file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.mm"
+ "${SOURCE}\n")
+
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Performing Test ${VAR}")
+ endif()
+ try_compile(${VAR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.mm
+ COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ ${CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS}
+ ${CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES}
+ CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
+ "${CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES}"
+ OUTPUT_VARIABLE OUTPUT)
+
+ foreach(_regex ${_FAIL_REGEX})
+ if("${OUTPUT}" MATCHES "${_regex}")
+ set(${VAR} 0)
+ endif()
+ endforeach()
+
+ if(${VAR})
+ set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Performing Test ${VAR} - Success")
+ endif()
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Performing Objective-C++ SOURCE FILE Test ${VAR} succeeded with the following output:\n"
+ "${OUTPUT}\n"
+ "Source file was:\n${SOURCE}\n")
+ else()
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Performing Test ${VAR} - Failed")
+ endif()
+ set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Performing Objective-C++ SOURCE FILE Test ${VAR} failed with the following output:\n"
+ "${OUTPUT}\n"
+ "Source file was:\n${SOURCE}\n")
+ endif()
+ endif()
+endmacro()
diff --git a/Modules/CheckOBJCXXSourceRuns.cmake b/Modules/CheckOBJCXXSourceRuns.cmake
new file mode 100644
index 0000000..a3d5923
--- /dev/null
+++ b/Modules/CheckOBJCXXSourceRuns.cmake
@@ -0,0 +1,145 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CheckOBJCXXSourceRuns
+---------------------
+
+Check if given Objective-C++ source compiles and links into an executable and can
+subsequently be run.
+
+.. command:: check_objcxx_source_runs
+
+ .. code-block:: cmake
+
+ check_objcxx_source_runs(<code> <resultVar>)
+
+ Check that the source supplied in ``<code>`` can be compiled as a Objective-C++ source
+ file, linked as an executable and then run. The ``<code>`` must contain at
+ least a ``main()`` function. If the ``<code>`` could be built and run
+ successfully, the internal cache variable specified by ``<resultVar>`` will
+ be set to 1, otherwise it will be set to an value that evaluates to boolean
+ false (e.g. an empty string or an error message).
+
+ The underlying check is performed by the :command:`try_run` command. The
+ compile and link commands can be influenced by setting any of the following
+ variables prior to calling ``check_objcxx_source_runs()``:
+
+ ``CMAKE_REQUIRED_FLAGS``
+ Additional flags to pass to the compiler. Note that the contents of
+ :variable:`CMAKE_OBJCXX_FLAGS <CMAKE_<LANG>_FLAGS>` and its associated
+ configuration-specific variable are automatically added to the compiler
+ command before the contents of ``CMAKE_REQUIRED_FLAGS``.
+
+ ``CMAKE_REQUIRED_DEFINITIONS``
+ A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form
+ ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by
+ ``<resultVar>`` will also be added automatically.
+
+ ``CMAKE_REQUIRED_INCLUDES``
+ A :ref:`;-list <CMake Language Lists>` of header search paths to pass to
+ the compiler. These will be the only header search paths used by
+ ``try_run()``, i.e. the contents of the :prop_dir:`INCLUDE_DIRECTORIES`
+ directory property will be ignored.
+
+ ``CMAKE_REQUIRED_LINK_OPTIONS``
+ A :ref:`;-list <CMake Language Lists>` of options to add to the link
+ command (see :command:`try_run` for further details).
+
+ ``CMAKE_REQUIRED_LIBRARIES``
+ A :ref:`;-list <CMake Language Lists>` of libraries to add to the link
+ command. These can be the name of system libraries or they can be
+ :ref:`Imported Targets <Imported Targets>` (see :command:`try_run` for
+ further details).
+
+ ``CMAKE_REQUIRED_QUIET``
+ If this variable evaluates to a boolean true value, all status messages
+ associated with the check will be suppressed.
+
+ The check is only performed once, with the result cached in the variable
+ named by ``<resultVar>``. Every subsequent CMake run will re-use this cached
+ value rather than performing the check again, even if the ``<code>`` changes.
+ In order to force the check to be re-evaluated, the variable named by
+ ``<resultVar>`` must be manually removed from the cache.
+
+#]=======================================================================]
+
+include_guard(GLOBAL)
+
+macro(CHECK_OBJCXX_SOURCE_RUNS SOURCE VAR)
+ if(NOT DEFINED "${VAR}")
+ set(MACRO_CHECK_FUNCTION_DEFINITIONS
+ "-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
+ if(CMAKE_REQUIRED_LINK_OPTIONS)
+ set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS
+ LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS})
+ else()
+ set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS)
+ endif()
+ if(CMAKE_REQUIRED_LIBRARIES)
+ set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES
+ LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+ else()
+ set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES)
+ endif()
+ if(CMAKE_REQUIRED_INCLUDES)
+ set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES
+ "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
+ else()
+ set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES)
+ endif()
+ file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.mm"
+ "${SOURCE}\n")
+
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Performing Test ${VAR}")
+ endif()
+ try_run(${VAR}_EXITCODE ${VAR}_COMPILED
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.mm
+ COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ ${CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS}
+ ${CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES}
+ CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
+ -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
+ "${CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES}"
+ COMPILE_OUTPUT_VARIABLE OUTPUT
+ RUN_OUTPUT_VARIABLE RUN_OUTPUT)
+
+ # if it did not compile make the return value fail code of 1
+ if(NOT ${VAR}_COMPILED)
+ set(${VAR}_EXITCODE 1)
+ endif()
+ # if the return value was 0 then it worked
+ if("${${VAR}_EXITCODE}" EQUAL 0)
+ set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Performing Test ${VAR} - Success")
+ endif()
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Performing Objective-C++ SOURCE FILE Test ${VAR} succeeded with the following output:\n"
+ "${OUTPUT}\n"
+ "...and run output:\n"
+ "${RUN_OUTPUT}\n"
+ "Return value: ${${VAR}}\n"
+ "Source file was:\n${SOURCE}\n")
+ else()
+ if(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES "FAILED_TO_RUN")
+ set(${VAR} "${${VAR}_EXITCODE}")
+ else()
+ set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
+ endif()
+
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Performing Test ${VAR} - Failed")
+ endif()
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Performing Objective-C++ SOURCE FILE Test ${VAR} failed with the following output:\n"
+ "${OUTPUT}\n"
+ "...and run output:\n"
+ "${RUN_OUTPUT}\n"
+ "Return value: ${${VAR}_EXITCODE}\n"
+ "Source file was:\n${SOURCE}\n")
+ endif()
+ endif()
+endmacro()
diff --git a/Modules/Compiler/AppleClang-OBJC.cmake b/Modules/Compiler/AppleClang-OBJC.cmake
new file mode 100644
index 0000000..d1f3706
--- /dev/null
+++ b/Modules/Compiler/AppleClang-OBJC.cmake
@@ -0,0 +1,17 @@
+include(Compiler/Clang-OBJC)
+
+if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 4.0)
+ set(CMAKE_OBJC90_STANDARD_COMPILE_OPTION "-std=c90")
+ set(CMAKE_OBJC90_EXTENSION_COMPILE_OPTION "-std=gnu90")
+ set(CMAKE_OBJC90_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_OBJC99_STANDARD_COMPILE_OPTION "-std=c99")
+ set(CMAKE_OBJC99_EXTENSION_COMPILE_OPTION "-std=gnu99")
+ set(CMAKE_OBJC99_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_OBJC11_STANDARD_COMPILE_OPTION "-std=c11")
+ set(CMAKE_OBJC11_EXTENSION_COMPILE_OPTION "-std=gnu11")
+ set(CMAKE_OBJC11_STANDARD__HAS_FULL_SUPPORT ON)
+endif()
+
+__compiler_check_default_language_standard(OBJC 4.0 99)
diff --git a/Modules/Compiler/AppleClang-OBJCXX.cmake b/Modules/Compiler/AppleClang-OBJCXX.cmake
new file mode 100644
index 0000000..7c6f763
--- /dev/null
+++ b/Modules/Compiler/AppleClang-OBJCXX.cmake
@@ -0,0 +1,37 @@
+include(Compiler/Clang-OBJCXX)
+
+if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 4.0)
+ set(CMAKE_OBJCXX98_STANDARD_COMPILE_OPTION "-std=c++98")
+ set(CMAKE_OBJCXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98")
+ set(CMAKE_OBJCXX98_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_OBJCXX11_STANDARD_COMPILE_OPTION "-std=c++11")
+ set(CMAKE_OBJCXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11")
+endif()
+
+if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 6.1)
+ set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std=c++14")
+ set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std=gnu++14")
+ set(CMAKE_OBJCXX14_STANDARD__HAS_FULL_SUPPORT ON)
+elseif(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 5.1)
+ # AppleClang 5.0 knows this flag, but does not set a __cplusplus macro greater than 201103L
+ set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std=c++1y")
+ set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std=gnu++1y")
+ set(CMAKE_OBJCXX14_STANDARD__HAS_FULL_SUPPORT ON)
+endif()
+
+if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 6.1)
+ set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std=c++1z")
+ set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z")
+endif()
+
+if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 8.0)
+ set(CMAKE_OBJCXX11_STANDARD__HAS_FULL_SUPPORT ON)
+endif()
+
+if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 10.0)
+ set(CMAKE_OBJCXX20_STANDARD_COMPILE_OPTION "-std=c++2a")
+ set(CMAKE_OBJCXX20_EXTENSION_COMPILE_OPTION "-std=gnu++2a")
+endif()
+
+__compiler_check_default_language_standard(OBJCXX 4.0 98)
diff --git a/Modules/Compiler/Clang-OBJC.cmake b/Modules/Compiler/Clang-OBJC.cmake
new file mode 100644
index 0000000..c61c497
--- /dev/null
+++ b/Modules/Compiler/Clang-OBJC.cmake
@@ -0,0 +1,18 @@
+include(Compiler/Clang)
+__compiler_clang(OBJC)
+
+if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 3.4)
+ set(CMAKE_OBJC90_STANDARD_COMPILE_OPTION "-std=c90")
+ set(CMAKE_OBJC90_EXTENSION_COMPILE_OPTION "-std=gnu90")
+ set(CMAKE_OBJC90_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_OBJC99_STANDARD_COMPILE_OPTION "-std=c99")
+ set(CMAKE_OBJC99_EXTENSION_COMPILE_OPTION "-std=gnu99")
+ set(CMAKE_OBJC99_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_OBJC11_STANDARD_COMPILE_OPTION "-std=c11")
+ set(CMAKE_OBJC11_EXTENSION_COMPILE_OPTION "-std=gnu11")
+ set(CMAKE_OBJC11_STANDARD__HAS_FULL_SUPPORT ON)
+endif()
+
+__compiler_check_default_language_standard(OBJC 3.4 99 3.6 11)
diff --git a/Modules/Compiler/Clang-OBJCXX.cmake b/Modules/Compiler/Clang-OBJCXX.cmake
new file mode 100644
index 0000000..b01ce64
--- /dev/null
+++ b/Modules/Compiler/Clang-OBJCXX.cmake
@@ -0,0 +1,70 @@
+include(Compiler/Clang)
+__compiler_clang(OBJCXX)
+
+if("x${CMAKE_OBJCXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
+ if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 2.1)
+ set(CMAKE_OBJCXX98_STANDARD_COMPILE_OPTION "-std=c++98")
+ set(CMAKE_OBJCXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98")
+ endif()
+
+ if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 3.1)
+ set(CMAKE_OBJCXX98_STANDARD__HAS_FULL_SUPPORT ON)
+ set(CMAKE_OBJCXX11_STANDARD_COMPILE_OPTION "-std=c++11")
+ set(CMAKE_OBJCXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11")
+ set(CMAKE_OBJCXX11_STANDARD__HAS_FULL_SUPPORT ON)
+ elseif(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 2.1)
+ set(CMAKE_OBJCXX11_STANDARD_COMPILE_OPTION "-std=c++0x")
+ set(CMAKE_OBJCXX11_EXTENSION_COMPILE_OPTION "-std=gnu++0x")
+ endif()
+
+ if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 3.5)
+ set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std=c++14")
+ set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std=gnu++14")
+ set(CMAKE_OBJCXX14_STANDARD__HAS_FULL_SUPPORT ON)
+ elseif(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 3.4)
+ set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std=c++1y")
+ set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std=gnu++1y")
+ set(CMAKE_OBJCXX14_STANDARD__HAS_FULL_SUPPORT ON)
+ endif()
+
+ set(_clang_version_std17 5.0)
+
+ if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS "${_clang_version_std17}")
+ set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std=c++17")
+ set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17")
+ elseif (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 3.5)
+ set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std=c++1z")
+ set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z")
+ endif()
+
+ if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS "${_clang_version_std17}")
+ set(CMAKE_OBJCXX20_STANDARD_COMPILE_OPTION "-std=c++2a")
+ set(CMAKE_OBJCXX20_EXTENSION_COMPILE_OPTION "-std=gnu++2a")
+ endif()
+
+ unset(_clang_version_std17)
+
+ __compiler_check_default_language_standard(OBJCXX 2.1 98)
+elseif(CMAKE_OBJCXX_COMPILER_VERSION VERSION_GREATER_EQUAL 3.9
+ AND CMAKE_OBJCXX_SIMULATE_VERSION VERSION_GREATER_EQUAL 19.0)
+ # This version of clang-cl and the MSVC version it simulates have
+ # support for -std: flags.
+ set(CMAKE_OBJCXX98_STANDARD_COMPILE_OPTION "")
+ set(CMAKE_OBJCXX98_EXTENSION_COMPILE_OPTION "")
+ set(CMAKE_OBJCXX98_STANDARD__HAS_FULL_SUPPORT ON)
+ set(CMAKE_OBJCXX11_STANDARD_COMPILE_OPTION "")
+ set(CMAKE_OBJCXX11_EXTENSION_COMPILE_OPTION "")
+ set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std:c++14")
+ set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std:c++14")
+ if (CMAKE_OBJCXX_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0)
+ set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std:c++17")
+ set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std:c++17")
+ set(CMAKE_OBJCXX20_STANDARD_COMPILE_OPTION "-std:c++latest")
+ set(CMAKE_OBJCXX20_EXTENSION_COMPILE_OPTION "-std:c++latest")
+ else()
+ set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std:c++latest")
+ set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std:c++latest")
+ endif()
+
+ __compiler_check_default_language_standard(OBJCXX 3.9 14)
+endif()
diff --git a/Modules/Compiler/GNU-OBJC.cmake b/Modules/Compiler/GNU-OBJC.cmake
new file mode 100644
index 0000000..5fba801
--- /dev/null
+++ b/Modules/Compiler/GNU-OBJC.cmake
@@ -0,0 +1,6 @@
+include(Compiler/GNU)
+__compiler_gnu(OBJC)
+
+if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2)
+ set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
+endif()
diff --git a/Modules/Compiler/GNU-OBJCXX.cmake b/Modules/Compiler/GNU-OBJCXX.cmake
new file mode 100644
index 0000000..66a547e
--- /dev/null
+++ b/Modules/Compiler/GNU-OBJCXX.cmake
@@ -0,0 +1,10 @@
+include(Compiler/GNU)
+__compiler_gnu(OBJC)
+
+if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2)
+ set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
+endif()
+
+if(NOT CMAKE_OBJCXX_LINK_FLAGS)
+ set(CMAKE_OBCXX_LINK_FLAGS "-lstdc++")
+endif()
diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake
index a2999fc..d824ee8 100644
--- a/Modules/FindPackageHandleStandardArgs.cmake
+++ b/Modules/FindPackageHandleStandardArgs.cmake
@@ -27,6 +27,7 @@ valid filepaths.
[VERSION_VAR <version-var>]
[HANDLE_COMPONENTS]
[CONFIG_MODE]
+ [REASON_FAILURE_MESSAGE <reason-failure-message>]
[FAIL_MESSAGE <custom-failure-message>]
)
@@ -81,6 +82,10 @@ valid filepaths.
will automatically check whether the package configuration file
was found.
+ ``REASON_FAILURE_MESSAGE <reason-failure-message>``
+ Specify a custom message of the reason for the failure which will be
+ appended to the default generated message.
+
``FAIL_MESSAGE <custom-failure-message>``
Specify a custom failure message instead of using the default
generated message. Not recommended.
@@ -133,11 +138,15 @@ include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake)
# internal helper macro
macro(_FPHSA_FAILURE_MESSAGE _msg)
+ set (__msg "${_msg}")
+ if (FPHSA_REASON_FAILURE_MESSAGE)
+ string(APPEND __msg "\n Reason given by package: ${FPHSA_REASON_FAILURE_MESSAGE}\n")
+ endif()
if (${_NAME}_FIND_REQUIRED)
- message(FATAL_ERROR "${_msg}")
+ message(FATAL_ERROR "${__msg}")
else ()
if (NOT ${_NAME}_FIND_QUIETLY)
- message(STATUS "${_msg}")
+ message(STATUS "${__msg}")
endif ()
endif ()
endmacro()
@@ -158,12 +167,18 @@ macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
foreach(currentConfigIndex RANGE ${configsCount})
list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename)
list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
- string(APPEND configsText " ${filename} (version ${version})\n")
+ string(APPEND configsText "\n ${filename} (version ${version})")
endforeach()
if (${_NAME}_NOT_FOUND_MESSAGE)
- string(APPEND configsText " Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n")
+ if (FPHSA_REASON_FAILURE_MESSAGE)
+ string(PREPEND FPHSA_REASON_FAILURE_MESSAGE "${${_NAME}_NOT_FOUND_MESSAGE}\n ")
+ else()
+ set(FPHSA_REASON_FAILURE_MESSAGE "${${_NAME}_NOT_FOUND_MESSAGE}")
+ endif()
+ else()
+ string(APPEND configsText "\n")
endif()
- _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
+ _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:${configsText}")
else()
# Simple case: No Config-file was found at all:
@@ -177,7 +192,7 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
# Set up the arguments for `cmake_parse_arguments`.
set(options CONFIG_MODE HANDLE_COMPONENTS)
- set(oneValueArgs FAIL_MESSAGE VERSION_VAR FOUND_VAR)
+ set(oneValueArgs FAIL_MESSAGE REASON_FAILURE_MESSAGE VERSION_VAR FOUND_VAR)
set(multiValueArgs REQUIRED_VARS)
# Check whether we are in 'simple' or 'extended' mode:
diff --git a/Modules/Platform/Apple-AppleClang-OBJC.cmake b/Modules/Platform/Apple-AppleClang-OBJC.cmake
new file mode 100644
index 0000000..b78edb1
--- /dev/null
+++ b/Modules/Platform/Apple-AppleClang-OBJC.cmake
@@ -0,0 +1,6 @@
+include(Platform/Apple-Clang-OBJC)
+if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 4.2)
+ set(CMAKE_OBJC_SYSTEM_FRAMEWORK_SEARCH_FLAG "-iframework ")
+else()
+ unset(CMAKE_OBJC_SYSTEM_FRAMEWORK_SEARCH_FLAG)
+endif()
diff --git a/Modules/Platform/Apple-AppleClang-OBJCXX.cmake b/Modules/Platform/Apple-AppleClang-OBJCXX.cmake
new file mode 100644
index 0000000..ed172f1
--- /dev/null
+++ b/Modules/Platform/Apple-AppleClang-OBJCXX.cmake
@@ -0,0 +1,6 @@
+include(Platform/Apple-Clang-OBJCXX)
+if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 4.2)
+ set(CMAKE_OBJCXX_SYSTEM_FRAMEWORK_SEARCH_FLAG "-iframework ")
+else()
+ unset(CMAKE_OBJCXX_SYSTEM_FRAMEWORK_SEARCH_FLAG)
+endif()
diff --git a/Modules/Platform/Apple-Clang-OBJC.cmake b/Modules/Platform/Apple-Clang-OBJC.cmake
new file mode 100644
index 0000000..63cd846
--- /dev/null
+++ b/Modules/Platform/Apple-Clang-OBJC.cmake
@@ -0,0 +1,2 @@
+include(Platform/Apple-Clang)
+__apple_compiler_clang(OBJC)
diff --git a/Modules/Platform/Apple-Clang-OBJCXX.cmake b/Modules/Platform/Apple-Clang-OBJCXX.cmake
new file mode 100644
index 0000000..28fc352
--- /dev/null
+++ b/Modules/Platform/Apple-Clang-OBJCXX.cmake
@@ -0,0 +1,2 @@
+include(Platform/Apple-Clang)
+__apple_compiler_clang(OBJCXX)
diff --git a/Modules/Platform/Apple-GNU-OBJC.cmake b/Modules/Platform/Apple-GNU-OBJC.cmake
new file mode 100644
index 0000000..aa8b33f
--- /dev/null
+++ b/Modules/Platform/Apple-GNU-OBJC.cmake
@@ -0,0 +1,4 @@
+include(Platform/Apple-GNU)
+__apple_compiler_gnu(OBJC)
+cmake_gnu_set_sysroot_flag(OBJC)
+cmake_gnu_set_osx_deployment_target_flag(OBJC)
diff --git a/Modules/Platform/Apple-GNU-OBJCXX.cmake b/Modules/Platform/Apple-GNU-OBJCXX.cmake
new file mode 100644
index 0000000..919e11d
--- /dev/null
+++ b/Modules/Platform/Apple-GNU-OBJCXX.cmake
@@ -0,0 +1,4 @@
+include(Platform/Apple-GNU)
+__apple_compiler_gnu(OBJCXX)
+cmake_gnu_set_sysroot_flag(OBJCXX)
+cmake_gnu_set_osx_deployment_target_flag(OBJCXX)
diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake
index 7e02814..d0bb359 100644
--- a/Modules/Platform/Darwin.cmake
+++ b/Modules/Platform/Darwin.cmake
@@ -119,10 +119,18 @@ set(CMAKE_C_CREATE_MACOSX_FRAMEWORK
set(CMAKE_CXX_CREATE_MACOSX_FRAMEWORK
"<CMAKE_CXX_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <LINK_FLAGS> -o <TARGET> <SONAME_FLAG> <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
+set(CMAKE_OBJC_CREATE_MACOSX_FRAMEWORK
+ "<CMAKE_OBJC_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS> <LINK_FLAGS> -o <TARGET> <SONAME_FLAG> <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
+
+set(CMAKE_OBJCXX_CREATE_MACOSX_FRAMEWORK
+ "<CMAKE_OBJCXX_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS> <LINK_FLAGS> -o <TARGET> <SONAME_FLAG> <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
+
# Set default framework search path flag for languages known to use a
# preprocessor that may find headers in frameworks.
set(CMAKE_C_FRAMEWORK_SEARCH_FLAG -F)
set(CMAKE_CXX_FRAMEWORK_SEARCH_FLAG -F)
+set(CMAKE_OBJC_FRAMEWORK_SEARCH_FLAG -F)
+set(CMAKE_OBJCXX_FRAMEWORK_SEARCH_FLAG -F)
set(CMAKE_Fortran_FRAMEWORK_SEARCH_FLAG -F)
# default to searching for frameworks first
@@ -222,7 +230,7 @@ unset(_apps_paths)
include(Platform/UnixPaths)
if(_CMAKE_OSX_SYSROOT_PATH AND EXISTS ${_CMAKE_OSX_SYSROOT_PATH}/usr/include)
list(APPEND CMAKE_SYSTEM_PREFIX_PATH ${_CMAKE_OSX_SYSROOT_PATH}/usr)
- foreach(lang C CXX)
+ foreach(lang C CXX OBJC OBJCXX)
list(APPEND _CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES_INIT ${_CMAKE_OSX_SYSROOT_PATH}/usr/include)
endforeach()
endif()
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 0c1f3b1..4e3e842 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -1145,7 +1145,7 @@ target_link_libraries(cpack CPackLib)
# Curses GUI
if(BUILD_CursesDialog)
- include(${CMake_SOURCE_DIR}/Source/CursesDialog/CMakeLists.txt)
+ add_subdirectory(CursesDialog)
endif()
# Qt GUI
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index d9ca09b..2196243 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 15)
-set(CMake_VERSION_PATCH 20190927)
+set(CMake_VERSION_PATCH 20190930)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CursesDialog/CMakeLists.txt b/Source/CursesDialog/CMakeLists.txt
index 270b07e..7009717 100644
--- a/Source/CursesDialog/CMakeLists.txt
+++ b/Source/CursesDialog/CMakeLists.txt
@@ -1,26 +1,22 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-set( CURSES_SRCS
- CursesDialog/cmCursesOptionsWidget.cxx
- CursesDialog/cmCursesBoolWidget.cxx
- CursesDialog/cmCursesCacheEntryComposite.cxx
- CursesDialog/cmCursesDummyWidget.cxx
- CursesDialog/cmCursesFilePathWidget.cxx
- CursesDialog/cmCursesForm.cxx
- CursesDialog/cmCursesLabelWidget.cxx
- CursesDialog/cmCursesLongMessageForm.cxx
- CursesDialog/cmCursesMainForm.cxx
- CursesDialog/cmCursesPathWidget.cxx
- CursesDialog/cmCursesStringWidget.cxx
- CursesDialog/cmCursesWidget.cxx
- CursesDialog/ccmake.cxx
- )
-
-include_directories(${CURSES_INCLUDE_PATH})
-
-
-add_executable(ccmake ${CURSES_SRCS} )
+add_executable(ccmake
+ ccmake.cxx
+ cmCursesBoolWidget.cxx
+ cmCursesCacheEntryComposite.cxx
+ cmCursesDummyWidget.cxx
+ cmCursesFilePathWidget.cxx
+ cmCursesForm.cxx
+ cmCursesLabelWidget.cxx
+ cmCursesLongMessageForm.cxx
+ cmCursesMainForm.cxx
+ cmCursesOptionsWidget.cxx
+ cmCursesPathWidget.cxx
+ cmCursesStringWidget.cxx
+ cmCursesWidget.cxx
+ )
+target_include_directories(ccmake PRIVATE ${CURSES_INCLUDE_PATH})
target_link_libraries(ccmake CMakeLib)
if(CMAKE_USE_SYSTEM_FORM)
find_path(CURSES_FORM_INCLUDE_DIR NAMES form.h HINTS ${CURSES_INCLUDE_PATH} ${CURSES_INCLUDE_PATH}/ncurses)
diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
index 47fe84c..561784c 100644
--- a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
+++ b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
@@ -13,9 +13,11 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmake.h"
+
+#include <cm/memory>
#include <cassert>
+#include <utility>
#include <vector>
cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
@@ -24,61 +26,65 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
, LabelWidth(labelwidth)
, EntryWidth(entrywidth)
{
- this->Label = new cmCursesLabelWidget(this->LabelWidth, 1, 1, 1, key);
- this->IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, " ");
- this->Entry = nullptr;
- this->Entry = new cmCursesStringWidget(this->EntryWidth, 1, 1, 1);
+ this->Label =
+ cm::make_unique<cmCursesLabelWidget>(this->LabelWidth, 1, 1, 1, key);
+ this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(1, 1, 1, 1, " ");
+ this->Entry =
+ cm::make_unique<cmCursesStringWidget>(this->EntryWidth, 1, 1, 1);
}
cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
- const std::string& key, cmake* cm, bool isNew, int labelwidth,
+ const std::string& key, cmState* state, bool isNew, int labelwidth,
int entrywidth)
: Key(key)
, LabelWidth(labelwidth)
, EntryWidth(entrywidth)
{
- this->Label = new cmCursesLabelWidget(this->LabelWidth, 1, 1, 1, key);
+ this->Label =
+ cm::make_unique<cmCursesLabelWidget>(this->LabelWidth, 1, 1, 1, key);
if (isNew) {
- this->IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, "*");
+ this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(1, 1, 1, 1, "*");
} else {
- this->IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, " ");
+ this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(1, 1, 1, 1, " ");
}
- this->Entry = nullptr;
- const char* value = cm->GetState()->GetCacheEntryValue(key);
+ const char* value = state->GetCacheEntryValue(key);
assert(value);
- switch (cm->GetState()->GetCacheEntryType(key)) {
- case cmStateEnums::BOOL:
- this->Entry = new cmCursesBoolWidget(this->EntryWidth, 1, 1, 1);
- if (cmIsOn(value)) {
- static_cast<cmCursesBoolWidget*>(this->Entry)->SetValueAsBool(true);
- } else {
- static_cast<cmCursesBoolWidget*>(this->Entry)->SetValueAsBool(false);
- }
+ switch (state->GetCacheEntryType(key)) {
+ case cmStateEnums::BOOL: {
+ auto bw = cm::make_unique<cmCursesBoolWidget>(this->EntryWidth, 1, 1, 1);
+ bw->SetValueAsBool(cmIsOn(value));
+ this->Entry = std::move(bw);
break;
- case cmStateEnums::PATH:
- this->Entry = new cmCursesPathWidget(this->EntryWidth, 1, 1, 1);
- static_cast<cmCursesPathWidget*>(this->Entry)->SetString(value);
+ }
+ case cmStateEnums::PATH: {
+ auto pw = cm::make_unique<cmCursesPathWidget>(this->EntryWidth, 1, 1, 1);
+ pw->SetString(value);
+ this->Entry = std::move(pw);
break;
- case cmStateEnums::FILEPATH:
- this->Entry = new cmCursesFilePathWidget(this->EntryWidth, 1, 1, 1);
- static_cast<cmCursesFilePathWidget*>(this->Entry)->SetString(value);
+ }
+ case cmStateEnums::FILEPATH: {
+ auto fpw =
+ cm::make_unique<cmCursesFilePathWidget>(this->EntryWidth, 1, 1, 1);
+ fpw->SetString(value);
+ this->Entry = std::move(fpw);
break;
+ }
case cmStateEnums::STRING: {
- const char* stringsProp =
- cm->GetState()->GetCacheEntryProperty(key, "STRINGS");
+ const char* stringsProp = state->GetCacheEntryProperty(key, "STRINGS");
if (stringsProp) {
- cmCursesOptionsWidget* ow =
- new cmCursesOptionsWidget(this->EntryWidth, 1, 1, 1);
- this->Entry = ow;
- std::vector<std::string> options = cmExpandedList(stringsProp);
- for (auto const& opt : options) {
+ auto ow =
+ cm::make_unique<cmCursesOptionsWidget>(this->EntryWidth, 1, 1, 1);
+ for (std::string const& opt : cmExpandedList(stringsProp)) {
ow->AddOption(opt);
}
ow->SetOption(value);
+ this->Entry = std::move(ow);
} else {
- this->Entry = new cmCursesStringWidget(this->EntryWidth, 1, 1, 1);
- static_cast<cmCursesStringWidget*>(this->Entry)->SetString(value);
+ auto sw =
+ cm::make_unique<cmCursesStringWidget>(this->EntryWidth, 1, 1, 1);
+ sw->SetString(value);
+ this->Entry = std::move(sw);
}
break;
}
@@ -91,12 +97,7 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
}
}
-cmCursesCacheEntryComposite::~cmCursesCacheEntryComposite()
-{
- delete this->Label;
- delete this->IsNewLabel;
- delete this->Entry;
-}
+cmCursesCacheEntryComposite::~cmCursesCacheEntryComposite() = default;
const char* cmCursesCacheEntryComposite::GetValue()
{
diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.h b/Source/CursesDialog/cmCursesCacheEntryComposite.h
index 0a69d3a..a711363 100644
--- a/Source/CursesDialog/cmCursesCacheEntryComposite.h
+++ b/Source/CursesDialog/cmCursesCacheEntryComposite.h
@@ -5,33 +5,38 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <memory>
#include <string>
class cmCursesLabelWidget;
class cmCursesWidget;
-class cmake;
+class cmState;
class cmCursesCacheEntryComposite
{
public:
cmCursesCacheEntryComposite(const std::string& key, int labelwidth,
int entrywidth);
- cmCursesCacheEntryComposite(const std::string& key, cmake* cm, bool isNew,
- int labelwidth, int entrywidth);
+ cmCursesCacheEntryComposite(const std::string& key, cmState* state,
+ bool isNew, int labelwidth, int entrywidth);
~cmCursesCacheEntryComposite();
cmCursesCacheEntryComposite(cmCursesCacheEntryComposite const&) = delete;
cmCursesCacheEntryComposite& operator=(cmCursesCacheEntryComposite const&) =
delete;
+ cmCursesCacheEntryComposite(cmCursesCacheEntryComposite&&) = default;
+ cmCursesCacheEntryComposite& operator=(cmCursesCacheEntryComposite&&) =
+ default;
+
const char* GetValue();
friend class cmCursesMainForm;
protected:
- cmCursesLabelWidget* Label;
- cmCursesLabelWidget* IsNewLabel;
- cmCursesWidget* Entry;
+ std::unique_ptr<cmCursesLabelWidget> Label;
+ std::unique_ptr<cmCursesLabelWidget> IsNewLabel;
+ std::unique_ptr<cmCursesWidget> Entry;
std::string Key;
int LabelWidth;
int EntryWidth;
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index 5f8a19e..219771b 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesMainForm.h"
-#include "cmAlgorithms.h"
#include "cmCursesCacheEntryComposite.h"
#include "cmCursesDummyWidget.h"
#include "cmCursesForm.h"
@@ -18,6 +17,8 @@
#include "cmVersion.h"
#include "cmake.h"
+#include <cm/memory>
+
#include <algorithm>
#include <cstdio>
#include <cstring>
@@ -34,8 +35,6 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args,
, InitialWidth(initWidth)
{
this->NumberOfPages = 0;
- this->Fields = nullptr;
- this->Entries = nullptr;
this->AdvancedMode = false;
this->NumberOfVisibleEntries = 0;
this->OkToGenerate = false;
@@ -43,7 +42,8 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args,
"Welcome to ccmake, curses based user interface for CMake.");
this->HelpMessage.emplace_back();
this->HelpMessage.emplace_back(s_ConstHelpMessage);
- this->CMakeInstance = new cmake(cmake::RoleProject, cmState::Project);
+ this->CMakeInstance =
+ cm::make_unique<cmake>(cmake::RoleProject, cmState::Project);
this->CMakeInstance->SetCMakeEditCommand(
cmSystemTools::GetCMakeCursesCommand());
@@ -52,8 +52,6 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args,
cmStrCat(cmSystemTools::GetProgramPath(this->Args[0]), "/cmake");
this->Args[0] = whereCMake;
this->CMakeInstance->SetArgs(this->Args);
- this->SearchString = "";
- this->OldSearchString = "";
this->SearchMode = false;
}
@@ -64,27 +62,15 @@ cmCursesMainForm::~cmCursesMainForm()
free_form(this->Form);
this->Form = nullptr;
}
- delete[] this->Fields;
-
- // Clean-up composites
- if (this->Entries) {
- cmDeleteAll(*this->Entries);
- }
- delete this->Entries;
- if (this->CMakeInstance) {
- delete this->CMakeInstance;
- this->CMakeInstance = nullptr;
- }
}
// See if a cache entry is in the list of entries in the ui.
bool cmCursesMainForm::LookForCacheEntry(const std::string& key)
{
- return this->Entries &&
- std::any_of(this->Entries->begin(), this->Entries->end(),
- [&key](cmCursesCacheEntryComposite* entry) {
- return key == entry->Key;
- });
+ return std::any_of(this->Entries.begin(), this->Entries.end(),
+ [&key](cmCursesCacheEntryComposite const& entry) {
+ return key == entry.Key;
+ });
}
// Create new cmCursesCacheEntryComposite entries from the cache
@@ -92,11 +78,10 @@ void cmCursesMainForm::InitializeUI()
{
// Create a vector of cmCursesCacheEntryComposite's
// which contain labels, entries and new entry markers
- std::vector<cmCursesCacheEntryComposite*>* newEntries =
- new std::vector<cmCursesCacheEntryComposite*>;
+ std::vector<cmCursesCacheEntryComposite> newEntries;
std::vector<std::string> cacheKeys =
this->CMakeInstance->GetState()->GetCacheEntryKeys();
- newEntries->reserve(cacheKeys.size());
+ newEntries.reserve(cacheKeys.size());
// Count non-internal and non-static entries
int count = 0;
@@ -112,13 +97,12 @@ void cmCursesMainForm::InitializeUI()
int entrywidth = this->InitialWidth - 35;
- cmCursesCacheEntryComposite* comp;
if (count == 0) {
// If cache is empty, display a label saying so and a
// dummy entry widget (does not respond to input)
- comp = new cmCursesCacheEntryComposite("EMPTY CACHE", 30, 30);
- comp->Entry = new cmCursesDummyWidget(1, 1, 1, 1);
- newEntries->push_back(comp);
+ cmCursesCacheEntryComposite comp("EMPTY CACHE", 30, 30);
+ comp.Entry = cm::make_unique<cmCursesDummyWidget>(1, 1, 1, 1);
+ newEntries.emplace_back(std::move(comp));
} else {
// Create the composites.
@@ -132,8 +116,8 @@ void cmCursesMainForm::InitializeUI()
}
if (!this->LookForCacheEntry(key)) {
- newEntries->push_back(new cmCursesCacheEntryComposite(
- key, this->CMakeInstance, true, 30, entrywidth));
+ newEntries.emplace_back(key, this->CMakeInstance->GetState(), true, 30,
+ entrywidth);
this->OkToGenerate = false;
}
}
@@ -148,18 +132,14 @@ void cmCursesMainForm::InitializeUI()
}
if (this->LookForCacheEntry(key)) {
- newEntries->push_back(new cmCursesCacheEntryComposite(
- key, this->CMakeInstance, false, 30, entrywidth));
+ newEntries.emplace_back(key, this->CMakeInstance->GetState(), false,
+ 30, entrywidth);
}
}
}
- // Clean old entries
- if (this->Entries) {
- cmDeleteAll(*this->Entries);
- }
- delete this->Entries;
- this->Entries = newEntries;
+ // Replace old entries
+ this->Entries = std::move(newEntries);
// Compute fields from composites
this->RePost();
@@ -173,18 +153,18 @@ void cmCursesMainForm::RePost()
free_form(this->Form);
this->Form = nullptr;
}
- delete[] this->Fields;
+ this->Fields.clear();
if (this->AdvancedMode) {
- this->NumberOfVisibleEntries = this->Entries->size();
+ this->NumberOfVisibleEntries = this->Entries.size();
} else {
// If normal mode, count only non-advanced entries
this->NumberOfVisibleEntries = 0;
- for (cmCursesCacheEntryComposite* entry : *this->Entries) {
+ for (cmCursesCacheEntryComposite& entry : this->Entries) {
const char* existingValue =
- this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
+ this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
bool advanced =
this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
- entry->GetValue(), "ADVANCED");
+ entry.GetValue(), "ADVANCED");
if (!existingValue || (!this->AdvancedMode && advanced)) {
continue;
}
@@ -197,38 +177,32 @@ void cmCursesMainForm::RePost()
}
// Assign the fields: 3 for each entry: label, new entry marker
// ('*' or ' ') and entry widget
- this->Fields = new FIELD*[3 * this->NumberOfVisibleEntries + 1];
- size_t cc;
- for (cc = 0; cc < 3 * this->NumberOfVisibleEntries + 1; cc++) {
- this->Fields[cc] = nullptr;
- }
+ this->Fields.reserve(3 * this->NumberOfVisibleEntries + 1);
// Assign fields
- int j = 0;
- for (cmCursesCacheEntryComposite* entry : *this->Entries) {
+ for (cmCursesCacheEntryComposite& entry : this->Entries) {
const char* existingValue =
- this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
+ this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
bool advanced =
this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
- entry->GetValue(), "ADVANCED");
+ entry.GetValue(), "ADVANCED");
if (!existingValue || (!this->AdvancedMode && advanced)) {
continue;
}
- this->Fields[3 * j] = entry->Label->Field;
- this->Fields[3 * j + 1] = entry->IsNewLabel->Field;
- this->Fields[3 * j + 2] = entry->Entry->Field;
- j++;
+ this->Fields.push_back(entry.Label->Field);
+ this->Fields.push_back(entry.IsNewLabel->Field);
+ this->Fields.push_back(entry.Entry->Field);
}
// if no cache entries there should still be one dummy field
- if (j == 0) {
- const auto& front = *this->Entries->front();
- this->Fields[0] = front.Label->Field;
- this->Fields[1] = front.IsNewLabel->Field;
- this->Fields[2] = front.Entry->Field;
+ if (this->Fields.empty()) {
+ const auto& front = this->Entries.front();
+ this->Fields.push_back(front.Label->Field);
+ this->Fields.push_back(front.IsNewLabel->Field);
+ this->Fields.push_back(front.Entry->Field);
this->NumberOfVisibleEntries = 1;
}
// Has to be null terminated.
- this->Fields[3 * this->NumberOfVisibleEntries] = nullptr;
+ this->Fields.push_back(nullptr);
}
void cmCursesMainForm::Render(int left, int top, int width, int height)
@@ -261,16 +235,16 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
height -= 7;
if (this->AdvancedMode) {
- this->NumberOfVisibleEntries = this->Entries->size();
+ this->NumberOfVisibleEntries = this->Entries.size();
} else {
// If normal, display only non-advanced entries
this->NumberOfVisibleEntries = 0;
- for (cmCursesCacheEntryComposite* entry : *this->Entries) {
+ for (cmCursesCacheEntryComposite& entry : this->Entries) {
const char* existingValue =
- this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
+ this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
bool advanced =
this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
- entry->GetValue(), "ADVANCED");
+ entry.GetValue(), "ADVANCED");
if (!existingValue || (!this->AdvancedMode && advanced)) {
continue;
}
@@ -283,12 +257,12 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
if (height > 0) {
bool isNewPage;
int i = 0;
- for (cmCursesCacheEntryComposite* entry : *this->Entries) {
+ for (cmCursesCacheEntryComposite& entry : this->Entries) {
const char* existingValue =
- this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
+ this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
bool advanced =
this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
- entry->GetValue(), "ADVANCED");
+ entry.GetValue(), "ADVANCED");
if (!existingValue || (!this->AdvancedMode && advanced)) {
continue;
}
@@ -299,16 +273,16 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
if (isNewPage) {
this->NumberOfPages++;
}
- entry->Label->Move(left, top + row - 1, isNewPage);
- entry->IsNewLabel->Move(left + 32, top + row - 1, false);
- entry->Entry->Move(left + 33, top + row - 1, false);
- entry->Entry->SetPage(this->NumberOfPages);
+ entry.Label->Move(left, top + row - 1, isNewPage);
+ entry.IsNewLabel->Move(left + 32, top + row - 1, false);
+ entry.Entry->Move(left + 33, top + row - 1, false);
+ entry.Entry->SetPage(this->NumberOfPages);
i++;
}
}
// Post the form
- this->Form = new_form(this->Fields);
+ this->Form = new_form(this->Fields.data());
post_form(this->Form);
// Update toolbar
this->UpdateStatusBar();
@@ -655,28 +629,28 @@ void cmCursesMainForm::RemoveEntry(const char* value)
}
auto removeIt =
- std::find_if(this->Entries->begin(), this->Entries->end(),
- [value](cmCursesCacheEntryComposite* entry) -> bool {
- const char* val = entry->GetValue();
+ std::find_if(this->Entries.begin(), this->Entries.end(),
+ [value](cmCursesCacheEntryComposite& entry) -> bool {
+ const char* val = entry.GetValue();
return val != nullptr && !strcmp(value, val);
});
- if (removeIt != this->Entries->end()) {
+ if (removeIt != this->Entries.end()) {
this->CMakeInstance->UnwatchUnusedCli(value);
- this->Entries->erase(removeIt);
+ this->Entries.erase(removeIt);
}
}
// copy from the list box to the cache manager
void cmCursesMainForm::FillCacheManagerFromUI()
{
- for (cmCursesCacheEntryComposite* entry : *this->Entries) {
- const std::string& cacheKey = entry->Key;
+ for (cmCursesCacheEntryComposite& entry : this->Entries) {
+ const std::string& cacheKey = entry.Key;
const char* existingValue =
this->CMakeInstance->GetState()->GetCacheEntryValue(cacheKey);
if (existingValue) {
std::string oldValue = existingValue;
- std::string newValue = entry->Entry->GetValue();
+ std::string newValue = entry.Entry->GetValue();
std::string fixedOldValue;
std::string fixedNewValue;
cmStateEnums::CacheEntryType t =
@@ -762,7 +736,7 @@ void cmCursesMainForm::HandleInput()
this->JumpToCacheEntry(this->SearchString.c_str());
this->OldSearchString = this->SearchString;
}
- this->SearchString = "";
+ this->SearchString.clear();
}
/*
else if ( key == KEY_ESCAPE )
@@ -778,7 +752,7 @@ void cmCursesMainForm::HandleInput()
}
} else if (key == ctrl('h') || key == KEY_BACKSPACE || key == KEY_DC) {
if (!this->SearchString.empty()) {
- this->SearchString.resize(this->SearchString.size() - 1);
+ this->SearchString.pop_back();
}
}
} else if (currentWidget && !this->SearchMode) {
@@ -867,17 +841,9 @@ void cmCursesMainForm::HandleInput()
curField, "HELPSTRING");
}
if (helpString) {
- char* message = new char
- [strlen(curField) + strlen(helpString) +
- strlen(
- "Current option is: \n Help string for this option is: \n") +
- 10];
- sprintf(
- message,
- "Current option is: %s\nHelp string for this option is: %s\n",
- curField, helpString);
- this->HelpMessage[1] = message;
- delete[] message;
+ this->HelpMessage[1] =
+ cmStrCat("Current option is: ", curField, '\n',
+ "Help string for this option is: ", helpString, '\n');
} else {
this->HelpMessage[1] = "";
}
@@ -973,14 +939,14 @@ void cmCursesMainForm::HandleInput()
if (nextCur) {
// make the next or prev. current field after deletion
- auto nextEntryIt =
- std::find_if(this->Entries->begin(), this->Entries->end(),
- [&nextVal](cmCursesCacheEntryComposite* entry) {
- return nextVal == entry->Key;
- });
-
- if (nextEntryIt != this->Entries->end()) {
- set_current_field(this->Form, (*nextEntryIt)->Entry->Field);
+ auto nextEntryIt = std::find_if(
+ this->Entries.begin(), this->Entries.end(),
+ [&nextVal](cmCursesCacheEntryComposite const& entry) {
+ return nextVal == entry.Key;
+ });
+
+ if (nextEntryIt != this->Entries.end()) {
+ set_current_field(this->Form, nextEntryIt->Entry->Field);
}
}
}
diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h
index f3194ab..48d1791 100644
--- a/Source/CursesDialog/cmCursesMainForm.h
+++ b/Source/CursesDialog/cmCursesMainForm.h
@@ -5,15 +5,16 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmCursesCacheEntryComposite.h"
#include "cmCursesForm.h"
#include "cmCursesStandardIncludes.h"
#include "cmStateTypes.h"
#include <cstddef>
+#include <memory>
#include <string>
#include <vector>
-class cmCursesCacheEntryComposite;
class cmake;
/** \class cmCursesMainForm
@@ -122,7 +123,7 @@ protected:
void JumpToCacheEntry(const char* str);
// Copies of cache entries stored in the user interface
- std::vector<cmCursesCacheEntryComposite*>* Entries;
+ std::vector<cmCursesCacheEntryComposite> Entries;
// Errors produced during last run of cmake
std::vector<std::string> Errors;
// Command line arguments to be passed to cmake each time
@@ -136,11 +137,7 @@ protected:
static const char* s_ConstHelpMessage;
// Fields displayed. Includes labels, new entry markers, entries
- FIELD** Fields;
- // Where is source of current project
- std::string WhereSource;
- // Where is cmake executable
- std::string WhereCMake;
+ std::vector<FIELD*> Fields;
// Number of entries shown (depends on mode -normal or advanced-)
size_t NumberOfVisibleEntries;
bool AdvancedMode;
@@ -150,7 +147,7 @@ protected:
int NumberOfPages;
int InitialWidth;
- cmake* CMakeInstance;
+ std::unique_ptr<cmake> CMakeInstance;
std::string SearchString;
std::string OldSearchString;
diff --git a/Source/CursesDialog/cmCursesStringWidget.cxx b/Source/CursesDialog/cmCursesStringWidget.cxx
index 3fc1858..d3a05e8 100644
--- a/Source/CursesDialog/cmCursesStringWidget.cxx
+++ b/Source/CursesDialog/cmCursesStringWidget.cxx
@@ -9,7 +9,6 @@
#include "cmStateTypes.h"
#include <cstdio>
-#include <cstring>
inline int ctrl(int z)
{
@@ -35,13 +34,13 @@ void cmCursesStringWidget::OnTab(cmCursesMainForm* /*unused*/,
void cmCursesStringWidget::OnReturn(cmCursesMainForm* fm, WINDOW* /*unused*/)
{
- FORM* form = fm->GetForm();
if (this->InEdit) {
cmCursesForm::LogMessage("String widget leaving edit.");
this->InEdit = false;
fm->PrintKeys();
- delete[] this->OriginalString;
+ this->OriginalString.clear();
// trick to force forms to update the field buffer
+ FORM* form = fm->GetForm();
form_driver(form, REQ_NEXT_FIELD);
form_driver(form, REQ_PREV_FIELD);
this->Done = true;
@@ -49,9 +48,7 @@ void cmCursesStringWidget::OnReturn(cmCursesMainForm* fm, WINDOW* /*unused*/)
cmCursesForm::LogMessage("String widget entering edit.");
this->InEdit = true;
fm->PrintKeys();
- char* buf = field_buffer(this->Field, 0);
- this->OriginalString = new char[strlen(buf) + 1];
- strcpy(this->OriginalString, buf);
+ this->OriginalString = field_buffer(this->Field, 0);
}
}
@@ -75,7 +72,7 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
return false;
}
- this->OriginalString = nullptr;
+ this->OriginalString.clear();
this->Done = false;
char debugMessage[128];
@@ -113,7 +110,7 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
key == ctrl('p') || key == KEY_NPAGE || key == ctrl('d') ||
key == KEY_PPAGE || key == ctrl('u')) {
this->InEdit = false;
- delete[] this->OriginalString;
+ this->OriginalString.clear();
// trick to force forms to update the field buffer
form_driver(form, REQ_NEXT_FIELD);
form_driver(form, REQ_PREV_FIELD);
@@ -125,7 +122,7 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
this->InEdit = false;
fm->PrintKeys();
this->SetString(this->OriginalString);
- delete[] this->OriginalString;
+ this->OriginalString.clear();
touchwin(w);
wrefresh(w);
return true;
@@ -188,23 +185,18 @@ bool cmCursesStringWidget::PrintKeys()
}
if (this->InEdit) {
char fmt_s[] = "%s";
- char firstLine[512];
// Clean the toolbar
- memset(firstLine, ' ', sizeof(firstLine));
- firstLine[511] = '\0';
curses_move(y - 4, 0);
- printw(fmt_s, firstLine);
- curses_move(y - 3, 0);
- printw(fmt_s, firstLine);
- curses_move(y - 2, 0);
- printw(fmt_s, firstLine);
- curses_move(y - 1, 0);
- printw(fmt_s, firstLine);
-
+ clrtoeol();
curses_move(y - 3, 0);
printw(fmt_s, "Editing option, press [enter] to confirm");
+ clrtoeol();
curses_move(y - 2, 0);
printw(fmt_s, " press [esc] to cancel");
+ clrtoeol();
+ curses_move(y - 1, 0);
+ clrtoeol();
+
return true;
}
return false;
diff --git a/Source/CursesDialog/cmCursesStringWidget.h b/Source/CursesDialog/cmCursesStringWidget.h
index 021515b..a41f0e8 100644
--- a/Source/CursesDialog/cmCursesStringWidget.h
+++ b/Source/CursesDialog/cmCursesStringWidget.h
@@ -23,9 +23,6 @@ class cmCursesStringWidget : public cmCursesWidget
public:
cmCursesStringWidget(int width, int height, int left, int top);
- cmCursesStringWidget(cmCursesStringWidget const&) = delete;
- cmCursesStringWidget& operator=(cmCursesStringWidget const&) = delete;
-
/**
* Handle user input. Called by the container of this widget
* when this widget has focus. Returns true if the input was
@@ -65,7 +62,7 @@ public:
protected:
// true if the widget is in edit mode
bool InEdit;
- char* OriginalString;
+ std::string OriginalString;
bool Done;
};
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 641cbaf..5a35007 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -707,7 +707,8 @@ struct CompilerIdNode : public cmGeneratorExpressionNode
};
static const CompilerIdNode cCompilerIdNode("C"), cxxCompilerIdNode("CXX"),
- cudaCompilerIdNode("CUDA"), fortranCompilerIdNode("Fortran");
+ cudaCompilerIdNode("CUDA"), objcCompilerIdNode("OBJC"),
+ objcxxCompilerIdNode("OBJCXX"), fortranCompilerIdNode("Fortran");
struct CompilerVersionNode : public cmGeneratorExpressionNode
{
@@ -771,6 +772,7 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode
static const CompilerVersionNode cCompilerVersionNode("C"),
cxxCompilerVersionNode("CXX"), cudaCompilerVersionNode("CUDA"),
+ objcCompilerVersionNode("OBJC"), objcxxCompilerVersionNode("OBJCXX"),
fortranCompilerVersionNode("Fortran");
struct PlatformIdNode : public cmGeneratorExpressionNode
@@ -2243,6 +2245,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
{ "NOT", &notNode },
{ "C_COMPILER_ID", &cCompilerIdNode },
{ "CXX_COMPILER_ID", &cxxCompilerIdNode },
+ { "OBJC_COMPILER_ID", &objcCompilerIdNode },
+ { "OBJCXX_COMPILER_ID", &objcxxCompilerIdNode },
{ "CUDA_COMPILER_ID", &cudaCompilerIdNode },
{ "Fortran_COMPILER_ID", &fortranCompilerIdNode },
{ "VERSION_GREATER", &versionGreaterNode },
@@ -2253,6 +2257,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
{ "C_COMPILER_VERSION", &cCompilerVersionNode },
{ "CXX_COMPILER_VERSION", &cxxCompilerVersionNode },
{ "CUDA_COMPILER_VERSION", &cudaCompilerVersionNode },
+ { "OBJC_COMPILER_VERSION", &objcCompilerVersionNode },
+ { "OBJCXX_COMPILER_VERSION", &objcxxCompilerVersionNode },
{ "Fortran_COMPILER_VERSION", &fortranCompilerVersionNode },
{ "PLATFORM_ID", &platformIdNode },
{ "COMPILE_FEATURES", &compileFeaturesNode },
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 7af3da5..6e6ca51 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1655,7 +1655,7 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
const char* deploymentTargetFlag =
this->Makefile->GetDefinition(deploymentTargetFlagVar);
if (!archs.empty() && !lang.empty() &&
- (lang[0] == 'C' || lang[0] == 'F')) {
+ (lang[0] == 'C' || lang[0] == 'F' || lang[0] == 'O')) {
for (std::string const& arch : archs) {
flags += " -arch ";
flags += arch;
@@ -1942,10 +1942,20 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
langStdMap["CXX"].emplace_back("11");
langStdMap["CXX"].emplace_back("98");
+ langStdMap["OBJCXX"].emplace_back("20");
+ langStdMap["OBJCXX"].emplace_back("17");
+ langStdMap["OBJCXX"].emplace_back("14");
+ langStdMap["OBJCXX"].emplace_back("11");
+ langStdMap["OBJCXX"].emplace_back("98");
+
langStdMap["C"].emplace_back("11");
langStdMap["C"].emplace_back("99");
langStdMap["C"].emplace_back("90");
+ langStdMap["OBJC"].emplace_back("11");
+ langStdMap["OBJC"].emplace_back("99");
+ langStdMap["OBJC"].emplace_back("90");
+
langStdMap["CUDA"].emplace_back("14");
langStdMap["CUDA"].emplace_back("11");
langStdMap["CUDA"].emplace_back("98");
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 640f823..d9fbe9d 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -38,6 +38,7 @@
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetLinkLibraryType.h"
@@ -4627,9 +4628,9 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
target->AppendProperty("COMPILE_FEATURES", feature.c_str());
- return lang == "C"
- ? this->AddRequiredTargetCFeature(target, feature, error)
- : this->AddRequiredTargetCxxFeature(target, feature, error);
+ return lang == "C" || lang == "OBJC"
+ ? this->AddRequiredTargetCFeature(target, feature, lang, error)
+ : this->AddRequiredTargetCxxFeature(target, feature, lang, error);
}
bool cmMakefile::CompileFeatureKnown(cmTarget const* target,
@@ -4721,30 +4722,33 @@ bool cmMakefile::HaveStandardAvailable(cmTarget const* target,
std::string const& lang,
const std::string& feature) const
{
- return lang == "C" ? this->HaveCStandardAvailable(target, feature)
- : this->HaveCxxStandardAvailable(target, feature);
+ return lang == "C" || lang == "OBJC"
+ ? this->HaveCStandardAvailable(target, feature, lang)
+ : this->HaveCxxStandardAvailable(target, feature, lang);
}
bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
- const std::string& feature) const
+ const std::string& feature,
+ std::string const& lang) const
{
const char* defaultCStandard =
- this->GetDefinition("CMAKE_C_STANDARD_DEFAULT");
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
if (!defaultCStandard) {
this->IssueMessage(
MessageType::INTERNAL_ERROR,
- "CMAKE_C_STANDARD_DEFAULT is not set. COMPILE_FEATURES support "
- "not fully configured for this compiler.");
+ cmStrCat("CMAKE_", lang,
+ "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support "
+ "not fully configured for this compiler."));
// Return true so the caller does not try to lookup the default standard.
return true;
}
if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
cmStrCmp(defaultCStandard)) == cm::cend(C_STANDARDS)) {
- std::ostringstream e;
- e << "The CMAKE_C_STANDARD_DEFAULT variable contains an "
- "invalid value: \""
- << defaultCStandard << "\".";
- this->IssueMessage(MessageType::INTERNAL_ERROR, e.str());
+ const std::string e = cmStrCat("The CMAKE_", lang,
+ "_STANDARD_DEFAULT variable contains an "
+ "invalid value: \"",
+ defaultCStandard, "\".");
+ this->IssueMessage(MessageType::INTERNAL_ERROR, e);
return false;
}
@@ -4752,19 +4756,20 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
bool needC99 = false;
bool needC11 = false;
- this->CheckNeededCLanguage(feature, needC90, needC99, needC11);
+ this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11);
- const char* existingCStandard = target->GetProperty("C_STANDARD");
+ const char* existingCStandard =
+ target->GetProperty(cmStrCat(lang, "_STANDARD"));
if (!existingCStandard) {
existingCStandard = defaultCStandard;
}
if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) {
- std::ostringstream e;
- e << "The C_STANDARD property on target \"" << target->GetName()
- << "\" contained an invalid value: \"" << existingCStandard << "\".";
- this->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ const std::string e = cmStrCat(
+ "The ", lang, "_STANDARD property on target \"", target->GetName(),
+ "\" contained an invalid value: \"", existingCStandard, "\".");
+ this->IssueMessage(MessageType::FATAL_ERROR, e);
return false;
}
@@ -4795,7 +4800,7 @@ bool cmMakefile::IsLaterStandard(std::string const& lang,
std::string const& lhs,
std::string const& rhs)
{
- if (lang == "C") {
+ if (lang == "C" || lang == "OBJC") {
const char* const* rhsIt = std::find_if(
cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), cmStrCmp(rhs));
@@ -4810,25 +4815,26 @@ bool cmMakefile::IsLaterStandard(std::string const& lang,
}
bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
- const std::string& feature) const
+ const std::string& feature,
+ std::string const& lang) const
{
const char* defaultCxxStandard =
- this->GetDefinition("CMAKE_CXX_STANDARD_DEFAULT");
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
if (!defaultCxxStandard) {
this->IssueMessage(
MessageType::INTERNAL_ERROR,
- "CMAKE_CXX_STANDARD_DEFAULT is not set. COMPILE_FEATURES support "
- "not fully configured for this compiler.");
+ cmStrCat("CMAKE_", lang,
+ "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support "
+ "not fully configured for this compiler."));
// Return true so the caller does not try to lookup the default standard.
return true;
}
if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
cmStrCmp(defaultCxxStandard)) == cm::cend(CXX_STANDARDS)) {
- std::ostringstream e;
- e << "The CMAKE_CXX_STANDARD_DEFAULT variable contains an "
- "invalid value: \""
- << defaultCxxStandard << "\".";
- this->IssueMessage(MessageType::INTERNAL_ERROR, e.str());
+ const std::string e =
+ cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ",
+ "invalid value: \"", defaultCxxStandard, "\".");
+ this->IssueMessage(MessageType::INTERNAL_ERROR, e);
return false;
}
@@ -4837,10 +4843,11 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
bool needCxx14 = false;
bool needCxx17 = false;
bool needCxx20 = false;
- this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14,
+ this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14,
needCxx17, needCxx20);
- const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
+ const char* existingCxxStandard =
+ target->GetProperty(cmStrCat(lang, "_STANDARD"));
if (!existingCxxStandard) {
existingCxxStandard = defaultCxxStandard;
}
@@ -4849,10 +4856,10 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
cmStrCmp(existingCxxStandard));
if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
- std::ostringstream e;
- e << "The CXX_STANDARD property on target \"" << target->GetName()
- << "\" contained an invalid value: \"" << existingCxxStandard << "\".";
- this->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ const std::string e = cmStrCat(
+ "The ", lang, "_STANDARD property on target \"", target->GetName(),
+ "\" contained an invalid value: \"", existingCxxStandard, "\".");
+ this->IssueMessage(MessageType::FATAL_ERROR, e);
return false;
}
@@ -4870,32 +4877,33 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
}
void cmMakefile::CheckNeededCxxLanguage(const std::string& feature,
+ std::string const& lang,
bool& needCxx98, bool& needCxx11,
bool& needCxx14, bool& needCxx17,
bool& needCxx20) const
{
if (const char* propCxx98 =
- this->GetDefinition("CMAKE_CXX98_COMPILE_FEATURES")) {
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "98_COMPILE_FEATURES"))) {
std::vector<std::string> props = cmExpandedList(propCxx98);
needCxx98 = cmContains(props, feature);
}
if (const char* propCxx11 =
- this->GetDefinition("CMAKE_CXX11_COMPILE_FEATURES")) {
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) {
std::vector<std::string> props = cmExpandedList(propCxx11);
needCxx11 = cmContains(props, feature);
}
if (const char* propCxx14 =
- this->GetDefinition("CMAKE_CXX14_COMPILE_FEATURES")) {
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "14_COMPILE_FEATURES"))) {
std::vector<std::string> props = cmExpandedList(propCxx14);
needCxx14 = cmContains(props, feature);
}
if (const char* propCxx17 =
- this->GetDefinition("CMAKE_CXX17_COMPILE_FEATURES")) {
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "17_COMPILE_FEATURES"))) {
std::vector<std::string> props = cmExpandedList(propCxx17);
needCxx17 = cmContains(props, feature);
}
if (const char* propCxx20 =
- this->GetDefinition("CMAKE_CXX20_COMPILE_FEATURES")) {
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "20_COMPILE_FEATURES"))) {
std::vector<std::string> props = cmExpandedList(propCxx20);
needCxx20 = cmContains(props, feature);
}
@@ -4903,6 +4911,7 @@ void cmMakefile::CheckNeededCxxLanguage(const std::string& feature,
bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
const std::string& feature,
+ std::string const& lang,
std::string* error) const
{
bool needCxx98 = false;
@@ -4911,13 +4920,14 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
bool needCxx17 = false;
bool needCxx20 = false;
- this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14,
+ this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14,
needCxx17, needCxx20);
- const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
+ const char* existingCxxStandard =
+ target->GetProperty(cmStrCat(lang, "_STANDARD"));
if (existingCxxStandard == nullptr) {
const char* defaultCxxStandard =
- this->GetDefinition("CMAKE_CXX_STANDARD_DEFAULT");
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
if (defaultCxxStandard && *defaultCxxStandard) {
existingCxxStandard = defaultCxxStandard;
}
@@ -4928,14 +4938,14 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
cmStrCmp(existingCxxStandard));
if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
- std::ostringstream e;
- e << "The CXX_STANDARD property on target \"" << target->GetName()
- << "\" contained an invalid value: \"" << existingCxxStandard << "\".";
+ const std::string e = cmStrCat(
+ "The ", lang, "_STANDARD property on target \"", target->GetName(),
+ "\" contained an invalid value: \"", existingCxxStandard, "\".");
if (error) {
- *error = e.str();
+ *error = e;
} else {
- this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
- e.str(), this->Backtrace);
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
+ this->Backtrace);
}
return false;
}
@@ -4976,7 +4986,7 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
// Ensure the C++ language level is high enough to support
// the needed C++ features.
if (!existingCxxLevel || existingCxxLevel < needCxxLevel) {
- target->SetProperty("CXX_STANDARD", *needCxxLevel);
+ target->SetProperty(cmStrCat(lang, "_STANDARD"), *needCxxLevel);
}
// Ensure the CUDA language level is high enough to support
@@ -4990,21 +5000,21 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
}
void cmMakefile::CheckNeededCLanguage(const std::string& feature,
- bool& needC90, bool& needC99,
- bool& needC11) const
+ std::string const& lang, bool& needC90,
+ bool& needC99, bool& needC11) const
{
if (const char* propC90 =
- this->GetDefinition("CMAKE_C90_COMPILE_FEATURES")) {
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "90_COMPILE_FEATURES"))) {
std::vector<std::string> props = cmExpandedList(propC90);
needC90 = cmContains(props, feature);
}
if (const char* propC99 =
- this->GetDefinition("CMAKE_C99_COMPILE_FEATURES")) {
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "99_COMPILE_FEATURES"))) {
std::vector<std::string> props = cmExpandedList(propC99);
needC99 = cmContains(props, feature);
}
if (const char* propC11 =
- this->GetDefinition("CMAKE_C11_COMPILE_FEATURES")) {
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) {
std::vector<std::string> props = cmExpandedList(propC11);
needC11 = cmContains(props, feature);
}
@@ -5012,18 +5022,20 @@ void cmMakefile::CheckNeededCLanguage(const std::string& feature,
bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
const std::string& feature,
+ std::string const& lang,
std::string* error) const
{
bool needC90 = false;
bool needC99 = false;
bool needC11 = false;
- this->CheckNeededCLanguage(feature, needC90, needC99, needC11);
+ this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11);
- const char* existingCStandard = target->GetProperty("C_STANDARD");
+ const char* existingCStandard =
+ target->GetProperty(cmStrCat(lang, "_STANDARD"));
if (existingCStandard == nullptr) {
const char* defaultCStandard =
- this->GetDefinition("CMAKE_C_STANDARD_DEFAULT");
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
if (defaultCStandard && *defaultCStandard) {
existingCStandard = defaultCStandard;
}
@@ -5031,14 +5043,14 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
if (existingCStandard) {
if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) {
- std::ostringstream e;
- e << "The C_STANDARD property on target \"" << target->GetName()
- << "\" contained an invalid value: \"" << existingCStandard << "\".";
+ const std::string e = cmStrCat(
+ "The ", lang, "_STANDARD property on target \"", target->GetName(),
+ "\" contained an invalid value: \"", existingCStandard, "\".");
if (error) {
- *error = e.str();
+ *error = e;
} else {
- this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
- e.str(), this->Backtrace);
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
+ this->Backtrace);
}
return false;
}
@@ -5069,11 +5081,11 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
}
if (setC11) {
- target->SetProperty("C_STANDARD", "11");
+ target->SetProperty(cmStrCat(lang, "_STANDARD"), "11");
} else if (setC99) {
- target->SetProperty("C_STANDARD", "99");
+ target->SetProperty(cmStrCat(lang, "_STANDARD"), "99");
} else if (setC90) {
- target->SetProperty("C_STANDARD", "90");
+ target->SetProperty(cmStrCat(lang, "_STANDARD"), "90");
}
return true;
}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index bb88bed..3a17aaf 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -1146,22 +1146,28 @@ private:
bool MightHaveCustomCommand(const std::string& name) const;
bool AddRequiredTargetCFeature(cmTarget* target, const std::string& feature,
+ std::string const& lang,
std::string* error = nullptr) const;
bool AddRequiredTargetCxxFeature(cmTarget* target,
const std::string& feature,
+ std::string const& lang,
std::string* error = nullptr) const;
- void CheckNeededCLanguage(const std::string& feature, bool& needC90,
+ void CheckNeededCLanguage(const std::string& feature,
+ std::string const& lang, bool& needC90,
bool& needC99, bool& needC11) const;
- void CheckNeededCxxLanguage(const std::string& feature, bool& needCxx98,
+ void CheckNeededCxxLanguage(const std::string& feature,
+ std::string const& lang, bool& needCxx98,
bool& needCxx11, bool& needCxx14,
bool& needCxx17, bool& needCxx20) const;
bool HaveCStandardAvailable(cmTarget const* target,
- const std::string& feature) const;
+ const std::string& feature,
+ std::string const& lang) const;
bool HaveCxxStandardAvailable(cmTarget const* target,
- const std::string& feature) const;
+ const std::string& feature,
+ std::string const& lang) const;
void CheckForUnusedVariables() const;
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index a9d4fee..1320b07 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -210,79 +210,18 @@ cmQtAutoGenerator::cmQtAutoGenerator(GenT genType)
cmQtAutoGenerator::~cmQtAutoGenerator() = default;
-bool cmQtAutoGenerator::Run(std::string const& infoFile,
- std::string const& config)
+bool cmQtAutoGenerator::InfoT::Read(std::istream& istr)
{
- // Info settings
- InfoFile_ = infoFile;
- cmSystemTools::CollapseFullPath(InfoFile_);
- if (!InfoFileTime_.Load(InfoFile_)) {
- cmSystemTools::Stderr(cmStrCat("AutoGen: The info file ",
- Quoted(InfoFile_), " is not readable\n"));
- return false;
- }
- InfoDir_ = cmSystemTools::GetFilenamePath(infoFile);
- InfoConfig_ = config;
-
- // Read info file
- {
- cmsys::ifstream ifs(InfoFile_.c_str(), (std::ios::in | std::ios::binary));
- if (!ifs) {
- Log().Error(GenType_,
- cmStrCat("Could not to open info file ", Quoted(InfoFile_)));
- return false;
- }
- try {
- ifs >> Info_;
- } catch (...) {
- Log().Error(GenType_,
- cmStrCat("Could not read info file ", Quoted(InfoFile_)));
- return false;
- }
- }
- // Info: setup logger
- {
- unsigned int value = 0;
- if (!InfoUInt("VERBOSITY", value, false)) {
- return false;
- }
- Logger_.RaiseVerbosity(value);
- }
- // Info: setup project directories
- if (!InfoString("CMAKE_SOURCE_DIR", ProjectDirs_.Source, true) ||
- !InfoString("CMAKE_BINARY_DIR", ProjectDirs_.Binary, true) ||
- !InfoString("CMAKE_CURRENT_SOURCE_DIR", ProjectDirs_.CurrentSource,
- true) ||
- !InfoString("CMAKE_CURRENT_BINARY_DIR", ProjectDirs_.CurrentBinary,
- true)) {
- return false;
- }
-
- if (!this->InitFromInfo()) {
+ try {
+ istr >> Json_;
+ } catch (...) {
return false;
}
- // Clear info
- Info_ = Json::nullValue;
-
- return this->Process();
-}
-
-bool cmQtAutoGenerator::LogInfoError(GenT genType,
- cm::string_view message) const
-{
- this->Log().Error(
- genType,
- cmStrCat("Info error in info file\n", Quoted(InfoFile()), ":\n", message));
- return false;
-}
-
-bool cmQtAutoGenerator::LogInfoError(cm::string_view message) const
-{
- return LogInfoError(GenType_, message);
+ return true;
}
-bool cmQtAutoGenerator::JsonGetArray(std::vector<std::string>& list,
- Json::Value const& jval)
+bool cmQtAutoGenerator::InfoT::GetJsonArray(std::vector<std::string>& list,
+ Json::Value const& jval)
{
Json::ArrayIndex const arraySize = jval.size();
if (arraySize == 0) {
@@ -301,8 +240,8 @@ bool cmQtAutoGenerator::JsonGetArray(std::vector<std::string>& list,
return picked;
}
-bool cmQtAutoGenerator::JsonGetArray(std::unordered_set<std::string>& list,
- Json::Value const& jval)
+bool cmQtAutoGenerator::InfoT::GetJsonArray(
+ std::unordered_set<std::string>& list, Json::Value const& jval)
{
Json::ArrayIndex const arraySize = jval.size();
if (arraySize == 0) {
@@ -321,141 +260,157 @@ bool cmQtAutoGenerator::JsonGetArray(std::unordered_set<std::string>& list,
return picked;
}
-std::string cmQtAutoGenerator::InfoConfigKey(std::string const& key) const
+std::string cmQtAutoGenerator::InfoT::ConfigKey(cm::string_view key) const
{
- return cmStrCat(key, '_', InfoConfig());
+ return cmStrCat(key, '_', Gen_.InfoConfig());
}
-bool cmQtAutoGenerator::InfoString(std::string const& key, std::string& value,
- bool required) const
+bool cmQtAutoGenerator::InfoT::GetString(std::string const& key,
+ std::string& value,
+ bool required) const
{
- Json::Value const& jval = Info()[key];
+ Json::Value const& jval = Json_[key];
if (!jval.isString()) {
if (!jval.isNull() || required) {
- return LogInfoError(cmStrCat(key, " is not a string."));
+ return LogError(cmStrCat(key, " is not a string."));
}
} else {
value = jval.asString();
if (value.empty() && required) {
- return LogInfoError(cmStrCat(key, " is empty."));
+ return LogError(cmStrCat(key, " is empty."));
}
}
return true;
}
-bool cmQtAutoGenerator::InfoStringConfig(std::string const& key,
- std::string& value,
-
- bool required) const
+bool cmQtAutoGenerator::InfoT::GetStringConfig(std::string const& key,
+ std::string& value,
+ bool required) const
{
{ // Try config
- std::string const configKey = InfoConfigKey(key);
- Json::Value const& jval = Info_[configKey];
+ std::string const configKey = ConfigKey(key);
+ Json::Value const& jval = Json_[configKey];
if (!jval.isNull()) {
if (!jval.isString()) {
- return LogInfoError(cmStrCat(configKey, " is not a string."));
+ return LogError(cmStrCat(configKey, " is not a string."));
}
value = jval.asString();
if (required && value.empty()) {
- return LogInfoError(cmStrCat(configKey, " is empty."));
+ return LogError(cmStrCat(configKey, " is empty."));
}
return true;
}
}
// Try plain
- return InfoString(key, value, required);
+ return GetString(key, value, required);
}
-bool cmQtAutoGenerator::InfoBool(std::string const& key, bool& value,
- bool required) const
+bool cmQtAutoGenerator::InfoT::GetBool(std::string const& key, bool& value,
+ bool required) const
{
- Json::Value const& jval = Info()[key];
+ Json::Value const& jval = Json_[key];
if (jval.isBool()) {
value = jval.asBool();
} else {
if (!jval.isNull() || required) {
- return LogInfoError(cmStrCat(key, " is not a boolean."));
+ return LogError(cmStrCat(key, " is not a boolean."));
}
}
return true;
}
-bool cmQtAutoGenerator::InfoUInt(std::string const& key, unsigned int& value,
- bool required) const
+bool cmQtAutoGenerator::InfoT::GetUInt(std::string const& key,
+ unsigned int& value,
+ bool required) const
{
- Json::Value const& jval = Info()[key];
+ Json::Value const& jval = Json_[key];
if (jval.isUInt()) {
value = jval.asUInt();
} else {
if (!jval.isNull() || required) {
- return LogInfoError(cmStrCat(key, " is not an unsigned integer."));
+ return LogError(cmStrCat(key, " is not an unsigned integer."));
}
}
return true;
}
-bool cmQtAutoGenerator::InfoArray(std::string const& key,
- std::vector<std::string>& list,
- bool required) const
+bool cmQtAutoGenerator::InfoT::GetArray(std::string const& key,
+ std::vector<std::string>& list,
+ bool required) const
{
- Json::Value const& jval = Info()[key];
+ Json::Value const& jval = Json_[key];
if (!jval.isArray()) {
if (!jval.isNull() || required) {
- return LogInfoError(cmStrCat(key, " is not an array."));
+ return LogError(cmStrCat(key, " is not an array."));
}
}
- return JsonGetArray(list, jval) || !required;
+ return GetJsonArray(list, jval) || !required;
}
-bool cmQtAutoGenerator::InfoArray(std::string const& key,
- std::unordered_set<std::string>& list,
- bool required) const
+bool cmQtAutoGenerator::InfoT::GetArray(std::string const& key,
+ std::unordered_set<std::string>& list,
+ bool required) const
{
- Json::Value const& jval = Info()[key];
+ Json::Value const& jval = Json_[key];
if (!jval.isArray()) {
if (!jval.isNull() || required) {
- return LogInfoError(cmStrCat(key, " is not an array."));
+ return LogError(cmStrCat(key, " is not an array."));
}
}
- return JsonGetArray(list, jval) || !required;
+ return GetJsonArray(list, jval) || !required;
}
-bool cmQtAutoGenerator::InfoArrayConfig(std::string const& key,
- std::vector<std::string>& list,
- bool required) const
+bool cmQtAutoGenerator::InfoT::GetArrayConfig(std::string const& key,
+ std::vector<std::string>& list,
+ bool required) const
{
{ // Try config
- std::string const configKey = InfoConfigKey(key);
- Json::Value const& jval = Info()[configKey];
+ std::string const configKey = ConfigKey(key);
+ Json::Value const& jval = Json_[configKey];
if (!jval.isNull()) {
if (!jval.isArray()) {
- return LogInfoError(cmStrCat(configKey, " is not an array string."));
+ return LogError(cmStrCat(configKey, " is not an array string."));
}
- if (!JsonGetArray(list, jval) && required) {
- return LogInfoError(cmStrCat(configKey, " is empty."));
+ if (!GetJsonArray(list, jval) && required) {
+ return LogError(cmStrCat(configKey, " is empty."));
}
return true;
}
}
// Try plain
- return InfoArray(key, list, required);
+ return GetArray(key, list, required);
+}
+
+bool cmQtAutoGenerator::InfoT::LogError(GenT genType,
+ cm::string_view message) const
+{
+ Gen_.Log().Error(genType,
+ cmStrCat("Info error in info file\n",
+ Quoted(Gen_.InfoFile()), ":\n", message));
+ return false;
}
-std::string cmQtAutoGenerator::SettingsFind(std::string const& content,
- const char* key)
+bool cmQtAutoGenerator::InfoT::LogError(cm::string_view message) const
{
- std::string prefix = cmStrCat(key, ':');
- std::string::size_type pos = content.find(prefix);
- if (pos != std::string::npos) {
+ return LogError(Gen_.GenType_, message);
+}
+
+std::string cmQtAutoGenerator::SettingsFind(cm::string_view content,
+ cm::string_view key)
+{
+ cm::string_view res;
+ std::string const prefix = cmStrCat(key, ':');
+ cm::string_view::size_type pos = content.find(prefix);
+ if (pos != cm::string_view::npos) {
pos += prefix.size();
if (pos < content.size()) {
- std::string::size_type posE = content.find('\n', pos);
- if ((posE != std::string::npos) && (posE != pos)) {
- return content.substr(pos, posE - pos);
+ cm::string_view::size_type posE = content.find('\n', pos);
+ if ((posE != cm::string_view::npos) && (posE != pos)) {
+ res = content.substr(pos, posE - pos);
}
}
}
- return std::string();
+ return std::string(res);
}
std::string cmQtAutoGenerator::MessagePath(cm::string_view path) const
@@ -470,3 +425,66 @@ std::string cmQtAutoGenerator::MessagePath(cm::string_view path) const
}
return cmQtAutoGen::Quoted(res);
}
+
+bool cmQtAutoGenerator::Run(cm::string_view infoFile, cm::string_view config)
+{
+ // Info config
+ InfoConfig_ = std::string(config);
+
+ // Info file
+ InfoFile_ = std::string(infoFile);
+ cmSystemTools::CollapseFullPath(InfoFile_);
+ InfoDir_ = cmSystemTools::GetFilenamePath(InfoFile_);
+
+ // Load info file time
+ if (!InfoFileTime_.Load(InfoFile_)) {
+ cmSystemTools::Stderr(cmStrCat("AutoGen: The info file ",
+ Quoted(InfoFile_), " is not readable\n"));
+ return false;
+ }
+
+ {
+ InfoT info(*this);
+
+ // Read info file
+ {
+ cmsys::ifstream ifs(InfoFile_.c_str(),
+ (std::ios::in | std::ios::binary));
+ if (!ifs) {
+ Log().Error(
+ GenType_,
+ cmStrCat("Could not to open info file ", Quoted(InfoFile_)));
+ return false;
+ }
+ if (!info.Read(ifs)) {
+ Log().Error(GenType_,
+ cmStrCat("Could not read info file ", Quoted(InfoFile_)));
+ return false;
+ }
+ }
+
+ // -- Read common info settings
+ {
+ unsigned int verbosity = 0;
+ // Info: setup project directories
+ if (!info.GetUInt("VERBOSITY", verbosity, false) ||
+ !info.GetString("CMAKE_SOURCE_DIR", ProjectDirs_.Source, true) ||
+ !info.GetString("CMAKE_BINARY_DIR", ProjectDirs_.Binary, true) ||
+ !info.GetString("CMAKE_CURRENT_SOURCE_DIR",
+ ProjectDirs_.CurrentSource, true) ||
+ !info.GetString("CMAKE_CURRENT_BINARY_DIR",
+ ProjectDirs_.CurrentBinary, true)) {
+ return false;
+ }
+ Logger_.RaiseVerbosity(verbosity);
+ }
+
+ // -- Call virtual init from info method.
+ if (!this->InitFromInfo(info)) {
+ return false;
+ }
+ }
+
+ // Call virtual process method.
+ return this->Process();
+}
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
index 7f83fc6..71ee9ce 100644
--- a/Source/cmQtAutoGenerator.h
+++ b/Source/cmQtAutoGenerator.h
@@ -11,6 +11,7 @@
#include <cm/string_view>
+#include <istream>
#include <mutex>
#include <string>
#include <unordered_set>
@@ -86,54 +87,78 @@ public:
cmQtAutoGenerator(cmQtAutoGenerator const&) = delete;
cmQtAutoGenerator& operator=(cmQtAutoGenerator const&) = delete;
- // -- Run
- bool Run(std::string const& infoFile, std::string const& config);
-
- // -- InfoFile
+ // -- Info options
std::string const& InfoFile() const { return InfoFile_; }
- Json::Value const& Info() const { return Info_; }
- cmFileTime const& InfoFileTime() const { return InfoFileTime_; }
std::string const& InfoDir() const { return InfoDir_; }
+ cmFileTime const& InfoFileTime() const { return InfoFileTime_; }
std::string const& InfoConfig() const { return InfoConfig_; }
- bool LogInfoError(GenT genType, cm::string_view message) const;
- bool LogInfoError(cm::string_view message) const;
+ // -- Info file parsing
+ /** Info file reader class. */
+ class InfoT
+ {
+ public:
+ InfoT(cmQtAutoGenerator& gen)
+ : Gen_(gen)
+ {
+ }
+
+ /** Read json data from a stream. */
+ bool Read(std::istream& istr);
+
+ /** Returns false if the JSON value isn't a string. */
+ bool GetString(std::string const& key, std::string& value,
+ bool required) const;
+ bool GetStringConfig(std::string const& key, std::string& value,
+ bool required) const;
+ bool GetBool(std::string const& key, bool& value, bool required) const;
+ bool GetUInt(std::string const& key, unsigned int& value,
+ bool required) const;
+ /** Returns false if the JSON value isn't an array. */
+ bool GetArray(std::string const& key, std::vector<std::string>& list,
+ bool required) const;
+ bool GetArray(std::string const& key,
+ std::unordered_set<std::string>& list, bool required) const;
+ bool GetArrayConfig(std::string const& key, std::vector<std::string>& list,
+ bool required) const;
- /** Returns true if strings were appended to the list. */
- static bool JsonGetArray(std::vector<std::string>& list,
- Json::Value const& jval);
- /** Returns true if strings were found in the JSON array. */
- static bool JsonGetArray(std::unordered_set<std::string>& list,
- Json::Value const& jval);
+ Json::Value const& GetValue(std::string const& key) const
+ {
+ return Json_[key];
+ }
- std::string InfoConfigKey(std::string const& key) const;
+ /** Returns true if strings were appended to the list. */
+ static bool GetJsonArray(std::vector<std::string>& list,
+ Json::Value const& jval);
+ /** Returns true if strings were found in the JSON array. */
+ static bool GetJsonArray(std::unordered_set<std::string>& list,
+ Json::Value const& jval);
- /** Returns false if the JSON value isn't a string. */
- bool InfoString(std::string const& key, std::string& value,
- bool required) const;
- bool InfoStringConfig(std::string const& key, std::string& value,
- bool required) const;
- bool InfoBool(std::string const& key, bool& value, bool required) const;
- bool InfoUInt(std::string const& key, unsigned int& value,
- bool required) const;
- /** Returns false if the JSON value isn't an array. */
- bool InfoArray(std::string const& key, std::vector<std::string>& list,
- bool required) const;
- bool InfoArray(std::string const& key, std::unordered_set<std::string>& list,
- bool required) const;
- bool InfoArrayConfig(std::string const& key, std::vector<std::string>& list,
- bool required) const;
+ bool LogError(GenT genType, cm::string_view message) const;
+ bool LogError(cm::string_view message) const;
+
+ private:
+ std::string ConfigKey(cm::string_view key) const;
+
+ private:
+ Json::Value Json_;
+ cmQtAutoGenerator& Gen_;
+ };
+
+ // -- Settings file
+ static std::string SettingsFind(cm::string_view content,
+ cm::string_view key);
// -- Directories
ProjectDirsT const& ProjectDirs() const { return ProjectDirs_; }
-
- // -- Utility
- static std::string SettingsFind(std::string const& content, const char* key);
std::string MessagePath(cm::string_view path) const;
+ // -- Run
+ bool Run(cm::string_view infoFile, cm::string_view config);
+
protected:
// -- Abstract processing interface
- virtual bool InitFromInfo() = 0;
+ virtual bool InitFromInfo(InfoT const& info) = 0;
virtual bool Process() = 0;
// - Utility classes
Logger const& Log() const { return Logger_; }
@@ -145,10 +170,9 @@ private:
Logger Logger_;
// -- Info file
std::string InfoFile_;
- cmFileTime InfoFileTime_;
std::string InfoDir_;
+ cmFileTime InfoFileTime_;
std::string InfoConfig_;
- Json::Value Info_;
// -- Directories
ProjectDirsT ProjectDirs_;
};
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 5f3cd5f..3b0f717 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -2,20 +2,33 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmQtAutoMocUic.h"
-#include <algorithm>
-#include <set>
-#include <utility>
-
-#include <cm/memory>
-
#include "cmAlgorithms.h"
#include "cmCryptoHash.h"
+#include "cmFileTime.h"
#include "cmGeneratedFileStream.h"
#include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmWorkerPool.h"
#include "cm_jsoncpp_value.h"
#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+
+#include <cm/memory>
+#include <cm/string_view>
+
+#include <algorithm>
+#include <atomic>
+#include <cstddef>
+#include <map>
+#include <mutex>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
#if defined(__APPLE__)
# include <unistd.h>
@@ -26,10 +39,533 @@ namespace {
constexpr std::size_t MocUnderscoreLength = 4; // Length of "moc_"
constexpr std::size_t UiUnderscoreLength = 3; // Length of "ui_"
-} // End of unnamed namespace
+/** \class cmQtAutoMocUicT
+ * \brief AUTOMOC and AUTOUIC generator
+ */
+class cmQtAutoMocUicT : public cmQtAutoGenerator
+{
+public:
+ cmQtAutoMocUicT();
+ ~cmQtAutoMocUicT() override;
+
+ cmQtAutoMocUicT(cmQtAutoMocUicT const&) = delete;
+ cmQtAutoMocUicT& operator=(cmQtAutoMocUicT const&) = delete;
+
+public:
+ // -- Types
+
+ /** Include string with sub parts. */
+ struct IncludeKeyT
+ {
+ IncludeKeyT(std::string const& key, std::size_t basePrefixLength);
+
+ std::string Key; // Full include string
+ std::string Dir; // Include directory
+ std::string Base; // Base part of the include file name
+ };
+
+ /** Search key plus regular expression pair. */
+ struct KeyExpT
+ {
+ KeyExpT(std::string key, std::string const& exp)
+ : Key(std::move(key))
+ , Exp(exp)
+ {
+ }
+
+ std::string Key;
+ cmsys::RegularExpression Exp;
+ };
+
+ /** Source file parsing cache. */
+ class ParseCacheT
+ {
+ public:
+ // -- Types
+
+ /** Entry of the file parsing cache. */
+ struct FileT
+ {
+ void Clear();
+
+ struct MocT
+ {
+ std::string Macro;
+ struct IncludeT
+ {
+ std::vector<IncludeKeyT> Underscore;
+ std::vector<IncludeKeyT> Dot;
+ } Include;
+ std::vector<std::string> Depends;
+ } Moc;
+
+ struct UicT
+ {
+ std::vector<IncludeKeyT> Include;
+ std::vector<std::string> Depends;
+ } Uic;
+ };
+ using FileHandleT = std::shared_ptr<FileT>;
+ using GetOrInsertT = std::pair<FileHandleT, bool>;
+
+ public:
+ ParseCacheT();
+ ~ParseCacheT();
+
+ bool ReadFromFile(std::string const& fileName);
+ bool WriteToFile(std::string const& fileName);
+
+ //! Always returns a valid handle
+ GetOrInsertT GetOrInsert(std::string const& fileName);
+
+ private:
+ std::unordered_map<std::string, FileHandleT> Map_;
+ };
+
+ /** Source file data. */
+ class SourceFileT
+ {
+ public:
+ SourceFileT(std::string fileName)
+ : FileName(std::move(fileName))
+ {
+ }
+
+ public:
+ std::string FileName;
+ cmFileTime FileTime;
+ ParseCacheT::FileHandleT ParseData;
+ std::string BuildPath;
+ bool IsHeader = false;
+ bool Moc = false;
+ bool Uic = false;
+ };
+ using SourceFileHandleT = std::shared_ptr<SourceFileT>;
+ using SourceFileMapT = std::map<std::string, SourceFileHandleT>;
+
+ /** Meta compiler file mapping information. */
+ struct MappingT
+ {
+ SourceFileHandleT SourceFile;
+ std::string OutputFile;
+ std::string IncludeString;
+ std::vector<SourceFileHandleT> IncluderFiles;
+ };
+ using MappingHandleT = std::shared_ptr<MappingT>;
+ using MappingMapT = std::map<std::string, MappingHandleT>;
+
+ /** Common settings. */
+ class BaseSettingsT
+ {
+ public:
+ // -- Constructors
+ BaseSettingsT();
+ ~BaseSettingsT();
+
+ BaseSettingsT(BaseSettingsT const&) = delete;
+ BaseSettingsT& operator=(BaseSettingsT const&) = delete;
+
+ // -- Attributes
+ // - Config
+ bool MultiConfig = false;
+ unsigned int QtVersionMajor = 4;
+ unsigned int ThreadCount = 0;
+ // - Directories
+ std::string AutogenBuildDir;
+ std::string AutogenIncludeDir;
+ // - Files
+ std::string CMakeExecutable;
+ cmFileTime CMakeExecutableTime;
+ std::string ParseCacheFile;
+ std::vector<std::string> HeaderExtensions;
+ };
+
+ /** Shared common variables. */
+ class BaseEvalT
+ {
+ public:
+ // -- Parse Cache
+ bool ParseCacheChanged = false;
+ cmFileTime ParseCacheTime;
+ ParseCacheT ParseCache;
+
+ // -- Sources
+ SourceFileMapT Headers;
+ SourceFileMapT Sources;
+ };
+
+ /** Moc settings. */
+ class MocSettingsT
+ {
+ public:
+ // -- Constructors
+ MocSettingsT();
+ ~MocSettingsT();
+
+ MocSettingsT(MocSettingsT const&) = delete;
+ MocSettingsT& operator=(MocSettingsT const&) = delete;
+
+ // -- Const methods
+ bool skipped(std::string const& fileName) const;
+ std::string MacrosString() const;
+
+ // -- Attributes
+ bool Enabled = false;
+ bool SettingsChanged = false;
+ bool RelaxedMode = false;
+ bool PathPrefix = false;
+ cmFileTime ExecutableTime;
+ std::string Executable;
+ std::string CompFileAbs;
+ std::string PredefsFileAbs;
+ std::unordered_set<std::string> SkipList;
+ std::vector<std::string> IncludePaths;
+ std::vector<std::string> Definitions;
+ std::vector<std::string> OptionsIncludes;
+ std::vector<std::string> OptionsDefinitions;
+ std::vector<std::string> OptionsExtra;
+ std::vector<std::string> PredefsCmd;
+ std::vector<KeyExpT> DependFilters;
+ std::vector<KeyExpT> MacroFilters;
+ cmsys::RegularExpression RegExpInclude;
+ };
+
+ /** Moc shared variables. */
+ class MocEvalT
+ {
+ public:
+ // -- predefines file
+ cmFileTime PredefsTime;
+ // -- Mappings
+ MappingMapT HeaderMappings;
+ MappingMapT SourceMappings;
+ MappingMapT Includes;
+ // -- Discovered files
+ SourceFileMapT HeadersDiscovered;
+ // -- Output directories
+ std::unordered_set<std::string> OutputDirs;
+ // -- Mocs compilation
+ bool CompUpdated = false;
+ std::vector<std::string> CompFiles;
+ };
+
+ /** Uic settings. */
+ class UicSettingsT
+ {
+ public:
+ struct UiFile
+ {
+ std::vector<std::string> Options;
+ };
+
+ public:
+ UicSettingsT();
+ ~UicSettingsT();
+
+ UicSettingsT(UicSettingsT const&) = delete;
+ UicSettingsT& operator=(UicSettingsT const&) = delete;
+
+ // -- Const methods
+ bool skipped(std::string const& fileName) const;
+
+ // -- Attributes
+ bool Enabled = false;
+ bool SettingsChanged = false;
+ cmFileTime ExecutableTime;
+ std::string Executable;
+ std::unordered_set<std::string> SkipList;
+ std::vector<std::string> Options;
+ std::unordered_map<std::string, UiFile> UiFiles;
+ std::vector<std::string> SearchPaths;
+ cmsys::RegularExpression RegExpInclude;
+ };
+
+ /** Uic shared variables. */
+ class UicEvalT
+ {
+ public:
+ // -- Discovered files
+ SourceFileMapT UiFiles;
+ // -- Mappings
+ MappingMapT Includes;
+ // -- Output directories
+ std::unordered_set<std::string> OutputDirs;
+ };
+
+ /** Abstract job class for concurrent job processing. */
+ class JobT : public cmWorkerPool::JobT
+ {
+ protected:
+ /** Protected default constructor. */
+ JobT(bool fence = false)
+ : cmWorkerPool::JobT(fence)
+ {
+ }
+
+ //! Get the generator. Only valid during Process() call!
+ cmQtAutoMocUicT* Gen() const
+ {
+ return static_cast<cmQtAutoMocUicT*>(UserData());
+ };
+
+ // -- Accessors. Only valid during Process() call!
+ Logger const& Log() const { return Gen()->Log(); }
+ BaseSettingsT const& BaseConst() const { return Gen()->BaseConst(); }
+ BaseEvalT& BaseEval() const { return Gen()->BaseEval(); }
+ MocSettingsT const& MocConst() const { return Gen()->MocConst(); }
+ MocEvalT& MocEval() const { return Gen()->MocEval(); }
+ UicSettingsT const& UicConst() const { return Gen()->UicConst(); }
+ UicEvalT& UicEval() const { return Gen()->UicEval(); }
+
+ // -- Logging
+ std::string MessagePath(cm::string_view path) const
+ {
+ return Gen()->MessagePath(path);
+ }
+ // - Error logging with automatic abort
+ void LogError(GenT genType, cm::string_view message) const;
+ void LogCommandError(GenT genType, cm::string_view message,
+ std::vector<std::string> const& command,
+ std::string const& output) const;
+
+ /** @brief Run an external process. Use only during Process() call! */
+ bool RunProcess(GenT genType, cmWorkerPool::ProcessResultT& result,
+ std::vector<std::string> const& command,
+ std::string* infoMessage = nullptr);
+ };
+
+ /** Fence job utility class. */
+ class JobFenceT : public JobT
+ {
+ public:
+ JobFenceT()
+ : JobT(true)
+ {
+ }
+ void Process() override{};
+ };
+
+ /** Generate moc_predefs.h. */
+ class JobMocPredefsT : public JobFenceT
+ {
+ void Process() override;
+ bool Update(std::string* reason) const;
+ };
+
+ /** File parse job base class. */
+ class JobParseT : public JobT
+ {
+ public:
+ JobParseT(SourceFileHandleT fileHandle)
+ : FileHandle(std::move(fileHandle))
+ {
+ }
+
+ protected:
+ bool ReadFile();
+ void CreateKeys(std::vector<IncludeKeyT>& container,
+ std::set<std::string> const& source,
+ std::size_t basePrefixLength);
+ void MocMacro();
+ void MocDependecies();
+ void MocIncludes();
+ void UicIncludes();
+
+ protected:
+ SourceFileHandleT FileHandle;
+ std::string Content;
+ };
+
+ /** Header file parse job. */
+ class JobParseHeaderT : public JobParseT
+ {
+ public:
+ using JobParseT::JobParseT;
+ void Process() override;
+ };
+
+ /** Source file parse job. */
+ class JobParseSourceT : public JobParseT
+ {
+ public:
+ using JobParseT::JobParseT;
+ void Process() override;
+ };
+
+ /** Evaluate cached file parse data - moc. */
+ class JobEvalCacheT : public JobT
+ {
+ protected:
+ std::string MessageSearchLocations() const;
+ std::vector<std::string> SearchLocations;
+ };
+
+ /** Evaluate cached file parse data - moc. */
+ class JobEvalCacheMocT : public JobEvalCacheT
+ {
+ void Process() override;
+ bool EvalHeader(SourceFileHandleT source);
+ bool EvalSource(SourceFileHandleT const& source);
+ bool FindIncludedHeader(SourceFileHandleT& headerHandle,
+ cm::string_view includerDir,
+ cm::string_view includeBase);
+ bool RegisterIncluded(std::string const& includeString,
+ SourceFileHandleT includerFileHandle,
+ SourceFileHandleT sourceFileHandle) const;
+ void RegisterMapping(MappingHandleT mappingHandle) const;
+ std::string MessageHeader(cm::string_view headerBase) const;
+ };
+
+ /** Evaluate cached file parse data - uic. */
+ class JobEvalCacheUicT : public JobEvalCacheT
+ {
+ void Process() override;
+ bool EvalFile(SourceFileHandleT const& sourceFileHandle);
+ bool FindIncludedUi(cm::string_view sourceDirPrefix,
+ cm::string_view includePrefix);
+ bool RegisterMapping(std::string const& includeString,
+ SourceFileHandleT includerFileHandle);
+
+ std::string UiName;
+ SourceFileHandleT UiFileHandle;
+ };
+
+ /** Evaluate cached file parse data - finish */
+ class JobEvalCacheFinishT : public JobFenceT
+ {
+ void Process() override;
+ };
+
+ /** Dependency probing base job. */
+ class JobProbeDepsT : public JobT
+ {
+ };
+
+ /** Probes file dependencies and generates moc compile jobs. */
+ class JobProbeDepsMocT : public JobProbeDepsT
+ {
+ void Process() override;
+ bool Generate(MappingHandleT const& mapping, bool compFile) const;
+ bool Probe(MappingT const& mapping, std::string* reason) const;
+ std::pair<std::string, cmFileTime> FindDependency(
+ std::string const& sourceDir, std::string const& includeString) const;
+ };
+
+ /** Probes file dependencies and generates uic compile jobs. */
+ class JobProbeDepsUicT : public JobProbeDepsT
+ {
+ void Process() override;
+ bool Probe(MappingT const& mapping, std::string* reason) const;
+ };
+
+ /** Dependency probing finish job. */
+ class JobProbeDepsFinishT : public JobFenceT
+ {
+ void Process() override;
+ };
+
+ /** Meta compiler base job. */
+ class JobCompileT : public JobT
+ {
+ public:
+ JobCompileT(MappingHandleT uicMapping, std::unique_ptr<std::string> reason)
+ : Mapping(std::move(uicMapping))
+ , Reason(std::move(reason))
+ {
+ }
+
+ protected:
+ MappingHandleT Mapping;
+ std::unique_ptr<std::string> Reason;
+ };
+
+ /** moc compiles a file. */
+ class JobCompileMocT : public JobCompileT
+ {
+ public:
+ using JobCompileT::JobCompileT;
+ void Process() override;
+ };
-cmQtAutoMocUic::IncludeKeyT::IncludeKeyT(std::string const& key,
- std::size_t basePrefixLength)
+ /** uic compiles a file. */
+ class JobCompileUicT : public JobCompileT
+ {
+ public:
+ using JobCompileT::JobCompileT;
+ void Process() override;
+ };
+
+ /** Generate mocs_compilation.cpp. */
+ class JobMocsCompilationT : public JobFenceT
+ {
+ private:
+ void Process() override;
+ };
+
+ /** @brief The last job. */
+ class JobFinishT : public JobFenceT
+ {
+ private:
+ void Process() override;
+ };
+
+ // -- Const settings interface
+ BaseSettingsT const& BaseConst() const { return this->BaseConst_; }
+ BaseEvalT& BaseEval() { return this->BaseEval_; }
+ MocSettingsT const& MocConst() const { return this->MocConst_; }
+ MocEvalT& MocEval() { return this->MocEval_; }
+ UicSettingsT const& UicConst() const { return this->UicConst_; }
+ UicEvalT& UicEval() { return this->UicEval_; }
+
+ // -- Parallel job processing interface
+ cmWorkerPool& WorkerPool() { return WorkerPool_; }
+ void AbortError() { Abort(true); }
+ void AbortSuccess() { Abort(false); }
+
+ // -- Utility
+ std::string AbsoluteBuildPath(cm::string_view relativePath) const;
+ std::string AbsoluteIncludePath(cm::string_view relativePath) const;
+ template <class JOBTYPE>
+ void CreateParseJobs(SourceFileMapT const& sourceMap);
+ std::string CollapseFullPathTS(std::string const& path) const;
+
+private:
+ // -- Abstract processing interface
+ bool InitFromInfo(InfoT const& info) override;
+ void InitJobs();
+ bool Process() override;
+ // -- Settings file
+ void SettingsFileRead();
+ bool SettingsFileWrite();
+ // -- Parse cache
+ void ParseCacheRead();
+ bool ParseCacheWrite();
+ // -- Thread processing
+ void Abort(bool error);
+ // -- Generation
+ bool CreateDirectories();
+
+private:
+ // -- Settings
+ BaseSettingsT BaseConst_;
+ BaseEvalT BaseEval_;
+ MocSettingsT MocConst_;
+ MocEvalT MocEval_;
+ UicSettingsT UicConst_;
+ UicEvalT UicEval_;
+ // -- Settings file
+ std::string SettingsFile_;
+ std::string SettingsStringMoc_;
+ std::string SettingsStringUic_;
+ // -- Worker thread pool
+ std::atomic<bool> JobError_ = ATOMIC_VAR_INIT(false);
+ cmWorkerPool WorkerPool_;
+ // -- Concurrent processing
+ mutable std::mutex CMakeLibMutex_;
+};
+
+cmQtAutoMocUicT::IncludeKeyT::IncludeKeyT(std::string const& key,
+ std::size_t basePrefixLength)
: Key(key)
, Dir(SubDirPrefix(key))
, Base(cmSystemTools::GetFilenameWithoutLastExtension(key))
@@ -39,7 +575,7 @@ cmQtAutoMocUic::IncludeKeyT::IncludeKeyT(std::string const& key,
}
}
-void cmQtAutoMocUic::ParseCacheT::FileT::Clear()
+void cmQtAutoMocUicT::ParseCacheT::FileT::Clear()
{
Moc.Macro.clear();
Moc.Include.Underscore.clear();
@@ -50,18 +586,8 @@ void cmQtAutoMocUic::ParseCacheT::FileT::Clear()
Uic.Depends.clear();
}
-cmQtAutoMocUic::ParseCacheT::FileHandleT cmQtAutoMocUic::ParseCacheT::Get(
- std::string const& fileName) const
-{
- auto it = Map_.find(fileName);
- if (it != Map_.end()) {
- return it->second;
- }
- return FileHandleT();
-}
-
-cmQtAutoMocUic::ParseCacheT::GetOrInsertT
-cmQtAutoMocUic::ParseCacheT::GetOrInsert(std::string const& fileName)
+cmQtAutoMocUicT::ParseCacheT::GetOrInsertT
+cmQtAutoMocUicT::ParseCacheT::GetOrInsert(std::string const& fileName)
{
// Find existing entry
{
@@ -77,15 +603,10 @@ cmQtAutoMocUic::ParseCacheT::GetOrInsert(std::string const& fileName)
};
}
-cmQtAutoMocUic::ParseCacheT::ParseCacheT() = default;
-cmQtAutoMocUic::ParseCacheT::~ParseCacheT() = default;
+cmQtAutoMocUicT::ParseCacheT::ParseCacheT() = default;
+cmQtAutoMocUicT::ParseCacheT::~ParseCacheT() = default;
-void cmQtAutoMocUic::ParseCacheT::Clear()
-{
- Map_.clear();
-}
-
-bool cmQtAutoMocUic::ParseCacheT::ReadFromFile(std::string const& fileName)
+bool cmQtAutoMocUicT::ParseCacheT::ReadFromFile(std::string const& fileName)
{
cmsys::ifstream fin(fileName.c_str());
if (!fin) {
@@ -148,7 +669,7 @@ bool cmQtAutoMocUic::ParseCacheT::ReadFromFile(std::string const& fileName)
return true;
}
-bool cmQtAutoMocUic::ParseCacheT::WriteToFile(std::string const& fileName)
+bool cmQtAutoMocUicT::ParseCacheT::WriteToFile(std::string const& fileName)
{
cmGeneratedFileStream ofs(fileName);
if (!ofs) {
@@ -180,24 +701,24 @@ bool cmQtAutoMocUic::ParseCacheT::WriteToFile(std::string const& fileName)
return ofs.Close();
}
-cmQtAutoMocUic::BaseSettingsT::BaseSettingsT() = default;
-cmQtAutoMocUic::BaseSettingsT::~BaseSettingsT() = default;
+cmQtAutoMocUicT::BaseSettingsT::BaseSettingsT() = default;
+cmQtAutoMocUicT::BaseSettingsT::~BaseSettingsT() = default;
-cmQtAutoMocUic::MocSettingsT::MocSettingsT()
+cmQtAutoMocUicT::MocSettingsT::MocSettingsT()
{
RegExpInclude.compile(
"(^|\n)[ \t]*#[ \t]*include[ \t]+"
"[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
}
-cmQtAutoMocUic::MocSettingsT::~MocSettingsT() = default;
+cmQtAutoMocUicT::MocSettingsT::~MocSettingsT() = default;
-bool cmQtAutoMocUic::MocSettingsT::skipped(std::string const& fileName) const
+bool cmQtAutoMocUicT::MocSettingsT::skipped(std::string const& fileName) const
{
return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
}
-std::string cmQtAutoMocUic::MocSettingsT::MacrosString() const
+std::string cmQtAutoMocUicT::MocSettingsT::MacrosString() const
{
std::string res;
const auto itB = MacroFilters.cbegin();
@@ -219,27 +740,27 @@ std::string cmQtAutoMocUic::MocSettingsT::MacrosString() const
return res;
}
-cmQtAutoMocUic::UicSettingsT::UicSettingsT()
+cmQtAutoMocUicT::UicSettingsT::UicSettingsT()
{
RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
"[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
}
-cmQtAutoMocUic::UicSettingsT::~UicSettingsT() = default;
+cmQtAutoMocUicT::UicSettingsT::~UicSettingsT() = default;
-bool cmQtAutoMocUic::UicSettingsT::skipped(std::string const& fileName) const
+bool cmQtAutoMocUicT::UicSettingsT::skipped(std::string const& fileName) const
{
return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
}
-void cmQtAutoMocUic::JobT::LogError(GenT genType,
- cm::string_view message) const
+void cmQtAutoMocUicT::JobT::LogError(GenT genType,
+ cm::string_view message) const
{
Gen()->AbortError();
Gen()->Log().Error(genType, message);
}
-void cmQtAutoMocUic::JobT::LogCommandError(
+void cmQtAutoMocUicT::JobT::LogCommandError(
GenT genType, cm::string_view message,
std::vector<std::string> const& command, std::string const& output) const
{
@@ -247,10 +768,10 @@ void cmQtAutoMocUic::JobT::LogCommandError(
Gen()->Log().ErrorCommand(genType, message, command, output);
}
-bool cmQtAutoMocUic::JobT::RunProcess(GenT genType,
- cmWorkerPool::ProcessResultT& result,
- std::vector<std::string> const& command,
- std::string* infoMessage)
+bool cmQtAutoMocUicT::JobT::RunProcess(GenT genType,
+ cmWorkerPool::ProcessResultT& result,
+ std::vector<std::string> const& command,
+ std::string* infoMessage)
{
// Log command
if (Log().Verbose()) {
@@ -268,7 +789,7 @@ bool cmQtAutoMocUic::JobT::RunProcess(GenT genType,
BaseConst().AutogenBuildDir);
}
-void cmQtAutoMocUic::JobMocPredefsT::Process()
+void cmQtAutoMocUicT::JobMocPredefsT::Process()
{
// (Re)generate moc_predefs.h on demand
std::unique_ptr<std::string> reason;
@@ -330,7 +851,7 @@ void cmQtAutoMocUic::JobMocPredefsT::Process()
}
}
-bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const
+bool cmQtAutoMocUicT::JobMocPredefsT::Update(std::string* reason) const
{
// Test if the file exists
if (!MocEval().PredefsTime.Load(MocConst().PredefsFileAbs)) {
@@ -369,7 +890,7 @@ bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const
return false;
}
-bool cmQtAutoMocUic::JobParseT::ReadFile()
+bool cmQtAutoMocUicT::JobParseT::ReadFile()
{
// Clear old parse information
FileHandle->ParseData->Clear();
@@ -396,9 +917,9 @@ bool cmQtAutoMocUic::JobParseT::ReadFile()
return true;
}
-void cmQtAutoMocUic::JobParseT::CreateKeys(std::vector<IncludeKeyT>& container,
- std::set<std::string> const& source,
- std::size_t basePrefixLength)
+void cmQtAutoMocUicT::JobParseT::CreateKeys(
+ std::vector<IncludeKeyT>& container, std::set<std::string> const& source,
+ std::size_t basePrefixLength)
{
if (source.empty()) {
return;
@@ -409,7 +930,7 @@ void cmQtAutoMocUic::JobParseT::CreateKeys(std::vector<IncludeKeyT>& container,
}
}
-void cmQtAutoMocUic::JobParseT::MocMacro()
+void cmQtAutoMocUicT::JobParseT::MocMacro()
{
for (KeyExpT const& filter : MocConst().MacroFilters) {
// Run a simple find string check
@@ -426,7 +947,7 @@ void cmQtAutoMocUic::JobParseT::MocMacro()
}
}
-void cmQtAutoMocUic::JobParseT::MocDependecies()
+void cmQtAutoMocUicT::JobParseT::MocDependecies()
{
if (MocConst().DependFilters.empty()) {
return;
@@ -467,7 +988,7 @@ void cmQtAutoMocUic::JobParseT::MocDependecies()
}
}
-void cmQtAutoMocUic::JobParseT::MocIncludes()
+void cmQtAutoMocUicT::JobParseT::MocIncludes()
{
if (Content.find("moc") == std::string::npos) {
return;
@@ -500,7 +1021,7 @@ void cmQtAutoMocUic::JobParseT::MocIncludes()
CreateKeys(Include.Dot, dot, 0);
}
-void cmQtAutoMocUic::JobParseT::UicIncludes()
+void cmQtAutoMocUicT::JobParseT::UicIncludes()
{
if (Content.find("ui_") == std::string::npos) {
return;
@@ -520,7 +1041,7 @@ void cmQtAutoMocUic::JobParseT::UicIncludes()
CreateKeys(FileHandle->ParseData->Uic.Include, includes, UiUnderscoreLength);
}
-void cmQtAutoMocUic::JobParseHeaderT::Process()
+void cmQtAutoMocUicT::JobParseHeaderT::Process()
{
if (!ReadFile()) {
return;
@@ -536,7 +1057,7 @@ void cmQtAutoMocUic::JobParseHeaderT::Process()
}
}
-void cmQtAutoMocUic::JobParseSourceT::Process()
+void cmQtAutoMocUicT::JobParseSourceT::Process()
{
if (!ReadFile()) {
return;
@@ -553,7 +1074,7 @@ void cmQtAutoMocUic::JobParseSourceT::Process()
}
}
-std::string cmQtAutoMocUic::JobEvalCacheT::MessageSearchLocations() const
+std::string cmQtAutoMocUicT::JobEvalCacheT::MessageSearchLocations() const
{
std::string res;
res.reserve(512);
@@ -565,7 +1086,7 @@ std::string cmQtAutoMocUic::JobEvalCacheT::MessageSearchLocations() const
return res;
}
-void cmQtAutoMocUic::JobEvalCacheMocT::Process()
+void cmQtAutoMocUicT::JobEvalCacheMocT::Process()
{
// Evaluate headers
for (auto const& pair : BaseEval().Headers) {
@@ -581,7 +1102,7 @@ void cmQtAutoMocUic::JobEvalCacheMocT::Process()
}
}
-bool cmQtAutoMocUic::JobEvalCacheMocT::EvalHeader(SourceFileHandleT source)
+bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalHeader(SourceFileHandleT source)
{
SourceFileT const& sourceFile = *source;
auto const& parseData = sourceFile.ParseData->Moc;
@@ -608,7 +1129,7 @@ bool cmQtAutoMocUic::JobEvalCacheMocT::EvalHeader(SourceFileHandleT source)
return true;
}
-bool cmQtAutoMocUic::JobEvalCacheMocT::EvalSource(
+bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalSource(
SourceFileHandleT const& source)
{
SourceFileT const& sourceFile = *source;
@@ -809,7 +1330,7 @@ bool cmQtAutoMocUic::JobEvalCacheMocT::EvalSource(
return true;
}
-bool cmQtAutoMocUic::JobEvalCacheMocT::FindIncludedHeader(
+bool cmQtAutoMocUicT::JobEvalCacheMocT::FindIncludedHeader(
SourceFileHandleT& headerHandle, cm::string_view includerDir,
cm::string_view includeBase)
{
@@ -874,7 +1395,7 @@ bool cmQtAutoMocUic::JobEvalCacheMocT::FindIncludedHeader(
return false;
}
-bool cmQtAutoMocUic::JobEvalCacheMocT::RegisterIncluded(
+bool cmQtAutoMocUicT::JobEvalCacheMocT::RegisterIncluded(
std::string const& includeString, SourceFileHandleT includerFileHandle,
SourceFileHandleT sourceFileHandle) const
{
@@ -922,7 +1443,7 @@ bool cmQtAutoMocUic::JobEvalCacheMocT::RegisterIncluded(
return true;
}
-void cmQtAutoMocUic::JobEvalCacheMocT::RegisterMapping(
+void cmQtAutoMocUicT::JobEvalCacheMocT::RegisterMapping(
MappingHandleT mappingHandle) const
{
auto& regMap = mappingHandle->SourceFile->IsHeader
@@ -941,14 +1462,14 @@ void cmQtAutoMocUic::JobEvalCacheMocT::RegisterMapping(
}
}
-std::string cmQtAutoMocUic::JobEvalCacheMocT::MessageHeader(
+std::string cmQtAutoMocUicT::JobEvalCacheMocT::MessageHeader(
cm::string_view headerBase) const
{
return MessagePath(cmStrCat(
headerBase, ".{", cmJoin(this->BaseConst().HeaderExtensions, ","), '}'));
}
-void cmQtAutoMocUic::JobEvalCacheUicT::Process()
+void cmQtAutoMocUicT::JobEvalCacheUicT::Process()
{
// Prepare buffers
SearchLocations.reserve((UicConst().SearchPaths.size() + 1) * 2);
@@ -967,7 +1488,7 @@ void cmQtAutoMocUic::JobEvalCacheUicT::Process()
}
}
-bool cmQtAutoMocUic::JobEvalCacheUicT::EvalFile(
+bool cmQtAutoMocUicT::JobEvalCacheUicT::EvalFile(
SourceFileHandleT const& sourceFileHandle)
{
SourceFileT const& sourceFile = *sourceFileHandle;
@@ -1002,7 +1523,7 @@ bool cmQtAutoMocUic::JobEvalCacheUicT::EvalFile(
return true;
}
-bool cmQtAutoMocUic::JobEvalCacheUicT::FindIncludedUi(
+bool cmQtAutoMocUicT::JobEvalCacheUicT::FindIncludedUi(
cm::string_view sourceDirPrefix, cm::string_view includePrefix)
{
// Clear locations buffer
@@ -1056,7 +1577,7 @@ bool cmQtAutoMocUic::JobEvalCacheUicT::FindIncludedUi(
return false;
}
-bool cmQtAutoMocUic::JobEvalCacheUicT::RegisterMapping(
+bool cmQtAutoMocUicT::JobEvalCacheUicT::RegisterMapping(
std::string const& includeString, SourceFileHandleT includerFileHandle)
{
auto& Includes = Gen()->UicEval().Includes;
@@ -1101,7 +1622,7 @@ bool cmQtAutoMocUic::JobEvalCacheUicT::RegisterMapping(
return true;
}
-void cmQtAutoMocUic::JobEvalCacheFinishT::Process()
+void cmQtAutoMocUicT::JobEvalCacheFinishT::Process()
{
// Add discovered header parse jobs
Gen()->CreateParseJobs<JobParseHeaderT>(MocEval().HeadersDiscovered);
@@ -1121,7 +1642,7 @@ void cmQtAutoMocUic::JobEvalCacheFinishT::Process()
}
}
-void cmQtAutoMocUic::JobProbeDepsMocT::Process()
+void cmQtAutoMocUicT::JobProbeDepsMocT::Process()
{
// Create moc header jobs
for (auto const& pair : MocEval().HeaderMappings) {
@@ -1143,8 +1664,8 @@ void cmQtAutoMocUic::JobProbeDepsMocT::Process()
}
}
-bool cmQtAutoMocUic::JobProbeDepsMocT::Generate(MappingHandleT const& mapping,
- bool compFile) const
+bool cmQtAutoMocUicT::JobProbeDepsMocT::Generate(MappingHandleT const& mapping,
+ bool compFile) const
{
std::unique_ptr<std::string> reason;
if (Log().Verbose()) {
@@ -1163,8 +1684,8 @@ bool cmQtAutoMocUic::JobProbeDepsMocT::Generate(MappingHandleT const& mapping,
return true;
}
-bool cmQtAutoMocUic::JobProbeDepsMocT::Probe(MappingT const& mapping,
- std::string* reason) const
+bool cmQtAutoMocUicT::JobProbeDepsMocT::Probe(MappingT const& mapping,
+ std::string* reason) const
{
std::string const& sourceFile = mapping.SourceFile->FileName;
std::string const& outputFile = mapping.OutputFile;
@@ -1254,7 +1775,7 @@ bool cmQtAutoMocUic::JobProbeDepsMocT::Probe(MappingT const& mapping,
}
std::pair<std::string, cmFileTime>
-cmQtAutoMocUic::JobProbeDepsMocT::FindDependency(
+cmQtAutoMocUicT::JobProbeDepsMocT::FindDependency(
std::string const& sourceDir, std::string const& includeString) const
{
using ResPair = std::pair<std::string, cmFileTime>;
@@ -1276,7 +1797,7 @@ cmQtAutoMocUic::JobProbeDepsMocT::FindDependency(
return ResPair();
}
-void cmQtAutoMocUic::JobProbeDepsUicT::Process()
+void cmQtAutoMocUicT::JobProbeDepsUicT::Process()
{
for (auto const& pair : Gen()->UicEval().Includes) {
MappingHandleT const& mapping = pair.second;
@@ -1295,8 +1816,8 @@ void cmQtAutoMocUic::JobProbeDepsUicT::Process()
}
}
-bool cmQtAutoMocUic::JobProbeDepsUicT::Probe(MappingT const& mapping,
- std::string* reason) const
+bool cmQtAutoMocUicT::JobProbeDepsUicT::Probe(MappingT const& mapping,
+ std::string* reason) const
{
std::string const& sourceFile = mapping.SourceFile->FileName;
std::string const& outputFile = mapping.OutputFile;
@@ -1345,7 +1866,7 @@ bool cmQtAutoMocUic::JobProbeDepsUicT::Probe(MappingT const& mapping,
return false;
}
-void cmQtAutoMocUic::JobProbeDepsFinishT::Process()
+void cmQtAutoMocUicT::JobProbeDepsFinishT::Process()
{
// Create output directories
{
@@ -1381,7 +1902,7 @@ void cmQtAutoMocUic::JobProbeDepsFinishT::Process()
Gen()->WorkerPool().EmplaceJob<JobFinishT>();
}
-void cmQtAutoMocUic::JobCompileMocT::Process()
+void cmQtAutoMocUicT::JobCompileMocT::Process()
{
std::string const& sourceFile = Mapping->SourceFile->FileName;
std::string const& outputFile = Mapping->OutputFile;
@@ -1458,7 +1979,7 @@ void cmQtAutoMocUic::JobCompileMocT::Process()
}
}
-void cmQtAutoMocUic::JobCompileUicT::Process()
+void cmQtAutoMocUicT::JobCompileUicT::Process()
{
std::string const& sourceFile = Mapping->SourceFile->FileName;
std::string const& outputFile = Mapping->OutputFile;
@@ -1501,7 +2022,7 @@ void cmQtAutoMocUic::JobCompileUicT::Process()
}
}
-void cmQtAutoMocUic::JobMocsCompilationT::Process()
+void cmQtAutoMocUicT::JobMocsCompilationT::Process()
{
// Compose mocs compilation file content
std::string content =
@@ -1546,39 +2067,41 @@ void cmQtAutoMocUic::JobMocsCompilationT::Process()
}
}
-void cmQtAutoMocUic::JobFinishT::Process()
+void cmQtAutoMocUicT::JobFinishT::Process()
{
Gen()->AbortSuccess();
}
-cmQtAutoMocUic::cmQtAutoMocUic()
+cmQtAutoMocUicT::cmQtAutoMocUicT()
: cmQtAutoGenerator(GenT::GEN)
{
}
-cmQtAutoMocUic::~cmQtAutoMocUic() = default;
+cmQtAutoMocUicT::~cmQtAutoMocUicT() = default;
-bool cmQtAutoMocUic::InitFromInfo()
+bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
{
// -- Required settings
- if (!InfoBool("MULTI_CONFIG", BaseConst_.MultiConfig, true) ||
- !InfoUInt("QT_VERSION_MAJOR", BaseConst_.QtVersionMajor, true) ||
- !InfoUInt("PARALLEL", BaseConst_.ThreadCount, false) ||
- !InfoString("BUILD_DIR", BaseConst_.AutogenBuildDir, true) ||
- !InfoStringConfig("INCLUDE_DIR", BaseConst_.AutogenIncludeDir, true) ||
- !InfoString("CMAKE_EXECUTABLE", BaseConst_.CMakeExecutable, true) ||
- !InfoStringConfig("PARSE_CACHE_FILE", BaseConst_.ParseCacheFile, true) ||
- !InfoStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
- !InfoArray("HEADER_EXTENSIONS", BaseConst_.HeaderExtensions, true) ||
- !InfoString("QT_MOC_EXECUTABLE", MocConst_.Executable, false) ||
- !InfoString("QT_UIC_EXECUTABLE", UicConst_.Executable, false)) {
+ if (!info.GetBool("MULTI_CONFIG", BaseConst_.MultiConfig, true) ||
+ !info.GetUInt("QT_VERSION_MAJOR", BaseConst_.QtVersionMajor, true) ||
+ !info.GetUInt("PARALLEL", BaseConst_.ThreadCount, false) ||
+ !info.GetString("BUILD_DIR", BaseConst_.AutogenBuildDir, true) ||
+ !info.GetStringConfig("INCLUDE_DIR", BaseConst_.AutogenIncludeDir,
+ true) ||
+ !info.GetString("CMAKE_EXECUTABLE", BaseConst_.CMakeExecutable, true) ||
+ !info.GetStringConfig("PARSE_CACHE_FILE", BaseConst_.ParseCacheFile,
+ true) ||
+ !info.GetStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
+ !info.GetArray("HEADER_EXTENSIONS", BaseConst_.HeaderExtensions, true) ||
+ !info.GetString("QT_MOC_EXECUTABLE", MocConst_.Executable, false) ||
+ !info.GetString("QT_UIC_EXECUTABLE", UicConst_.Executable, false)) {
return false;
}
// -- Checks
if (!BaseConst_.CMakeExecutableTime.Load(BaseConst_.CMakeExecutable)) {
- return LogInfoError(cmStrCat("The CMake executable ",
- MessagePath(BaseConst_.CMakeExecutable),
- " does not exist."));
+ return info.LogError(cmStrCat("The CMake executable ",
+ MessagePath(BaseConst_.CMakeExecutable),
+ " does not exist."));
}
// -- Evaluate values
@@ -1598,19 +2121,20 @@ bool cmQtAutoMocUic::InitFromInfo()
} tmp;
// -- Required settings
- if (!InfoBool("MOC_RELAXED_MODE", MocConst_.RelaxedMode, false) ||
- !InfoBool("MOC_PATH_PREFIX", MocConst_.PathPrefix, true) ||
- !InfoArray("MOC_SKIP", MocConst_.SkipList, false) ||
- !InfoArrayConfig("MOC_DEFINITIONS", MocConst_.Definitions, false) ||
- !InfoArrayConfig("MOC_INCLUDES", MocConst_.IncludePaths, false) ||
- !InfoArray("MOC_OPTIONS", MocConst_.OptionsExtra, false) ||
- !InfoStringConfig("MOC_COMPILATION_FILE", MocConst_.CompFileAbs,
- true) ||
- !InfoArray("MOC_PREDEFS_CMD", MocConst_.PredefsCmd, false) ||
- !InfoStringConfig("MOC_PREDEFS_FILE", MocConst_.PredefsFileAbs,
- !MocConst_.PredefsCmd.empty()) ||
- !InfoArray("MOC_MACRO_NAMES", tmp.MacroNames, true) ||
- !InfoArray("MOC_DEPEND_FILTERS", tmp.DependFilters, false)) {
+ if (!info.GetBool("MOC_RELAXED_MODE", MocConst_.RelaxedMode, false) ||
+ !info.GetBool("MOC_PATH_PREFIX", MocConst_.PathPrefix, true) ||
+ !info.GetArray("MOC_SKIP", MocConst_.SkipList, false) ||
+ !info.GetArrayConfig("MOC_DEFINITIONS", MocConst_.Definitions,
+ false) ||
+ !info.GetArrayConfig("MOC_INCLUDES", MocConst_.IncludePaths, false) ||
+ !info.GetArray("MOC_OPTIONS", MocConst_.OptionsExtra, false) ||
+ !info.GetStringConfig("MOC_COMPILATION_FILE", MocConst_.CompFileAbs,
+ true) ||
+ !info.GetArray("MOC_PREDEFS_CMD", MocConst_.PredefsCmd, false) ||
+ !info.GetStringConfig("MOC_PREDEFS_FILE", MocConst_.PredefsFileAbs,
+ !MocConst_.PredefsCmd.empty()) ||
+ !info.GetArray("MOC_MACRO_NAMES", tmp.MacroNames, true) ||
+ !info.GetArray("MOC_DEPEND_FILTERS", tmp.DependFilters, false)) {
return false;
}
@@ -1621,18 +2145,17 @@ bool cmQtAutoMocUic::InitFromInfo()
}
// Dependency filters
{
- Json::Value const& val = Info()["MOC_DEPEND_FILTERS"];
+ Json::Value const& val = info.GetValue("MOC_DEPEND_FILTERS");
if (!val.isArray()) {
- return LogInfoError("MOC_DEPEND_FILTERS JSON value is not an array.");
+ return info.LogError("MOC_DEPEND_FILTERS JSON value is not an array.");
}
Json::ArrayIndex const arraySize = val.size();
for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
// Test entry closure
- auto testEntry = [this, ii](bool test,
- cm::string_view message) -> bool {
+ auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
if (!test) {
- this->LogInfoError(
- cmStrCat("MOC_DEPEND_FILTERS filter ", ii, ": ", message));
+ info.LogError(
+ cmStrCat("MOC_DEPEND_FILTERS filter ", ii, ": ", msg));
}
return !test;
};
@@ -1671,9 +2194,9 @@ bool cmQtAutoMocUic::InitFromInfo()
}
// Check if moc executable exists (by reading the file time)
if (!MocConst_.ExecutableTime.Load(MocConst_.Executable)) {
- return LogInfoError(cmStrCat("The moc executable ",
- MessagePath(MocConst_.Executable),
- " does not exist."));
+ return info.LogError(cmStrCat("The moc executable ",
+ MessagePath(MocConst_.Executable),
+ " does not exist."));
}
}
@@ -1683,25 +2206,23 @@ bool cmQtAutoMocUic::InitFromInfo()
UicConst_.Enabled = true;
// -- Required settings
- if (!InfoArray("UIC_SKIP", UicConst_.SkipList, false) ||
- !InfoArray("UIC_SEARCH_PATHS", UicConst_.SearchPaths, false) ||
- !InfoArrayConfig("UIC_OPTIONS", UicConst_.Options, false)) {
+ if (!info.GetArray("UIC_SKIP", UicConst_.SkipList, false) ||
+ !info.GetArray("UIC_SEARCH_PATHS", UicConst_.SearchPaths, false) ||
+ !info.GetArrayConfig("UIC_OPTIONS", UicConst_.Options, false)) {
return false;
}
// .ui files
{
- Json::Value const& val = Info()["UIC_UI_FILES"];
+ Json::Value const& val = info.GetValue("UIC_UI_FILES");
if (!val.isArray()) {
- return LogInfoError("UIC_UI_FILES JSON value is not an array.");
+ return info.LogError("UIC_UI_FILES JSON value is not an array.");
}
Json::ArrayIndex const arraySize = val.size();
for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
// Test entry closure
- auto testEntry = [this, ii](bool test,
- cm::string_view message) -> bool {
+ auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
if (!test) {
- this->LogInfoError(
- cmStrCat("UIC_UI_FILES entry ", ii, ": ", message));
+ info.LogError(cmStrCat("UIC_UI_FILES entry ", ii, ": ", msg));
}
return !test;
};
@@ -1722,31 +2243,31 @@ bool cmQtAutoMocUic::InitFromInfo()
}
auto& uiFile = UicConst_.UiFiles[entryName.asString()];
- JsonGetArray(uiFile.Options, entryOptions);
+ InfoT::GetJsonArray(uiFile.Options, entryOptions);
}
}
// -- Evaluate settings
// Check if uic executable exists (by reading the file time)
if (!UicConst_.ExecutableTime.Load(UicConst_.Executable)) {
- return LogInfoError(cmStrCat("The uic executable ",
- MessagePath(UicConst_.Executable),
- " does not exist."));
+ return info.LogError(cmStrCat("The uic executable ",
+ MessagePath(UicConst_.Executable),
+ " does not exist."));
}
}
// -- Headers
{
- Json::Value const& val = Info()["HEADERS"];
+ Json::Value const& val = info.GetValue("HEADERS");
if (!val.isArray()) {
- return LogInfoError("HEADERS JSON value is not an array.");
+ return info.LogError("HEADERS JSON value is not an array.");
}
Json::ArrayIndex const arraySize = val.size();
for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
// Test entry closure
- auto testEntry = [this, ii](bool test, cm::string_view message) -> bool {
+ auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
if (!test) {
- this->LogInfoError(cmStrCat("HEADERS entry ", ii, ": ", message));
+ info.LogError(cmStrCat("HEADERS entry ", ii, ": ", msg));
}
return !test;
};
@@ -1778,9 +2299,8 @@ bool cmQtAutoMocUic::InitFromInfo()
cmFileTime fileTime;
if (!fileTime.Load(name)) {
- LogInfoError(cmStrCat("The header file ", this->MessagePath(name),
- " does not exist."));
- return false;
+ return info.LogError(cmStrCat(
+ "The header file ", this->MessagePath(name), " does not exist."));
}
SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(name);
@@ -1790,7 +2310,7 @@ bool cmQtAutoMocUic::InitFromInfo()
sourceHandle->Uic = (flags[1] == 'U');
if (sourceHandle->Moc && MocConst().Enabled) {
if (build.empty()) {
- return LogInfoError(
+ return info.LogError(
cmStrCat("Header file ", ii, " build path is empty"));
}
sourceHandle->BuildPath = std::move(build);
@@ -1801,16 +2321,16 @@ bool cmQtAutoMocUic::InitFromInfo()
// -- Sources
{
- Json::Value const& val = Info()["SOURCES"];
+ Json::Value const& val = info.GetValue("SOURCES");
if (!val.isArray()) {
- return LogInfoError("SOURCES JSON value is not an array.");
+ return info.LogError("SOURCES JSON value is not an array.");
}
Json::ArrayIndex const arraySize = val.size();
for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
// Test entry closure
- auto testEntry = [this, ii](bool test, cm::string_view message) -> bool {
+ auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
if (!test) {
- this->LogInfoError(cmStrCat("SOURCES entry ", ii, ": ", message));
+ info.LogError(cmStrCat("SOURCES entry ", ii, ": ", msg));
}
return !test;
};
@@ -1838,9 +2358,8 @@ bool cmQtAutoMocUic::InitFromInfo()
cmFileTime fileTime;
if (!fileTime.Load(name)) {
- LogInfoError(cmStrCat("The source file ", this->MessagePath(name),
- " does not exist."));
- return false;
+ return info.LogError(cmStrCat(
+ "The source file ", this->MessagePath(name), " does not exist."));
}
SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(name);
@@ -1896,7 +2415,7 @@ bool cmQtAutoMocUic::InitFromInfo()
}
template <class JOBTYPE>
-void cmQtAutoMocUic::CreateParseJobs(SourceFileMapT const& sourceMap)
+void cmQtAutoMocUicT::CreateParseJobs(SourceFileMapT const& sourceMap)
{
cmFileTime const parseCacheTime = BaseEval().ParseCacheTime;
ParseCacheT& parseCache = BaseEval().ParseCache;
@@ -1913,13 +2432,13 @@ void cmQtAutoMocUic::CreateParseJobs(SourceFileMapT const& sourceMap)
}
/** Concurrently callable implementation of cmSystemTools::CollapseFullPath */
-std::string cmQtAutoMocUic::CollapseFullPathTS(std::string const& path) const
+std::string cmQtAutoMocUicT::CollapseFullPathTS(std::string const& path) const
{
std::lock_guard<std::mutex> guard(CMakeLibMutex_);
return cmSystemTools::CollapseFullPath(path, ProjectDirs().CurrentSource);
}
-void cmQtAutoMocUic::InitJobs()
+void cmQtAutoMocUicT::InitJobs()
{
// Add moc_predefs.h job
if (MocConst().Enabled && !MocConst().PredefsCmd.empty()) {
@@ -1946,7 +2465,7 @@ void cmQtAutoMocUic::InitJobs()
}
}
-bool cmQtAutoMocUic::Process()
+bool cmQtAutoMocUicT::Process()
{
SettingsFileRead();
ParseCacheRead();
@@ -1969,7 +2488,7 @@ bool cmQtAutoMocUic::Process()
return true;
}
-void cmQtAutoMocUic::SettingsFileRead()
+void cmQtAutoMocUicT::SettingsFileRead()
{
// Compose current settings strings
{
@@ -2048,7 +2567,7 @@ void cmQtAutoMocUic::SettingsFileRead()
}
}
-bool cmQtAutoMocUic::SettingsFileWrite()
+bool cmQtAutoMocUicT::SettingsFileWrite()
{
// Only write if any setting changed
if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
@@ -2083,7 +2602,7 @@ bool cmQtAutoMocUic::SettingsFileWrite()
return true;
}
-void cmQtAutoMocUic::ParseCacheRead()
+void cmQtAutoMocUicT::ParseCacheRead()
{
cm::string_view reason;
// Don't read the cache if it is invalid
@@ -2109,7 +2628,7 @@ void cmQtAutoMocUic::ParseCacheRead()
}
}
-bool cmQtAutoMocUic::ParseCacheWrite()
+bool cmQtAutoMocUicT::ParseCacheWrite()
{
if (BaseEval().ParseCacheChanged) {
if (Log().Verbose()) {
@@ -2128,7 +2647,7 @@ bool cmQtAutoMocUic::ParseCacheWrite()
return true;
}
-bool cmQtAutoMocUic::CreateDirectories()
+bool cmQtAutoMocUicT::CreateDirectories()
{
// Create AUTOGEN include directory
if (!cmSystemTools::MakeDirectory(BaseConst().AutogenIncludeDir)) {
@@ -2141,7 +2660,7 @@ bool cmQtAutoMocUic::CreateDirectories()
return true;
}
-void cmQtAutoMocUic::Abort(bool error)
+void cmQtAutoMocUicT::Abort(bool error)
{
if (error) {
JobError_.store(true);
@@ -2149,14 +2668,21 @@ void cmQtAutoMocUic::Abort(bool error)
WorkerPool_.Abort();
}
-std::string cmQtAutoMocUic::AbsoluteBuildPath(
+std::string cmQtAutoMocUicT::AbsoluteBuildPath(
cm::string_view relativePath) const
{
return cmStrCat(BaseConst().AutogenBuildDir, '/', relativePath);
}
-std::string cmQtAutoMocUic::AbsoluteIncludePath(
+std::string cmQtAutoMocUicT::AbsoluteIncludePath(
cm::string_view relativePath) const
{
return cmStrCat(BaseConst().AutogenIncludeDir, '/', relativePath);
}
+
+} // End of unnamed namespace
+
+bool cmQtAutoMocUic(cm::string_view infoFile, cm::string_view config)
+{
+ return cmQtAutoMocUicT().Run(infoFile, config);
+}
diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h
index 7101b8f..ffcc2db 100644
--- a/Source/cmQtAutoMocUic.h
+++ b/Source/cmQtAutoMocUic.h
@@ -5,555 +5,12 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmFileTime.h"
-#include "cmQtAutoGen.h"
-#include "cmQtAutoGenerator.h"
-#include "cmWorkerPool.h"
-#include "cmsys/RegularExpression.hxx"
-
#include <cm/string_view>
-#include <atomic>
-#include <cstddef>
-#include <map>
-#include <memory>
-#include <mutex>
-#include <set>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-#include <utility>
-#include <vector>
-
-/** \class cmQtAutoMocUic
- * \brief AUTOMOC and AUTOUIC generator
+/**
+ * Process AUTOMOC and AUTOUIC
+ * @return true on success
*/
-class cmQtAutoMocUic : public cmQtAutoGenerator
-{
-public:
- cmQtAutoMocUic();
- ~cmQtAutoMocUic() override;
-
- cmQtAutoMocUic(cmQtAutoMocUic const&) = delete;
- cmQtAutoMocUic& operator=(cmQtAutoMocUic const&) = delete;
-
-public:
- // -- Types
-
- /** Include string with sub parts. */
- struct IncludeKeyT
- {
- IncludeKeyT(std::string const& key, std::size_t basePrefixLength);
-
- std::string Key; // Full include string
- std::string Dir; // Include directory
- std::string Base; // Base part of the include file name
- };
-
- /** Search key plus regular expression pair. */
- struct KeyExpT
- {
- KeyExpT() = default;
-
- KeyExpT(std::string key, std::string const& exp)
- : Key(std::move(key))
- , Exp(exp)
- {
- }
-
- std::string Key;
- cmsys::RegularExpression Exp;
- };
-
- /** Source file parsing cache. */
- class ParseCacheT
- {
- public:
- // -- Types
-
- /** Entry of the file parsing cache. */
- struct FileT
- {
- void Clear();
-
- struct MocT
- {
- std::string Macro;
- struct IncludeT
- {
- std::vector<IncludeKeyT> Underscore;
- std::vector<IncludeKeyT> Dot;
- } Include;
- std::vector<std::string> Depends;
- } Moc;
-
- struct UicT
- {
- std::vector<IncludeKeyT> Include;
- std::vector<std::string> Depends;
- } Uic;
- };
- using FileHandleT = std::shared_ptr<FileT>;
- using GetOrInsertT = std::pair<FileHandleT, bool>;
-
- public:
- ParseCacheT();
- ~ParseCacheT();
-
- void Clear();
-
- bool ReadFromFile(std::string const& fileName);
- bool WriteToFile(std::string const& fileName);
-
- //! Might return an invalid handle
- FileHandleT Get(std::string const& fileName) const;
- //! Always returns a valid handle
- GetOrInsertT GetOrInsert(std::string const& fileName);
-
- private:
- std::unordered_map<std::string, FileHandleT> Map_;
- };
-
- /** Source file data. */
- class SourceFileT
- {
- public:
- SourceFileT(std::string fileName)
- : FileName(std::move(fileName))
- {
- }
-
- public:
- std::string FileName;
- cmFileTime FileTime;
- ParseCacheT::FileHandleT ParseData;
- std::string BuildPath;
- bool IsHeader = false;
- bool Moc = false;
- bool Uic = false;
- };
- using SourceFileHandleT = std::shared_ptr<SourceFileT>;
- using SourceFileMapT = std::map<std::string, SourceFileHandleT>;
-
- /** Meta compiler file mapping information. */
- struct MappingT
- {
- SourceFileHandleT SourceFile;
- std::string OutputFile;
- std::string IncludeString;
- std::vector<SourceFileHandleT> IncluderFiles;
- };
- using MappingHandleT = std::shared_ptr<MappingT>;
- using MappingMapT = std::map<std::string, MappingHandleT>;
-
- /** Common settings. */
- class BaseSettingsT
- {
- public:
- // -- Constructors
- BaseSettingsT();
- ~BaseSettingsT();
-
- BaseSettingsT(BaseSettingsT const&) = delete;
- BaseSettingsT& operator=(BaseSettingsT const&) = delete;
-
- // -- Attributes
- // - Config
- bool MultiConfig = false;
- unsigned int QtVersionMajor = 4;
- unsigned int ThreadCount = 0;
- // - Directories
- std::string AutogenBuildDir;
- std::string AutogenIncludeDir;
- // - Files
- std::string CMakeExecutable;
- cmFileTime CMakeExecutableTime;
- std::string ParseCacheFile;
- std::vector<std::string> HeaderExtensions;
- };
-
- /** Shared common variables. */
- class BaseEvalT
- {
- public:
- // -- Parse Cache
- bool ParseCacheChanged = false;
- cmFileTime ParseCacheTime;
- ParseCacheT ParseCache;
-
- // -- Sources
- SourceFileMapT Headers;
- SourceFileMapT Sources;
- };
-
- /** Moc settings. */
- class MocSettingsT
- {
- public:
- // -- Constructors
- MocSettingsT();
- ~MocSettingsT();
-
- MocSettingsT(MocSettingsT const&) = delete;
- MocSettingsT& operator=(MocSettingsT const&) = delete;
-
- // -- Const methods
- bool skipped(std::string const& fileName) const;
- std::string MacrosString() const;
-
- // -- Attributes
- bool Enabled = false;
- bool SettingsChanged = false;
- bool RelaxedMode = false;
- bool PathPrefix = false;
- cmFileTime ExecutableTime;
- std::string Executable;
- std::string CompFileAbs;
- std::string PredefsFileAbs;
- std::unordered_set<std::string> SkipList;
- std::vector<std::string> IncludePaths;
- std::vector<std::string> Definitions;
- std::vector<std::string> OptionsIncludes;
- std::vector<std::string> OptionsDefinitions;
- std::vector<std::string> OptionsExtra;
- std::vector<std::string> PredefsCmd;
- std::vector<KeyExpT> DependFilters;
- std::vector<KeyExpT> MacroFilters;
- cmsys::RegularExpression RegExpInclude;
- };
-
- /** Moc shared variables. */
- class MocEvalT
- {
- public:
- // -- predefines file
- cmFileTime PredefsTime;
- // -- Mappings
- MappingMapT HeaderMappings;
- MappingMapT SourceMappings;
- MappingMapT Includes;
- // -- Discovered files
- SourceFileMapT HeadersDiscovered;
- // -- Output directories
- std::unordered_set<std::string> OutputDirs;
- // -- Mocs compilation
- bool CompUpdated = false;
- std::vector<std::string> CompFiles;
- };
-
- /** Uic settings. */
- class UicSettingsT
- {
- public:
- struct UiFile
- {
- std::vector<std::string> Options;
- };
-
- public:
- UicSettingsT();
- ~UicSettingsT();
-
- UicSettingsT(UicSettingsT const&) = delete;
- UicSettingsT& operator=(UicSettingsT const&) = delete;
-
- // -- Const methods
- bool skipped(std::string const& fileName) const;
-
- // -- Attributes
- bool Enabled = false;
- bool SettingsChanged = false;
- cmFileTime ExecutableTime;
- std::string Executable;
- std::unordered_set<std::string> SkipList;
- std::vector<std::string> Options;
- std::unordered_map<std::string, UiFile> UiFiles;
- std::vector<std::string> SearchPaths;
- cmsys::RegularExpression RegExpInclude;
- };
-
- /** Uic shared variables. */
- class UicEvalT
- {
- public:
- // -- Discovered files
- SourceFileMapT UiFiles;
- // -- Mappings
- MappingMapT Includes;
- // -- Output directories
- std::unordered_set<std::string> OutputDirs;
- };
-
- /** Abstract job class for concurrent job processing. */
- class JobT : public cmWorkerPool::JobT
- {
- protected:
- /** Protected default constructor. */
- JobT(bool fence = false)
- : cmWorkerPool::JobT(fence)
- {
- }
-
- //! Get the generator. Only valid during Process() call!
- cmQtAutoMocUic* Gen() const
- {
- return static_cast<cmQtAutoMocUic*>(UserData());
- };
-
- // -- Accessors. Only valid during Process() call!
- Logger const& Log() const { return Gen()->Log(); }
- BaseSettingsT const& BaseConst() const { return Gen()->BaseConst(); }
- BaseEvalT& BaseEval() const { return Gen()->BaseEval(); }
- MocSettingsT const& MocConst() const { return Gen()->MocConst(); }
- MocEvalT& MocEval() const { return Gen()->MocEval(); }
- UicSettingsT const& UicConst() const { return Gen()->UicConst(); }
- UicEvalT& UicEval() const { return Gen()->UicEval(); }
-
- // -- Logging
- std::string MessagePath(cm::string_view path) const
- {
- return Gen()->MessagePath(path);
- }
- // - Error logging with automatic abort
- void LogError(GenT genType, cm::string_view message) const;
- void LogCommandError(GenT genType, cm::string_view message,
- std::vector<std::string> const& command,
- std::string const& output) const;
-
- /** @brief Run an external process. Use only during Process() call! */
- bool RunProcess(GenT genType, cmWorkerPool::ProcessResultT& result,
- std::vector<std::string> const& command,
- std::string* infoMessage = nullptr);
- };
-
- /** Fence job utility class. */
- class JobFenceT : public JobT
- {
- public:
- JobFenceT()
- : JobT(true)
- {
- }
- void Process() override{};
- };
-
- /** Generate moc_predefs.h. */
- class JobMocPredefsT : public JobFenceT
- {
- void Process() override;
- bool Update(std::string* reason) const;
- };
-
- /** File parse job base class. */
- class JobParseT : public JobT
- {
- public:
- JobParseT(SourceFileHandleT fileHandle)
- : FileHandle(std::move(fileHandle))
- {
- }
-
- protected:
- bool ReadFile();
- void CreateKeys(std::vector<IncludeKeyT>& container,
- std::set<std::string> const& source,
- std::size_t basePrefixLength);
- void MocMacro();
- void MocDependecies();
- void MocIncludes();
- void UicIncludes();
-
- protected:
- SourceFileHandleT FileHandle;
- std::string Content;
- };
-
- /** Header file parse job. */
- class JobParseHeaderT : public JobParseT
- {
- public:
- using JobParseT::JobParseT;
- void Process() override;
- };
-
- /** Source file parse job. */
- class JobParseSourceT : public JobParseT
- {
- public:
- using JobParseT::JobParseT;
- void Process() override;
- };
-
- /** Evaluate cached file parse data - moc. */
- class JobEvalCacheT : public JobT
- {
- protected:
- std::string MessageSearchLocations() const;
- std::vector<std::string> SearchLocations;
- };
-
- /** Evaluate cached file parse data - moc. */
- class JobEvalCacheMocT : public JobEvalCacheT
- {
- void Process() override;
- bool EvalHeader(SourceFileHandleT source);
- bool EvalSource(SourceFileHandleT const& source);
- bool FindIncludedHeader(SourceFileHandleT& headerHandle,
- cm::string_view includerDir,
- cm::string_view includeBase);
- bool RegisterIncluded(std::string const& includeString,
- SourceFileHandleT includerFileHandle,
- SourceFileHandleT sourceFileHandle) const;
- void RegisterMapping(MappingHandleT mappingHandle) const;
- std::string MessageHeader(cm::string_view headerBase) const;
- };
-
- /** Evaluate cached file parse data - uic. */
- class JobEvalCacheUicT : public JobEvalCacheT
- {
- void Process() override;
- bool EvalFile(SourceFileHandleT const& sourceFileHandle);
- bool FindIncludedUi(cm::string_view sourceDirPrefix,
- cm::string_view includePrefix);
- bool RegisterMapping(std::string const& includeString,
- SourceFileHandleT includerFileHandle);
-
- std::string UiName;
- SourceFileHandleT UiFileHandle;
- };
-
- /** Evaluate cached file parse data - finish */
- class JobEvalCacheFinishT : public JobFenceT
- {
- void Process() override;
- };
-
- /** Dependency probing base job. */
- class JobProbeDepsT : public JobT
- {
- };
-
- /** Probes file dependencies and generates moc compile jobs. */
- class JobProbeDepsMocT : public JobProbeDepsT
- {
- void Process() override;
- bool Generate(MappingHandleT const& mapping, bool compFile) const;
- bool Probe(MappingT const& mapping, std::string* reason) const;
- std::pair<std::string, cmFileTime> FindDependency(
- std::string const& sourceDir, std::string const& includeString) const;
- };
-
- /** Probes file dependencies and generates uic compile jobs. */
- class JobProbeDepsUicT : public JobProbeDepsT
- {
- void Process() override;
- bool Probe(MappingT const& mapping, std::string* reason) const;
- };
-
- /** Dependency probing finish job. */
- class JobProbeDepsFinishT : public JobFenceT
- {
- void Process() override;
- };
-
- /** Meta compiler base job. */
- class JobCompileT : public JobT
- {
- public:
- JobCompileT(MappingHandleT uicMapping, std::unique_ptr<std::string> reason)
- : Mapping(std::move(uicMapping))
- , Reason(std::move(reason))
- {
- }
-
- protected:
- MappingHandleT Mapping;
- std::unique_ptr<std::string> Reason;
- };
-
- /** moc compiles a file. */
- class JobCompileMocT : public JobCompileT
- {
- public:
- using JobCompileT::JobCompileT;
- void Process() override;
- };
-
- /** uic compiles a file. */
- class JobCompileUicT : public JobCompileT
- {
- public:
- using JobCompileT::JobCompileT;
- void Process() override;
- };
-
- /** Generate mocs_compilation.cpp. */
- class JobMocsCompilationT : public JobFenceT
- {
- private:
- void Process() override;
- };
-
- /** @brief The last job. */
- class JobFinishT : public JobFenceT
- {
- private:
- void Process() override;
- };
-
- // -- Const settings interface
- BaseSettingsT const& BaseConst() const { return this->BaseConst_; }
- BaseEvalT& BaseEval() { return this->BaseEval_; }
- MocSettingsT const& MocConst() const { return this->MocConst_; }
- MocEvalT& MocEval() { return this->MocEval_; }
- UicSettingsT const& UicConst() const { return this->UicConst_; }
- UicEvalT& UicEval() { return this->UicEval_; }
-
- // -- Parallel job processing interface
- cmWorkerPool& WorkerPool() { return WorkerPool_; }
- void AbortError() { Abort(true); }
- void AbortSuccess() { Abort(false); }
-
- // -- Utility
- std::string AbsoluteBuildPath(cm::string_view relativePath) const;
- std::string AbsoluteIncludePath(cm::string_view relativePath) const;
- template <class JOBTYPE>
- void CreateParseJobs(SourceFileMapT const& sourceMap);
- std::string CollapseFullPathTS(std::string const& path) const;
-
-private:
- // -- Abstract processing interface
- bool InitFromInfo() override;
- void InitJobs();
- bool Process() override;
- // -- Settings file
- void SettingsFileRead();
- bool SettingsFileWrite();
- // -- Parse cache
- void ParseCacheRead();
- bool ParseCacheWrite();
- // -- Thread processing
- void Abort(bool error);
- // -- Generation
- bool CreateDirectories();
-
-private:
- // -- Settings
- BaseSettingsT BaseConst_;
- BaseEvalT BaseEval_;
- MocSettingsT MocConst_;
- MocEvalT MocEval_;
- UicSettingsT UicConst_;
- UicEvalT UicEval_;
- // -- Settings file
- std::string SettingsFile_;
- std::string SettingsStringMoc_;
- std::string SettingsStringUic_;
- // -- Worker thread pool
- std::atomic<bool> JobError_ = ATOMIC_VAR_INIT(false);
- cmWorkerPool WorkerPool_;
- // -- Concurrent processing
- mutable std::mutex CMakeLibMutex_;
-};
+bool cmQtAutoMocUic(cm::string_view infoFile, cm::string_view config);
#endif
diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx
index b0b15d4..4a3ecfa 100644
--- a/Source/cmQtAutoRcc.cxx
+++ b/Source/cmQtAutoRcc.cxx
@@ -5,37 +5,105 @@
#include "cmAlgorithms.h"
#include "cmCryptoHash.h"
#include "cmDuration.h"
+#include "cmFileLock.h"
#include "cmFileLockResult.h"
+#include "cmFileTime.h"
#include "cmProcessOutput.h"
#include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include <cm/string_view>
-
#include <algorithm>
+#include <string>
+#include <vector>
+
+namespace {
-cmQtAutoRcc::cmQtAutoRcc()
+/** \class cmQtAutoRccT
+ * \brief AUTORCC generator
+ */
+class cmQtAutoRccT : public cmQtAutoGenerator
+{
+public:
+ cmQtAutoRccT();
+ ~cmQtAutoRccT() override;
+
+ cmQtAutoRccT(cmQtAutoRccT const&) = delete;
+ cmQtAutoRccT& operator=(cmQtAutoRccT const&) = delete;
+
+private:
+ // -- Utility
+ bool IsMultiConfig() const { return MultiConfig_; }
+ std::string MultiConfigOutput() const;
+
+ // -- Abstract processing interface
+ bool InitFromInfo(InfoT const& info) override;
+ bool Process() override;
+ // -- Settings file
+ bool SettingsFileRead();
+ bool SettingsFileWrite();
+ // -- Tests
+ bool TestQrcRccFiles(bool& generate);
+ bool TestResources(bool& generate);
+ bool TestInfoFile();
+ // -- Generation
+ bool GenerateRcc();
+ bool GenerateWrapper();
+
+private:
+ // -- Config settings
+ bool MultiConfig_ = false;
+ // -- Directories
+ std::string AutogenBuildDir_;
+ std::string IncludeDir_;
+ // -- Qt environment
+ std::string RccExecutable_;
+ cmFileTime RccExecutableTime_;
+ std::vector<std::string> RccListOptions_;
+ // -- Job
+ std::string LockFile_;
+ cmFileLock LockFileLock_;
+ std::string QrcFile_;
+ std::string QrcFileName_;
+ std::string QrcFileDir_;
+ cmFileTime QrcFileTime_;
+ std::string RccPathChecksum_;
+ std::string RccFileName_;
+ std::string RccFileOutput_;
+ std::string RccFilePublic_;
+ cmFileTime RccFileTime_;
+ std::string Reason;
+ std::vector<std::string> Options_;
+ std::vector<std::string> Inputs_;
+ // -- Settings file
+ std::string SettingsFile_;
+ std::string SettingsString_;
+ bool SettingsChanged_ = false;
+ bool BuildFileChanged_ = false;
+};
+
+cmQtAutoRccT::cmQtAutoRccT()
: cmQtAutoGenerator(GenT::RCC)
{
}
-cmQtAutoRcc::~cmQtAutoRcc() = default;
+cmQtAutoRccT::~cmQtAutoRccT() = default;
-bool cmQtAutoRcc::InitFromInfo()
+bool cmQtAutoRccT::InitFromInfo(InfoT const& info)
{
// -- Required settings
- if (!InfoBool("MULTI_CONFIG", MultiConfig_, true) ||
- !InfoString("BUILD_DIR", AutogenBuildDir_, true) ||
- !InfoStringConfig("INCLUDE_DIR", IncludeDir_, true) ||
- !InfoString("RCC_EXECUTABLE", RccExecutable_, true) ||
- !InfoArray("RCC_LIST_OPTIONS", RccListOptions_, false) ||
- !InfoString("LOCK_FILE", LockFile_, true) ||
- !InfoStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
- !InfoString("SOURCE", QrcFile_, true) ||
- !InfoString("OUTPUT_CHECKSUM", RccPathChecksum_, true) ||
- !InfoString("OUTPUT_NAME", RccFileName_, true) ||
- !InfoArray("OPTIONS", Options_, false) ||
- !InfoArray("INPUTS", Inputs_, false)) {
+ if (!info.GetBool("MULTI_CONFIG", MultiConfig_, true) ||
+ !info.GetString("BUILD_DIR", AutogenBuildDir_, true) ||
+ !info.GetStringConfig("INCLUDE_DIR", IncludeDir_, true) ||
+ !info.GetString("RCC_EXECUTABLE", RccExecutable_, true) ||
+ !info.GetArray("RCC_LIST_OPTIONS", RccListOptions_, false) ||
+ !info.GetString("LOCK_FILE", LockFile_, true) ||
+ !info.GetStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
+ !info.GetString("SOURCE", QrcFile_, true) ||
+ !info.GetString("OUTPUT_CHECKSUM", RccPathChecksum_, true) ||
+ !info.GetString("OUTPUT_NAME", RccFileName_, true) ||
+ !info.GetArray("OPTIONS", Options_, false) ||
+ !info.GetArray("INPUTS", Inputs_, false)) {
return false;
}
@@ -54,14 +122,14 @@ bool cmQtAutoRcc::InitFromInfo()
// -- Checks
if (!RccExecutableTime_.Load(RccExecutable_)) {
- return LogInfoError(cmStrCat(
+ return info.LogError(cmStrCat(
"The rcc executable ", MessagePath(RccExecutable_), " does not exist."));
}
return true;
}
-bool cmQtAutoRcc::Process()
+bool cmQtAutoRccT::Process()
{
if (!SettingsFileRead()) {
return false;
@@ -94,13 +162,13 @@ bool cmQtAutoRcc::Process()
return SettingsFileWrite();
}
-std::string cmQtAutoRcc::MultiConfigOutput() const
+std::string cmQtAutoRccT::MultiConfigOutput() const
{
return cmStrCat(RccPathChecksum_, '/',
AppendFilenameSuffix(RccFileName_, "_CMAKE_"));
}
-bool cmQtAutoRcc::SettingsFileRead()
+bool cmQtAutoRccT::SettingsFileRead()
{
// Compose current settings strings
{
@@ -178,7 +246,7 @@ bool cmQtAutoRcc::SettingsFileRead()
return true;
}
-bool cmQtAutoRcc::SettingsFileWrite()
+bool cmQtAutoRccT::SettingsFileWrite()
{
// Only write if any setting changed
if (SettingsChanged_) {
@@ -205,7 +273,7 @@ bool cmQtAutoRcc::SettingsFileWrite()
}
/// Do basic checks if rcc generation is required
-bool cmQtAutoRcc::TestQrcRccFiles(bool& generate)
+bool cmQtAutoRccT::TestQrcRccFiles(bool& generate)
{
// Test if the rcc input file exists
if (!QrcFileTime_.Load(QrcFile_)) {
@@ -262,7 +330,7 @@ bool cmQtAutoRcc::TestQrcRccFiles(bool& generate)
return true;
}
-bool cmQtAutoRcc::TestResources(bool& generate)
+bool cmQtAutoRccT::TestResources(bool& generate)
{
// Read resource files list
if (Inputs_.empty()) {
@@ -301,7 +369,7 @@ bool cmQtAutoRcc::TestResources(bool& generate)
return true;
}
-bool cmQtAutoRcc::TestInfoFile()
+bool cmQtAutoRccT::TestInfoFile()
{
// Test if the rcc output file is older than the info file
if (RccFileTime_.Older(InfoFileTime())) {
@@ -324,7 +392,7 @@ bool cmQtAutoRcc::TestInfoFile()
return true;
}
-bool cmQtAutoRcc::GenerateRcc()
+bool cmQtAutoRccT::GenerateRcc()
{
// Make parent directory
if (!MakeParentDirectory(RccFileOutput_)) {
@@ -376,7 +444,7 @@ bool cmQtAutoRcc::GenerateRcc()
return true;
}
-bool cmQtAutoRcc::GenerateWrapper()
+bool cmQtAutoRccT::GenerateWrapper()
{
// Generate a wrapper source file on demand
if (IsMultiConfig()) {
@@ -426,3 +494,10 @@ bool cmQtAutoRcc::GenerateWrapper()
}
return true;
}
+
+} // End of unnamed namespace
+
+bool cmQtAutoRcc(cm::string_view infoFile, cm::string_view config)
+{
+ return cmQtAutoRccT().Run(infoFile, config);
+}
diff --git a/Source/cmQtAutoRcc.h b/Source/cmQtAutoRcc.h
index 945b68f..a74b33a 100644
--- a/Source/cmQtAutoRcc.h
+++ b/Source/cmQtAutoRcc.h
@@ -5,74 +5,12 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmFileLock.h"
-#include "cmFileTime.h"
-#include "cmQtAutoGenerator.h"
+#include <cm/string_view>
-#include <string>
-#include <vector>
-
-/** \class cmQtAutoRcc
- * \brief AUTORCC generator
+/**
+ * Process AUTORCC
+ * @return true on success
*/
-class cmQtAutoRcc : public cmQtAutoGenerator
-{
-public:
- cmQtAutoRcc();
- ~cmQtAutoRcc() override;
-
- cmQtAutoRcc(cmQtAutoRcc const&) = delete;
- cmQtAutoRcc& operator=(cmQtAutoRcc const&) = delete;
-
-private:
- // -- Utility
- bool IsMultiConfig() const { return MultiConfig_; }
- std::string MultiConfigOutput() const;
-
- // -- Abstract processing interface
- bool InitFromInfo() override;
- bool Process() override;
- // -- Settings file
- bool SettingsFileRead();
- bool SettingsFileWrite();
- // -- Tests
- bool TestQrcRccFiles(bool& generate);
- bool TestResources(bool& generate);
- bool TestInfoFile();
- // -- Generation
- bool GenerateRcc();
- bool GenerateWrapper();
-
-private:
- // -- Config settings
- bool MultiConfig_ = false;
- // -- Directories
- std::string AutogenBuildDir_;
- std::string IncludeDir_;
- // -- Qt environment
- std::string RccExecutable_;
- cmFileTime RccExecutableTime_;
- std::vector<std::string> RccListOptions_;
- // -- Job
- std::string LockFile_;
- cmFileLock LockFileLock_;
- std::string QrcFile_;
- std::string QrcFileName_;
- std::string QrcFileDir_;
- cmFileTime QrcFileTime_;
- std::string RccPathChecksum_;
- std::string RccFileName_;
- std::string RccFileOutput_;
- std::string RccFilePublic_;
- cmFileTime RccFileTime_;
- std::string Reason;
- std::vector<std::string> Options_;
- std::vector<std::string> Inputs_;
- // -- Settings file
- std::string SettingsFile_;
- std::string SettingsString_;
- bool SettingsChanged_ = false;
- bool BuildFileChanged_ = false;
-};
+bool cmQtAutoRcc(cm::string_view infoFile, cm::string_view config);
#endif
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index ae77d9e..62ead60 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -332,6 +332,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("C_STANDARD");
initProp("C_STANDARD_REQUIRED");
initProp("C_EXTENSIONS");
+ initProp("OBJC_STANDARD");
+ initProp("OBJC_STANDARD_REQUIRED");
+ initProp("OBJC_EXTENSIONS");
initProp("CXX_CLANG_TIDY");
initProp("CXX_COMPILER_LAUNCHER");
initProp("CXX_CPPLINT");
@@ -340,6 +343,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("CXX_STANDARD");
initProp("CXX_STANDARD_REQUIRED");
initProp("CXX_EXTENSIONS");
+ initProp("OBJCXX_STANDARD");
+ initProp("OBJCXX_STANDARD_REQUIRED");
+ initProp("OBJCXX_EXTENSIONS");
initProp("CUDA_STANDARD");
initProp("CUDA_STANDARD_REQUIRED");
initProp("CUDA_EXTENSIONS");
@@ -452,6 +458,8 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
this->GetType() != cmStateEnums::UTILITY) {
initProp("C_VISIBILITY_PRESET");
initProp("CXX_VISIBILITY_PRESET");
+ initProp("OBJC_VISIBILITY_PRESET");
+ initProp("OBJCXX_VISIBILITY_PRESET");
initProp("CUDA_VISIBILITY_PRESET");
initProp("VISIBILITY_INLINES_HIDDEN");
}
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index bf856d7..7bb3dce 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -27,6 +27,7 @@
#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32)
# include "bindexplib.h"
+# include "cmFileTime.h"
# include "cmsys/ConsoleBuf.hxx"
#endif
@@ -48,6 +49,8 @@
#include <sstream>
#include <utility>
+#include <cm/string_view>
+
class cmConnection;
int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
@@ -1057,19 +1060,15 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
#ifndef CMAKE_BOOTSTRAP
if ((args[1] == "cmake_autogen") && (args.size() >= 4)) {
- cmQtAutoMocUic autoGen;
- std::string const& infoFile = args[2];
- std::string const& config = args[3];
- return autoGen.Run(infoFile, config) ? 0 : 1;
+ cm::string_view const infoFile = args[2];
+ cm::string_view const config = args[3];
+ return cmQtAutoMocUic(infoFile, config) ? 0 : 1;
}
if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) {
- cmQtAutoRcc autoRcc;
- std::string const& infoFile = args[2];
- std::string config;
- if (args.size() > 3) {
- config = args[3];
- }
- return autoRcc.Run(infoFile, config) ? 0 : 1;
+ cm::string_view const infoFile = args[2];
+ cm::string_view const config =
+ (args.size() > 3) ? cm::string_view(args[3]) : cm::string_view();
+ return cmQtAutoRcc(infoFile, config) ? 0 : 1;
}
#endif
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index c284603..789fc0e 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -2328,6 +2328,79 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CFBundleTest")
ADD_TEST_MACRO(ObjC++ ObjC++)
+
+ add_test(Objective-C.simple-build-test ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/Objective-C/simple-build-test"
+ "${CMake_BINARY_DIR}/Tests/Objective-C/simple-build-test"
+ --build-two-config
+ ${build_generator_args}
+ --build-project simple-build-test
+ --build-options ${build_options}
+ --test-command simple-build-test
+ )
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Objective-C/simple-build-test")
+
+ add_test(Objective-C.c-file-extension-test ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/Objective-C/c-file-extension-test"
+ "${CMake_BINARY_DIR}/Tests/Objective-C/c-file-extension-test"
+ --build-two-config
+ ${build_generator_args}
+ --build-project c-file-extension-test
+ --build-options ${build_options}
+ --test-command c-file-extension-test
+ )
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Objective-C/c-file-extension-test")
+
+ add_test(Objective-C.objc-file-extension-test ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/Objective-C/objc-file-extension-test"
+ "${CMake_BINARY_DIR}/Tests/Objective-C/objc-file-extension-test"
+ --build-two-config
+ ${build_generator_args}
+ --build-project objc-file-extension-test
+ --build-options ${build_options}
+ --test-command objc-file-extension-test
+ )
+ list(APPEND TEST_BUILD_DIRS "${CMAKE_BINARY_DIR}/Tests/Objective-C/objc-file-extension-test")
+
+ add_test(Objective-CXX.simple-build-test ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/Objective-C++/simple-build-test"
+ "${CMake_BINARY_DIR}/Tests/Objective-C++/simple-build-test"
+ --build-two-config
+ ${build_generator_args}
+ --build-project simple-build-test
+ --build-options ${build_options}
+ --test-command simple-build-test
+ )
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Objective-C++/simple-build-test")
+
+ add_test(Objective-CXX.cxx-file-extension-test ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/Objective-C++/cxx-file-extension-test"
+ "${CMake_BINARY_DIR}/Tests/Objective-C++/cxx-file-extension-test"
+ --build-two-config
+ ${build_generator_args}
+ --build-project cxx-file-extension-test
+ --build-options ${build_options}
+ --test-command cxx-file-extension-test
+ )
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Objective-C++/cxx-file-extension-test")
+
+ add_test(Objective-CXX.objcxx-file-extension-test ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/Objective-C++/objcxx-file-extension-test"
+ "${CMake_BINARY_DIR}/Tests/Objective-C++/objcxx-file-extension-test"
+ --build-two-config
+ ${build_generator_args}
+ --build-project objcxx-file-extension-test
+ --build-options ${build_options}
+ --test-command objcxx-file-extension-test
+ )
+ list(APPEND TEST_BUILD_DIRS "${CMAKE_BINARY_DIR}/Tests/Objective-C++/objcxx-file-extension-test")
+
endif ()
endif ()
diff --git a/Tests/CMakeOnly/CMakeLists.txt b/Tests/CMakeOnly/CMakeLists.txt
index 19f3f79..03babd2 100644
--- a/Tests/CMakeOnly/CMakeLists.txt
+++ b/Tests/CMakeOnly/CMakeLists.txt
@@ -30,6 +30,17 @@ add_CMakeOnly_test(CheckStructHasMember)
add_CMakeOnly_test(CompilerIdC)
add_CMakeOnly_test(CompilerIdCXX)
+
+if(CMAKE_OBJC_COMPILER)
+ add_CMakeOnly_test(CompilerIdOBJC)
+ add_CMakeOnly_test(CheckOBJCCompilerFlag)
+endif()
+
+if(CMAKE_OBJCXX_COMPILER)
+ add_CMakeOnly_test(CompilerIdOBJCXX)
+ add_CMakeOnly_test(CheckOBJCXXCompilerFlag)
+endif()
+
if(CMAKE_Fortran_COMPILER)
add_CMakeOnly_test(CompilerIdFortran)
endif()
diff --git a/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt b/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt
index ca4becb..90aa921 100644
--- a/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt
+++ b/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt
@@ -5,10 +5,20 @@ include(CheckLanguage)
set(langs )
set(expect_C 1)
set(expect_CXX 1)
+
+if(APPLE)
+ set(expect_OBJC 1)
+ set(expect_OBJCXX 1)
+endif()
unset(expect_Fortran)
set(expect_NoSuchLanguage 0)
-foreach(lang C CXX Fortran CUDA NoSuchLanguage)
+set(LANGUAGES C CXX Fortran CUDA NoSuchLanguage)
+if(APPLE)
+ list(APPEND LANGUAGES OBJC OBJCXX)
+endif()
+
+foreach(lang ${LANGUAGES})
check_language(${lang})
if(NOT DEFINED CMAKE_${lang}_COMPILER)
message(FATAL_ERROR "check_language(${lang}) did not set result")
diff --git a/Tests/CMakeOnly/CheckOBJCCompilerFlag/CMakeLists.txt b/Tests/CMakeOnly/CheckOBJCCompilerFlag/CMakeLists.txt
new file mode 100644
index 0000000..a9a96ee
--- /dev/null
+++ b/Tests/CMakeOnly/CheckOBJCCompilerFlag/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 2.8.12)
+
+project(CheckOBJCCompilerFlag)
+
+include(CheckOBJCCompilerFlag)
+
+if(CMAKE_COMPILER_IS_GNUOBJC)
+ set(COMPILER_FLAG -fobjc-direct-dispatch)
+else()
+ set(COMPILER_FLAG -fobjc-gc)
+endif()
+
+CHECK_OBJC_COMPILER_FLAGS(${COMPILER_FLAG} HAS_COMPILER_FLAG)
+
+if(NOT HAS_COMPILER_FLAG)
+ message(SEND_ERROR "Test fail: HAS_COMPILER_FLAG: ${COMPILER_FLAG}")
+endif
diff --git a/Tests/CMakeOnly/CheckOBJCXXCompilerFlag/CMakeLists.txt b/Tests/CMakeOnly/CheckOBJCXXCompilerFlag/CMakeLists.txt
new file mode 100644
index 0000000..f83b738
--- /dev/null
+++ b/Tests/CMakeOnly/CheckOBJCXXCompilerFlag/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 2.8.12)
+
+project(CheckOBJCXXCompilerFlag)
+
+include(CheckOBJCXXCompilerFlag)
+
+if(CMAKE_COMPILER_IS_GNUOBJCXX)
+ set(COMPILER_FLAG -fobjc-direct-dispatch)
+else()
+ set(COMPILER_FLAG -fobjc-gc)
+endif()
+
+CHECK_OBJCXX_COMPILER_FLAGS(${COMPILER_FLAG} HAS_COMPILER_FLAG)
+
+if(NOT HAS_COMPILER_FLAG)
+ message(SEND_ERROR "Test fail: HAS_COMPILER_FLAG: ${COMPILER_FLAG}")
+endif()
diff --git a/Tests/CMakeOnly/CompilerIdOBJC/CMakeLists.txt b/Tests/CMakeOnly/CompilerIdOBJC/CMakeLists.txt
new file mode 100644
index 0000000..8f13787
--- /dev/null
+++ b/Tests/CMakeOnly/CompilerIdOBJC/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 2.8.12)
+project(CompilerIdOBJC OBJC)
+
+foreach(v
+ CMAKE_OBJC_COMPILER
+ CMAKE_OBJC_COMPILER_ID
+ CMAKE_OBJC_COMPILER_VERSION
+ )
+ if(${v})
+ message(STATUS "${v}=[${${v}}]")
+ else()
+ message(SEND_ERROR "${v} not set!")
+ endif()
+endforeach()
diff --git a/Tests/CMakeOnly/CompilerIdOBJCXX/CMakeLists.txt b/Tests/CMakeOnly/CompilerIdOBJCXX/CMakeLists.txt
new file mode 100644
index 0000000..8f41db0
--- /dev/null
+++ b/Tests/CMakeOnly/CompilerIdOBJCXX/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 2.8.12)
+project(CompilerIdOBJCXX OBJCXX)
+
+foreach(v
+ CMAKE_OBJCXX_COMPILER
+ CMAKE_OBJCXX_COMPILER_ID
+ CMAKE_OBJCXX_COMPILER_VERSION
+ )
+ if(${v})
+ message(STATUS "${v}=[${${v}}]")
+ else()
+ message(SEND_ERROR "${v} not set!")
+ endif()
+endforeach()
diff --git a/Tests/Objective-C++/cxx-file-extension-test/CMakeLists.txt b/Tests/Objective-C++/cxx-file-extension-test/CMakeLists.txt
new file mode 100644
index 0000000..0b33875
--- /dev/null
+++ b/Tests/Objective-C++/cxx-file-extension-test/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.15)
+
+project(cxx-file-extension-test CXX)
+
+add_executable(cxx-file-extension-test main.mm)
diff --git a/Tests/Objective-C++/cxx-file-extension-test/main.mm b/Tests/Objective-C++/cxx-file-extension-test/main.mm
new file mode 100644
index 0000000..1c159a9
--- /dev/null
+++ b/Tests/Objective-C++/cxx-file-extension-test/main.mm
@@ -0,0 +1,8 @@
+#ifndef __OBJC__
+# error "Compiler cannot compile Objective-C"
+#endif
+
+int main()
+{
+ return 0;
+}
diff --git a/Tests/Objective-C++/objcxx-file-extension-test/CMakeLists.txt b/Tests/Objective-C++/objcxx-file-extension-test/CMakeLists.txt
new file mode 100644
index 0000000..eda7bba
--- /dev/null
+++ b/Tests/Objective-C++/objcxx-file-extension-test/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.15)
+
+project(objcxx-file-extension-test OBJCXX CXX)
+
+add_executable(objcxx-file-extension-test main.mm)
+target_link_libraries(objcxx-file-extension-test "-framework Foundation")
diff --git a/Tests/Objective-C++/objcxx-file-extension-test/main.mm b/Tests/Objective-C++/objcxx-file-extension-test/main.mm
new file mode 100644
index 0000000..d4aa1bb
--- /dev/null
+++ b/Tests/Objective-C++/objcxx-file-extension-test/main.mm
@@ -0,0 +1,14 @@
+#ifndef __OBJC__
+# error "Compiler is not an Objective-C compiler."
+#endif
+
+#import <Foundation/Foundation.h>
+#include <iostream>
+
+int main()
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ std::cout << "Hello World" << std::endl;
+ [pool release];
+ return 0;
+}
diff --git a/Tests/Objective-C++/simple-build-test/CMakeLists.txt b/Tests/Objective-C++/simple-build-test/CMakeLists.txt
new file mode 100644
index 0000000..cf27683
--- /dev/null
+++ b/Tests/Objective-C++/simple-build-test/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.15)
+
+set(CMAKE_MACOSX_RPATH OFF)
+
+project(simple-build-test OBJCXX)
+
+add_library(foo SHARED foo.mm)
+target_link_libraries(foo "-framework Foundation")
+
+add_executable(simple-build-test main.mm)
+target_link_libraries(simple-build-test "-framework Foundation" foo)
diff --git a/Tests/Objective-C++/simple-build-test/foo.h b/Tests/Objective-C++/simple-build-test/foo.h
new file mode 100644
index 0000000..b3fb084
--- /dev/null
+++ b/Tests/Objective-C++/simple-build-test/foo.h
@@ -0,0 +1,9 @@
+#import <Foundation/Foundation.h>
+
+@interface Foo : NSObject {
+ NSNumber* age;
+}
+
+@property (nonatomic, retain) NSNumber* age;
+
+@end
diff --git a/Tests/Objective-C++/simple-build-test/foo.mm b/Tests/Objective-C++/simple-build-test/foo.mm
new file mode 100644
index 0000000..2d452a8
--- /dev/null
+++ b/Tests/Objective-C++/simple-build-test/foo.mm
@@ -0,0 +1,7 @@
+#import "foo.h"
+
+@implementation Foo
+
+@synthesize age;
+
+@end
diff --git a/Tests/Objective-C++/simple-build-test/main.mm b/Tests/Objective-C++/simple-build-test/main.mm
new file mode 100644
index 0000000..7c85551
--- /dev/null
+++ b/Tests/Objective-C++/simple-build-test/main.mm
@@ -0,0 +1,14 @@
+#import <Foundation/Foundation.h>
+#import "foo.h"
+#include <iostream>
+
+int main(int argc, char **argv)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ Foo *theFoo = [[Foo alloc] init];
+ theFoo.age = [NSNumber numberWithInt:argc];
+ NSLog(@"%d\n",[theFoo.age intValue]);
+ std::cout << [theFoo.age intValue] << std::endl;
+ [pool release];
+ return 0;
+}
diff --git a/Tests/Objective-C/c-file-extension-test/CMakeLists.txt b/Tests/Objective-C/c-file-extension-test/CMakeLists.txt
new file mode 100644
index 0000000..e091448
--- /dev/null
+++ b/Tests/Objective-C/c-file-extension-test/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.15)
+
+project(c-file-extension-test C)
+
+add_executable(c-file-extension-test main.m)
diff --git a/Tests/Objective-C/c-file-extension-test/main.m b/Tests/Objective-C/c-file-extension-test/main.m
new file mode 100644
index 0000000..1c159a9
--- /dev/null
+++ b/Tests/Objective-C/c-file-extension-test/main.m
@@ -0,0 +1,8 @@
+#ifndef __OBJC__
+# error "Compiler cannot compile Objective-C"
+#endif
+
+int main()
+{
+ return 0;
+}
diff --git a/Tests/Objective-C/objc-file-extension-test/CMakeLists.txt b/Tests/Objective-C/objc-file-extension-test/CMakeLists.txt
new file mode 100644
index 0000000..27e88be
--- /dev/null
+++ b/Tests/Objective-C/objc-file-extension-test/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.15)
+
+project(objc-file-extension-test OBJC CXX)
+
+add_executable(objc-file-extension-test main.m)
+target_link_libraries(objc-file-extension-test "-framework Foundation")
diff --git a/Tests/Objective-C/objc-file-extension-test/main.m b/Tests/Objective-C/objc-file-extension-test/main.m
new file mode 100644
index 0000000..2ec3917
--- /dev/null
+++ b/Tests/Objective-C/objc-file-extension-test/main.m
@@ -0,0 +1,12 @@
+#ifndef __OBJC__
+# error "Compiler is not an Objective-C compiler."
+#endif
+
+#import <Foundation/Foundation.h>
+
+int main()
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [pool release];
+ return 0;
+}
diff --git a/Tests/Objective-C/simple-build-test/CMakeLists.txt b/Tests/Objective-C/simple-build-test/CMakeLists.txt
new file mode 100644
index 0000000..5ab46ac
--- /dev/null
+++ b/Tests/Objective-C/simple-build-test/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.15)
+
+set(CMAKE_MACOSX_RPATH OFF)
+
+project(simple-build-test OBJC)
+
+add_library(foo SHARED foo.m)
+target_link_libraries(foo "-framework Foundation")
+
+add_executable(simple-build-test main.m)
+target_link_libraries(simple-build-test "-framework Foundation" foo)
diff --git a/Tests/Objective-C/simple-build-test/foo.h b/Tests/Objective-C/simple-build-test/foo.h
new file mode 100644
index 0000000..b3fb084
--- /dev/null
+++ b/Tests/Objective-C/simple-build-test/foo.h
@@ -0,0 +1,9 @@
+#import <Foundation/Foundation.h>
+
+@interface Foo : NSObject {
+ NSNumber* age;
+}
+
+@property (nonatomic, retain) NSNumber* age;
+
+@end
diff --git a/Tests/Objective-C/simple-build-test/foo.m b/Tests/Objective-C/simple-build-test/foo.m
new file mode 100644
index 0000000..2d452a8
--- /dev/null
+++ b/Tests/Objective-C/simple-build-test/foo.m
@@ -0,0 +1,7 @@
+#import "foo.h"
+
+@implementation Foo
+
+@synthesize age;
+
+@end
diff --git a/Tests/Objective-C/simple-build-test/main.m b/Tests/Objective-C/simple-build-test/main.m
new file mode 100644
index 0000000..970d554
--- /dev/null
+++ b/Tests/Objective-C/simple-build-test/main.m
@@ -0,0 +1,12 @@
+#import <Foundation/Foundation.h>
+#import "foo.h"
+
+int main(int argc, char **argv)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ Foo *theFoo = [[Foo alloc] init];
+ theFoo.age = [NSNumber numberWithInt:argc];
+ NSLog(@"%d\n",[theFoo.age intValue]);
+ [pool release];
+ return 0;
+}
diff --git a/Tests/RunCMake/FPHSA/CustomMessageConfig.cmake b/Tests/RunCMake/FPHSA/CustomMessageConfig.cmake
new file mode 100644
index 0000000..e25db1a
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/CustomMessageConfig.cmake
@@ -0,0 +1 @@
+# pseudo config module
diff --git a/Tests/RunCMake/FPHSA/CustomMessageConfigVersion.cmake b/Tests/RunCMake/FPHSA/CustomMessageConfigVersion.cmake
new file mode 100644
index 0000000..b7c9e18
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/CustomMessageConfigVersion.cmake
@@ -0,0 +1,4 @@
+# pseudo find_module
+
+set (PACKAGE_VERSION 2)
+set (PACKAGE_VERSION_UNSUITABLE TRUE)
diff --git a/Tests/RunCMake/FPHSA/FindCustomMessage.cmake b/Tests/RunCMake/FPHSA/FindCustomMessage.cmake
new file mode 100644
index 0000000..4d67db8
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/FindCustomMessage.cmake
@@ -0,0 +1,17 @@
+# pseudo find_module
+
+if (REASON_FAILURE_MESSAGE)
+ list (PREPEND REASON_FAILURE_MESSAGE "REASON_FAILURE_MESSAGE")
+endif()
+
+include(FindPackageHandleStandardArgs)
+
+if (CONFIG_MODE)
+ find_package (CustomMessage QUIET CONFIG HINTS "${CMAKE_MODULE_PATH}")
+ find_package_handle_standard_args(CustomMessage CONFIG_MODE
+ ${REASON_FAILURE_MESSAGE})
+else()
+ find_package_handle_standard_args(CustomMessage REQUIRED_VARS FOOBAR
+ VERSION_VAR CustomMessage_VERSION
+ ${REASON_FAILURE_MESSAGE})
+endif()
diff --git a/Tests/RunCMake/FPHSA/RunCMakeTest.cmake b/Tests/RunCMake/FPHSA/RunCMakeTest.cmake
index dd73cd4..f3e6c3e 100644
--- a/Tests/RunCMake/FPHSA/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FPHSA/RunCMakeTest.cmake
@@ -39,3 +39,10 @@ unset(RunCMake_DEFAULT_stderr)
# check if searching for a version 0 works
list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DPseudo_VERSION=0")
run_cmake(exact_0_matching)
+
+# check custom error message
+set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DCustomMessage_VERSION=1.2.3.4")
+run_cmake(custom_message_1)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DCONFIG_MODE=TRUE")
+run_cmake(custom_message_2)
+run_cmake(custom_message_3)
diff --git a/Tests/RunCMake/FPHSA/custom_message_1-result.txt b/Tests/RunCMake/FPHSA/custom_message_1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/FPHSA/custom_message_1-stderr.txt b/Tests/RunCMake/FPHSA/custom_message_1-stderr.txt
new file mode 100644
index 0000000..992fe39
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_1-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at .+/Modules/FindPackageHandleStandardArgs.cmake:[0-9]+ \(message\):
+ Could NOT find CustomMessage \(missing: FOOBAR\) \(found suitable version
+ "1\.2\.3\.4", minimum required is "1\.2"\)
+
+ Reason given by package: Reason Failure
+
+Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/FPHSA/custom_message_1.cmake b/Tests/RunCMake/FPHSA/custom_message_1.cmake
new file mode 100644
index 0000000..330de50
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_1.cmake
@@ -0,0 +1,4 @@
+
+set (REASON_FAILURE_MESSAGE "Reason Failure")
+
+find_package(CustomMessage 1.2 REQUIRED)
diff --git a/Tests/RunCMake/FPHSA/custom_message_2-result.txt b/Tests/RunCMake/FPHSA/custom_message_2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/FPHSA/custom_message_2-stderr.txt b/Tests/RunCMake/FPHSA/custom_message_2-stderr.txt
new file mode 100644
index 0000000..4940752
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_2-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Error at .+/Modules/FindPackageHandleStandardArgs.cmake:[0-9]+ \(message\):
+ Could NOT find CustomMessage \(Required is at least version "1\.2"\), checked
+ the following files:
+
+ .+/Tests/RunCMake/FPHSA/CustomMessageConfig.cmake \(version 2\)
+ Reason given by package: Not Found Message
+
+Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/FPHSA/custom_message_2.cmake b/Tests/RunCMake/FPHSA/custom_message_2.cmake
new file mode 100644
index 0000000..a3f2d96
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_2.cmake
@@ -0,0 +1,5 @@
+
+unset (REASON_FAILURE_MESSAGE)
+set (CustomMessage_NOT_FOUND_MESSAGE "Not Found Message")
+
+find_package(CustomMessage 1.2 REQUIRED)
diff --git a/Tests/RunCMake/FPHSA/custom_message_3-result.txt b/Tests/RunCMake/FPHSA/custom_message_3-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/FPHSA/custom_message_3-stderr.txt b/Tests/RunCMake/FPHSA/custom_message_3-stderr.txt
new file mode 100644
index 0000000..dc55843
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_3-stderr.txt
@@ -0,0 +1,9 @@
+^CMake Error at .+/Modules/FindPackageHandleStandardArgs.cmake:[0-9]+ \(message\):
+ Could NOT find CustomMessage \(Required is at least version "1\.2"\), checked
+ the following files:
+
+ .+/Tests/RunCMake/FPHSA/CustomMessageConfig.cmake \(version 2\)
+ Reason given by package: Not Found Message
+ Reason Failure
+
+Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/FPHSA/custom_message_3.cmake b/Tests/RunCMake/FPHSA/custom_message_3.cmake
new file mode 100644
index 0000000..203e012
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_3.cmake
@@ -0,0 +1,5 @@
+
+set (REASON_FAILURE_MESSAGE "Reason Failure")
+set (CustomMessage_NOT_FOUND_MESSAGE "Not Found Message")
+
+find_package(CustomMessage 1.2 REQUIRED)
diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt
index 54e96a2..498e556 100644
--- a/Tests/TryCompile/CMakeLists.txt
+++ b/Tests/TryCompile/CMakeLists.txt
@@ -313,6 +313,60 @@ if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
TEST_ASSERT(C_STRICT_PROTOTYPES "CHECK_C_COMPILER_FLAG failed -Werror -Wstrict-prototypes")
endif()
+#########################################################################
+#
+# Test that the CHECK_OBJCC_SOURCE_COMPILES, CHECK_OBJCXX_SOURCE_COMPILES
+# CHECK_OBJC_SOURCE_RUNS and CHECK_OBJCXX_SOURCE_RUNS macros work
+
+if (APPLE)
+ enable_language(OBJC)
+ enable_language(OBJCXX)
+
+ include(CheckOBJCSourceCompiles)
+ include(CheckOBJCXXSourceCompiles)
+ include(CheckOBJCSourceRuns)
+ include(CheckOBJCXXSourceRuns)
+
+ CHECK_OBJC_SOURCE_COMPILES("I don't build in Objective-C" OBJC_BUILD_SHOULD_FAIL)
+ CHECK_OBJC_SOURCE_COMPILES("int main() { return 0; }" SIMPLE_OBJC_BUILD_SHOULD_WORK)
+
+ TEST_FAIL(OBJC_BUILD_SHOULD_FAIL "CHECK_OBJC_SOURCE_COMPILES() succeeded, but should have failed")
+ TEST_ASSERT(SIMPLE_OBJC_BUILD_SHOULD_WORK "CHECK_OBJC_SOURCE_COMPILES() failed, but should have succeeded")
+
+ set(CMAKE_REQUIRED_LIBRARIES "-framework Foundation")
+
+ CHECK_OBJC_SOURCE_COMPILES("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 0;\n}\n" OBJC_BUILD_SHOULD_WORK)
+ CHECK_OBJC_SOURCE_RUNS("int main() { return 2; }" SIMPLE_OBJC_RUN_SHOULD_FAIL)
+ CHECK_OBJC_SOURCE_RUNS("int main() { return 0; }" SIMPLE_OBJC_RUN_SHOULD_WORK)
+ CHECK_OBJC_SOURCE_RUNS("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 2;\n}\n" OBJC_RUN_SHOULD_FAIL)
+ CHECK_OBJC_SOURCE_RUNS("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 0;\n}\n" OBJC_RUN_SHOULD_WORK)
+
+ TEST_ASSERT(OBJC_BUILD_SHOULD_WORK "CHECK_OBJC_SOURCE_COMPILES() failed, but should have succeeded")
+ TEST_FAIL(SIMPLE_OBJC_RUN_SHOULD_FAIL "CHECK_OBJC_SOURC_RUNS() succeeds, but should have failed")
+ TEST_ASSERT(SIMPLE_OBJC_RUN_SHOULD_WORK "CHECK_OBJC_SOURCE_RUNS() failed, but should have succeeded")
+ TEST_FAIL(OBJC_RUN_SHOULD_FAIL "CHECK_OBJC_SOURCE_RUNS() succeeds, but should have failed")
+ TEST_ASSERT(OBJC_RUN_SHOULD_WORK "CHECK_OBJC_SOURCE_RUNS() failed, but should have succeeded")
+
+
+ CHECK_OBJCXX_SOURCE_COMPILES("I don't build in Objective-C++" OBJCXX_BUILD_SHOULD_FAIL)
+ CHECK_OBJCXX_SOURCE_COMPILES("int main() { return 0; }" SIMPLE_OBJCXX_BUILD_SHOULD_WORK)
+
+ TEST_FAIL(OBJCXX_BUILD_SHOULD_FAIL "CHECK_OBJCXX_SOURCE_COMPILES() succeeded, but should have failed")
+ TEST_ASSERT(SIMPLE_OBJCXX_BUILD_SHOULD_WORK "CHECK_OBJCXX_SOURCE_COMPILES() failed, but should have succeeded")
+
+ CHECK_OBJCXX_SOURCE_COMPILES("#import <Foundation/Foundation.h>\n#include <iostream>\nint main()\n{\nNSObject *foo;\nstd::cout << \"Hello\" << std::endl;\nreturn 0;\n}\n" OBJCXX_BUILD_SHOULD_WORK)
+ CHECK_OBJCXX_SOURCE_RUNS("int main() { return 2; }" SIMPLE_OBJCXX_RUN_SHOULD_FAIL)
+ CHECK_OBJCXX_SOURCE_RUNS("int main() { return 0; }" SIMPLE_OBJCXX_RUN_SHOULD_WORK)
+ CHECK_OBJCXX_SOURCE_RUNS("#import <Foundation/Foundation.h>\n#include <vector>\nint main()\n{\nNSObject *foo;\nstd::vector<int> bar;\nreturn 2;\n}\n" OBJCXX_RUN_SHOULD_FAIL)
+ CHECK_OBJCXX_SOURCE_RUNS("#import <Foundation/Foundation.h>\n#include <vector>\nint main()\n{\nNSObject *foo;\nstd::vector<int> bar;\nreturn 0;\n}\n" OBJCXX_RUN_SHOULD_WORK)
+
+ TEST_ASSERT(OBJCXX_BUILD_SHOULD_WORK "CHECK_OBJCXX_SOURCE_COMPILES() failed, but should have succeeded")
+ TEST_FAIL(SIMPLE_OBJCXX_RUN_SHOULD_FAIL "CHECK_OBJCXX_SOURC_RUNS() succeeds, but should have failed")
+ TEST_ASSERT(SIMPLE_OBJCXX_RUN_SHOULD_WORK "CHECK_OBJCXX_SOURCE_RUNS() failed, but should have succeeded")
+ TEST_FAIL(OBJCXX_RUN_SHOULD_FAIL "CHECK_OBJCXX_SOURCE_RUNS() succeeds, but should have failed")
+ TEST_ASSERT(OBJCXX_RUN_SHOULD_WORK "CHECK_OBJCXX_SOURCE_RUNS() failed, but should have succeeded")
+endif()
+
#######################################################################
#
# also test that the check_prototype_definition macro works