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/prop_dir/EXCLUDE_FROM_ALL.rst20
-rw-r--r--Help/prop_tgt/EXCLUDE_FROM_ALL.rst16
-rw-r--r--Help/prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM.rst2
-rw-r--r--Help/prop_tgt/UNITY_BUILD.rst2
-rw-r--r--Help/prop_tgt/UNITY_BUILD_BATCH_SIZE.rst2
-rw-r--r--Help/release/3.14.rst8
-rw-r--r--Help/release/3.15.rst9
-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/CMakeDetermineCompilerId.cmake8
-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/FindCurses.cmake16
-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/QtDialog/QCMake.cxx4
-rw-r--r--Source/cmGeneratorExpressionNode.cxx8
-rw-r--r--Source/cmGlobalCommonGenerator.cxx66
-rw-r--r--Source/cmGlobalCommonGenerator.h24
-rw-r--r--Source/cmGlobalGenerator.cxx54
-rw-r--r--Source/cmGlobalGenerator.h3
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx96
-rw-r--r--Source/cmGlobalNinjaGenerator.h13
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx71
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h4
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx2
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.cxx4
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx2
-rw-r--r--Source/cmLocalCommonGenerator.h2
-rw-r--r--Source/cmLocalGenerator.cxx12
-rw-r--r--Source/cmLocalNinjaGenerator.cxx4
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx2
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.h3
-rw-r--r--Source/cmMakefile.cxx158
-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/CMakeLists.txt4
-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/RunCMake/IfacePaths/BinInInstallPrefix-CMP0052-NEW-stderr_INCLUDE_DIRECTORIES.txt2
-rw-r--r--Tests/RunCMake/IfacePaths/BinInInstallPrefix-CMP0052-WARN-stderr_INCLUDE_DIRECTORIES.txt6
-rw-r--r--Tests/RunCMake/IfacePaths/BinaryDirectoryInInterface-stderr_INCLUDE_DIRECTORIES.txt2
-rw-r--r--Tests/RunCMake/IfacePaths/InstallInBinDir-stderr_INCLUDE_DIRECTORIES.txt2
-rw-r--r--Tests/RunCMake/IfacePaths/InstallInSrcDir-stderr_INCLUDE_DIRECTORIES.txt2
-rw-r--r--Tests/RunCMake/IfacePaths/SrcInInstallPrefix-CMP0052-NEW-stderr_INCLUDE_DIRECTORIES.txt2
-rw-r--r--Tests/RunCMake/IfacePaths/SrcInInstallPrefix-CMP0052-WARN-stderr_INCLUDE_DIRECTORIES.txt6
-rw-r--r--Tests/RunCMake/RunCMake.cmake5
-rw-r--r--Tests/RunCMake/VS10Project/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-result.txt1
-rw-r--r--Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-stderr.txt7
-rw-r--r--Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName.cmake9
-rw-r--r--Tests/RunCMake/add_subdirectory/ExcludeFromAll-build-sub-stderr.txt1
-rw-r--r--Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake10
-rw-r--r--Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt23
-rw-r--r--Tests/RunCMake/add_subdirectory/ExcludeFromAll/SubSub/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/add_subdirectory/ExcludeFromAll/SubSub/subsub.cpp4
-rw-r--r--Tests/RunCMake/add_subdirectory/ExcludeFromAll/check-sub.cmake34
-rw-r--r--Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake75
-rw-r--r--Tests/RunCMake/add_subdirectory/ExcludeFromAll/subinc.cpp4
-rw-r--r--Tests/RunCMake/add_subdirectory/ExcludeFromAll/zot.cpp4
-rw-r--r--Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake36
-rw-r--r--Tests/TryCompile/CMakeLists.txt54
151 files changed, 4496 insertions, 1517 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/prop_dir/EXCLUDE_FROM_ALL.rst b/Help/prop_dir/EXCLUDE_FROM_ALL.rst
index 9d3192c..8e3cca0 100644
--- a/Help/prop_dir/EXCLUDE_FROM_ALL.rst
+++ b/Help/prop_dir/EXCLUDE_FROM_ALL.rst
@@ -1,15 +1,13 @@
EXCLUDE_FROM_ALL
----------------
-Exclude the directory from the all target of its parent.
+Set this directory property to a true value on a subdirectory to exclude
+its targets from the "all" target of its ancestors. If excluded, running
+e.g. ``make`` in the parent directory will not build targets the
+subdirectory by default. This does not affect the "all" target of the
+subdirectory itself. Running e.g. ``make`` inside the subdirectory will
+still build its targets.
-A property on a directory that indicates if its targets are excluded
-from the default build target. If it is not, then with a Makefile for
-example typing make will cause the targets to be built. The same
-concept applies to the default build of other generators.
-
-Targets inherit the :prop_tgt:`EXCLUDE_FROM_ALL` property from the directory
-that they are created in. When a directory is excluded, all of its targets will
-have :prop_tgt:`EXCLUDE_FROM_ALL` set to ``TRUE``. After creating such a target
-you can change its :prop_tgt:`EXCLUDE_FROM_ALL` property to ``FALSE``. This
-will cause the target to be included in the default build target.
+If the :prop_tgt:`EXCLUDE_FROM_ALL` target property is set on a target
+then its value determines whether the target is included in the "all"
+target of this directory and its ancestors.
diff --git a/Help/prop_tgt/EXCLUDE_FROM_ALL.rst b/Help/prop_tgt/EXCLUDE_FROM_ALL.rst
index 0eee297..3aa296d 100644
--- a/Help/prop_tgt/EXCLUDE_FROM_ALL.rst
+++ b/Help/prop_tgt/EXCLUDE_FROM_ALL.rst
@@ -1,12 +1,15 @@
EXCLUDE_FROM_ALL
----------------
-Exclude the target from the all target.
+Set this target property to a true (or false) value to exclude (or include)
+the target from the "all" target of the containing directory and its
+ancestors. If excluded, running e.g. ``make`` in the containing directory
+or its ancestors will not build the target by default.
-A property on a target that indicates if the target is excluded from
-the default build target. If it is not, then with a Makefile for
-example typing make will cause this target to be built. The same
-concept applies to the default build of other generators.
+If this target property is not set then the target will be included in
+the "all" target of the containing directory. Furthermore, it will be
+included in the "all" target of its ancestor directories unless the
+:prop_dir:`EXCLUDE_FROM_ALL` directory property is set.
With ``EXCLUDE_FROM_ALL`` set to false or not set at all, the target
will be brought up to date as part of doing a ``make install`` or its
@@ -16,6 +19,3 @@ target has undefined behavior. Note that such a target can still safely
be listed in an :command:`install(TARGETS)` command as long as the install
components the target belongs to are not part of the set of components
that anything tries to install.
-
-This property is enabled by default for targets that are created in
-directories that have :prop_dir:`EXCLUDE_FROM_ALL` set to ``TRUE``.
diff --git a/Help/prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM.rst b/Help/prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM.rst
index d740303..9c3e7ea 100644
--- a/Help/prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM.rst
+++ b/Help/prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM.rst
@@ -1,7 +1,7 @@
PRECOMPILE_HEADERS_REUSE_FROM
-----------------------------
-Target from which to reuse the precomipled headers build artifact.
+Target from which to reuse the precompiled headers build artifact.
See the second signature of :command:`target_precompile_headers` command
for more detailed information.
diff --git a/Help/prop_tgt/UNITY_BUILD.rst b/Help/prop_tgt/UNITY_BUILD.rst
index d326ee2..beac5d4 100644
--- a/Help/prop_tgt/UNITY_BUILD.rst
+++ b/Help/prop_tgt/UNITY_BUILD.rst
@@ -31,7 +31,7 @@ ODR (One definition rule) errors
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Since multiple source files are included into one source file,
-it can lead to ODR errors. This section contains properites
+it can lead to ODR errors. This section contains properties
which help fixing these errors.
The source files marked by :prop_sf:`GENERATED` will be skipped
diff --git a/Help/prop_tgt/UNITY_BUILD_BATCH_SIZE.rst b/Help/prop_tgt/UNITY_BUILD_BATCH_SIZE.rst
index 2426689..84047f2 100644
--- a/Help/prop_tgt/UNITY_BUILD_BATCH_SIZE.rst
+++ b/Help/prop_tgt/UNITY_BUILD_BATCH_SIZE.rst
@@ -8,6 +8,6 @@ If the property is not set, CMake will use the value provided
by :variable:`CMAKE_UNITY_BUILD_BATCH_SIZE`.
By setting it to value `0` the generated unity source file will
-contain all the source files that would be otherwise be split
+contain all the source files that would otherwise be split
into multiple batches. It is not recommended to do so, since it
would affect performance.
diff --git a/Help/release/3.14.rst b/Help/release/3.14.rst
index 229d8dc..8a9738c 100644
--- a/Help/release/3.14.rst
+++ b/Help/release/3.14.rst
@@ -428,3 +428,11 @@ Changes made since CMake 3.14.0 include the following.
policy :policy:`CMP0088` ``NEW`` behavior accidentally interpreted
a relative path to the ``.y`` input as relative to the build tree
directory instead of the source tree directory. This has been fixed.
+
+3.14.7
+------
+
+* In CMake 3.14.0 through 3.14.6, the :prop_dir:`EXCLUDE_FROM_ALL`
+ directory property was regressed from pre-3.14 behavior and caused
+ targets within the directory to be excluded even from its own "all".
+ This has been fixed.
diff --git a/Help/release/3.15.rst b/Help/release/3.15.rst
index 48f3aa4..957e6e9 100644
--- a/Help/release/3.15.rst
+++ b/Help/release/3.15.rst
@@ -376,3 +376,12 @@ Changes made since CMake 3.15.0 include the following.
* ``CrayPrgEnv`` compiler wrapper support has been updated for the 19.06
release of the Cray Programming Environment for which the default linking
mode on XC Cray systems is now dynamic instead of static.
+
+3.15.4
+------
+
+* In CMake 3.15.0 through 3.15.3, the :prop_dir:`EXCLUDE_FROM_ALL`
+ directory property was regressed from pre-3.14 behavior and caused
+ targets within the directory to be excluded even from its own "all".
+ This has been fixed.
+ The bug also existed in 3.14.0 through 3.14.6 and is fixed in 3.14.7.
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/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index 40658ea..908e530 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -284,7 +284,13 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
set(id_cl icl.exe)
endif()
if(CMAKE_VS_PLATFORM_TOOLSET_VERSION)
- set(id_toolset_version_props "<Import Project=\"${CMAKE_GENERATOR_INSTANCE}\\VC\\Auxiliary\\Build\\${CMAKE_VS_PLATFORM_TOOLSET_VERSION}\\Microsoft.VCToolsVersion.${CMAKE_VS_PLATFORM_TOOLSET_VERSION}.props\" />")
+ if(CMAKE_VS_PLATFORM_TOOLSET_VERSION VERSION_GREATER_EQUAL "14.20")
+ set(id_sep ".")
+ else()
+ set(id_sep "\\")
+ endif()
+ set(id_toolset_version_props "<Import Project=\"${CMAKE_GENERATOR_INSTANCE}\\VC\\Auxiliary\\Build${id_sep}${CMAKE_VS_PLATFORM_TOOLSET_VERSION}\\Microsoft.VCToolsVersion.${CMAKE_VS_PLATFORM_TOOLSET_VERSION}.props\" />")
+ unset(id_sep)
endif()
endif()
else()
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/FindCurses.cmake b/Modules/FindCurses.cmake
index b3cd8fa..5abc08a 100644
--- a/Modules/FindCurses.cmake
+++ b/Modules/FindCurses.cmake
@@ -18,6 +18,8 @@ This module defines the following variables:
The include directories needed to use Curses.
``CURSES_LIBRARIES``
The libraries needed to use Curses.
+``CURSES_CFLAGS``
+ Parameters which ought be given to C/C++ compilers when using Curses.
``CURSES_HAVE_CURSES_H``
True if curses.h is available.
``CURSES_HAVE_NCURSES_H``
@@ -56,7 +58,7 @@ else()
set(CURSES_NEED_NCURSES TRUE)
endif()
-find_library(CURSES_CURSES_LIBRARY NAMES curses )
+find_library(CURSES_CURSES_LIBRARY NAMES curses)
find_library(CURSES_NCURSES_LIBRARY NAMES "${NCURSES_LIBRARY_NAME}" )
set(CURSES_USE_NCURSES FALSE)
@@ -118,7 +120,7 @@ if(CURSES_USE_NCURSES)
if(CURSES_NCURSES_INCLUDE_PATH)
if (CURSES_NEED_WIDE)
find_path(CURSES_INCLUDE_PATH
- NAMES ncursesw/ncurses.h ncursesw/curses.h
+ NAMES ncursesw/ncurses.h ncursesw/curses.h ncursesw.h cursesw.h
PATHS ${CURSES_NCURSES_INCLUDE_PATH}
NO_DEFAULT_PATH
)
@@ -133,7 +135,7 @@ if(CURSES_USE_NCURSES)
if (CURSES_NEED_WIDE)
find_path(CURSES_INCLUDE_PATH
- NAMES ncursesw/ncurses.h ncursesw/curses.h
+ NAMES ncursesw/ncurses.h ncursesw/curses.h ncursesw.h cursesw.h
HINTS "${_cursesParentDir}/include"
)
else()
@@ -238,10 +240,16 @@ if(CURSES_FORM_LIBRARY)
set(CURSES_LIBRARIES ${CURSES_LIBRARIES} ${CURSES_FORM_LIBRARY})
endif()
-# Provide the *_INCLUDE_DIRS result.
+# Provide the *_INCLUDE_DIRS and *_CFLAGS results.
set(CURSES_INCLUDE_DIRS ${CURSES_INCLUDE_PATH})
set(CURSES_INCLUDE_DIR ${CURSES_INCLUDE_PATH}) # compatibility
+find_package(PkgConfig QUIET)
+if(PKG_CONFIG_FOUND)
+ pkg_check_modules(NCURSES QUIET ${NCURSES_LIBRARY_NAME})
+ set(CURSES_CFLAGS ${NCURSES_CFLAGS_OTHER})
+endif()
+
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Curses DEFAULT_MSG
CURSES_LIBRARY CURSES_INCLUDE_PATH)
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 91050d5..add8a86 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 20190929)
+set(CMake_VERSION_PATCH 20191002)
#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/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index ece3307..b608fcb 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -257,14 +257,14 @@ void QCMake::setProperties(const QCMakePropertyList& newProps)
}
}
- // remove some properites
+ // remove some properties
foreach (QString const& s, toremove) {
this->CMakeInstance->UnwatchUnusedCli(s.toLocal8Bit().data());
state->RemoveCacheEntry(s.toLocal8Bit().data());
}
- // add some new properites
+ // add some new properties
foreach (QCMakeProperty const& s, props) {
this->CMakeInstance->WatchUnusedCli(s.Key.toLocal8Bit().data());
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/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx
index bf992b4..93ff00b 100644
--- a/Source/cmGlobalCommonGenerator.cxx
+++ b/Source/cmGlobalCommonGenerator.cxx
@@ -2,6 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalCommonGenerator.h"
+#include "cmGeneratorTarget.h"
+#include "cmLocalGenerator.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+
+#include <utility>
+
class cmake;
cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm)
@@ -10,3 +19,60 @@ cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm)
}
cmGlobalCommonGenerator::~cmGlobalCommonGenerator() = default;
+
+std::map<std::string, cmGlobalCommonGenerator::DirectoryTarget>
+cmGlobalCommonGenerator::ComputeDirectoryTargets() const
+{
+ std::map<std::string, DirectoryTarget> dirTargets;
+ for (cmLocalGenerator* lg : this->LocalGenerators) {
+ std::string const& currentBinaryDir(
+ lg->GetStateSnapshot().GetDirectory().GetCurrentBinary());
+ DirectoryTarget& dirTarget = dirTargets[currentBinaryDir];
+ dirTarget.LG = lg;
+
+ // The directory-level rule should depend on the target-level rules
+ // for all targets in the directory.
+ for (auto gt : lg->GetGeneratorTargets()) {
+ cmStateEnums::TargetType const type = gt->GetType();
+ if (type != cmStateEnums::EXECUTABLE &&
+ type != cmStateEnums::STATIC_LIBRARY &&
+ type != cmStateEnums::SHARED_LIBRARY &&
+ type != cmStateEnums::MODULE_LIBRARY &&
+ type != cmStateEnums::OBJECT_LIBRARY &&
+ type != cmStateEnums::UTILITY) {
+ continue;
+ }
+ DirectoryTarget::Target t;
+ t.GT = gt;
+ if (const char* exclude = gt->GetProperty("EXCLUDE_FROM_ALL")) {
+ if (cmIsOn(exclude)) {
+ // This target has been explicitly excluded.
+ t.ExcludeFromAll = true;
+ } else {
+ // This target has been explicitly un-excluded. The directory-level
+ // rule for every directory between this and the root should depend
+ // on the target-level rule for this target.
+ for (cmStateSnapshot dir =
+ lg->GetStateSnapshot().GetBuildsystemDirectoryParent();
+ dir.IsValid(); dir = dir.GetBuildsystemDirectoryParent()) {
+ std::string const& d = dir.GetDirectory().GetCurrentBinary();
+ dirTargets[d].Targets.emplace_back(t);
+ }
+ }
+ }
+ dirTarget.Targets.emplace_back(t);
+ }
+
+ // The directory-level rule should depend on the directory-level
+ // rules of the subdirectories.
+ for (cmStateSnapshot const& state : lg->GetStateSnapshot().GetChildren()) {
+ DirectoryTarget::Dir d;
+ d.Path = state.GetDirectory().GetCurrentBinary();
+ d.ExcludeFromAll =
+ state.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL");
+ dirTarget.Children.emplace_back(std::move(d));
+ }
+ }
+
+ return dirTargets;
+}
diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h
index e19118b..de81da7 100644
--- a/Source/cmGlobalCommonGenerator.h
+++ b/Source/cmGlobalCommonGenerator.h
@@ -7,7 +7,13 @@
#include "cmGlobalGenerator.h"
+#include <map>
+#include <string>
+#include <vector>
+
class cmake;
+class cmGeneratorTarget;
+class cmLocalGenerator;
/** \class cmGlobalCommonGenerator
* \brief Common infrastructure for Makefile and Ninja global generators.
@@ -17,6 +23,24 @@ class cmGlobalCommonGenerator : public cmGlobalGenerator
public:
cmGlobalCommonGenerator(cmake* cm);
~cmGlobalCommonGenerator() override;
+
+ struct DirectoryTarget
+ {
+ cmLocalGenerator* LG = nullptr;
+ struct Target
+ {
+ cmGeneratorTarget const* GT = nullptr;
+ bool ExcludeFromAll = false;
+ };
+ std::vector<Target> Targets;
+ struct Dir
+ {
+ std::string Path;
+ bool ExcludeFromAll = false;
+ };
+ std::vector<Dir> Children;
+ };
+ std::map<std::string, DirectoryTarget> ComputeDirectoryTargets() const;
};
#endif
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index c4974f3..abe483a9 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -355,6 +355,42 @@ bool cmGlobalGenerator::CheckTargetsForType() const
return failed;
}
+bool cmGlobalGenerator::CheckTargetsForPchCompilePdb() const
+{
+ if (!this->GetLanguageEnabled("C") && !this->GetLanguageEnabled("CXX")) {
+ return false;
+ }
+ bool failed = false;
+ for (cmLocalGenerator* generator : this->LocalGenerators) {
+ for (cmGeneratorTarget* target : generator->GetGeneratorTargets()) {
+ if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET ||
+ target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY ||
+ target->GetType() == cmStateEnums::TargetType::UTILITY ||
+ cmIsOn(target->GetProperty("ghs_integrity_app"))) {
+ continue;
+ }
+
+ const std::string reuseFrom =
+ target->GetSafeProperty("PRECOMPILE_HEADERS_REUSE_FROM");
+ const std::string compilePdb =
+ target->GetSafeProperty("COMPILE_PDB_NAME");
+
+ if (!reuseFrom.empty() && reuseFrom != compilePdb) {
+ const std::string e = cmStrCat(
+ "PRECOMPILE_HEADERS_REUSE_FROM property is set on target (\"",
+ target->GetName(),
+ "\"). Reusable precompile headers requires the COMPILE_PDB_NAME"
+ " property to have the value \"",
+ reuseFrom, "\"\n");
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
+ target->GetBacktrace());
+ failed = true;
+ }
+ }
+ }
+ return failed;
+}
+
bool cmGlobalGenerator::IsExportedTargetsFile(
const std::string& filename) const
{
@@ -1398,6 +1434,10 @@ bool cmGlobalGenerator::Compute()
return false;
}
+ if (this->CheckTargetsForPchCompilePdb()) {
+ return false;
+ }
+
for (cmLocalGenerator* localGen : this->LocalGenerators) {
localGen->ComputeHomeRelativeOutputPath();
}
@@ -2037,10 +2077,18 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
return this->IsExcluded(rootSnp, snp);
}
-bool cmGlobalGenerator::IsExcluded(cmGeneratorTarget* target) const
+bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
+ cmGeneratorTarget* target) const
{
- return target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
- target->GetPropertyAsBool("EXCLUDE_FROM_ALL");
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return true;
+ }
+ if (const char* exclude = target->GetProperty("EXCLUDE_FROM_ALL")) {
+ return cmIsOn(exclude);
+ }
+ // This target is included in its directory. Check whether the
+ // directory is excluded.
+ return this->IsExcluded(root, target->GetLocalGenerator());
}
void cmGlobalGenerator::GetEnabledLanguages(
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 3075c1a..eb5ee27 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -511,7 +511,7 @@ protected:
bool IsExcluded(cmStateSnapshot const& root,
cmStateSnapshot const& snp) const;
bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen) const;
- bool IsExcluded(cmGeneratorTarget* target) const;
+ bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target) const;
virtual void InitializeProgressMarks() {}
struct GlobalTargetInfo
@@ -610,6 +610,7 @@ private:
bool CheckTargetsForMissingSources() const;
bool CheckTargetsForType() const;
+ bool CheckTargetsForPchCompilePdb() const;
void CreateLocalGenerators();
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 7bba874..d8fe258 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -20,6 +20,7 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmLocalNinjaGenerator.h"
@@ -888,16 +889,6 @@ void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os)
<< cmVersion::GetMinorVersion() << "\n\n";
}
-void cmGlobalNinjaGenerator::AddDependencyToAll(cmGeneratorTarget* target)
-{
- this->AppendTargetOutputs(target, this->AllDependencies);
-}
-
-void cmGlobalNinjaGenerator::AddDependencyToAll(const std::string& input)
-{
- this->AllDependencies.push_back(input);
-}
-
void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
{
for (auto const& asd : this->AssumedSourceDependencies) {
@@ -1096,59 +1087,32 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os)
cmGlobalNinjaGenerator::WriteDivider(os);
os << "# Folder targets.\n\n";
- std::string const& rootBinaryDir =
- this->LocalGenerators[0]->GetBinaryDirectory();
+ std::map<std::string, DirectoryTarget> dirTargets =
+ this->ComputeDirectoryTargets();
- std::map<std::string, cmNinjaDeps> targetsPerFolder;
- for (cmLocalGenerator const* lg : this->LocalGenerators) {
- std::string const& currentBinaryFolder(
- lg->GetStateSnapshot().GetDirectory().GetCurrentBinary());
-
- // Do not generate a rule for the root binary dir.
- if (currentBinaryFolder == rootBinaryDir) {
- continue;
- }
-
- // The directory-level rule should depend on the target-level rules
- // for all targets in the directory.
- cmNinjaDeps& folderTargets = targetsPerFolder[currentBinaryFolder];
- for (auto gt : lg->GetGeneratorTargets()) {
- cmStateEnums::TargetType const type = gt->GetType();
- if ((type == cmStateEnums::EXECUTABLE ||
- type == cmStateEnums::STATIC_LIBRARY ||
- type == cmStateEnums::SHARED_LIBRARY ||
- type == cmStateEnums::MODULE_LIBRARY ||
- type == cmStateEnums::OBJECT_LIBRARY ||
- type == cmStateEnums::UTILITY) &&
- !gt->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
- folderTargets.push_back(gt->GetName());
+ for (auto const& it : dirTargets) {
+ cmNinjaBuild build("phony");
+ cmGlobalNinjaGenerator::WriteDivider(os);
+ std::string const& currentBinaryDir = it.first;
+ DirectoryTarget const& dt = it.second;
+
+ // Setup target
+ build.Comment = "Folder: " + currentBinaryDir;
+ build.Outputs.emplace_back(
+ this->ConvertToNinjaPath(currentBinaryDir + "/all"));
+ for (DirectoryTarget::Target const& t : dt.Targets) {
+ if (!t.ExcludeFromAll) {
+ this->AppendTargetOutputs(t.GT, build.ExplicitDeps);
}
}
-
- // The directory-level rule should depend on the directory-level
- // rules of the subdirectories.
- for (cmStateSnapshot const& state : lg->GetStateSnapshot().GetChildren()) {
- std::string const& currentBinaryDir =
- state.GetDirectory().GetCurrentBinary();
- folderTargets.push_back(
- this->ConvertToNinjaPath(currentBinaryDir + "/all"));
- }
- }
-
- if (!targetsPerFolder.empty()) {
- cmNinjaBuild build("phony");
- build.Outputs.emplace_back("");
- for (auto& it : targetsPerFolder) {
- cmGlobalNinjaGenerator::WriteDivider(os);
- std::string const& currentBinaryDir = it.first;
-
- // Setup target
- build.Comment = "Folder: " + currentBinaryDir;
- build.Outputs[0] = this->ConvertToNinjaPath(currentBinaryDir + "/all");
- build.ExplicitDeps = std::move(it.second);
- // Write target
- this->WriteBuild(os, build);
+ for (DirectoryTarget::Dir const& d : dt.Children) {
+ if (!d.ExcludeFromAll) {
+ build.ExplicitDeps.emplace_back(
+ this->ConvertToNinjaPath(d.Path + "/all"));
+ }
}
+ // Write target
+ this->WriteBuild(os, build);
}
}
@@ -1281,22 +1245,18 @@ void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os)
cmGlobalNinjaGenerator::WriteDivider(os);
os << "# Built-in targets\n\n";
- this->WriteTargetAll(os);
+ this->WriteTargetDefault(os);
this->WriteTargetRebuildManifest(os);
this->WriteTargetClean(os);
this->WriteTargetHelp(os);
}
-void cmGlobalNinjaGenerator::WriteTargetAll(std::ostream& os)
+void cmGlobalNinjaGenerator::WriteTargetDefault(std::ostream& os)
{
- cmNinjaBuild build("phony");
- build.Comment = "The main all target.";
- build.Outputs.push_back(this->TargetAll);
- build.ExplicitDeps = this->AllDependencies;
- this->WriteBuild(os, build);
-
if (!this->HasOutputPathPrefix()) {
- cmGlobalNinjaGenerator::WriteDefault(os, build.Outputs,
+ cmNinjaDeps all;
+ all.push_back(this->TargetAll);
+ cmGlobalNinjaGenerator::WriteDefault(os, all,
"Make the all target the default.");
}
}
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 7aa231e..1bfbffa 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -17,7 +17,6 @@
#include "cmGeneratedFileStream.h"
#include "cmGlobalCommonGenerator.h"
-#include "cmGlobalGenerator.h"
#include "cmGlobalGeneratorFactory.h"
#include "cmNinjaTypes.h"
#include "cmPolicies.h"
@@ -294,19 +293,12 @@ public:
cmNinjaDeps& outputs);
void AppendTargetDependsClosure(cmGeneratorTarget const* target,
cmNinjaOuts& outputs, bool omit_self);
- void AddDependencyToAll(cmGeneratorTarget* target);
- void AddDependencyToAll(const std::string& input);
const std::vector<cmLocalGenerator*>& GetLocalGenerators() const
{
return LocalGenerators;
}
- bool IsExcluded(cmGeneratorTarget* target)
- {
- return cmGlobalGenerator::IsExcluded(target);
- }
-
int GetRuleCmdLength(const std::string& name) { return RuleCmdLength[name]; }
void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target);
@@ -373,7 +365,7 @@ private:
void WriteUnknownExplicitDependencies(std::ostream& os);
void WriteBuiltinTargets(std::ostream& os);
- void WriteTargetAll(std::ostream& os);
+ void WriteTargetDefault(std::ostream& os);
void WriteTargetRebuildManifest(std::ostream& os);
bool WriteTargetCleanAdditional(std::ostream& os);
void WriteTargetClean(std::ostream& os);
@@ -400,9 +392,6 @@ private:
/// Length of rule command, used by rsp file evaluation
std::unordered_map<std::string, int> RuleCmdLength;
- /// The set of dependencies to add to the "all" target.
- cmNinjaDeps AllDependencies;
-
bool UsingGCCOnWindows = false;
/// The set of custom commands we have seen.
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 0b211b8..4c2d69f 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -233,6 +233,11 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
// Write out the "special" stuff
lg->WriteSpecialTargetsTop(makefileStream);
+ // Write the directory level rules.
+ for (auto const& it : this->ComputeDirectoryTargets()) {
+ this->WriteDirectoryRules2(makefileStream, it.second);
+ }
+
// Write the target convenience rules
for (cmLocalGenerator* localGen : this->LocalGenerators) {
this->WriteConvenienceRules2(
@@ -388,41 +393,37 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules(
}
void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
- std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3* lg,
- const char* pass, bool check_all, bool check_relink,
- std::vector<std::string> const& commands)
+ std::ostream& ruleFileStream, DirectoryTarget const& dt, const char* pass,
+ bool check_all, bool check_relink, std::vector<std::string> const& commands)
{
- // Get the relative path to the subdirectory from the top.
+ auto* lg = static_cast<cmLocalUnixMakefileGenerator3*>(dt.LG);
std::string makeTarget =
cmStrCat(lg->GetCurrentBinaryDirectory(), '/', pass);
// The directory-level rule should depend on the target-level rules
// for all targets in the directory.
std::vector<std::string> depends;
- for (cmGeneratorTarget* gtarget : lg->GetGeneratorTargets()) {
- int type = gtarget->GetType();
- if ((type == cmStateEnums::EXECUTABLE) ||
- (type == cmStateEnums::STATIC_LIBRARY) ||
- (type == cmStateEnums::SHARED_LIBRARY) ||
- (type == cmStateEnums::MODULE_LIBRARY) ||
- (type == cmStateEnums::OBJECT_LIBRARY) ||
- (type == cmStateEnums::UTILITY)) {
- // Add this to the list of depends rules in this directory.
- if ((!check_all || !gtarget->GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
- (!check_relink ||
- gtarget->NeedRelinkBeforeInstall(lg->GetConfigName()))) {
- std::string tname =
- cmStrCat(lg->GetRelativeTargetDirectory(gtarget), '/', pass);
- depends.push_back(std::move(tname));
- }
+ for (DirectoryTarget::Target const& t : dt.Targets) {
+ // Add this to the list of depends rules in this directory.
+ if ((!check_all || !t.ExcludeFromAll) &&
+ (!check_relink ||
+ t.GT->NeedRelinkBeforeInstall(lg->GetConfigName()))) {
+ // The target may be from a different directory; use its local gen.
+ auto const* tlg = static_cast<cmLocalUnixMakefileGenerator3 const*>(
+ t.GT->GetLocalGenerator());
+ std::string tname =
+ cmStrCat(tlg->GetRelativeTargetDirectory(t.GT), '/', pass);
+ depends.push_back(std::move(tname));
}
}
// The directory-level rule should depend on the directory-level
// rules of the subdirectories.
- for (cmStateSnapshot const& c : lg->GetStateSnapshot().GetChildren()) {
- std::string subdir =
- cmStrCat(c.GetDirectory().GetCurrentBinary(), '/', pass);
+ for (DirectoryTarget::Dir const& d : dt.Children) {
+ if (check_all && d.ExcludeFromAll) {
+ continue;
+ }
+ std::string subdir = cmStrCat(d.Path, '/', pass);
depends.push_back(std::move(subdir));
}
@@ -444,8 +445,9 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
}
void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
- std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3* lg)
+ std::ostream& ruleFileStream, DirectoryTarget const& dt)
{
+ auto* lg = static_cast<cmLocalUnixMakefileGenerator3*>(dt.LG);
// Begin the directory-level rules section.
{
std::string dir =
@@ -461,17 +463,17 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
}
// Write directory-level rules for "all".
- this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
+ this->WriteDirectoryRule2(ruleFileStream, dt, "all", true, false);
+
+ // Write directory-level rules for "preinstall".
+ this->WriteDirectoryRule2(ruleFileStream, dt, "preinstall", true, true);
// Write directory-level rules for "clean".
{
std::vector<std::string> cmds;
lg->AppendDirectoryCleanCommand(cmds);
- this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false, cmds);
+ this->WriteDirectoryRule2(ruleFileStream, dt, "clean", false, false, cmds);
}
-
- // Write directory-level rules for "preinstall".
- this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
}
std::vector<cmGlobalGenerator::GeneratedMakeCommand>
@@ -617,9 +619,6 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
std::string localName;
std::string makeTargetName;
- // write the directory level rules for this local gen
- this->WriteDirectoryRules2(ruleFileStream, lg);
-
bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
if (regenerate) {
depends.emplace_back("cmake_check_build_system");
@@ -738,14 +737,6 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
lg->WriteMakeRule(ruleFileStream,
"Pre-install relink rule for target.", localName,
depends, commands, true);
-
- if (!this->IsExcluded(gtarget)) {
- depends.clear();
- depends.push_back(localName);
- commands.clear();
- lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
- "preinstall", depends, commands, true);
- }
}
// add the clean rule
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 6a39509..79db30e 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -164,11 +164,11 @@ protected:
cmLocalUnixMakefileGenerator3*);
void WriteDirectoryRule2(std::ostream& ruleFileStream,
- cmLocalUnixMakefileGenerator3* lg, const char* pass,
+ DirectoryTarget const& dt, const char* pass,
bool check_all, bool check_relink,
std::vector<std::string> const& commands = {});
void WriteDirectoryRules2(std::ostream& ruleFileStream,
- cmLocalUnixMakefileGenerator3* lg);
+ DirectoryTarget const& dt);
void AppendGlobalTargetDepends(std::vector<std::string>& depends,
cmGeneratorTarget* target);
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 0bc08a5..0f939cc 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -214,7 +214,7 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets()
tgt->IsImported()) {
continue;
}
- if (!this->IsExcluded(tgt)) {
+ if (!this->IsExcluded(gen[0], tgt)) {
allBuild->AddUtility(tgt->GetName());
}
}
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
index 2ba1aff..1eca1f6 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
@@ -390,7 +390,9 @@ std::string cmGlobalVisualStudioVersionedGenerator::GetAuxiliaryToolset() const
GetVSInstance(instancePath);
std::stringstream path;
path << instancePath;
- path << "/VC/Auxiliary/Build/";
+ path << "/VC/Auxiliary/Build";
+ path << (cmSystemTools::VersionCompareGreaterEq(version, "14.20") ? '.'
+ : '/');
path << version;
path << "/Microsoft.VCToolsVersion." << version << ".props";
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 4202175..f42218b 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -563,7 +563,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
cmObjectLibraryCommands::Accept);
}
- if (!this->IsExcluded(target)) {
+ if (!this->IsExcluded(gens[0], target)) {
allbuild->AddUtility(target->GetName());
}
}
diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h
index abebbc2..eaef6ab 100644
--- a/Source/cmLocalCommonGenerator.h
+++ b/Source/cmLocalCommonGenerator.h
@@ -25,7 +25,7 @@ public:
std::string wd);
~cmLocalCommonGenerator() override;
- std::string const& GetConfigName() { return this->ConfigName; }
+ std::string const& GetConfigName() const { return this->ConfigName; }
std::string GetWorkingDirectory() const { return this->WorkingDirectory; }
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/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 82dc943..187a847 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -88,10 +88,6 @@ void cmLocalNinjaGenerator::Generate()
auto tg = cmNinjaTargetGenerator::New(target);
if (tg) {
tg->Generate();
- // Add the target to "all" if required.
- if (!this->GetGlobalNinjaGenerator()->IsExcluded(target)) {
- this->GetGlobalNinjaGenerator()->AddDependencyToAll(target);
- }
}
}
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 1d87e93..c50989e 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -809,7 +809,7 @@ void cmLocalUnixMakefileGenerator3::WriteConvenienceRule(
}
std::string cmLocalUnixMakefileGenerator3::GetRelativeTargetDirectory(
- cmGeneratorTarget* target)
+ cmGeneratorTarget const* target) const
{
std::string dir =
cmStrCat(this->HomeRelativeOutputPath, this->GetTargetDirectory(target));
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index c02c0dc..f2295ef 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -139,7 +139,8 @@ public:
void WriteSpecialTargetsTop(std::ostream& makefileStream);
void WriteSpecialTargetsBottom(std::ostream& makefileStream);
- std::string GetRelativeTargetDirectory(cmGeneratorTarget* target);
+ std::string GetRelativeTargetDirectory(
+ cmGeneratorTarget const* target) const;
// File pairs for implicit dependency scanning. The key of the map
// is the depender and the value is the explicit dependee.
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index a528fc6..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"
@@ -1776,7 +1777,7 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
cmMakefile* subMf = new cmMakefile(this->GlobalGenerator, newSnapshot);
this->GetGlobalGenerator()->AddMakefile(subMf);
- if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+ if (excludeFromAll) {
subMf->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
@@ -2051,9 +2052,7 @@ cmTarget* cmMakefile::AddLibrary(const std::string& lname,
// over changes in CMakeLists.txt, making the information stale and
// hence useless.
target->ClearDependencyInformation(*this);
- if (excludeFromAll ||
- (type != cmStateEnums::INTERFACE_LIBRARY &&
- this->GetPropertyAsBool("EXCLUDE_FROM_ALL"))) {
+ if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
target->AddSources(srcs);
@@ -2066,7 +2065,7 @@ cmTarget* cmMakefile::AddExecutable(const std::string& exeName,
bool excludeFromAll)
{
cmTarget* target = this->AddNewTarget(cmStateEnums::EXECUTABLE, exeName);
- if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+ if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
target->AddSources(srcs);
@@ -2093,7 +2092,7 @@ cmTarget* cmMakefile::AddNewUtilityTarget(const std::string& utilityName,
{
cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName);
target->SetIsGeneratorProvided(origin == cmCommandOrigin::Generator);
- if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+ if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
return target;
@@ -4629,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,
@@ -4723,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;
}
@@ -4754,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;
}
@@ -4797,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));
@@ -4812,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;
}
@@ -4839,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;
}
@@ -4851,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;
}
@@ -4872,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);
}
@@ -4905,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;
@@ -4913,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;
}
@@ -4930,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;
}
@@ -4978,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
@@ -4992,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);
}
@@ -5014,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;
}
@@ -5033,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;
}
@@ -5071,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 7a2ecc2..0d5b363 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");
@@ -453,6 +459,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/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 026baa7..bd068fd 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -434,8 +434,8 @@ if(UNIX)
add_RunCMake_test(CPackSymlinks)
endif()
-set(IfacePaths_INCLUDE_DIRECTORIES_ARGS -DTEST_PROP=INCLUDE_DIRECTORIES)
-add_RunCMake_test(IfacePaths_INCLUDE_DIRECTORIES TEST_DIR IfacePaths)
+set(IfacePaths_INCDIRS_ARGS -DTEST_PROP=INCLUDE_DIRECTORIES)
+add_RunCMake_test(IfacePaths_INCDIRS TEST_DIR IfacePaths)
set(IfacePaths_SOURCES_ARGS -DTEST_PROP=SOURCES)
add_RunCMake_test(IfacePaths_SOURCES TEST_DIR IfacePaths)
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/RunCMake/IfacePaths/BinInInstallPrefix-CMP0052-NEW-stderr_INCLUDE_DIRECTORIES.txt b/Tests/RunCMake/IfacePaths/BinInInstallPrefix-CMP0052-NEW-stderr_INCLUDE_DIRECTORIES.txt
index f2d749b..d5c480d 100644
--- a/Tests/RunCMake/IfacePaths/BinInInstallPrefix-CMP0052-NEW-stderr_INCLUDE_DIRECTORIES.txt
+++ b/Tests/RunCMake/IfacePaths/BinInInstallPrefix-CMP0052-NEW-stderr_INCLUDE_DIRECTORIES.txt
@@ -1,6 +1,6 @@
CMake Error in CMakeLists.txt:
Target "testTarget" INTERFACE_INCLUDE_DIRECTORIES property contains path:
- ".*Tests/RunCMake/IfacePaths_INCLUDE_DIRECTORIES/prefix/BinInInstallPrefix-CMP0052-NEW-build/foo"
+ ".*Tests/RunCMake/IfacePaths_INCDIRS/prefix/BinInInstallPrefix-CMP0052-NEW-build/foo"
which is prefixed in the build directory.
diff --git a/Tests/RunCMake/IfacePaths/BinInInstallPrefix-CMP0052-WARN-stderr_INCLUDE_DIRECTORIES.txt b/Tests/RunCMake/IfacePaths/BinInInstallPrefix-CMP0052-WARN-stderr_INCLUDE_DIRECTORIES.txt
index 3d83892..eb4d56d 100644
--- a/Tests/RunCMake/IfacePaths/BinInInstallPrefix-CMP0052-WARN-stderr_INCLUDE_DIRECTORIES.txt
+++ b/Tests/RunCMake/IfacePaths/BinInInstallPrefix-CMP0052-WARN-stderr_INCLUDE_DIRECTORIES.txt
@@ -6,15 +6,15 @@ CMake Warning \(dev\) in CMakeLists.txt:
Directory:
- ".*Tests/RunCMake/IfacePaths_INCLUDE_DIRECTORIES/prefix/BinInInstallPrefix-CMP0052-WARN-build/foo"
+ ".*Tests/RunCMake/IfacePaths_INCDIRS/prefix/BinInInstallPrefix-CMP0052-WARN-build/foo"
in INTERFACE_INCLUDE_DIRECTORIES of target "testTarget" is a subdirectory
of the install directory:
- ".*Tests/RunCMake/IfacePaths_INCLUDE_DIRECTORIES/prefix"
+ ".*Tests/RunCMake/IfacePaths_INCDIRS/prefix"
however it is also a subdirectory of the build tree:
- ".*Tests/RunCMake/IfacePaths_INCLUDE_DIRECTORIES/prefix/BinInInstallPrefix-CMP0052-WARN-build"
+ ".*Tests/RunCMake/IfacePaths_INCDIRS/prefix/BinInInstallPrefix-CMP0052-WARN-build"
This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/IfacePaths/BinaryDirectoryInInterface-stderr_INCLUDE_DIRECTORIES.txt b/Tests/RunCMake/IfacePaths/BinaryDirectoryInInterface-stderr_INCLUDE_DIRECTORIES.txt
index ed7cd58..8794a87 100644
--- a/Tests/RunCMake/IfacePaths/BinaryDirectoryInInterface-stderr_INCLUDE_DIRECTORIES.txt
+++ b/Tests/RunCMake/IfacePaths/BinaryDirectoryInInterface-stderr_INCLUDE_DIRECTORIES.txt
@@ -1,6 +1,6 @@
CMake Error in CMakeLists.txt:
Target "testTarget" INTERFACE_INCLUDE_DIRECTORIES property contains path:
- ".*RunCMake/IfacePaths_INCLUDE_DIRECTORIES/BinaryDirectoryInInterface-build/foo"
+ ".*RunCMake/IfacePaths_INCDIRS/BinaryDirectoryInInterface-build/foo"
which is prefixed in the build directory.
diff --git a/Tests/RunCMake/IfacePaths/InstallInBinDir-stderr_INCLUDE_DIRECTORIES.txt b/Tests/RunCMake/IfacePaths/InstallInBinDir-stderr_INCLUDE_DIRECTORIES.txt
index 3d60831..4ba9360 100644
--- a/Tests/RunCMake/IfacePaths/InstallInBinDir-stderr_INCLUDE_DIRECTORIES.txt
+++ b/Tests/RunCMake/IfacePaths/InstallInBinDir-stderr_INCLUDE_DIRECTORIES.txt
@@ -1,6 +1,6 @@
CMake Error in CMakeLists.txt:
Target "testTarget" INTERFACE_INCLUDE_DIRECTORIES property contains path:
- ".*Tests/RunCMake/IfacePaths_INCLUDE_DIRECTORIES/InstallInBinDir-build/foo"
+ ".*Tests/RunCMake/IfacePaths_INCDIRS/InstallInBinDir-build/foo"
which is prefixed in the build directory.
diff --git a/Tests/RunCMake/IfacePaths/InstallInSrcDir-stderr_INCLUDE_DIRECTORIES.txt b/Tests/RunCMake/IfacePaths/InstallInSrcDir-stderr_INCLUDE_DIRECTORIES.txt
index 11994dd..3c126df 100644
--- a/Tests/RunCMake/IfacePaths/InstallInSrcDir-stderr_INCLUDE_DIRECTORIES.txt
+++ b/Tests/RunCMake/IfacePaths/InstallInSrcDir-stderr_INCLUDE_DIRECTORIES.txt
@@ -1,6 +1,6 @@
CMake Error in CMakeLists.txt:
Target "testTarget" INTERFACE_INCLUDE_DIRECTORIES property contains path:
- ".*Tests/RunCMake/IfacePaths_INCLUDE_DIRECTORIES/copy/foo"
+ ".*Tests/RunCMake/IfacePaths_INCDIRS/copy/foo"
which is prefixed in the source directory.
diff --git a/Tests/RunCMake/IfacePaths/SrcInInstallPrefix-CMP0052-NEW-stderr_INCLUDE_DIRECTORIES.txt b/Tests/RunCMake/IfacePaths/SrcInInstallPrefix-CMP0052-NEW-stderr_INCLUDE_DIRECTORIES.txt
index ed5df34..38bfa4e 100644
--- a/Tests/RunCMake/IfacePaths/SrcInInstallPrefix-CMP0052-NEW-stderr_INCLUDE_DIRECTORIES.txt
+++ b/Tests/RunCMake/IfacePaths/SrcInInstallPrefix-CMP0052-NEW-stderr_INCLUDE_DIRECTORIES.txt
@@ -1,6 +1,6 @@
CMake Error in CMakeLists.txt:
Target "testTarget" INTERFACE_INCLUDE_DIRECTORIES property contains path:
- ".*Tests/RunCMake/IfacePaths_INCLUDE_DIRECTORIES/prefix/src/foo"
+ ".*Tests/RunCMake/IfacePaths_INCDIRS/prefix/src/foo"
which is prefixed in the source directory.
diff --git a/Tests/RunCMake/IfacePaths/SrcInInstallPrefix-CMP0052-WARN-stderr_INCLUDE_DIRECTORIES.txt b/Tests/RunCMake/IfacePaths/SrcInInstallPrefix-CMP0052-WARN-stderr_INCLUDE_DIRECTORIES.txt
index cb5a51c..fd6e372 100644
--- a/Tests/RunCMake/IfacePaths/SrcInInstallPrefix-CMP0052-WARN-stderr_INCLUDE_DIRECTORIES.txt
+++ b/Tests/RunCMake/IfacePaths/SrcInInstallPrefix-CMP0052-WARN-stderr_INCLUDE_DIRECTORIES.txt
@@ -6,15 +6,15 @@ CMake Warning \(dev\) in CMakeLists.txt:
Directory:
- ".*Tests/RunCMake/IfacePaths_INCLUDE_DIRECTORIES/prefix/src/foo"
+ ".*Tests/RunCMake/IfacePaths_INCDIRS/prefix/src/foo"
in INTERFACE_INCLUDE_DIRECTORIES of target "testTarget" is a subdirectory
of the install directory:
- ".*Tests/RunCMake/IfacePaths_INCLUDE_DIRECTORIES/prefix"
+ ".*Tests/RunCMake/IfacePaths_INCDIRS/prefix"
however it is also a subdirectory of the source tree:
- ".*Tests/RunCMake/IfacePaths_INCLUDE_DIRECTORIES/prefix/src"
+ ".*Tests/RunCMake/IfacePaths_INCDIRS/prefix/src"
This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake
index 568bdf8..da4d1e5 100644
--- a/Tests/RunCMake/RunCMake.cmake
+++ b/Tests/RunCMake/RunCMake.cmake
@@ -92,9 +92,12 @@ function(run_cmake test)
set(maybe_input_file "")
endif()
if(RunCMake_TEST_COMMAND)
+ if(NOT RunCMake_TEST_COMMAND_WORKING_DIRECTORY)
+ set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ endif()
execute_process(
COMMAND ${RunCMake_TEST_COMMAND}
- WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}"
+ WORKING_DIRECTORY "${RunCMake_TEST_COMMAND_WORKING_DIRECTORY}"
OUTPUT_VARIABLE actual_stdout
ERROR_VARIABLE ${actual_stderr_var}
RESULT_VARIABLE actual_result
diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
index dcdd177..44ccd6b 100644
--- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
@@ -26,6 +26,7 @@ run_cmake(VsPackageReferences)
run_cmake(VsDpiAware)
run_cmake(VsDpiAwareBadParam)
run_cmake(VsPrecompileHeaders)
+run_cmake(VsPrecompileHeadersReuseFromCompilePDBName)
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05)
run_cmake(VsJustMyCode)
diff --git a/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-result.txt b/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-stderr.txt b/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-stderr.txt
new file mode 100644
index 0000000..2ff57cd
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error at VsPrecompileHeadersReuseFromCompilePDBName.cmake:6 \(add_library\):
+ PRECOMPILE_HEADERS_REUSE_FROM property is set on target \("b"\). Reusable
+ precompile headers requires the COMPILE_PDB_NAME property to have the value
+ "a"
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName.cmake b/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName.cmake
new file mode 100644
index 0000000..ec11008
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName.cmake
@@ -0,0 +1,9 @@
+project(VsPrecompileHeadersReuseFromCompilePDBName CXX)
+
+add_library(a SHARED empty.cxx)
+target_precompile_headers(a PRIVATE <windows.h>)
+
+add_library(b SHARED empty.cxx)
+target_precompile_headers(b REUSE_FROM a)
+
+set_target_properties(b PROPERTIES COMPILE_PDB_NAME b)
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll-build-sub-stderr.txt b/Tests/RunCMake/add_subdirectory/ExcludeFromAll-build-sub-stderr.txt
new file mode 100644
index 0000000..8d98f9d
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll-build-sub-stderr.txt
@@ -0,0 +1 @@
+.*
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake b/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake
index f686005..57ab938 100644
--- a/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake
@@ -4,3 +4,13 @@ add_subdirectory(ExcludeFromAll EXCLUDE_FROM_ALL)
add_executable(main main.cpp)
target_link_libraries(main PRIVATE foo)
+
+file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
+set(main_exe \"$<TARGET_FILE:main>\")
+set(foo_lib \"$<TARGET_FILE:foo>\")
+set(bar_lib \"$<TARGET_FILE:bar>\")
+set(zot_lib \"$<TARGET_FILE:zot>\")
+set(subinc_lib \"$<TARGET_FILE:subinc>\")
+set(subsub_lib \"$<TARGET_FILE:subsub>\")
+set(subsubinc_lib \"$<TARGET_FILE:subsubinc>\")
+")
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt
index 9e6462b..9ed9e55 100644
--- a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt
@@ -1,20 +1,13 @@
-add_library(bar STATIC bar.cpp)
+project(ExcludeFromAllSub NONE)
-add_library(foo STATIC foo.cpp)
-
-add_library(baz STATIC foo.cpp)
-set_target_properties(baz PROPERTIES EXCLUDE_FROM_ALL OFF)
-
-file(GENERATE
- OUTPUT "${CMAKE_BINARY_DIR}/main.txt"
- CONTENT "$<TARGET_FILE_NAME:main>")
+add_subdirectory(SubSub EXCLUDE_FROM_ALL)
-file(GENERATE
- OUTPUT "${CMAKE_BINARY_DIR}/bar.txt"
- CONTENT "$<TARGET_FILE_NAME:bar>")
+add_library(bar STATIC EXCLUDE_FROM_ALL bar.cpp)
-file(GENERATE
- OUTPUT "${CMAKE_BINARY_DIR}/baz.txt"
- CONTENT "$<TARGET_FILE_NAME:baz>")
+add_library(zot STATIC zot.cpp)
+add_library(foo STATIC foo.cpp)
target_include_directories(foo PUBLIC .)
+
+add_library(subinc STATIC subinc.cpp)
+set_target_properties(subinc PROPERTIES EXCLUDE_FROM_ALL OFF)
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/SubSub/CMakeLists.txt b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/SubSub/CMakeLists.txt
new file mode 100644
index 0000000..ec28275
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/SubSub/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_library(subsub STATIC subsub.cpp)
+add_library(subsubinc STATIC subsub.cpp)
+set_property(TARGET subsubinc PROPERTY EXCLUDE_FROM_ALL OFF)
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/SubSub/subsub.cpp b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/SubSub/subsub.cpp
new file mode 100644
index 0000000..ca689ed
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/SubSub/subsub.cpp
@@ -0,0 +1,4 @@
+int subsub()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check-sub.cmake b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check-sub.cmake
new file mode 100644
index 0000000..d318c10
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check-sub.cmake
@@ -0,0 +1,34 @@
+if(EXISTS ${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
+ include(${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
+ if(RunCMake_TEST_FAILED)
+ return()
+ endif()
+
+ foreach(file
+ "${foo_lib}"
+ "${subinc_lib}"
+ "${zot_lib}"
+ "${subsubinc_lib}"
+ )
+ if(NOT EXISTS "${file}")
+ set(RunCMake_TEST_FAILED
+ "Artifact should exist but is missing:\n ${file}")
+ return()
+ endif()
+ endforeach()
+ foreach(file
+ "${main_exe}"
+ "${bar_lib}"
+ "${subsub_lib}"
+ )
+ if(EXISTS "${file}")
+ set(RunCMake_TEST_FAILED
+ "Artifact should be missing but exists:\n ${file}")
+ return()
+ endif()
+ endforeach()
+else()
+ set(RunCMake_TEST_FAILED "
+ '${RunCMake_TEST_BINARY_DIR}/check-debug.cmake' missing
+")
+endif()
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake
index 14ec482..d4bdef2 100644
--- a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake
@@ -1,44 +1,37 @@
-# Use globbing to check if exes / libs were built because determining
-# exactly where these files will live inside a CMake -P script is
-# pretty challenging.
-
-file(READ "${RunCMake_TEST_BINARY_DIR}/main.txt" main_exe)
-file(READ "${RunCMake_TEST_BINARY_DIR}/bar.txt" bar_lib)
-file(READ "${RunCMake_TEST_BINARY_DIR}/baz.txt" baz_lib)
-
-set(found_main FALSE)
-file(GLOB_RECURSE files
- LIST_DIRECTORIES FALSE
- RELATIVE "${RunCMake_TEST_BINARY_DIR}"
- "${RunCMake_TEST_BINARY_DIR}/*")
-foreach (file IN LISTS files)
- if (file MATCHES "${main_exe}")
- set(found_main TRUE)
+if(EXISTS ${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
+ include(${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
+ if(RunCMake_TEST_FAILED)
+ return()
endif()
-endforeach()
-if (NOT found_main)
- set(RunCMake_TEST_FAILED "'main' missing from ${RunCMake_TEST_BINARY_DIR}")
-endif()
-set(found_bar FALSE)
-set(found_baz FALSE)
-file(GLOB_RECURSE files
- LIST_DIRECTORIES FALSE
- RELATIVE "${RunCMake_TEST_BINARY_DIR}/ExcludeFromAll"
- "${RunCMake_TEST_BINARY_DIR}/ExcludeFromAll/*")
-foreach (file IN LISTS files)
- if (file MATCHES "${bar_lib}")
- set(found_bar TRUE)
- endif()
- if (file MATCHES "${baz_lib}")
- set(found_baz TRUE)
- endif()
-endforeach()
-if (found_bar)
- set(RunCMake_TEST_FAILED
- "'bar' was not excluded from ${RunCMake_TEST_BINARY_DIR}/ExcludeFromAll")
-endif()
-if (NOT found_baz)
- set(RunCMake_TEST_FAILED
- "'baz' missing from ${RunCMake_TEST_BINARY_DIR}/ExcludeFromAll")
+ foreach(file
+ "${foo_lib}"
+ "${subinc_lib}"
+ "${main_exe}"
+ "${subsubinc_lib}"
+ )
+ if(EXISTS "${file}")
+ # Remove for next step of test.
+ file(REMOVE "${file}")
+ else()
+ set(RunCMake_TEST_FAILED
+ "Artifact should exist but is missing:\n ${file}")
+ return()
+ endif()
+ endforeach()
+ foreach(file
+ "${zot_lib}"
+ "${bar_lib}"
+ "${subsub_lib}"
+ )
+ if(EXISTS "${file}")
+ set(RunCMake_TEST_FAILED
+ "Artifact should be missing but exists:\n ${file}")
+ return()
+ endif()
+ endforeach()
+else()
+ set(RunCMake_TEST_FAILED "
+ '${RunCMake_TEST_BINARY_DIR}/check-debug.cmake' missing
+")
endif()
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/subinc.cpp b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/subinc.cpp
new file mode 100644
index 0000000..e9faacd
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/subinc.cpp
@@ -0,0 +1,4 @@
+int subinc()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/zot.cpp b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/zot.cpp
new file mode 100644
index 0000000..ba7e966
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/zot.cpp
@@ -0,0 +1,4 @@
+int zot()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake b/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake
index 781e483..951e03c 100644
--- a/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake
@@ -27,14 +27,34 @@ run_cmake_install(CMP0082-OLD -DCMP0082_VALUE=OLD)
run_cmake_install(CMP0082-NEW -DCMP0082_VALUE=NEW)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ExcludeFromAll-build)
-set(RunCMake_TEST_NO_CLEAN 1)
-
-file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
-file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
-
+if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+endif()
run_cmake(ExcludeFromAll)
+set(RunCMake_TEST_NO_CLEAN 1)
set(RunCMake-check-file ExcludeFromAll/check.cmake)
-run_cmake_command(ExcludeFromAll-build ${CMAKE_COMMAND} --build .)
-
-unset(RunCMake_TEST_BINARY_DIR)
+run_cmake_command(ExcludeFromAll-build ${CMAKE_COMMAND} --build . --config Debug)
+if(RunCMake_GENERATOR STREQUAL "Ninja")
+ if(WIN32)
+ set(slash [[\]])
+ else()
+ set(slash [[/]])
+ endif()
+ set(RunCMake-check-file ExcludeFromAll/check-sub.cmake)
+ run_cmake_command(ExcludeFromAll-build-sub ${CMAKE_COMMAND} --build . --target "ExcludeFromAll${slash}all")
+elseif(RunCMake_GENERATOR MATCHES "Make")
+ set(RunCMake-check-file ExcludeFromAll/check-sub.cmake)
+ set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY ${RunCMake_BINARY_DIR}/ExcludeFromAll-build/ExcludeFromAll)
+ run_cmake_command(ExcludeFromAll-build-sub "${RunCMake_MAKE_PROGRAM}")
+elseif(RunCMake_GENERATOR MATCHES "^Visual Studio [1-9][0-9]")
+ set(RunCMake-check-file ExcludeFromAll/check-sub.cmake)
+ run_cmake_command(ExcludeFromAll-build-sub ${CMAKE_COMMAND} --build ExcludeFromAll --config Debug)
+elseif(RunCMake_GENERATOR STREQUAL "Xcode")
+ set(RunCMake-check-file ExcludeFromAll/check-sub.cmake)
+ set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY ${RunCMake_BINARY_DIR}/ExcludeFromAll-build/ExcludeFromAll)
+ run_cmake_command(ExcludeFromAll-build-sub xcodebuild -configuration Debug)
+endif()
+unset(RunCMake-check-file)
unset(RunCMake_TEST_NO_CLEAN)
+unset(RunCMake_TEST_OPTIONS)
+unset(RunCMake_TEST_BINARY_DIR)
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