diff options
115 files changed, 2059 insertions, 689 deletions
diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index 0d8a166..8ce6529 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -17,7 +17,7 @@ and load its package-specific details. Search Modes ^^^^^^^^^^^^ -The command has two very distinct ways of conducting the search: +The command has a few modes by which it searches for packages: **Module mode** In this mode, CMake searches for a file called ``Find<PackageName>.cmake``, @@ -60,7 +60,17 @@ The command has two very distinct ways of conducting the search: Config mode is supported by both the :ref:`basic <Basic Signature>` and :ref:`full <Full Signature>` command signatures. -The command arguments determine which of the above modes is used. When the +**FetchContent redirection mode** + .. versionadded:: 3.24 + A call to ``find_package()`` can be redirected internally to a package + provided by the :module:`FetchContent` module. To the caller, the behavior + will appear similar to Config mode, except that the search logic is + by-passed and the component information is not used. See + :command:`FetchContent_Declare` and :command:`FetchContent_MakeAvailable` + for further details. + +When not redirected to a package provided by :module:`FetchContent`, the +command arguments determine whether Module or Config mode is used. When the `basic signature`_ is used, the command searches in Module mode first. If the package is not found, the search falls back to Config mode. A user may set the :variable:`CMAKE_FIND_PACKAGE_PREFER_CONFIG` variable @@ -70,7 +80,7 @@ forced to use only Module mode with a ``MODULE`` keyword. If the `full signature`_ is used, the command only searches in Config mode. Where possible, user code should generally look for packages using the -`basic signature`_, since that allows the package to be found with either mode. +`basic signature`_, since that allows the package to be found with any mode. Project maintainers wishing to provide a config package should understand the bigger picture, as explained in :ref:`Full Signature` and all subsequent sections on this page. @@ -203,9 +213,12 @@ proceeds at once with Config mode search. Config mode search attempts to locate a configuration file provided by the package to be found. A cache entry called ``<PackageName>_DIR`` is created to -hold the directory containing the file. By default the command -searches for a package with the name ``<PackageName>``. If the ``NAMES`` option -is given the names following it are used instead of ``<PackageName>``. +hold the directory containing the file. By default, the command searches for +a package with the name ``<PackageName>``. If the ``NAMES`` option is given, +the names following it are used instead of ``<PackageName>``. The names are +also considered when determining whether to redirect the call to a package +provided by :module:`FetchContent`. + The command searches for a file called ``<PackageName>Config.cmake`` or ``<lowercasePackageName>-config.cmake`` for each name specified. A replacement set of possible configuration file names may be given @@ -242,6 +255,14 @@ Config Mode Search Procedure whether the :ref:`full <full signature>` or :ref:`basic <basic signature>` signature was given. +.. versionadded:: 3.24 + All calls to ``find_package()`` (even in Module mode) first look for a config + package file in the :variable:`CMAKE_FIND_PACKAGE_REDIRECTS_DIR` directory. + The :module:`FetchContent` module, or even the project itself, may write files + to that location to redirect ``find_package()`` calls to content already + provided by the project. If no config package file is found in that location, + the search proceeds with the logic described below. + CMake constructs a set of possible installation prefixes for the package. Under each prefix several directories are searched for a configuration file. The tables below show the directories searched. @@ -420,7 +441,8 @@ to resolve symbolic links and store the real path to the file. Every non-REQUIRED ``find_package`` call can be disabled or made REQUIRED: * Setting the :variable:`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>` variable - to ``TRUE`` disables the package. + to ``TRUE`` disables the package. This also disables redirection to a + package provided by :module:`FetchContent`. * Setting the :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable to ``TRUE`` makes the package REQUIRED. @@ -443,8 +465,8 @@ version (see :ref:`format specification <FIND_PACKAGE_VERSION_FORMAT>`). If the ``EXACT`` option is given, only a version of the package claiming an exact match of the requested version may be found. CMake does not establish any convention for the meaning of version numbers. Package version -numbers are checked by "version" files provided by the packages -themselves. For a candidate package configuration file +numbers are checked by "version" files provided by the packages themselves +or by :module:`FetchContent`. For a candidate package configuration file ``<config-file>.cmake`` the corresponding version file is located next to it and named either ``<config-file>-version.cmake`` or ``<config-file>Version.cmake``. If no such version file is available diff --git a/Help/command/try_compile.rst b/Help/command/try_compile.rst index 08f8d5b..4b2a631 100644 --- a/Help/command/try_compile.rst +++ b/Help/command/try_compile.rst @@ -150,6 +150,7 @@ Other Behavior Settings * :variable:`CMAKE_LINK_SEARCH_END_STATIC` * :variable:`CMAKE_MSVC_RUNTIME_LIBRARY` * :variable:`CMAKE_POSITION_INDEPENDENT_CODE` + * :variable:`CMAKE_WATCOM_RUNTIME_LIBRARY` If :policy:`CMP0056` is set to ``NEW``, then :variable:`CMAKE_EXE_LINKER_FLAGS` is passed in as well. diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index b3091fa..259cebb 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -58,6 +58,7 @@ Policies Introduced by CMake 3.24 .. toctree:: :maxdepth: 1 + CMP0136: Watcom runtime library flags are selected by an abstraction. </policy/CMP0136> CMP0135: ExternalProject ignores timestamps in archives by default for the URL download method. </policy/CMP0135> CMP0134: Fallback to \"HOST\" Windows registry view when \"TARGET\" view is not usable. </policy/CMP0134> CMP0133: The CPack module disables SLA by default in the CPack DragNDrop Generator. </policy/CMP0133> diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 8c2f8c4..20b62c5 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -171,6 +171,7 @@ Properties on Targets /prop_tgt/COMPILE_PDB_NAME_CONFIG /prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY /prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG + /prop_tgt/COMPILE_WARNING_AS_ERROR /prop_tgt/CONFIG_OUTPUT_NAME /prop_tgt/CONFIG_POSTFIX /prop_tgt/CROSSCOMPILING_EMULATOR @@ -423,6 +424,7 @@ Properties on Targets /prop_tgt/VS_WINRT_COMPONENT /prop_tgt/VS_WINRT_EXTENSIONS /prop_tgt/VS_WINRT_REFERENCES + /prop_tgt/WATCOM_RUNTIME_LIBRARY /prop_tgt/WIN32_EXECUTABLE /prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS /prop_tgt/XCODE_ATTRIBUTE_an-attribute diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 70dfc35..80160b6 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -59,6 +59,7 @@ Variables that Provide Information /variable/CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES /variable/CMAKE_FIND_DEBUG_MODE /variable/CMAKE_FIND_PACKAGE_NAME + /variable/CMAKE_FIND_PACKAGE_REDIRECTS_DIR /variable/CMAKE_FIND_PACKAGE_SORT_DIRECTION /variable/CMAKE_FIND_PACKAGE_SORT_ORDER /variable/CMAKE_GENERATOR @@ -400,6 +401,7 @@ Variables that Control the Build /variable/CMAKE_BUILD_WITH_INSTALL_RPATH /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG + /variable/CMAKE_COMPILE_WARNING_AS_ERROR /variable/CMAKE_CONFIG_POSTFIX /variable/CMAKE_CROSS_CONFIGS /variable/CMAKE_CTEST_ARGUMENTS @@ -520,6 +522,7 @@ Variables that Control the Build /variable/CMAKE_VS_SDK_REFERENCE_DIRECTORIES /variable/CMAKE_VS_SDK_SOURCE_DIRECTORIES /variable/CMAKE_VS_WINRT_BY_DEFAULT + /variable/CMAKE_WATCOM_RUNTIME_LIBRARY /variable/CMAKE_WIN32_EXECUTABLE /variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS /variable/CMAKE_XCODE_ATTRIBUTE_an-attribute diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index 82e27b8..06f0d4e 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -357,14 +357,20 @@ See `Build and Test Mode`_. Specify the directory in which to look for tests. ``--test-output-size-passed <size>`` + .. versionadded:: 3.4 + Limit the output for passed tests to ``<size>`` bytes. ``--test-output-size-failed <size>`` + .. versionadded:: 3.4 + Limit the output for failed tests to ``<size>`` bytes. ``--test-output-truncation <mode>`` - Truncate 'tail' (default), 'middle' or 'head' of test output once maximum - output size is reached. + .. versionadded:: 3.24 + + Truncate ``tail`` (default), ``middle`` or ``head`` of test output once + maximum output size is reached. ``--overwrite`` Overwrite CTest configuration option. diff --git a/Help/policy/CMP0136.rst b/Help/policy/CMP0136.rst new file mode 100644 index 0000000..5414278 --- /dev/null +++ b/Help/policy/CMP0136.rst @@ -0,0 +1,50 @@ +CMP0136 +------- + +.. versionadded:: 3.24 + +Watcom runtime library flags are selected by an abstraction. + +Compilers targeting the Watcom ABI have flags to select the Watcom runtime +library. + +In CMake 3.23 and below, Watcom runtime library selection flags are added to +the default :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` cache entries by CMake +automatically. This allows users to edit their cache entries to adjust the +flags. However, the presence of such default flags is problematic for +projects that want to choose a different runtime library programmatically. +In particular, it requires string editing of the +:variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` variables with knowledge of the +CMake builtin defaults so they can be replaced. + +CMake 3.24 and above prefer to leave the Watcom runtime library selection flags +out of the default :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` values and instead +offer a first-class abstraction. The :variable:`CMAKE_WATCOM_RUNTIME_LIBRARY` +variable and :prop_tgt:`WATCOM_RUNTIME_LIBRARY` target property may be set to +select the Watcom runtime library. If they are not set then CMake uses the +default value ``MultiThreadedDLL`` on Windows and ``SingleThreaded`` on other +platforms, which is equivalent to the original flags. + +This policy provides compatibility with projects that have not been updated +to be aware of the abstraction. The policy setting takes effect as of the +first :command:`project` or :command:`enable_language` command that enables +a language whose compiler targets the Watcom ABI. + +.. note:: + + Once the policy has taken effect at the top of a project, that choice + must be used throughout the tree. In projects that have nested projects + in subdirectories, be sure to convert everything together. + +The ``OLD`` behavior for this policy is to place Watcom runtime library +flags in the default :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` cache +entries and ignore the :variable:`CMAKE_WATCOM_RUNTIME_LIBRARY` abstraction. +The ``NEW`` behavior for this policy is to *not* place Watcom runtime +library flags in the default cache entries and use the abstraction instead. + +This policy was introduced in CMake version 3.24. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +Unlike many policies, CMake version |release| does *not* warn +when this policy is not set and simply uses ``OLD`` behavior. + +.. include:: DEPRECATED.txt diff --git a/Help/prop_tgt/COMPILE_WARNING_AS_ERROR.rst b/Help/prop_tgt/COMPILE_WARNING_AS_ERROR.rst new file mode 100644 index 0000000..86a0f7f --- /dev/null +++ b/Help/prop_tgt/COMPILE_WARNING_AS_ERROR.rst @@ -0,0 +1,10 @@ +COMPILE_WARNING_AS_ERROR +------------------------ + +.. versionadded:: 3.24 + +Specify whether to treat warnings on compile as errors. +If enabled, adds a flag to treat warnings on compile as errors. + +This property is initialized by the value of the variable +:variable:`CMAKE_COMPILE_WARNING_AS_ERROR` if it is set when a target is created. diff --git a/Help/prop_tgt/WATCOM_RUNTIME_LIBRARY-VALUES.txt b/Help/prop_tgt/WATCOM_RUNTIME_LIBRARY-VALUES.txt new file mode 100644 index 0000000..cdf99d0 --- /dev/null +++ b/Help/prop_tgt/WATCOM_RUNTIME_LIBRARY-VALUES.txt @@ -0,0 +1,20 @@ +``SingleThreaded`` + Compile without additional flags to use a single-threaded + statically-linked runtime library. +``SingleThreadedDLL`` + Compile with ``-br`` or equivalent flag(s) to use a single-threaded + dynamically-linked runtime library. This is not available for Linux + targets. +``MultiThreaded`` + Compile with ``-bm`` or equivalent flag(s) to use a multi-threaded + statically-linked runtime library. +``MultiThreadedDLL`` + Compile with ``-bm -br`` or equivalent flag(s) to use a multi-threaded + dynamically-linked runtime library. This is not available for Linux + targets. + +The value is ignored on non-Watcom compilers but an unsupported value will +be rejected as an error when using a compiler targeting the Watcom ABI. + +The value may also be the empty string (``""``) in which case no runtime +library selection flag will be added explicitly by CMake. diff --git a/Help/prop_tgt/WATCOM_RUNTIME_LIBRARY.rst b/Help/prop_tgt/WATCOM_RUNTIME_LIBRARY.rst new file mode 100644 index 0000000..3752862 --- /dev/null +++ b/Help/prop_tgt/WATCOM_RUNTIME_LIBRARY.rst @@ -0,0 +1,34 @@ +WATCOM_RUNTIME_LIBRARY +---------------------- + +.. versionadded:: 3.24 + +Select the Watcom runtime library for use by compilers targeting the Watcom ABI. + +The allowed values are: + +.. include:: WATCOM_RUNTIME_LIBRARY-VALUES.txt + +Use :manual:`generator expressions <cmake-generator-expressions(7)>` to +support per-configuration specification. + +For example, the code: + +.. code-block:: cmake + + add_executable(foo foo.c) + set_property(TARGET foo PROPERTY + WATCOM_RUNTIME_LIBRARY "MultiThreaded") + +selects for the target ``foo`` a multi-threaded statically-linked runtime +library. + +If this property is not set then CMake uses the default value +``MultiThreadedDLL`` on Windows and ``SingleThreaded`` on other +platforms to select a Watcom runtime library. + +.. note:: + + This property has effect only when policy :policy:`CMP0136` is set to ``NEW`` + prior to the first :command:`project` or :command:`enable_language` command + that enables a language using a compiler targeting the Watcom ABI. diff --git a/Help/release/dev/FetchContent_find_package_integration.rst b/Help/release/dev/FetchContent_find_package_integration.rst new file mode 100644 index 0000000..4ca7afc --- /dev/null +++ b/Help/release/dev/FetchContent_find_package_integration.rst @@ -0,0 +1,17 @@ +FetchContent_find_package_integration +------------------------------------- + +* Integration has been added between the :module:`FetchContent` module and the + :command:`find_package` command, enabling the following new capabilities: + + * :command:`FetchContent_MakeAvailable` can now try to satisfy a dependency + by calling :command:`find_package` first. A new + :variable:`FETCHCONTENT_TRY_FIND_PACKAGE_MODE` variable controls whether + this is done by default for all dependencies, is opt-in per dependency, + or is disabled entirely. + + * :command:`find_package` can be re-routed to call + :command:`FetchContent_MakeAvailable` instead. A new read-only + :variable:`CMAKE_FIND_PACKAGE_REDIRECTS_DIR` variable points to a + directory where config package files can be located to facilitate these + re-routed calls. diff --git a/Help/release/dev/ctest-output-truncation.rst b/Help/release/dev/ctest-output-truncation.rst new file mode 100644 index 0000000..85fb37c --- /dev/null +++ b/Help/release/dev/ctest-output-truncation.rst @@ -0,0 +1,11 @@ +ctest-output-truncation +----------------------- + +* :manual:`ctest(1)` gained a ``--test-output-truncation`` option (and + corresponding :variable:`CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION` variable) to + specify the truncation mode once the maximum test output size has been + reached. Possible values are ``tail`` (default), ``middle`` or ``head``. +* :manual:`cmake-presets(7)` files now support schema version ``5``. +* :manual:`cmake-presets(7)` files gained support for specifying a + ``testOutputTruncation`` field in test presets, which specifies the truncation + mode once the maximum test output size has been reached. diff --git a/Help/release/dev/watcom-runtime-library.rst b/Help/release/dev/watcom-runtime-library.rst new file mode 100644 index 0000000..3a07b32 --- /dev/null +++ b/Help/release/dev/watcom-runtime-library.rst @@ -0,0 +1,7 @@ +watcom-runtime-library +---------------------- + +* The :variable:`CMAKE_WATCOM_RUNTIME_LIBRARY` variable and + :prop_tgt:`WATCOM_RUNTIME_LIBRARY` target property were introduced to + select the runtime library used by compilers targeting the Watcom ABI. + See policy :policy:`CMP0136`. diff --git a/Help/release/dev/werror-property.rst b/Help/release/dev/werror-property.rst new file mode 100644 index 0000000..c337df7 --- /dev/null +++ b/Help/release/dev/werror-property.rst @@ -0,0 +1,8 @@ +werror-property +--------------- + +* Added the Target Property :prop_tgt:`COMPILE_WARNING_AS_ERROR` and the + Variable :variable:`CMAKE_COMPILE_WARNING_AS_ERROR` which initializes the + Target Property. If :prop_tgt:`COMPILE_WARNING_AS_ERROR` is true, it expands + to a different flag depending on the compiler such that any warnings at + compile will be treated as errors. diff --git a/Help/variable/CMAKE_COMPILE_WARNING_AS_ERROR.rst b/Help/variable/CMAKE_COMPILE_WARNING_AS_ERROR.rst new file mode 100644 index 0000000..56dc6a6 --- /dev/null +++ b/Help/variable/CMAKE_COMPILE_WARNING_AS_ERROR.rst @@ -0,0 +1,9 @@ +CMAKE_COMPILE_WARNING_AS_ERROR +------------------------------ + +.. versionadded:: 3.24 + +Specify whether to treat warnings on compile as errors. + +This variable is used to initialize the +:prop_tgt:`COMPILE_WARNING_AS_ERROR` property on all the targets. diff --git a/Help/variable/CMAKE_FIND_PACKAGE_REDIRECTS_DIR.rst b/Help/variable/CMAKE_FIND_PACKAGE_REDIRECTS_DIR.rst new file mode 100644 index 0000000..fa414e4 --- /dev/null +++ b/Help/variable/CMAKE_FIND_PACKAGE_REDIRECTS_DIR.rst @@ -0,0 +1,27 @@ +CMAKE_FIND_PACKAGE_REDIRECTS_DIR +-------------------------------- + +.. versionadded:: 3.24 + +This read-only variable specifies a directory that the :command:`find_package` +command will check first before searching anywhere else for a module or config +package file. A config package file in this directory will always be found in +preference to any other Find module file or config package file. + +The primary purpose of this variable is to facilitate integration between +:command:`find_package` and :command:`FetchContent_MakeAvailable`. The latter +command may create files in the ``CMAKE_FIND_PACKAGE_REDIRECTS_DIR`` directory +when it populates a dependency. This allows subsequent calls to +:command:`find_package` for the same dependency to re-use the populated +contents instead of trying to satisfy the dependency from somewhere external +to the build. Projects may also want to write files into this directory in +some situations (see :ref:`FetchContent-find_package-integration` for examples). + +The directory that ``CMAKE_FIND_PACKAGE_REDIRECTS_DIR`` points to will always +be erased and recreated empty at the start of every CMake run. Any files +written into this directory during the CMake run will be lost the next time +CMake configures the project. + +``CMAKE_FIND_PACKAGE_REDIRECTS_DIR`` is only set in CMake project mode. +It is not set when CMake is run in script mode +(i.e. :manual:`cmake -P ... <cmake(1)>`). diff --git a/Help/variable/CMAKE_WATCOM_RUNTIME_LIBRARY.rst b/Help/variable/CMAKE_WATCOM_RUNTIME_LIBRARY.rst new file mode 100644 index 0000000..feb2a60 --- /dev/null +++ b/Help/variable/CMAKE_WATCOM_RUNTIME_LIBRARY.rst @@ -0,0 +1,36 @@ +CMAKE_WATCOM_RUNTIME_LIBRARY +---------------------------- + +.. versionadded:: 3.24 + +Select the Watcom runtime library for use by compilers targeting the Watcom ABI. +This variable is used to initialize the :prop_tgt:`WATCOM_RUNTIME_LIBRARY` +property on all targets as they are created. It is also propagated by +calls to the :command:`try_compile` command into the test project. + +The allowed values are: + +.. include:: ../prop_tgt/WATCOM_RUNTIME_LIBRARY-VALUES.txt + +Use :manual:`generator expressions <cmake-generator-expressions(7)>` to +support per-configuration specification. + +For example, the code: + +.. code-block:: cmake + + set(CMAKE_WATCOM_RUNTIME_LIBRARY "MultiThreaded") + +selects for all following targets a multi-threaded statically-linked runtime +library. + +If this variable is not set then the :prop_tgt:`WATCOM_RUNTIME_LIBRARY` target +property will not be set automatically. If that property is not set then +CMake uses the default value ``MultiThreadedDLL`` on Windows and +``SingleThreaded`` on other platforms to select a Watcom runtime library. + +.. note:: + + This variable has effect only when policy :policy:`CMP0136` is set to ``NEW`` + prior to the first :command:`project` or :command:`enable_language` command + that enables a language using a compiler targeting the Watcom ABI. diff --git a/Modules/Compiler/Fujitsu.cmake b/Modules/Compiler/Fujitsu.cmake index 78495cb..55c2aa4 100644 --- a/Modules/Compiler/Fujitsu.cmake +++ b/Modules/Compiler/Fujitsu.cmake @@ -11,6 +11,7 @@ include(Compiler/CMakeCommonCompilerMacros) macro(__compiler_fujitsu lang) set(CMAKE_${lang}_VERBOSE_FLAG "-###") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-cwno") # Initial configuration flags string(APPEND CMAKE_${lang}_FLAGS_INIT " ") diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake index 2eef532..c5946f0 100644 --- a/Modules/Compiler/GNU.cmake +++ b/Modules/Compiler/GNU.cmake @@ -18,6 +18,7 @@ set(__pch_header_OBJCXX "objective-c++-header") macro(__compiler_gnu lang) # Feature flags. set(CMAKE_${lang}_VERBOSE_FLAG "-v") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror") set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") set (_CMAKE_${lang}_PIE_MAY_BE_SUPPORTED_BY_LINKER NO) if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.4) diff --git a/Modules/Compiler/Intel.cmake b/Modules/Compiler/Intel.cmake index 9a760c8..20989d2 100644 --- a/Modules/Compiler/Intel.cmake +++ b/Modules/Compiler/Intel.cmake @@ -13,6 +13,7 @@ include(Compiler/CMakeCommonCompilerMacros) if(CMAKE_HOST_WIN32) # MSVC-like macro(__compiler_intel lang) + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror-all") endmacro() else() # GNU-like @@ -24,6 +25,7 @@ else() string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -Os") string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3") string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror-all") set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}") if(CMAKE_${lang}_COMPILER_ARG1) diff --git a/Modules/Compiler/IntelLLVM.cmake b/Modules/Compiler/IntelLLVM.cmake index 14b7ad8..c344f32 100644 --- a/Modules/Compiler/IntelLLVM.cmake +++ b/Modules/Compiler/IntelLLVM.cmake @@ -20,6 +20,7 @@ if(CMAKE_HOST_WIN32) macro(__compiler_intel_llvm lang) if(NOT "x${lang}" STREQUAL "xFortran") set(CMAKE_${lang}_COMPILE_OPTIONS_INVALID_PCH -Winvalid-pch) + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-WX") endif() endmacro() else() @@ -38,6 +39,7 @@ else() set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") set(CMAKE_${lang}_LINK_OPTIONS_PIE ${CMAKE_${lang}_COMPILE_OPTIONS_PIE} "-pie") set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "-no-pie") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror") set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC") set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared") diff --git a/Modules/Compiler/LCC.cmake b/Modules/Compiler/LCC.cmake index 8353ab6..bdee9a6 100644 --- a/Modules/Compiler/LCC.cmake +++ b/Modules/Compiler/LCC.cmake @@ -18,6 +18,7 @@ set(__pch_header_OBJCXX "objective-c++-header") macro(__compiler_lcc lang) # Feature flags. set(CMAKE_${lang}_VERBOSE_FLAG "-v") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror") set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") set (_CMAKE_${lang}_PIE_MAY_BE_SUPPORTED_BY_LINKER NO) set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") diff --git a/Modules/Compiler/MSVC-C.cmake b/Modules/Compiler/MSVC-C.cmake index df3691c..6bf6b4e 100644 --- a/Modules/Compiler/MSVC-C.cmake +++ b/Modules/Compiler/MSVC-C.cmake @@ -1,6 +1,9 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. +include(Compiler/MSVC) +__compiler_msvc(C) + include(Compiler/CMakeCommonCompilerMacros) if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.27) @@ -67,16 +70,3 @@ else() endif() set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC) -set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl") -set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") - -# /JMC "Just My Code" is only supported by MSVC 19.05 onward. -if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05) - set(CMAKE_C_COMPILE_OPTIONS_JMC "-JMC") -endif() - -# The `/external:I` flag was made non-experimental in 19.29.30036.3. -if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30036.3) - set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-external:I") - set(_CMAKE_INCLUDE_SYSTEM_FLAG_C_WARNING "-external:W0 ") -endif () diff --git a/Modules/Compiler/MSVC-CXX.cmake b/Modules/Compiler/MSVC-CXX.cmake index 17cbc3c..75165fd 100644 --- a/Modules/Compiler/MSVC-CXX.cmake +++ b/Modules/Compiler/MSVC-CXX.cmake @@ -1,10 +1,10 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -include(Compiler/CMakeCommonCompilerMacros) +include(Compiler/MSVC) +__compiler_msvc(CXX) -set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl") -set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") +include(Compiler/CMakeCommonCompilerMacros) if ((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.0.24215.1 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) OR @@ -76,14 +76,3 @@ elseif (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0) _record_compiler_features(CXX "" CMAKE_CXX_COMPILE_FEATURES) endmacro() endif() - -# /JMC "Just My Code" is only supported by MSVC 19.05 onward. -if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05) - set(CMAKE_CXX_COMPILE_OPTIONS_JMC "-JMC") -endif() - -# The `/external:I` flag was made non-experimental in 19.29.30036.3. -if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30036.3) - set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-external:I") - set(_CMAKE_INCLUDE_SYSTEM_FLAG_CXX_WARNING "-external:W0 ") -endif () diff --git a/Modules/Compiler/MSVC.cmake b/Modules/Compiler/MSVC.cmake new file mode 100644 index 0000000..154b657 --- /dev/null +++ b/Modules/Compiler/MSVC.cmake @@ -0,0 +1,25 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# This module is shared by multiple languages; use include blocker. +if(__COMPILER_MSVC) + return() +endif() +set(__COMPILER_MSVC 1) + +macro(__compiler_msvc lang) + set(CMAKE_${lang}_CLANG_TIDY_DRIVER_MODE "cl") + set(CMAKE_${lang}_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-WX") + + # /JMC "Just My Code" is only supported by MSVC 19.05 onward. + if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05) + set(CMAKE_${lang}_COMPILE_OPTIONS_JMC "-JMC") + endif() + + # The `/external:I` flag was made non-experimental in 19.29.30036.3. + if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30036.3) + set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-external:I") + set(_CMAKE_INCLUDE_SYSTEM_FLAG_${lang}_WARNING "-external:W0 ") + endif () +endmacro() diff --git a/Modules/Compiler/NVHPC.cmake b/Modules/Compiler/NVHPC.cmake index b51bb43..21d0665 100644 --- a/Modules/Compiler/NVHPC.cmake +++ b/Modules/Compiler/NVHPC.cmake @@ -13,4 +13,5 @@ include(Compiler/PGI) macro(__compiler_nvhpc lang) # Logic specific to NVHPC. set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "--Werror all-warnings") endmacro() diff --git a/Modules/Compiler/SunPro-ASM.cmake b/Modules/Compiler/SunPro-ASM.cmake index 0d67400..fc0f2fa 100644 --- a/Modules/Compiler/SunPro-ASM.cmake +++ b/Modules/Compiler/SunPro-ASM.cmake @@ -1,3 +1,6 @@ +include(Compiler/SunPro) +__compiler_sunpro(ASM) + set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s ) set(CMAKE_ASM_VERBOSE_FLAG "-#") diff --git a/Modules/Compiler/SunPro-C.cmake b/Modules/Compiler/SunPro-C.cmake index 7a406ac..b06719d 100644 --- a/Modules/Compiler/SunPro-C.cmake +++ b/Modules/Compiler/SunPro-C.cmake @@ -2,6 +2,7 @@ # file Copyright.txt or https://cmake.org/licensing for details. include(Compiler/SunPro) +__compiler_sunpro(C) set(CMAKE_C_VERBOSE_FLAG "-#") diff --git a/Modules/Compiler/SunPro-CXX.cmake b/Modules/Compiler/SunPro-CXX.cmake index aa8a9c5..f835f2d 100644 --- a/Modules/Compiler/SunPro-CXX.cmake +++ b/Modules/Compiler/SunPro-CXX.cmake @@ -2,6 +2,7 @@ # file Copyright.txt or https://cmake.org/licensing for details. include(Compiler/SunPro) +__compiler_sunpro(CXX) set(CMAKE_CXX_VERBOSE_FLAG "-v") diff --git a/Modules/Compiler/SunPro-Fortran.cmake b/Modules/Compiler/SunPro-Fortran.cmake index 0ba5015..d336980 100644 --- a/Modules/Compiler/SunPro-Fortran.cmake +++ b/Modules/Compiler/SunPro-Fortran.cmake @@ -1,3 +1,6 @@ +include(Compiler/SunPro) +__compiler_sunpro(Fortran) + set(CMAKE_Fortran_VERBOSE_FLAG "-v") set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-fixed") set(CMAKE_Fortran_FORMAT_FREE_FLAG "-free") diff --git a/Modules/Compiler/SunPro.cmake b/Modules/Compiler/SunPro.cmake index 52da39a..331cdfc 100644 --- a/Modules/Compiler/SunPro.cmake +++ b/Modules/Compiler/SunPro.cmake @@ -8,3 +8,7 @@ endif() set(__COMPILER_SUNPRO 1) include(Compiler/CMakeCommonCompilerMacros) + +macro(__compiler_sunpro lang) + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-errwarn=%all") +endmacro() diff --git a/Modules/Compiler/XL.cmake b/Modules/Compiler/XL.cmake index 8b9d4a9..844fcfd 100644 --- a/Modules/Compiler/XL.cmake +++ b/Modules/Compiler/XL.cmake @@ -15,6 +15,7 @@ macro(__compiler_xl lang) set(CMAKE_${lang}_VERBOSE_FLAG "-V") set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-qpic") set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-qpic") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-qhalt=i") set(CMAKE_${lang}_RESPONSE_FILE_FLAG "-qoptfile=") set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "-qoptfile=") diff --git a/Modules/Compiler/XLClang.cmake b/Modules/Compiler/XLClang.cmake index cdf0fdc..8c3e5e9 100644 --- a/Modules/Compiler/XLClang.cmake +++ b/Modules/Compiler/XLClang.cmake @@ -17,6 +17,7 @@ macro(__compiler_xlclang lang) set(CMAKE_${lang}_VERBOSE_FLAG "-V") set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIC") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror") set(CMAKE_${lang}_RESPONSE_FILE_FLAG "@") set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "@") endmacro() diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index 7e14756..1b81778 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -102,7 +102,12 @@ Commands .. code-block:: cmake - FetchContent_Declare(<name> <contentOptions>...) + FetchContent_Declare( + <name> + <contentOptions>... + [OVERRIDE_FIND_PACKAGE | + FIND_PACKAGE_ARGS args...] + ) The ``FetchContent_Declare()`` function records the options that describe how to populate the specified content. If such details have already @@ -169,6 +174,36 @@ Commands they do for :command:`ExternalProject_Add`. Previously, these variables were ignored by the ``FetchContent`` module. + .. versionadded:: 3.24 + + ``FIND_PACKAGE_ARGS`` + This option is for scenarios where the + :command:`FetchContent_MakeAvailable` command may first try a call to + :command:`find_package` to satisfy the dependency for ``<name>``. + By default, such a call would be simply ``find_package(<name>)``, but + ``FIND_PACKAGE_ARGS`` can be used to provide additional arguments to be + appended after the ``<name>``. ``FIND_PACKAGE_ARGS`` can also be given + with nothing after it, which indicates that :command:`find_package` can + still be called if :variable:`FETCHCONTENT_TRY_FIND_PACKAGE_MODE` is + set to ``OPT_IN`` or is not set. + + Everything after the ``FIND_PACKAGE_ARGS`` keyword is appended to the + :command:`find_package` call, so all other ``<contentOptions>`` must + come before the ``FIND_PACKAGE_ARGS`` keyword. + ``OVERRIDE_FIND_PACKAGE`` cannot be used when ``FIND_PACKAGE_ARGS`` is + given. + + ``OVERRIDE_FIND_PACKAGE`` + When a ``FetchContent_Declare(<name> ...)`` call includes this option, + subsequent calls to ``find_package(<name> ...)`` will ensure that + ``FetchContent_MakeAvailable(<name>)`` has been called, then use the + config package files in the :variable:`CMAKE_FIND_PACKAGE_REDIRECTS_DIR` + directory (which are usually created by ``FetchContent_MakeAvailable()``). + This effectively makes :command:`FetchContent_MakeAvailable` override + :command:`find_package` for the named dependency, allowing the former to + satisfy the package requirements of the latter. ``FIND_PACKAGE_ARGS`` + cannot be used when ``OVERRIDE_FIND_PACKAGE`` is given. + .. command:: FetchContent_MakeAvailable .. versionadded:: 3.14 @@ -177,9 +212,22 @@ Commands FetchContent_MakeAvailable(<name1> [<name2>...]) - This command ensures that each of the named dependencies are populated and - potentially added to the build by the time it returns. It iterates over - the list, and for each dependency, the following logic is applied: + This command ensures that each of the named dependencies are made available + to the project by the time it returns. There must have been a call to + :command:`FetchContent_Declare` for each dependency, and the first such call + will control how that dependency will be made available, as described below. + + .. versionadded:: 3.24 + If permitted, :command:`find_package(<name> [<args>...]) <find_package>` + will be called, where ``<args>...`` may be provided by the + ``FIND_PACKAGE_ARGS`` option in :command:`FetchContent_Declare`. + The value of the :variable:`FETCHCONTENT_TRY_FIND_PACKAGE_MODE` variable + at the time :command:`FetchContent_Declare` was called determines whether + ``FetchContent_MakeAvailable()`` can call :command:`find_package`. + + If :command:`find_package` was unsuccessful or was not allowed to be called, + ``FetchContent_MakeAvailable()`` then uses the following logic to make the + dependency available: * If the dependency has already been populated earlier in this run, set the ``<lowercaseName>_POPULATED``, ``<lowercaseName>_SOURCE_DIR`` and @@ -194,6 +242,37 @@ Commands the declared details and use content provided at the specified location instead. + * .. versionadded:: 3.24 + + Ensure the :variable:`CMAKE_FIND_PACKAGE_REDIRECTS_DIR` directory + contains a ``<lowercaseName>-config.cmake`` and a + ``<lowercaseName>-config-version.cmake`` file (or equivalently + ``<name>Config.cmake`` and ``<name>ConfigVersion.cmake``). + The directory that the :variable:`CMAKE_FIND_PACKAGE_REDIRECTS_DIR` + variable points to is cleared at the start of every CMake run. + If no config file exists when :command:`FetchContent_Populate` returns, + a minimal one will be written which :command:`includes <include>` any + ``<lowercaseName>-extra.cmake`` or ``<name>Extra.cmake`` file with the + ``OPTIONAL`` flag (so the files can be missing and won't generate a + warning). Similarly, if no config version file exists, a very simple + one will be written which sets ``PACKAGE_VERSION_COMPATIBLE`` to true. + CMake cannot automatically determine an arbitrary dependency's version, + so it cannot set ``PACKAGE_VERSION`` or ``PACKAGE_VERSION_EXACT``. + When a dependency is pulled in via :command:`add_subdirectory` in the + next step, it may choose to overwrite the generated config version file + in :variable:`CMAKE_FIND_PACKAGE_REDIRECTS_DIR` with one that also sets + ``PACKAGE_VERSION``, and if appropriate, ``PACKAGE_VERSION_EXACT``. + The dependency may also write a ``<lowercaseName>-extra.cmake`` or + ``<name>Extra.cmake`` file to perform custom processing or define any + variables that their normal (installed) package config file would + otherwise usually define (many projects don't do any custom processing + or set any variables and therefore have no need to do this). + If required, the main project can write these files instead if the + dependency project doesn't do so. This allows the main project to + add missing details from older dependencies that haven't or can't be + updated to support this functionality. + See `Integrating With find_package()`_ for examples. + * If the top directory of the populated content contains a ``CMakeLists.txt`` file, call :command:`add_subdirectory` to add it to the main build. It is not an error for there to be no ``CMakeLists.txt`` file, which @@ -437,8 +516,10 @@ Variables A number of cache variables can influence the behavior where details from a :command:`FetchContent_Declare` call are used to populate content. -The variables are all intended for the developer to customize behavior and -should not normally be set by the project. + +.. note:: + All of these variables are intended for the developer to customize behavior. + They should not normally be set by the project. .. variable:: FETCHCONTENT_BASE_DIR @@ -481,8 +562,53 @@ should not normally be set by the project. This can speed up the configure stage, but not as much as :variable:`FETCHCONTENT_FULLY_DISCONNECTED`. It is ``OFF`` by default. -In addition to the above cache variables, the following cache variables are -also defined for each content name: +.. variable:: FETCHCONTENT_TRY_FIND_PACKAGE_MODE + + .. versionadded:: 3.24 + + This variable modifies the details that :command:`FetchContent_Declare` + records for a given dependency. While it ultimately controls the behavior + of :command:`FetchContent_MakeAvailable`, it is the variable's value when + :command:`FetchContent_Declare` is called that gets used. It makes no + difference what the variable is set to when + :command:`FetchContent_MakeAvailable` is called. Since the variable should + only be set by the user and not by projects directly, it will typically have + the same value throughout anyway, so this distinction is not usually + noticeable. + + ``FETCHCONTENT_TRY_FIND_PACKAGE_MODE`` ultimately controls whether + :command:`FetchContent_MakeAvailable` is allowed to call + :command:`find_package` to satisfy a dependency. The variable can be set + to one of the following values: + + ``OPT_IN`` + :command:`FetchContent_MakeAvailable` will only call + :command:`find_package` if the :command:`FetchContent_Declare` call + included a ``FIND_PACKAGE_ARGS`` keyword. This is also the default + behavior if ``FETCHCONTENT_TRY_FIND_PACKAGE_MODE`` is not set. + + ``ALWAYS`` + :command:`find_package` will be called by + :command:`FetchContent_MakeAvailable` regardless of whether the + :command:`FetchContent_Declare` call included a ``FIND_PACKAGE_ARGS`` + keyword or not. If no ``FIND_PACKAGE_ARGS`` keyword was given, the + behavior will be as though ``FIND_PACKAGE_ARGS`` had been provided, + with no additional arguments after it. + + ``NEVER`` + :command:`FetchContent_MakeAvailable` will not call + :command:`find_package`. Any ``FIND_PACKAGE_ARGS`` given to the + :command:`FetchContent_Declare` call will be ignored. + + As a special case, if the :variable:`FETCHCONTENT_SOURCE_DIR_<uppercaseName>` + variable has a non-empty value for a dependency, it is assumed that the + user is overriding all other methods of making that dependency available. + ``FETCHCONTENT_TRY_FIND_PACKAGE_MODE`` will have no effect on that + dependency and :command:`FetchContent_MakeAvailable` will not try to call + :command:`find_package` for it. + +In addition to the above, the following variables are also defined for each +content name: .. variable:: FETCHCONTENT_SOURCE_DIR_<uppercaseName> @@ -511,6 +637,9 @@ also defined for each content name: Examples ^^^^^^^^ +Typical Case +"""""""""""" + This first fairly straightforward example ensures that some popular testing frameworks are available to the main build: @@ -532,6 +661,135 @@ frameworks are available to the main build: # Catch2 will be available to the rest of the build FetchContent_MakeAvailable(googletest Catch2) +.. _FetchContent-find_package-integration: + +Integrating With find_package() +""""""""""""""""""""""""""""""" + +For the previous example, if the user wanted to try to find ``googletest`` +and ``Catch2`` via :command:`find_package` first before trying to download +and build them from source, they could set the +:variable:`FETCHCONTENT_TRY_FIND_PACKAGE_MODE` variable to ``ALWAYS``. +This would also affect any other calls to :command:`FetchContent_Declare` +throughout the project, which might not be acceptable. The behavior can be +enabled for just these two dependencies instead by adding ``FIND_PACKAGE_ARGS`` +to the declared details and leaving +:variable:`FETCHCONTENT_TRY_FIND_PACKAGE_MODE` unset, or set to ``OPT_IN``: + +.. code-block:: cmake + + include(FetchContent) + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 + FIND_PACKAGE_ARGS NAMES gtest + ) + FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG de6fe184a9ac1a06895cdd1c9b437f0a0bdf14ad # v2.13.4 + FIND_PACKAGE_ARGS + ) + + # This will try calling find_package() first for both dependencies + FetchContent_MakeAvailable(googletest Catch2) + +For ``Catch2``, no additional arguments to :command:`find_package` are needed, +so no additional arguments are provided after the ``FIND_PACKAGE_ARGS`` +keyword. For ``googletest``, its package is more commonly called ``gtest``, +so arguments are added to support it being found by that name. + +If the user wanted to disable :command:`FetchContent_MakeAvailable` from +calling :command:`find_package` for any dependency, even if it provided +``FIND_PACKAGE_ARGS`` in its declared details, they could set +:variable:`FETCHCONTENT_TRY_FIND_PACKAGE_MODE` to ``NEVER``. + +If the project wanted to indicate that these two dependencies should be +downloaded and built from source and that :command:`find_package` calls +should be redirected to use the built dependencies, the +``OVERRIDE_FIND_PACKAGE`` option should be used when declaring the content +details: + +.. code-block:: cmake + + include(FetchContent) + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 + OVERRIDE_FIND_PACKAGE + ) + FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG de6fe184a9ac1a06895cdd1c9b437f0a0bdf14ad # v2.13.4 + OVERRIDE_FIND_PACKAGE + ) + + # The following will automatically forward through to FetchContent_MakeAvailable() + find_package(googletest) + find_package(Catch2) + +CMake provides a FindGTest module which defines some variables that older +projects may use instead of linking to the imported targets. To support +those cases, we can provide an extras file. In keeping with the +"first to define, wins" philosophy of ``FetchContent``, we only write out +that file if something else hasn't already done so. + +.. code-block:: cmake + + FetchContent_MakeAvailable(googletest) + + if(NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletest-extras.cmake AND + NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletestExtras.cmake) + file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletest-extras.cmake + [=[ + if("${GTEST_LIBRARIES}" STREQUAL "" AND TARGET GTest::gtest) + set(GTEST_LIBRARIES GTest::gtest) + endif() + if("${GTEST_MAIN_LIBRARIES}" STREQUAL "" AND TARGET GTest::gtest_main) + set(GTEST_MAIN_LIBRARIES GTest::gtest_main) + endif() + if("${GTEST_BOTH_LIBRARIES}" STREQUAL "") + set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES}) + endif() + ]=] + endif() + +Projects will also likely be using ``find_package(GTest)`` rather than +``find_package(googletest)``, but it is possible to make use of the +:variable:`CMAKE_FIND_PACKAGE_REDIRECTS_DIR` area to pull in the latter as +a dependency of the former. This is likely to be sufficient to satisfy +a typical ``find_package(GTest)`` call. + +.. code-block:: cmake + + FetchContent_MakeAvailable(googletest) + + if(NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/gtest-config.cmake AND + NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/GTestConfig.cmake) + file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/gtest-config.cmake + [=[ + include(CMakeFindDependencyMacro) + find_dependency(googletest) + ]=] + endif() + + if(NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/gtest-config-version.cmake AND + NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/GTestConfigVersion.cmake) + file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/gtest-config-version.cmake + [=[ + include(${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletest-config-version.cmake OPTIONAL) + if(NOT PACKAGE_VERSION_COMPATIBLE) + include(${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletestConfigVersion.cmake OPTIONAL) + endif() + ]=] + endif() + +Overriding Where To Find CMakeLists.txt +""""""""""""""""""""""""""""""""""""""" + If the sub-project's ``CMakeLists.txt`` file is not at the top level of its source tree, the ``SOURCE_SUBDIR`` option can be used to tell ``FetchContent`` where to find it. The following example shows how to use that option and @@ -550,6 +808,9 @@ it into the main build: set(protobuf_BUILD_TESTS OFF) FetchContent_MakeAvailable(protobuf) +Complex Dependency Hierarchies +"""""""""""""""""""""""""""""" + In more complex project hierarchies, the dependency relationships can be more complicated. Consider a hierarchy where ``projA`` is the top level project and it depends directly on projects ``projB`` and ``projC``. Both ``projB`` and @@ -647,6 +908,8 @@ A few key points should be noted in the above: child projects. This saves repeating the same thing at each level of the project hierarchy unnecessarily. +Populating Content Without Adding It To The Build +""""""""""""""""""""""""""""""""""""""""""""""""" Projects don't always need to add the populated content to the build. Sometimes the project just wants to make the downloaded content available at @@ -682,7 +945,10 @@ named toolchain file relative to the build directory. Because the tarball has already been downloaded and unpacked by then, the toolchain file will be in place, even the very first time that ``cmake`` is run in the build directory. -Lastly, the following example demonstrates how one might download and unpack a +Populating Content In CMake Script Mode +""""""""""""""""""""""""""""""""""""""" + +This last example demonstrates how one might download and unpack a firmware tarball using CMake's :manual:`script mode <cmake(1)>`. The call to :command:`FetchContent_Populate` specifies all the content details and the unpacked firmware will be placed in a ``firmware`` directory below the @@ -722,19 +988,79 @@ current working directory. function(__FetchContent_declareDetails contentName) string(TOLOWER ${contentName} contentNameLower) - set(propertyName "_FetchContent_${contentNameLower}_savedDetails") - get_property(alreadyDefined GLOBAL PROPERTY ${propertyName} DEFINED) - if(NOT alreadyDefined) - define_property(GLOBAL PROPERTY ${propertyName} - BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" - FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + set(savedDetailsPropertyName "_FetchContent_${contentNameLower}_savedDetails") + get_property(alreadyDefined GLOBAL PROPERTY ${savedDetailsPropertyName} DEFINED) + if(alreadyDefined) + return() + endif() + + if("${FETCHCONTENT_TRY_FIND_PACKAGE_MODE}" STREQUAL "ALWAYS") + set(__tryFindPackage TRUE) + set(__tryFindPackageAllowed TRUE) + elseif("${FETCHCONTENT_TRY_FIND_PACKAGE_MODE}" STREQUAL "NEVER") + set(__tryFindPackage FALSE) + set(__tryFindPackageAllowed FALSE) + elseif("${FETCHCONTENT_TRY_FIND_PACKAGE_MODE}" STREQUAL "OPT_IN" OR + NOT DEFINED FETCHCONTENT_TRY_FIND_PACKAGE_MODE) + set(__tryFindPackage FALSE) + set(__tryFindPackageAllowed TRUE) + else() + message(FATAL_ERROR + "Unsupported value for FETCHCONTENT_TRY_FIND_PACKAGE_MODE: " + "${FETCHCONTENT_TRY_FIND_PACKAGE_MODE}" ) - set(__cmdArgs) - foreach(__item IN LISTS ARGN) - string(APPEND __cmdArgs " [==[${__item}]==]") - endforeach() + endif() + + set(__cmdArgs) + set(__findPackageArgs) + foreach(__item IN LISTS ARGN) + if(DEFINED __findPackageArgs) + # All remaining args are for find_package() + string(APPEND __findPackageArgs " [==[${__item}]==]") + continue() + endif() + + # Still processing non-find_package() args + if(__item STREQUAL "FIND_PACKAGE_ARGS") + if(__tryFindPackageAllowed) + set(__tryFindPackage TRUE) + endif() + # All arguments after this keyword are for find_package(). Define the + # variable but with an empty value initially. This allows us to check + # at the start of the loop whether to store remaining items in this + # variable or not. Note that there could be no more args, which is still + # a valid case because we automatically provide ${contentName} as the + # package name and there may not need to be any further arguments. + set(__findPackageArgs "") + continue() # Don't store this item + elseif(__item STREQUAL "OVERRIDE_FIND_PACKAGE") + set(__tryFindPackageAllowed FALSE) + # Define a separate dedicated property for find_package() to check + # in its implementation. This will be a placeholder until FetchContent + # actually does the population. After that, we will have created a + # stand-in config file that find_package() will pick up instead. + set(propertyName "_FetchContent_${contentNameLower}_override_find_package") + define_property(GLOBAL PROPERTY ${propertyName}) + set_property(GLOBAL PROPERTY ${propertyName} TRUE) + endif() + + string(APPEND __cmdArgs " [==[${__item}]==]") + endforeach() + + define_property(GLOBAL PROPERTY ${savedDetailsPropertyName}) + cmake_language(EVAL CODE + "set_property(GLOBAL PROPERTY ${savedDetailsPropertyName} ${__cmdArgs})" + ) + + if(__tryFindPackage AND __tryFindPackageAllowed) + set(propertyName "_FetchContent_${contentNameLower}_find_package_args") + define_property(GLOBAL PROPERTY ${propertyName}) + if(NOT QUIET IN_LIST __findPackageArgs) + list(INSERT __findPackageArgs 0 QUIET) + endif() cmake_language(EVAL CODE - "set_property(GLOBAL PROPERTY ${propertyName} ${__cmdArgs})") + "set_property(GLOBAL PROPERTY ${propertyName} ${__findPackageArgs})" + ) endif() endfunction() @@ -763,6 +1089,15 @@ endfunction() # SOURCE_DIR and BUILD_DIR. function(FetchContent_Declare contentName) + # Always check this even if we won't save these details. + # This helps projects catch errors earlier. + if("OVERRIDE_FIND_PACKAGE" IN_LIST ARGN AND "FIND_PACKAGE_ARGS" IN_LIST ARGN) + message(FATAL_ERROR + "Cannot specify both OVERRIDE_FIND_PACKAGE and FIND_PACKAGE_ARGS " + "when declaring details for ${contentName}" + ) + endif() + set(options "") set(oneValueArgs SVN_REPOSITORY) set(multiValueArgs "") @@ -810,35 +1145,35 @@ endfunction() # The setter also records the source and binary dirs used. #======================================================================= -# Internal use, projects must not call this directly. It is -# intended for use by the FetchContent_Populate() function to +# Internal use, projects must not call this directly. It is intended +# for use by things like the FetchContent_Populate() function to # record when FetchContent_Populate() is called for a particular # content name. -function(__FetchContent_setPopulated contentName sourceDir binaryDir) +function(__FetchContent_setPopulated contentName) + + cmake_parse_arguments(PARSE_ARGV 1 arg + "" + "SOURCE_DIR;BINARY_DIR" + "" + ) + if(NOT "${arg_UNPARSED_ARGUMENTS}" STREQUAL "") + message(FATAL_ERROR "Unsupported arguments: ${arg_UNPARSED_ARGUMENTS}") + endif() string(TOLOWER ${contentName} contentNameLower) set(prefix "_FetchContent_${contentNameLower}") set(propertyName "${prefix}_sourceDir") - define_property(GLOBAL PROPERTY ${propertyName} - BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" - FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" - ) - set_property(GLOBAL PROPERTY ${propertyName} ${sourceDir}) + define_property(GLOBAL PROPERTY ${propertyName}) + set_property(GLOBAL PROPERTY ${propertyName} "${arg_SOURCE_DIR}") set(propertyName "${prefix}_binaryDir") - define_property(GLOBAL PROPERTY ${propertyName} - BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" - FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" - ) - set_property(GLOBAL PROPERTY ${propertyName} ${binaryDir}) + define_property(GLOBAL PROPERTY ${propertyName}) + set_property(GLOBAL PROPERTY ${propertyName} "${arg_BINARY_DIR}") set(propertyName "${prefix}_populated") - define_property(GLOBAL PROPERTY ${propertyName} - BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" - FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" - ) - set_property(GLOBAL PROPERTY ${propertyName} True) + define_property(GLOBAL PROPERTY ${propertyName}) + set_property(GLOBAL PROPERTY ${propertyName} TRUE) endfunction() @@ -1134,7 +1469,15 @@ function(FetchContent_Populate contentName) # populated this content before in case the caller forgot to check. FetchContent_GetProperties(${contentName}) if(${contentNameLower}_POPULATED) - message(FATAL_ERROR "Content ${contentName} already populated in ${${contentNameLower}_SOURCE_DIR}") + if("${${contentNameLower}_SOURCE_DIR}" STREQUAL "") + message(FATAL_ERROR + "Content ${contentName} already populated by find_package()" + ) + else() + message(FATAL_ERROR + "Content ${contentName} already populated in ${${contentNameLower}_SOURCE_DIR}" + ) + endif() endif() __FetchContent_getSavedDetails(${contentName} contentDetails) @@ -1212,7 +1555,9 @@ function(FetchContent_Populate contentName) set(__detailsQuoted) foreach(__item IN LISTS contentDetails) - string(APPEND __detailsQuoted " [==[${__item}]==]") + if(NOT __item STREQUAL "OVERRIDE_FIND_PACKAGE") + string(APPEND __detailsQuoted " [==[${__item}]==]") + endif() endforeach() cmake_language(EVAL CODE " __FetchContent_directPopulate( @@ -1232,8 +1577,8 @@ function(FetchContent_Populate contentName) __FetchContent_setPopulated( ${contentName} - ${${contentNameLower}_SOURCE_DIR} - ${${contentNameLower}_BINARY_DIR} + SOURCE_DIR "${${contentNameLower}_SOURCE_DIR}" + BINARY_DIR "${${contentNameLower}_BINARY_DIR}" ) # Pass variables back to the caller. The variables passed back here @@ -1245,6 +1590,53 @@ function(FetchContent_Populate contentName) endfunction() +function(__FetchContent_setupFindPackageRedirection contentName) + + __FetchContent_getSavedDetails(${contentName} contentDetails) + + string(TOLOWER ${contentName} contentNameLower) + get_property(wantFindPackage GLOBAL PROPERTY + _FetchContent_${contentNameLower}_find_package_args + DEFINED + ) + + if(NOT wantFindPackage AND NOT OVERRIDE_FIND_PACKAGE IN_LIST contentDetails) + # No find_package() redirection allowed + return() + endif() + + # We write out dep-config.cmake and dep-config-version.cmake file name + # forms here because they are forced to lowercase. FetchContent + # dependency names are case-insensitive, but find_package() config files + # are only case-insensitive for the -config and -config-version forms, + # not the Config and ConfigVersion forms. + set(inFileDir ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/FetchContent) + set(configFilePrefix1 "${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/${contentName}Config") + set(configFilePrefix2 "${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/${contentNameLower}-config") + if(NOT EXISTS "${configFilePrefix1}.cmake" AND + NOT EXISTS "${configFilePrefix2}.cmake") + configure_file(${inFileDir}/package-config.cmake.in + "${configFilePrefix2}.cmake" @ONLY + ) + endif() + if(NOT EXISTS "${configFilePrefix1}Version.cmake" AND + NOT EXISTS "${configFilePrefix2}-version.cmake") + configure_file(${inFileDir}/package-config-version.cmake.in + "${configFilePrefix2}-version.cmake" @ONLY + ) + endif() + + # Now that we've created the redirected package config files, prevent + # find_package() from delegating to FetchContent and let it find these + # config files through its normal processing. + set(propertyName "${prefix}_override_find_package") + set(GLOBAL PROPERTY ${propertyName} FALSE) + set(${contentName}_DIR "${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}" + CACHE INTERNAL "Redirected by FetchContent" + ) + +endfunction() + # Arguments are assumed to be the names of dependencies that have been # declared previously and should be populated. It is not an error if # any of them have already been populated (they will just be skipped in @@ -1255,9 +1647,48 @@ macro(FetchContent_MakeAvailable) foreach(__cmake_contentName IN ITEMS ${ARGV}) string(TOLOWER ${__cmake_contentName} __cmake_contentNameLower) + + # If user specified FETCHCONTENT_SOURCE_DIR_... for this dependency, that + # overrides everything else and we shouldn't try to use find_package(). + string(TOUPPER ${__cmake_contentName} __cmake_contentNameUpper) + if("${FETCHCONTENT_SOURCE_DIR_${__cmake_contentNameUpper}}" STREQUAL "") + # Check if we've been asked to try find_package() first, even if we + # have already populated this dependency. If we previously tried to + # use find_package() for this and it succeeded, those things might + # no longer be in scope, so we have to do it again. + set(__cmake_fpArgsPropName "_FetchContent_${__cmake_contentNameLower}_find_package_args") + get_property(__cmake_haveFpArgs GLOBAL PROPERTY ${__cmake_fpArgsPropName} DEFINED) + if(__cmake_haveFpArgs) + message(VERBOSE "Trying find_package(${__cmake_contentName} ...) before FetchContent") + get_property(__cmake_fpArgs GLOBAL PROPERTY ${__cmake_fpArgsPropName}) + + # This call could lead to FetchContent_MakeAvailable() being called for + # a nested dependency and it may occur in the current variable scope. + # We have to save/restore the variables we need to preserve. + list(APPEND __cmake_fcCurrentNameStack + ${__cmake_contentName} + ${__cmake_contentNameLower} + ) + find_package(${__cmake_contentName} ${__cmake_fpArgs}) + list(POP_BACK __cmake_fcCurrentNameStack + __cmake_contentNameLower + __cmake_contentName + ) + + if(${__cmake_contentName}_FOUND) + set(${__cmake_contentNameLower}_SOURCE_DIR "") + set(${__cmake_contentNameLower}_BINARY_DIR "") + set(${__cmake_contentNameLower}_POPULATED TRUE) + __FetchContent_setPopulated(${__cmake_contentName}) + continue() + endif() + endif() + endif() + FetchContent_GetProperties(${__cmake_contentName}) if(NOT ${__cmake_contentNameLower}_POPULATED) FetchContent_Populate(${__cmake_contentName}) + __FetchContent_setupFindPackageRedirection(${__cmake_contentName}) # Only try to call add_subdirectory() if the populated content # can be treated that way. Protecting the call with the check @@ -1283,13 +1714,13 @@ macro(FetchContent_MakeAvailable) endif() unset(__cmake_srcdir) + unset(__cmake_contentDetails) + unset(__cmake_arg_SOURCE_SUBDIR) endif() endforeach() # clear local variables to prevent leaking into the caller's scope unset(__cmake_contentName) unset(__cmake_contentNameLower) - unset(__cmake_contentDetails) - unset(__cmake_arg_SOURCE_SUBDIR) endmacro() diff --git a/Modules/FetchContent/package-config-version.cmake.in b/Modules/FetchContent/package-config-version.cmake.in new file mode 100644 index 0000000..7f19094 --- /dev/null +++ b/Modules/FetchContent/package-config-version.cmake.in @@ -0,0 +1,5 @@ +# Automatically generated by CMake's FetchContent module. +# Do not edit this file, it will be regenerated every time CMake runs. + +# Version not available, assuming it is compatible +set(PACKAGE_VERSION_COMPATIBLE TRUE) diff --git a/Modules/FetchContent/package-config.cmake.in b/Modules/FetchContent/package-config.cmake.in new file mode 100644 index 0000000..c3b64c9 --- /dev/null +++ b/Modules/FetchContent/package-config.cmake.in @@ -0,0 +1,11 @@ +# Automatically generated by CMake's FetchContent module. +# Do not edit this file, it will be regenerated every time CMake runs. + +# Projects or the dependencies themselves can provide the following files. +# The files should define any additional commands or variables that the +# dependency would normally provide but which won't be available globally +# if the dependency is brought into the build via FetchContent instead. +# For dependencies that only provide imported targets and no commands, +# these typically won't be needed. +include("${CMAKE_CURRENT_LIST_DIR}/@contentNameLower@-extra.cmake" OPTIONAL) +include("${CMAKE_CURRENT_LIST_DIR}/@contentName@Extra.cmake" OPTIONAL) diff --git a/Modules/FindJNI.cmake b/Modules/FindJNI.cmake index 96f136a..e93b91e 100644 --- a/Modules/FindJNI.cmake +++ b/Modules/FindJNI.cmake @@ -234,46 +234,41 @@ endif() if (WIN32) set (_JNI_HINTS) - execute_process(COMMAND REG QUERY HKLM\\SOFTWARE\\JavaSoft\\JDK - RESULT_VARIABLE _JNI_RESULT - OUTPUT_VARIABLE _JNI_VERSIONS - ERROR_QUIET) - if (NOT _JNI_RESULT) - string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\JDK\\\\[0-9.]+" _JNI_VERSIONS "${_JNI_VERSIONS}") - if (_JNI_VERSIONS) - # sort versions. Most recent first - ## handle version 9 apart from other versions to get correct ordering - set (_JNI_V9 ${_JNI_VERSIONS}) - list (FILTER _JNI_VERSIONS EXCLUDE REGEX "JDK\\\\9") - list (SORT _JNI_VERSIONS) - list (REVERSE _JNI_VERSIONS) - list (FILTER _JNI_V9 INCLUDE REGEX "JDK\\\\9") - list (SORT _JNI_V9) - list (REVERSE _JNI_V9) - list (APPEND _JNI_VERSIONS ${_JNI_V9}) - foreach (_JNI_HINT IN LISTS _JNI_VERSIONS) - list(APPEND _JNI_HINTS "[${_JNI_HINT};JavaHome]") - endforeach() + macro (_JNI_GET_INSTALLED_VERSIONS _KIND) + execute_process(COMMAND REG QUERY "HKLM\\SOFTWARE\\JavaSoft\\${_KIND}" + RESULT_VARIABLE _JAVA_RESULT + OUTPUT_VARIABLE _JAVA_VERSIONS + ERROR_QUIET) + if (NOT _JAVA_RESULT) + string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\[0-9._]+" _JNI_VERSIONS "${_JAVA_VERSIONS}") + string (REGEX REPLACE "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\([0-9._]+)" "\\1" _JNI_VERSIONS "${_JNI_VERSIONS}") + if (_JNI_VERSIONS) + # sort versions. Most recent first + list (SORT _JNI_VERSIONS COMPARE NATURAL ORDER DESCENDING) + foreach (_JNI_VERSION IN LISTS _JNI_VERSIONS) + string(REPLACE "_" "." _JNI_CMAKE_VERSION "${_JNI_VERSION}") + if (JNI_FIND_VERSION_EXACT + AND NOT _JNI_CMAKE_VERSION MATCHES "^${JNI_FIND_VERSION}") + continue() + endif() + if (DEFINED JNI_FIND_VERSION AND _JNI_CMAKE_VERSION VERSION_LESS JNI_FIND_VERSION) + break() + endif() + list(APPEND _JNI_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\${_KIND}\\${_JNI_VERSION};JavaHome]") + endforeach() + endif() endif() - endif() + endmacro() + + # for version 9 and upper + _JNI_GET_INSTALLED_VERSIONS("JDK") + + # for versions older than 9 + _JNI_GET_INSTALLED_VERSIONS("Java Development Kit") foreach (_JNI_HINT IN LISTS _JNI_HINTS) list(APPEND JAVA_AWT_LIBRARY_DIRECTORIES "${_JNI_HINT}/lib") endforeach() - - get_filename_component(java_install_version - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit;CurrentVersion]" NAME) - - list(APPEND JAVA_AWT_LIBRARY_DIRECTORIES - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.9;JavaHome]/lib" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.8;JavaHome]/lib" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.7;JavaHome]/lib" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.6;JavaHome]/lib" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.5;JavaHome]/lib" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.4;JavaHome]/lib" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.3;JavaHome]/lib" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\${java_install_version};JavaHome]/lib" - ) endif() set(_JNI_JAVA_DIRECTORIES_BASE @@ -357,16 +352,6 @@ if (WIN32) foreach (_JNI_HINT IN LISTS _JNI_HINTS) list(APPEND JAVA_AWT_INCLUDE_DIRECTORIES "${_JNI_HINT}/include") endforeach() - list(APPEND JAVA_AWT_INCLUDE_DIRECTORIES - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.9;JavaHome]/include" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.8;JavaHome]/include" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.7;JavaHome]/include" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.6;JavaHome]/include" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.5;JavaHome]/include" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.4;JavaHome]/include" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.3;JavaHome]/include" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\${java_install_version};JavaHome]/include" - ) endif() JAVA_APPEND_LIBRARY_DIRECTORIES(JAVA_AWT_INCLUDE_DIRECTORIES diff --git a/Modules/FindJava.cmake b/Modules/FindJava.cmake index 4f0e0fe..7a95ef5 100644 --- a/Modules/FindJava.cmake +++ b/Modules/FindJava.cmake @@ -90,50 +90,35 @@ if(_JAVA_HOME) endif() if (WIN32) macro (_JAVA_GET_INSTALLED_VERSIONS _KIND) - execute_process(COMMAND REG QUERY HKLM\\SOFTWARE\\JavaSoft\\${_KIND} + execute_process(COMMAND REG QUERY "HKLM\\SOFTWARE\\JavaSoft\\${_KIND}" RESULT_VARIABLE _JAVA_RESULT OUTPUT_VARIABLE _JAVA_VERSIONS ERROR_QUIET) if (NOT _JAVA_RESULT) - string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\[0-9.]+" _JAVA_VERSIONS "${_JAVA_VERSIONS}") + string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\[0-9._]+" _JAVA_VERSIONS "${_JAVA_VERSIONS}") + string (REGEX REPLACE "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\([0-9._]+)" "\\1" _JAVA_VERSIONS "${_JAVA_VERSIONS}") if (_JAVA_VERSIONS) # sort versions. Most recent first - ## handle version 9 apart from other versions to get correct ordering - set (_JAVA_V9 ${_JAVA_VERSIONS}) - list (FILTER _JAVA_VERSIONS EXCLUDE REGEX "${_KIND}\\\\9") - list (SORT _JAVA_VERSIONS) - list (REVERSE _JAVA_VERSIONS) - list (FILTER _JAVA_V9 INCLUDE REGEX "${_KIND}\\\\9") - list (SORT _JAVA_V9) - list (REVERSE _JAVA_V9) - list (APPEND _JAVA_VERSIONS ${_JAVA_V9}) - foreach (_JAVA_HINT IN LISTS _JAVA_VERSIONS) - list(APPEND _JAVA_HINTS "[${_JAVA_HINT};JavaHome]/bin") + list (SORT _JAVA_VERSIONS COMPARE NATURAL ORDER DESCENDING) + foreach (_JAVA_VERSION IN LISTS _JAVA_VERSIONS) + string(REPLACE "_" "." _JAVA_CMAKE_VERSION "${_JAVA_VERSION}") + if (Java_FIND_VERSION_EXACT + AND NOT _JAVA_CMAKE_VERSION MATCHES "^${Java_FIND_VERSION}") + continue() + endif() + list(APPEND _JAVA_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\${_KIND}\\${_JAVA_VERSION};JavaHome]/bin") endforeach() endif() endif() endmacro() - # search for installed versions for version 9 and upper + # for version 9 and upper _JAVA_GET_INSTALLED_VERSIONS("JDK") _JAVA_GET_INSTALLED_VERSIONS("JRE") - list(APPEND _JAVA_HINTS - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.9;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.8;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.7;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.6;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.5;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.4;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.3;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.9;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.8;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.7;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.6;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.5;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.4;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.3;JavaHome]/bin" - ) + # for versions older than 9 + _JAVA_GET_INSTALLED_VERSIONS("Java Development Kit") + _JAVA_GET_INSTALLED_VERSIONS("Java Runtime Environment") endif() # Hard-coded guesses should still go in PATHS. This ensures that the user @@ -336,13 +321,13 @@ else() find_package_handle_standard_args(Java REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE - VERSION_VAR Java_VERSION_STRING + VERSION_VAR Java_VERSION ) else() find_package_handle_standard_args(Java REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE Java_JAVADOC_EXECUTABLE - VERSION_VAR Java_VERSION_STRING + VERSION_VAR Java_VERSION ) endif() endif() diff --git a/Modules/Platform/Linux-OpenWatcom-C.cmake b/Modules/Platform/Linux-OpenWatcom-C.cmake index 383349a..7236c74 100644 --- a/Modules/Platform/Linux-OpenWatcom-C.cmake +++ b/Modules/Platform/Linux-OpenWatcom-C.cmake @@ -1 +1,2 @@ include(Platform/Linux-OpenWatcom) +__linux_open_watcom(C) diff --git a/Modules/Platform/Linux-OpenWatcom-CXX.cmake b/Modules/Platform/Linux-OpenWatcom-CXX.cmake index 383349a..a5f386b 100644 --- a/Modules/Platform/Linux-OpenWatcom-CXX.cmake +++ b/Modules/Platform/Linux-OpenWatcom-CXX.cmake @@ -1 +1,2 @@ include(Platform/Linux-OpenWatcom) +__linux_open_watcom(CXX) diff --git a/Modules/Platform/Linux-OpenWatcom.cmake b/Modules/Platform/Linux-OpenWatcom.cmake index 5b4e995..678d373 100644 --- a/Modules/Platform/Linux-OpenWatcom.cmake +++ b/Modules/Platform/Linux-OpenWatcom.cmake @@ -10,6 +10,14 @@ string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " system linux opt noextension") string(APPEND CMAKE_MODULE_LINKER_FLAGS_INIT " system linux") string(APPEND CMAKE_SHARED_LINKER_FLAGS_INIT " system linux") +cmake_policy(GET CMP0136 __LINUX_WATCOM_CMP0136) +if(__LINUX_WATCOM_CMP0136 STREQUAL "NEW") + set(CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT "SingleThreaded") +else() + set(CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT "") +endif() +unset(__LINUX_WATCOM_CMP0136) + # single/multi-threaded /-bm # default is setup for single-threaded libraries string(APPEND CMAKE_C_FLAGS_INIT " -bt=linux") @@ -23,3 +31,8 @@ if(CMAKE_CROSSCOMPILING) set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES $ENV{WATCOM}/lh) endif() endif() + +macro(__linux_open_watcom lang) + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_SingleThreaded "") + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_MultiThreaded -bm) +endmacro() diff --git a/Modules/Platform/OS2-OpenWatcom-C.cmake b/Modules/Platform/OS2-OpenWatcom-C.cmake index 21a4d9e..a6a6b78 100644 --- a/Modules/Platform/OS2-OpenWatcom-C.cmake +++ b/Modules/Platform/OS2-OpenWatcom-C.cmake @@ -1 +1,2 @@ include(Platform/OS2-OpenWatcom) +__os2_open_watcom(C) diff --git a/Modules/Platform/OS2-OpenWatcom-CXX.cmake b/Modules/Platform/OS2-OpenWatcom-CXX.cmake index 21a4d9e..846bb29 100644 --- a/Modules/Platform/OS2-OpenWatcom-CXX.cmake +++ b/Modules/Platform/OS2-OpenWatcom-CXX.cmake @@ -1 +1,2 @@ include(Platform/OS2-OpenWatcom) +__os2_open_watcom(CXX) diff --git a/Modules/Platform/OS2-OpenWatcom.cmake b/Modules/Platform/OS2-OpenWatcom.cmake index 998fb9f..720b953 100644 --- a/Modules/Platform/OS2-OpenWatcom.cmake +++ b/Modules/Platform/OS2-OpenWatcom.cmake @@ -16,6 +16,14 @@ endif() set(CMAKE_C_COMPILE_OPTIONS_DLL "-bd") # Note: This variable is a ';' separated list set(CMAKE_SHARED_LIBRARY_C_FLAGS "-bd") # ... while this is a space separated string. +cmake_policy(GET CMP0136 __OS2_WATCOM_CMP0136) +if(__OS2_WATCOM_CMP0136 STREQUAL "NEW") + set(CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT "SingleThreaded") +else() + set(CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT "") +endif() +unset(__OS2_WATCOM_CMP0136) + string(APPEND CMAKE_C_FLAGS_INIT " -bt=os2") string(APPEND CMAKE_CXX_FLAGS_INIT " -bt=os2 -xs") @@ -33,3 +41,10 @@ if(NOT CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES) set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES $ENV{WATCOM}/h $ENV{WATCOM}/h/os2) endif() endif() + +macro(__os2_open_watcom lang) + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_SingleThreaded "") + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_SingleThreadedDLL -br) + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_MultiThreaded -bm) + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_MultiThreadedDLL -bm -br) +endmacro() diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake index 7600c8d..82c4383 100644 --- a/Modules/Platform/Windows-Clang.cmake +++ b/Modules/Platform/Windows-Clang.cmake @@ -39,6 +39,7 @@ macro(__windows_compiler_clang_gnu lang) set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP) set(CMAKE_${lang}_LINKER_MANIFEST_FLAG " -Xlinker /MANIFESTINPUT:") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror") if("${CMAKE_${lang}_SIMULATE_VERSION}" MATCHES "^([0-9]+)\\.([0-9]+)") math(EXPR MSVC_VERSION "${CMAKE_MATCH_1}*100 + ${CMAKE_MATCH_2}") @@ -189,6 +190,7 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC" macro(__windows_compiler_clang_base lang) set(_COMPILE_${lang} "${_COMPILE_${lang}_MSVC}") __windows_compiler_msvc(${lang}) + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-WX") set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-imsvc ") endmacro() else() diff --git a/Modules/Platform/Windows-OpenWatcom.cmake b/Modules/Platform/Windows-OpenWatcom.cmake index 19bcb97..657a923 100644 --- a/Modules/Platform/Windows-OpenWatcom.cmake +++ b/Modules/Platform/Windows-OpenWatcom.cmake @@ -14,11 +14,20 @@ set(CMAKE_SHARED_LIBRARY_C_FLAGS "-bd") # ... while this is a space separated st set(CMAKE_RC_COMPILER "rc" ) -# single/multi-threaded /-bm -# static/DLL run-time libraries /-br -# default is setup for multi-threaded + DLL run-time libraries -string(APPEND CMAKE_C_FLAGS_INIT " -bt=nt -dWIN32 -br -bm") -string(APPEND CMAKE_CXX_FLAGS_INIT " -bt=nt -xs -dWIN32 -br -bm") +cmake_policy(GET CMP0136 __WINDOWS_WATCOM_CMP0136) +if(__WINDOWS_WATCOM_CMP0136 STREQUAL "NEW") + set(CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT "MultiThreadedDLL") + set(_br_bm "") +else() + set(CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT "") + set(_br_bm "-br -bm") +endif() + +string(APPEND CMAKE_C_FLAGS_INIT " -bt=nt -dWIN32 ${_br_bm}") +string(APPEND CMAKE_CXX_FLAGS_INIT " -bt=nt -xs -dWIN32 ${_br_bm}") + +unset(__WINDOWS_WATCOM_CMP0136) +unset(_br_bm) if(CMAKE_CROSSCOMPILING) if(NOT CMAKE_C_STANDARD_INCLUDE_DIRECTORIES) @@ -32,4 +41,9 @@ endif() macro(__windows_open_watcom lang) set(CMAKE_${lang}_CREATE_WIN32_EXE "system nt_win") set(CMAKE_${lang}_CREATE_CONSOLE_EXE "system nt") + + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_SingleThreaded "") + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_SingleThreadedDLL -br) + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_MultiThreaded -bm) + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_MultiThreadedDLL -bm -br) endmacro() diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index f607e15..2b65e0a 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 23) -set(CMake_VERSION_PATCH 20220506) +set(CMake_VERSION_PATCH 20220510) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CTest/cmCTestResourceSpec.cxx b/Source/CTest/cmCTestResourceSpec.cxx index 101dc2c..142b07d 100644 --- a/Source/CTest/cmCTestResourceSpec.cxx +++ b/Source/CTest/cmCTestResourceSpec.cxx @@ -19,6 +19,8 @@ #include "cmJSONHelpers.h" namespace { +using JSONHelperBuilder = + cmJSONHelperBuilder<cmCTestResourceSpec::ReadFileResult>; const cmsys::RegularExpression IdentifierRegex{ "^[a-z_][a-z0-9_]*$" }; const cmsys::RegularExpression IdRegex{ "^[a-z0-9_]+$" }; @@ -34,21 +36,19 @@ struct TopVersion }; auto const VersionFieldHelper = - cmJSONIntHelper<cmCTestResourceSpec::ReadFileResult>( - cmCTestResourceSpec::ReadFileResult::READ_OK, - cmCTestResourceSpec::ReadFileResult::INVALID_VERSION); + JSONHelperBuilder::Int(cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_VERSION); -auto const VersionHelper = - cmJSONRequiredHelper<Version, cmCTestResourceSpec::ReadFileResult>( - cmCTestResourceSpec::ReadFileResult::NO_VERSION, - cmJSONObjectHelper<Version, cmCTestResourceSpec::ReadFileResult>( - cmCTestResourceSpec::ReadFileResult::READ_OK, - cmCTestResourceSpec::ReadFileResult::INVALID_VERSION) - .Bind("major"_s, &Version::Major, VersionFieldHelper) - .Bind("minor"_s, &Version::Minor, VersionFieldHelper)); +auto const VersionHelper = JSONHelperBuilder::Required<Version>( + cmCTestResourceSpec::ReadFileResult::NO_VERSION, + JSONHelperBuilder::Object<Version>( + cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_VERSION) + .Bind("major"_s, &Version::Major, VersionFieldHelper) + .Bind("minor"_s, &Version::Minor, VersionFieldHelper)); auto const RootVersionHelper = - cmJSONObjectHelper<TopVersion, cmCTestResourceSpec::ReadFileResult>( + JSONHelperBuilder::Object<TopVersion>( cmCTestResourceSpec::ReadFileResult::READ_OK, cmCTestResourceSpec::ReadFileResult::INVALID_ROOT) .Bind("version"_s, &TopVersion::Version, VersionHelper, false); @@ -56,7 +56,7 @@ auto const RootVersionHelper = cmCTestResourceSpec::ReadFileResult ResourceIdHelper(std::string& out, const Json::Value* value) { - auto result = cmJSONStringHelper( + auto result = JSONHelperBuilder::String( cmCTestResourceSpec::ReadFileResult::READ_OK, cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE)(out, value); if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) { @@ -70,27 +70,24 @@ cmCTestResourceSpec::ReadFileResult ResourceIdHelper(std::string& out, } auto const ResourceHelper = - cmJSONObjectHelper<cmCTestResourceSpec::Resource, - cmCTestResourceSpec::ReadFileResult>( + JSONHelperBuilder::Object<cmCTestResourceSpec::Resource>( cmCTestResourceSpec::ReadFileResult::READ_OK, cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE) .Bind("id"_s, &cmCTestResourceSpec::Resource::Id, ResourceIdHelper) .Bind("slots"_s, &cmCTestResourceSpec::Resource::Capacity, - cmJSONUIntHelper( + JSONHelperBuilder::UInt( cmCTestResourceSpec::ReadFileResult::READ_OK, cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE, 1), false); auto const ResourceListHelper = - cmJSONVectorHelper<cmCTestResourceSpec::Resource, - cmCTestResourceSpec::ReadFileResult>( + JSONHelperBuilder::Vector<cmCTestResourceSpec::Resource>( cmCTestResourceSpec::ReadFileResult::READ_OK, cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE_TYPE, ResourceHelper); auto const ResourceMapHelper = - cmJSONMapFilterHelper<std::vector<cmCTestResourceSpec::Resource>, - cmCTestResourceSpec::ReadFileResult>( + JSONHelperBuilder::MapFilter<std::vector<cmCTestResourceSpec::Resource>>( cmCTestResourceSpec::ReadFileResult::READ_OK, cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, ResourceListHelper, [](const std::string& key) -> bool { @@ -98,7 +95,7 @@ auto const ResourceMapHelper = return IdentifierRegex.find(key.c_str(), match); }); -auto const SocketSetHelper = cmJSONVectorHelper< +auto const SocketSetHelper = JSONHelperBuilder::Vector< std::map<std::string, std::vector<cmCTestResourceSpec::Resource>>>( cmCTestResourceSpec::ReadFileResult::READ_OK, cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, ResourceMapHelper); @@ -125,16 +122,14 @@ cmCTestResourceSpec::ReadFileResult SocketHelper( } auto const LocalRequiredHelper = - cmJSONRequiredHelper<cmCTestResourceSpec::Socket, - cmCTestResourceSpec::ReadFileResult>( + JSONHelperBuilder::Required<cmCTestResourceSpec::Socket>( cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, SocketHelper); -auto const RootHelper = - cmJSONObjectHelper<cmCTestResourceSpec, cmCTestResourceSpec::ReadFileResult>( - cmCTestResourceSpec::ReadFileResult::READ_OK, - cmCTestResourceSpec::ReadFileResult::INVALID_ROOT) - .Bind("local", &cmCTestResourceSpec::LocalSocket, LocalRequiredHelper, - false); +auto const RootHelper = JSONHelperBuilder::Object<cmCTestResourceSpec>( + cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_ROOT) + .Bind("local", &cmCTestResourceSpec::LocalSocket, + LocalRequiredHelper, false); } cmCTestResourceSpec::ReadFileResult cmCTestResourceSpec::ReadFromJSONFile( diff --git a/Source/cmCMakePresetsGraphReadJSON.cxx b/Source/cmCMakePresetsGraphReadJSON.cxx index 0d3a91f..d11e839 100644 --- a/Source/cmCMakePresetsGraphReadJSON.cxx +++ b/Source/cmCMakePresetsGraphReadJSON.cxx @@ -31,6 +31,7 @@ using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset; using BuildPreset = cmCMakePresetsGraph::BuildPreset; using TestPreset = cmCMakePresetsGraph::TestPreset; using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy; +using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>; constexpr int MIN_VERSION = 1; constexpr int MAX_VERSION = 5; @@ -59,29 +60,26 @@ std::unique_ptr<cmCMakePresetsGraphInternal::NotCondition> InvertCondition( return retval; } -auto const ConditionStringHelper = cmJSONStringHelper<ReadFileResult>( +auto const ConditionStringHelper = JSONHelperBuilder::String( ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION); -auto const ConditionBoolHelper = cmJSONBoolHelper<ReadFileResult>( +auto const ConditionBoolHelper = JSONHelperBuilder::Bool( ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION); -auto const ConditionStringListHelper = - cmJSONVectorHelper<std::string, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, - ConditionStringHelper); +auto const ConditionStringListHelper = JSONHelperBuilder::Vector<std::string>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, + ConditionStringHelper); auto const ConstConditionHelper = - cmJSONObjectHelper<cmCMakePresetsGraphInternal::ConstCondition, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_CONDITION, false) + JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::ConstCondition>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) .Bind("value"_s, &cmCMakePresetsGraphInternal::ConstCondition::Value, ConditionBoolHelper, true); auto const EqualsConditionHelper = - cmJSONObjectHelper<cmCMakePresetsGraphInternal::EqualsCondition, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_CONDITION, false) + JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::EqualsCondition>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) .Bind("lhs"_s, &cmCMakePresetsGraphInternal::EqualsCondition::Lhs, ConditionStringHelper, true) @@ -89,9 +87,8 @@ auto const EqualsConditionHelper = ConditionStringHelper, true); auto const InListConditionHelper = - cmJSONObjectHelper<cmCMakePresetsGraphInternal::InListCondition, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_CONDITION, false) + JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::InListCondition>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) .Bind("string"_s, &cmCMakePresetsGraphInternal::InListCondition::String, ConditionStringHelper, true) @@ -99,9 +96,8 @@ auto const InListConditionHelper = ConditionStringListHelper, true); auto const MatchesConditionHelper = - cmJSONObjectHelper<cmCMakePresetsGraphInternal::MatchesCondition, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_CONDITION, false) + JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::MatchesCondition>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) .Bind("string"_s, &cmCMakePresetsGraphInternal::MatchesCondition::String, ConditionStringHelper, true) @@ -113,23 +109,20 @@ ReadFileResult SubConditionHelper( const Json::Value* value); auto const ListConditionVectorHelper = - cmJSONVectorHelper<std::unique_ptr<cmCMakePresetsGraph::Condition>, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_CONDITION, - SubConditionHelper); + JSONHelperBuilder::Vector<std::unique_ptr<cmCMakePresetsGraph::Condition>>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, + SubConditionHelper); auto const AnyAllOfConditionHelper = - cmJSONObjectHelper<cmCMakePresetsGraphInternal::AnyAllOfCondition, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_CONDITION, false) + JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::AnyAllOfCondition>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) .Bind("conditions"_s, &cmCMakePresetsGraphInternal::AnyAllOfCondition::Conditions, ListConditionVectorHelper); auto const NotConditionHelper = - cmJSONObjectHelper<cmCMakePresetsGraphInternal::NotCondition, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_CONDITION, false) + JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::NotCondition>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) .Bind("condition"_s, &cmCMakePresetsGraphInternal::NotCondition::SubCondition, @@ -251,37 +244,36 @@ ReadFileResult EnvironmentHelper(cm::optional<std::string>& out, return ReadFileResult::INVALID_PRESET; } -auto const VersionIntHelper = cmJSONIntHelper<ReadFileResult>( +auto const VersionIntHelper = JSONHelperBuilder::Int( ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION); -auto const VersionHelper = cmJSONRequiredHelper<int, ReadFileResult>( +auto const VersionHelper = JSONHelperBuilder::Required<int>( ReadFileResult::NO_VERSION, VersionIntHelper); auto const RootVersionHelper = - cmJSONObjectHelper<int, ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_ROOT) + JSONHelperBuilder::Object<int>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_ROOT) .Bind("version"_s, VersionHelper, false); -auto const CMakeVersionUIntHelper = cmJSONUIntHelper<ReadFileResult>( +auto const CMakeVersionUIntHelper = JSONHelperBuilder::UInt( ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION); auto const CMakeVersionHelper = - cmJSONObjectHelper<CMakeVersion, ReadFileResult>( + JSONHelperBuilder::Object<CMakeVersion>( ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false) .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false) .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false) .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false); -auto const IncludeHelper = cmJSONStringHelper<ReadFileResult>( +auto const IncludeHelper = JSONHelperBuilder::String( ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE); -auto const IncludeVectorHelper = - cmJSONVectorHelper<std::string, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE, IncludeHelper); +auto const IncludeVectorHelper = JSONHelperBuilder::Vector<std::string>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE, IncludeHelper); auto const RootPresetsHelper = - cmJSONObjectHelper<RootPresets, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false) + JSONHelperBuilder::Object<RootPresets>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_ROOT, false) .Bind<int>("version"_s, nullptr, VersionHelper) .Bind("configurePresets"_s, &RootPresets::ConfigurePresets, cmCMakePresetsGraphInternal::ConfigurePresetsHelper, false) @@ -302,7 +294,7 @@ namespace cmCMakePresetsGraphInternal { cmCMakePresetsGraph::ReadFileResult PresetStringHelper( std::string& out, const Json::Value* value) { - static auto const helper = cmJSONStringHelper<ReadFileResult>( + static auto const helper = JSONHelperBuilder::String( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); return helper(out, value); @@ -311,7 +303,7 @@ cmCMakePresetsGraph::ReadFileResult PresetStringHelper( cmCMakePresetsGraph::ReadFileResult PresetVectorStringHelper( std::vector<std::string>& out, const Json::Value* value) { - static auto const helper = cmJSONVectorHelper<std::string, ReadFileResult>( + static auto const helper = JSONHelperBuilder::Vector<std::string>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, cmCMakePresetsGraphInternal::PresetStringHelper); @@ -321,7 +313,7 @@ cmCMakePresetsGraph::ReadFileResult PresetVectorStringHelper( cmCMakePresetsGraph::ReadFileResult PresetBoolHelper(bool& out, const Json::Value* value) { - static auto const helper = cmJSONBoolHelper<ReadFileResult>( + static auto const helper = JSONHelperBuilder::Bool( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); return helper(out, value); @@ -330,7 +322,7 @@ cmCMakePresetsGraph::ReadFileResult PresetBoolHelper(bool& out, cmCMakePresetsGraph::ReadFileResult PresetOptionalBoolHelper( cm::optional<bool>& out, const Json::Value* value) { - static auto const helper = cmJSONOptionalHelper<bool, ReadFileResult>( + static auto const helper = JSONHelperBuilder::Optional<bool>( ReadFileResult::READ_OK, PresetBoolHelper); return helper(out, value); @@ -339,7 +331,7 @@ cmCMakePresetsGraph::ReadFileResult PresetOptionalBoolHelper( cmCMakePresetsGraph::ReadFileResult PresetIntHelper(int& out, const Json::Value* value) { - static auto const helper = cmJSONIntHelper<ReadFileResult>( + static auto const helper = JSONHelperBuilder::Int( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); return helper(out, value); @@ -348,8 +340,8 @@ cmCMakePresetsGraph::ReadFileResult PresetIntHelper(int& out, cmCMakePresetsGraph::ReadFileResult PresetOptionalIntHelper( cm::optional<int>& out, const Json::Value* value) { - static auto const helper = cmJSONOptionalHelper<int, ReadFileResult>( - ReadFileResult::READ_OK, PresetIntHelper); + static auto const helper = + JSONHelperBuilder::Optional<int>(ReadFileResult::READ_OK, PresetIntHelper); return helper(out, value); } @@ -357,7 +349,7 @@ cmCMakePresetsGraph::ReadFileResult PresetOptionalIntHelper( cmCMakePresetsGraph::ReadFileResult PresetVectorIntHelper( std::vector<int>& out, const Json::Value* value) { - static auto const helper = cmJSONVectorHelper<int, ReadFileResult>( + static auto const helper = JSONHelperBuilder::Vector<int>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper); return helper(out, value); @@ -409,10 +401,9 @@ cmCMakePresetsGraph::ReadFileResult EnvironmentMapHelper( std::map<std::string, cm::optional<std::string>>& out, const Json::Value* value) { - static auto const helper = - cmJSONMapHelper<cm::optional<std::string>, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, - EnvironmentHelper); + static auto const helper = JSONHelperBuilder::Map<cm::optional<std::string>>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, + EnvironmentHelper); return helper(out, value); } diff --git a/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx b/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx index eefe2fe..430d7ee 100644 --- a/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx +++ b/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx @@ -20,6 +20,7 @@ namespace { using ReadFileResult = cmCMakePresetsGraph::ReadFileResult; using BuildPreset = cmCMakePresetsGraph::BuildPreset; +using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>; ReadFileResult PackageResolveModeHelper(cm::optional<PackageResolveMode>& out, const Json::Value* value) @@ -53,8 +54,8 @@ std::function<ReadFileResult(BuildPreset&, const Json::Value*)> const }; auto const BuildPresetHelper = - cmJSONObjectHelper<BuildPreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + JSONHelperBuilder::Object<BuildPreset>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_PRESET, false) .Bind("name"_s, &BuildPreset::Name, cmCMakePresetsGraphInternal::PresetStringHelper) .Bind("inherits"_s, &BuildPreset::Inherits, @@ -99,7 +100,7 @@ namespace cmCMakePresetsGraphInternal { ReadFileResult BuildPresetsHelper(std::vector<BuildPreset>& out, const Json::Value* value) { - static auto const helper = cmJSONVectorHelper<BuildPreset, ReadFileResult>( + static auto const helper = JSONHelperBuilder::Vector<BuildPreset>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, BuildPresetHelper); diff --git a/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx b/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx index 0f44546..7cff55a 100644 --- a/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx +++ b/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx @@ -21,6 +21,7 @@ using ReadFileResult = cmCMakePresetsGraph::ReadFileResult; using CacheVariable = cmCMakePresetsGraph::CacheVariable; using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset; using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy; +using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>; ReadFileResult ArchToolsetStrategyHelper( cm::optional<ArchToolsetStrategy>& out, const Json::Value* value) @@ -53,7 +54,7 @@ ArchToolsetHelper( cm::optional<ArchToolsetStrategy> ConfigurePreset::*strategyField) { auto const objectHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + JSONHelperBuilder::Object<ConfigurePreset>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("value", valueField, cmCMakePresetsGraphInternal::PresetStringHelper, false) @@ -85,7 +86,7 @@ auto const ArchitectureHelper = ArchToolsetHelper( auto const ToolsetHelper = ArchToolsetHelper( &ConfigurePreset::Toolset, &ConfigurePreset::ToolsetStrategy); -auto const VariableStringHelper = cmJSONStringHelper<ReadFileResult>( +auto const VariableStringHelper = JSONHelperBuilder::String( ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE); ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value) @@ -104,7 +105,7 @@ ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value) } auto const VariableObjectHelper = - cmJSONObjectHelper<CacheVariable, ReadFileResult>( + JSONHelperBuilder::Object<CacheVariable>( ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false) .Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false) .Bind("value"_s, &CacheVariable::Value, VariableValueHelper); @@ -138,11 +139,11 @@ ReadFileResult VariableHelper(cm::optional<CacheVariable>& out, } auto const VariablesHelper = - cmJSONMapHelper<cm::optional<CacheVariable>, ReadFileResult>( + JSONHelperBuilder::Map<cm::optional<CacheVariable>>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper); auto const PresetWarningsHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + JSONHelperBuilder::Object<ConfigurePreset>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("dev"_s, &ConfigurePreset::WarnDev, cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false) @@ -156,7 +157,7 @@ auto const PresetWarningsHelper = cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false); auto const PresetErrorsHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + JSONHelperBuilder::Object<ConfigurePreset>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("dev"_s, &ConfigurePreset::ErrorDev, cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false) @@ -164,7 +165,7 @@ auto const PresetErrorsHelper = cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false); auto const PresetDebugHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + JSONHelperBuilder::Object<ConfigurePreset>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("output"_s, &ConfigurePreset::DebugOutput, cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false) @@ -174,7 +175,7 @@ auto const PresetDebugHelper = cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false); auto const ConfigurePresetHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + JSONHelperBuilder::Object<ConfigurePreset>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("name"_s, &ConfigurePreset::Name, cmCMakePresetsGraphInternal::PresetStringHelper) @@ -218,10 +219,9 @@ namespace cmCMakePresetsGraphInternal { ReadFileResult ConfigurePresetsHelper(std::vector<ConfigurePreset>& out, const Json::Value* value) { - static auto const helper = - cmJSONVectorHelper<ConfigurePreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, - ConfigurePresetHelper); + static auto const helper = JSONHelperBuilder::Vector<ConfigurePreset>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, + ConfigurePresetHelper); return helper(out, value); } diff --git a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx index b874575..c07d380 100644 --- a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx +++ b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx @@ -21,6 +21,7 @@ namespace { using ReadFileResult = cmCMakePresetsGraph::ReadFileResult; using TestPreset = cmCMakePresetsGraph::TestPreset; +using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>; ReadFileResult TestPresetOutputVerbosityHelper( TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value) @@ -53,9 +54,8 @@ ReadFileResult TestPresetOutputVerbosityHelper( } auto const TestPresetOptionalOutputVerbosityHelper = - cmJSONOptionalHelper<TestPreset::OutputOptions::VerbosityEnum, - ReadFileResult>(ReadFileResult::READ_OK, - TestPresetOutputVerbosityHelper); + JSONHelperBuilder::Optional<TestPreset::OutputOptions::VerbosityEnum>( + ReadFileResult::READ_OK, TestPresetOutputVerbosityHelper); ReadFileResult TestPresetOutputTruncationHelper( cm::optional<cmCTestTypes::TruncationMode>& out, const Json::Value* value) @@ -88,9 +88,9 @@ ReadFileResult TestPresetOutputTruncationHelper( } auto const TestPresetOptionalOutputHelper = - cmJSONOptionalHelper<TestPreset::OutputOptions, ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::OutputOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::OutputOptions, ReadFileResult>( + JSONHelperBuilder::Object<TestPreset::OutputOptions>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("shortProgress"_s, &TestPreset::OutputOptions::ShortProgress, cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false) @@ -122,12 +122,10 @@ auto const TestPresetOptionalOutputHelper = cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false)); auto const TestPresetOptionalFilterIncludeIndexObjectHelper = - cmJSONOptionalHelper<TestPreset::IncludeOptions::IndexOptions, - ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::IncludeOptions::IndexOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::IncludeOptions::IndexOptions, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_PRESET) + JSONHelperBuilder::Object<TestPreset::IncludeOptions::IndexOptions>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) .Bind("start"_s, &TestPreset::IncludeOptions::IndexOptions::Start, cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false) .Bind("end"_s, &TestPreset::IncludeOptions::IndexOptions::End, @@ -161,9 +159,9 @@ ReadFileResult TestPresetOptionalFilterIncludeIndexHelper( } auto const TestPresetOptionalFilterIncludeHelper = - cmJSONOptionalHelper<TestPreset::IncludeOptions, ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::IncludeOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::IncludeOptions, ReadFileResult>( + JSONHelperBuilder::Object<TestPreset::IncludeOptions>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) .Bind("name"_s, &TestPreset::IncludeOptions::Name, cmCMakePresetsGraphInternal::PresetStringHelper, false) @@ -175,12 +173,10 @@ auto const TestPresetOptionalFilterIncludeHelper = cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)); auto const TestPresetOptionalFilterExcludeFixturesHelper = - cmJSONOptionalHelper<TestPreset::ExcludeOptions::FixturesOptions, - ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::ExcludeOptions::FixturesOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::ExcludeOptions::FixturesOptions, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_PRESET) + JSONHelperBuilder::Object<TestPreset::ExcludeOptions::FixturesOptions>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) .Bind("any"_s, &TestPreset::ExcludeOptions::FixturesOptions::Any, cmCMakePresetsGraphInternal::PresetStringHelper, false) .Bind("setup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Setup, @@ -189,9 +185,9 @@ auto const TestPresetOptionalFilterExcludeFixturesHelper = cmCMakePresetsGraphInternal::PresetStringHelper, false)); auto const TestPresetOptionalFilterExcludeHelper = - cmJSONOptionalHelper<TestPreset::ExcludeOptions, ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::ExcludeOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::ExcludeOptions, ReadFileResult>( + JSONHelperBuilder::Object<TestPreset::ExcludeOptions>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) .Bind("name"_s, &TestPreset::ExcludeOptions::Name, cmCMakePresetsGraphInternal::PresetStringHelper, false) @@ -221,9 +217,8 @@ ReadFileResult TestPresetExecutionShowOnlyHelper( } auto const TestPresetOptionalExecutionShowOnlyHelper = - cmJSONOptionalHelper<TestPreset::ExecutionOptions::ShowOnlyEnum, - ReadFileResult>(ReadFileResult::READ_OK, - TestPresetExecutionShowOnlyHelper); + JSONHelperBuilder::Optional<TestPreset::ExecutionOptions::ShowOnlyEnum>( + ReadFileResult::READ_OK, TestPresetExecutionShowOnlyHelper); ReadFileResult TestPresetExecutionModeHelper( TestPreset::ExecutionOptions::RepeatOptions::ModeEnum& out, @@ -256,12 +251,10 @@ ReadFileResult TestPresetExecutionModeHelper( } auto const TestPresetOptionalExecutionRepeatHelper = - cmJSONOptionalHelper<TestPreset::ExecutionOptions::RepeatOptions, - ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::ExecutionOptions::RepeatOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::ExecutionOptions::RepeatOptions, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_PRESET) + JSONHelperBuilder::Object<TestPreset::ExecutionOptions::RepeatOptions>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) .Bind("mode"_s, &TestPreset::ExecutionOptions::RepeatOptions::Mode, TestPresetExecutionModeHelper, true) .Bind("count"_s, &TestPreset::ExecutionOptions::RepeatOptions::Count, @@ -299,14 +292,13 @@ ReadFileResult TestPresetExecutionNoTestsActionHelper( } auto const TestPresetOptionalExecutionNoTestsActionHelper = - cmJSONOptionalHelper<TestPreset::ExecutionOptions::NoTestsActionEnum, - ReadFileResult>(ReadFileResult::READ_OK, - TestPresetExecutionNoTestsActionHelper); + JSONHelperBuilder::Optional<TestPreset::ExecutionOptions::NoTestsActionEnum>( + ReadFileResult::READ_OK, TestPresetExecutionNoTestsActionHelper); auto const TestPresetExecutionHelper = - cmJSONOptionalHelper<TestPreset::ExecutionOptions, ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::ExecutionOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::ExecutionOptions, ReadFileResult>( + JSONHelperBuilder::Object<TestPreset::ExecutionOptions>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) .Bind("stopOnFailure"_s, &TestPreset::ExecutionOptions::StopOnFailure, cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false) @@ -334,9 +326,9 @@ auto const TestPresetExecutionHelper = TestPresetOptionalExecutionNoTestsActionHelper, false)); auto const TestPresetFilterHelper = - cmJSONOptionalHelper<TestPreset::FilterOptions, ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::FilterOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::FilterOptions, ReadFileResult>( + JSONHelperBuilder::Object<TestPreset::FilterOptions>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) .Bind("include"_s, &TestPreset::FilterOptions::Include, TestPresetOptionalFilterIncludeHelper, false) @@ -344,8 +336,8 @@ auto const TestPresetFilterHelper = TestPresetOptionalFilterExcludeHelper, false)); auto const TestPresetHelper = - cmJSONObjectHelper<TestPreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + JSONHelperBuilder::Object<TestPreset>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_PRESET, false) .Bind("name"_s, &TestPreset::Name, cmCMakePresetsGraphInternal::PresetStringHelper) .Bind("inherits"_s, &TestPreset::Inherits, @@ -386,7 +378,7 @@ namespace cmCMakePresetsGraphInternal { cmCMakePresetsGraph::ReadFileResult TestPresetsHelper( std::vector<cmCMakePresetsGraph::TestPreset>& out, const Json::Value* value) { - static auto const helper = cmJSONVectorHelper<TestPreset, ReadFileResult>( + static auto const helper = JSONHelperBuilder::Vector<TestPreset>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, TestPresetHelper); diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 324ce87..4909948 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -108,7 +108,7 @@ public: std::string value = makefile->GetSafeDefinition(var); if (warnCMP0067 && !value.empty()) { value.clear(); - warnCMP0067Variables.push_back(var); + warnCMP0067Variables.emplace_back(var); } return value; }; @@ -228,6 +228,8 @@ std::string const kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES = std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES = "CMAKE_TRY_COMPILE_PLATFORM_VARIABLES"; std::string const kCMAKE_WARN_DEPRECATED = "CMAKE_WARN_DEPRECATED"; +std::string const kCMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT = + "CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT"; /* GHS Multi platform variables */ std::set<std::string> const ghs_platform_vars{ @@ -335,11 +337,11 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } else if (argv[i] == "__CMAKE_INTERNAL") { doing = DoingCMakeInternal; } else if (doing == DoingCMakeFlags) { - cmakeFlags.push_back(argv[i]); + cmakeFlags.emplace_back(argv[i]); } else if (doing == DoingCompileDefinitions) { cmExpandList(argv[i], compileDefs); } else if (doing == DoingLinkOptions) { - linkOptions.push_back(argv[i]); + linkOptions.emplace_back(argv[i]); } else if (doing == DoingLinkLibraries) { libsToLink += "\"" + cmTrimWhitespace(argv[i]) + "\" "; if (cmTarget* tgt = this->Makefile->FindTargetToUse(argv[i])) { @@ -364,7 +366,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, return -1; } if (tgt->IsImported()) { - targets.push_back(argv[i]); + targets.emplace_back(argv[i]); } } } else if (doing == DoingOutputVariable) { @@ -377,7 +379,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, copyFileError = argv[i]; doing = DoingNone; } else if (doing == DoingSources) { - sources.push_back(argv[i]); + sources.emplace_back(argv[i]); } else if (doing == DoingCMakeInternal) { cmakeInternal = argv[i]; doing = DoingNone; @@ -488,7 +490,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, // Choose sources. if (!useSources) { - sources.push_back(argv[2]); + sources.emplace_back(argv[2]); } // Detect languages to enable. @@ -555,6 +557,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, !msvcRuntimeLibraryDefault->empty() ? "NEW" : "OLD"); } + /* Set Watcom runtime library policy to match our selection. */ + if (cmValue watcomRuntimeLibraryDefault = this->Makefile->GetDefinition( + kCMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT)) { + fprintf(fout, "cmake_policy(SET CMP0136 %s)\n", + !watcomRuntimeLibraryDefault->empty() ? "NEW" : "OLD"); + } + /* Set CUDA architectures policy to match outer project. */ if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0104) != cmPolicies::NEW && @@ -720,103 +729,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, fname.c_str()); } - // Forward a set of variables to the inner project cache. - { - std::set<std::string> vars; - vars.insert(&c_properties[lang_property_start], - &c_properties[lang_property_start + lang_property_size]); - vars.insert(&cxx_properties[lang_property_start], - &cxx_properties[lang_property_start + lang_property_size]); - vars.insert(&cuda_properties[lang_property_start], - &cuda_properties[lang_property_start + lang_property_size]); - vars.insert( - &fortran_properties[lang_property_start], - &fortran_properties[lang_property_start + lang_property_size]); - vars.insert(&hip_properties[lang_property_start], - &hip_properties[lang_property_start + lang_property_size]); - vars.insert(&objc_properties[lang_property_start], - &objc_properties[lang_property_start + lang_property_size]); - vars.insert( - &objcxx_properties[lang_property_start], - &objcxx_properties[lang_property_start + lang_property_size]); - vars.insert(&ispc_properties[lang_property_start], - &ispc_properties[lang_property_start + lang_property_size]); - vars.insert(&swift_properties[lang_property_start], - &swift_properties[lang_property_start + lang_property_size]); - vars.insert(kCMAKE_CUDA_ARCHITECTURES); - vars.insert(kCMAKE_CUDA_RUNTIME_LIBRARY); - vars.insert(kCMAKE_ENABLE_EXPORTS); - vars.insert(kCMAKE_HIP_ARCHITECTURES); - vars.insert(kCMAKE_HIP_RUNTIME_LIBRARY); - vars.insert(kCMAKE_ISPC_INSTRUCTION_SETS); - vars.insert(kCMAKE_ISPC_HEADER_SUFFIX); - vars.insert(kCMAKE_LINK_SEARCH_END_STATIC); - vars.insert(kCMAKE_LINK_SEARCH_START_STATIC); - vars.insert(kCMAKE_OSX_ARCHITECTURES); - vars.insert(kCMAKE_OSX_DEPLOYMENT_TARGET); - vars.insert(kCMAKE_OSX_SYSROOT); - vars.insert(kCMAKE_APPLE_ARCH_SYSROOTS); - vars.insert(kCMAKE_POSITION_INDEPENDENT_CODE); - vars.insert(kCMAKE_SYSROOT); - vars.insert(kCMAKE_SYSROOT_COMPILE); - vars.insert(kCMAKE_SYSROOT_LINK); - vars.insert(kCMAKE_WARN_DEPRECATED); - vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s); - - if (cmValue varListStr = this->Makefile->GetDefinition( - kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) { - std::vector<std::string> varList = cmExpandedList(*varListStr); - vars.insert(varList.begin(), varList.end()); - } - - if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0083) == - cmPolicies::NEW) { - // To ensure full support of PIE, propagate cache variables - // driving the link options - vars.insert(&c_properties[pie_property_start], - &c_properties[pie_property_start + pie_property_size]); - vars.insert(&cxx_properties[pie_property_start], - &cxx_properties[pie_property_start + pie_property_size]); - vars.insert(&cuda_properties[pie_property_start], - &cuda_properties[pie_property_start + pie_property_size]); - vars.insert( - &fortran_properties[pie_property_start], - &fortran_properties[pie_property_start + pie_property_size]); - vars.insert(&hip_properties[pie_property_start], - &hip_properties[pie_property_start + pie_property_size]); - vars.insert(&objc_properties[pie_property_start], - &objc_properties[pie_property_start + pie_property_size]); - vars.insert( - &objcxx_properties[pie_property_start], - &objcxx_properties[pie_property_start + pie_property_size]); - vars.insert(&ispc_properties[pie_property_start], - &ispc_properties[pie_property_start + pie_property_size]); - vars.insert(&swift_properties[pie_property_start], - &swift_properties[pie_property_start + pie_property_size]); - } - - /* for the TRY_COMPILEs we want to be able to specify the architecture. - So the user can set CMAKE_OSX_ARCHITECTURES to i386;ppc and then set - CMAKE_TRY_COMPILE_OSX_ARCHITECTURES first to i386 and then to ppc to - have the tests run for each specific architecture. Since - cmLocalGenerator doesn't allow building for "the other" - architecture only via CMAKE_OSX_ARCHITECTURES. - */ - if (cmValue tcArchs = this->Makefile->GetDefinition( - kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES)) { - vars.erase(kCMAKE_OSX_ARCHITECTURES); - std::string flag = "-DCMAKE_OSX_ARCHITECTURES=" + *tcArchs; - cmakeFlags.push_back(std::move(flag)); - } - - for (std::string const& var : vars) { - if (cmValue val = this->Makefile->GetDefinition(var)) { - std::string flag = "-D" + var + "=" + *val; - cmakeFlags.push_back(std::move(flag)); - } - } - } - /* Set the appropriate policy information for ENABLE_EXPORTS */ fprintf(fout, "cmake_policy(SET CMP0065 %s)\n", this->Makefile->GetPolicyStatus(cmPolicies::CMP0065) == @@ -959,12 +871,106 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, projectName = "CMAKE_TRY_COMPILE"; } + // Forward a set of variables to the inner project cache. + if (this->SrcFileSignature) { + std::set<std::string> vars; + vars.insert(&c_properties[lang_property_start], + &c_properties[lang_property_start + lang_property_size]); + vars.insert(&cxx_properties[lang_property_start], + &cxx_properties[lang_property_start + lang_property_size]); + vars.insert(&cuda_properties[lang_property_start], + &cuda_properties[lang_property_start + lang_property_size]); + vars.insert(&fortran_properties[lang_property_start], + &fortran_properties[lang_property_start + lang_property_size]); + vars.insert(&hip_properties[lang_property_start], + &hip_properties[lang_property_start + lang_property_size]); + vars.insert(&objc_properties[lang_property_start], + &objc_properties[lang_property_start + lang_property_size]); + vars.insert(&objcxx_properties[lang_property_start], + &objcxx_properties[lang_property_start + lang_property_size]); + vars.insert(&ispc_properties[lang_property_start], + &ispc_properties[lang_property_start + lang_property_size]); + vars.insert(&swift_properties[lang_property_start], + &swift_properties[lang_property_start + lang_property_size]); + vars.insert(kCMAKE_CUDA_ARCHITECTURES); + vars.insert(kCMAKE_CUDA_RUNTIME_LIBRARY); + vars.insert(kCMAKE_ENABLE_EXPORTS); + vars.insert(kCMAKE_HIP_ARCHITECTURES); + vars.insert(kCMAKE_HIP_RUNTIME_LIBRARY); + vars.insert(kCMAKE_ISPC_INSTRUCTION_SETS); + vars.insert(kCMAKE_ISPC_HEADER_SUFFIX); + vars.insert(kCMAKE_LINK_SEARCH_END_STATIC); + vars.insert(kCMAKE_LINK_SEARCH_START_STATIC); + vars.insert(kCMAKE_OSX_ARCHITECTURES); + vars.insert(kCMAKE_OSX_DEPLOYMENT_TARGET); + vars.insert(kCMAKE_OSX_SYSROOT); + vars.insert(kCMAKE_APPLE_ARCH_SYSROOTS); + vars.insert(kCMAKE_POSITION_INDEPENDENT_CODE); + vars.insert(kCMAKE_SYSROOT); + vars.insert(kCMAKE_SYSROOT_COMPILE); + vars.insert(kCMAKE_SYSROOT_LINK); + vars.insert(kCMAKE_WARN_DEPRECATED); + vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s); + vars.emplace("CMAKE_WATCOM_RUNTIME_LIBRARY"_s); + + if (cmValue varListStr = this->Makefile->GetDefinition( + kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) { + std::vector<std::string> varList = cmExpandedList(*varListStr); + vars.insert(varList.begin(), varList.end()); + } + + if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0083) == + cmPolicies::NEW) { + // To ensure full support of PIE, propagate cache variables + // driving the link options + vars.insert(&c_properties[pie_property_start], + &c_properties[pie_property_start + pie_property_size]); + vars.insert(&cxx_properties[pie_property_start], + &cxx_properties[pie_property_start + pie_property_size]); + vars.insert(&cuda_properties[pie_property_start], + &cuda_properties[pie_property_start + pie_property_size]); + vars.insert(&fortran_properties[pie_property_start], + &fortran_properties[pie_property_start + pie_property_size]); + vars.insert(&hip_properties[pie_property_start], + &hip_properties[pie_property_start + pie_property_size]); + vars.insert(&objc_properties[pie_property_start], + &objc_properties[pie_property_start + pie_property_size]); + vars.insert(&objcxx_properties[pie_property_start], + &objcxx_properties[pie_property_start + pie_property_size]); + vars.insert(&ispc_properties[pie_property_start], + &ispc_properties[pie_property_start + pie_property_size]); + vars.insert(&swift_properties[pie_property_start], + &swift_properties[pie_property_start + pie_property_size]); + } + + /* for the TRY_COMPILEs we want to be able to specify the architecture. + So the user can set CMAKE_OSX_ARCHITECTURES to i386;ppc and then set + CMAKE_TRY_COMPILE_OSX_ARCHITECTURES first to i386 and then to ppc to + have the tests run for each specific architecture. Since + cmLocalGenerator doesn't allow building for "the other" + architecture only via CMAKE_OSX_ARCHITECTURES. + */ + if (cmValue tcArchs = this->Makefile->GetDefinition( + kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES)) { + vars.erase(kCMAKE_OSX_ARCHITECTURES); + std::string flag = "-DCMAKE_OSX_ARCHITECTURES=" + *tcArchs; + cmakeFlags.emplace_back(std::move(flag)); + } + + for (std::string const& var : vars) { + if (cmValue val = this->Makefile->GetDefinition(var)) { + std::string flag = "-D" + var + "=" + *val; + cmakeFlags.emplace_back(std::move(flag)); + } + } + } + if (this->Makefile->GetState()->UseGhsMultiIDE()) { // Forward the GHS variables to the inner project cache. for (std::string const& var : ghs_platform_vars) { if (cmValue val = this->Makefile->GetDefinition(var)) { std::string flag = "-D" + var + "=" + "'" + *val + "'"; - cmakeFlags.push_back(std::move(flag)); + cmakeFlags.emplace_back(std::move(flag)); } } } @@ -1109,18 +1115,18 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName, // if a config was specified try that first if (cmNonempty(config)) { std::string tmp = cmStrCat('/', *config); - searchDirs.push_back(std::move(tmp)); + searchDirs.emplace_back(std::move(tmp)); } searchDirs.emplace_back("/Debug"); #if defined(__APPLE__) std::string app = "/" + targetName + ".app"; if (cmNonempty(config)) { std::string tmp = cmStrCat('/', *config, app); - searchDirs.push_back(std::move(tmp)); + searchDirs.emplace_back(std::move(tmp)); } std::string tmp = "/Debug" + app; searchDirs.emplace_back(std::move(tmp)); - searchDirs.push_back(std::move(app)); + searchDirs.emplace_back(std::move(app)); #endif searchDirs.emplace_back("/Development"); diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index e23ed0b..6586c69 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -23,6 +23,7 @@ #include "cmsys/String.h" #include "cmAlgorithms.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" @@ -44,6 +45,8 @@ class cmExecutionStatus; class cmFileList; +cmFindPackageCommand::PathLabel + cmFindPackageCommand::PathLabel::PackageRedirect("PACKAGE_REDIRECT"); cmFindPackageCommand::PathLabel cmFindPackageCommand::PathLabel::UserRegistry( "PACKAGE_REGISTRY"); cmFindPackageCommand::PathLabel cmFindPackageCommand::PathLabel::Builds( @@ -111,8 +114,10 @@ void cmFindPackageCommand::AppendSearchPathGroups() { std::vector<cmFindCommon::PathLabel>* labels; - // Update the All group with new paths + // Update the All group with new paths. Note that package redirection must + // take precedence over everything else, so it has to be first in the array. labels = &this->PathGroupLabelMap[PathGroup::All]; + labels->insert(labels->begin(), PathLabel::PackageRedirect); labels->insert( std::find(labels->begin(), labels->end(), PathLabel::CMakeSystem), PathLabel::UserRegistry); @@ -124,6 +129,8 @@ void cmFindPackageCommand::AppendSearchPathGroups() // Create the new path objects this->LabeledPaths.insert( + std::make_pair(PathLabel::PackageRedirect, cmSearchPath(this))); + this->LabeledPaths.insert( std::make_pair(PathLabel::UserRegistry, cmSearchPath(this))); this->LabeledPaths.insert( std::make_pair(PathLabel::Builds, cmSearchPath(this))); @@ -568,9 +575,62 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) this->SetModuleVariables(components); + // See if we have been told to delegate to FetchContent or some other + // redirected config package first. We have to check all names that + // find_package() may look for, but only need to invoke the override for the + // first one that matches. + auto overrideNames = this->Names; + if (overrideNames.empty()) { + overrideNames.push_back(this->Name); + } + bool forceConfigMode = false; + const auto redirectsDir = + this->Makefile->GetSafeDefinition("CMAKE_FIND_PACKAGE_REDIRECTS_DIR"); + for (const auto& overrideName : overrideNames) { + const auto nameLower = cmSystemTools::LowerCase(overrideName); + const auto delegatePropName = + cmStrCat("_FetchContent_", nameLower, "_override_find_package"); + const cmValue delegateToFetchContentProp = + this->Makefile->GetState()->GetGlobalProperty(delegatePropName); + if (delegateToFetchContentProp.IsOn()) { + // When this property is set, the FetchContent module has already been + // included at least once, so we know the FetchContent_MakeAvailable() + // command will be defined. Any future find_package() calls after this + // one for this package will by-pass this once-only delegation. + // The following call will typically create a <name>-config.cmake file + // in the redirectsDir, which we still want to process like any other + // config file to ensure we follow normal find_package() processing. + cmListFileFunction func( + "FetchContent_MakeAvailable", 0, 0, + { cmListFileArgument(overrideName, cmListFileArgument::Unquoted, 0) }); + if (!this->Makefile->ExecuteCommand(func, this->Status)) { + return false; + } + } + + if (cmSystemTools::FileExists( + cmStrCat(redirectsDir, '/', nameLower, "-config.cmake")) || + cmSystemTools::FileExists( + cmStrCat(redirectsDir, '/', overrideName, "Config.cmake"))) { + // Force the use of this redirected config package file, regardless of + // the type of find_package() call. Files in the redirectsDir must always + // take priority over everything else. + forceConfigMode = true; + this->UseConfigFiles = true; + this->UseFindModules = false; + this->Names.clear(); + this->Names.emplace_back(overrideName); // Force finding this one + this->Variable = cmStrCat(this->Name, "_DIR"); + this->SetConfigDirCacheVariable(redirectsDir); + break; + } + } + // See if there is a Find<PackageName>.cmake module. bool loadedPackage = false; - if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) { + if (forceConfigMode) { + loadedPackage = this->FindPackageUsingConfigMode(); + } else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) { if (this->UseConfigFiles && this->FindPackageUsingConfigMode()) { loadedPackage = true; } else { @@ -1185,19 +1245,24 @@ bool cmFindPackageCommand::FindConfig() } else { init = this->Variable + "-NOTFOUND"; } + // We force the value since we do not get here if it was already set. + this->SetConfigDirCacheVariable(init); + + return found; +} + +void cmFindPackageCommand::SetConfigDirCacheVariable(const std::string& value) +{ std::string help = cmStrCat("The directory containing a CMake configuration file for ", this->Name, '.'); - // We force the value since we do not get here if it was already set. - this->Makefile->AddCacheDefinition(this->Variable, init, help.c_str(), + this->Makefile->AddCacheDefinition(this->Variable, value, help.c_str(), cmStateEnums::PATH, true); if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == cmPolicies::NEW && this->Makefile->IsNormalDefinitionSet(this->Variable)) { - this->Makefile->AddDefinition(this->Variable, init); + this->Makefile->AddDefinition(this->Variable, value); } - - return found; } bool cmFindPackageCommand::FindPrefixedConfig() @@ -1348,6 +1413,8 @@ inline std::size_t collectPathsForDebug(std::string& buffer, void cmFindPackageCommand::ComputePrefixes() { + this->FillPrefixesPackageRedirect(); + if (!this->NoDefaultPath) { if (!this->NoPackageRootPath) { this->FillPrefixesPackageRoot(); @@ -1381,6 +1448,23 @@ void cmFindPackageCommand::ComputePrefixes() this->ComputeFinalPaths(IgnorePaths::No); } +void cmFindPackageCommand::FillPrefixesPackageRedirect() +{ + cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRedirect]; + + const auto redirectDir = + this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_REDIRECTS_DIR"); + if (redirectDir && !redirectDir->empty()) { + paths.AddPath(*redirectDir); + } + if (this->DebugMode) { + std::string debugBuffer = + "The internally managed CMAKE_FIND_PACKAGE_REDIRECTS_DIR.\n"; + collectPathsForDebug(debugBuffer, paths); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer); + } +} + void cmFindPackageCommand::FillPrefixesPackageRoot() { cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot]; diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 03f29b6..902fa32 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -76,6 +76,7 @@ private: : cmFindCommon::PathLabel(label) { } + static PathLabel PackageRedirect; static PathLabel UserRegistry; static PathLabel Builds; static PathLabel SystemRegistry; @@ -119,8 +120,10 @@ private: }; bool ReadListFile(const std::string& f, PolicyScopeRule psr); void StoreVersionFound(); + void SetConfigDirCacheVariable(const std::string& value); void ComputePrefixes(); + void FillPrefixesPackageRedirect(); void FillPrefixesPackageRoot(); void FillPrefixesCMakeEnvironment(); void FillPrefixesCMakeVariable(); diff --git a/Source/cmJSONHelpers.h b/Source/cmJSONHelpers.h index 6690aef..48decbc 100644 --- a/Source/cmJSONHelpers.h +++ b/Source/cmJSONHelpers.h @@ -14,146 +14,126 @@ #include <cm3p/json/value.h> -template <typename T, typename E> -using cmJSONHelper = std::function<E(T& out, const Json::Value* value)>; +template <typename T, typename E, typename... CallState> +using cmJSONHelper = + std::function<E(T& out, const Json::Value* value, CallState&&... state)>; -template <typename T, typename E> -class cmJSONObjectHelper +template <typename E, typename... CallState> +struct cmJSONHelperBuilder { -public: - cmJSONObjectHelper(E&& success, E&& fail, bool allowExtra = true); - - template <typename U, typename M, typename F> - cmJSONObjectHelper& Bind(const cm::string_view& name, M U::*member, F func, - bool required = true); - template <typename M, typename F> - cmJSONObjectHelper& Bind(const cm::string_view& name, std::nullptr_t, F func, - bool required = true); - template <typename F> - cmJSONObjectHelper& Bind(const cm::string_view& name, F func, - bool required = true); - - E operator()(T& out, const Json::Value* value) const; - -private: - // Not a true cmJSONHelper, it just happens to match the signature - using MemberFunction = std::function<E(T& out, const Json::Value* value)>; - struct Member + template <typename T> + class Object { - cm::string_view Name; - MemberFunction Function; - bool Required; - }; - std::vector<Member> Members; - bool AnyRequired = false; - E Success; - E Fail; - bool AllowExtra; - - cmJSONObjectHelper& BindPrivate(const cm::string_view& name, - MemberFunction&& func, bool required); -}; - -template <typename T, typename E> -cmJSONObjectHelper<T, E>::cmJSONObjectHelper(E&& success, E&& fail, - bool allowExtra) - : Success(std::move(success)) - , Fail(std::move(fail)) - , AllowExtra(allowExtra) -{ -} + public: + Object(E&& success, E&& fail, bool allowExtra = true) + : Success(std::move(success)) + , Fail(std::move(fail)) + , AllowExtra(allowExtra) + { + } -template <typename T, typename E> -template <typename U, typename M, typename F> -cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind( - const cm::string_view& name, M U::*member, F func, bool required) -{ - return this->BindPrivate( - name, - [func, member](T& out, const Json::Value* value) -> E { - return func(out.*member, value); - }, - required); -} + template <typename U, typename M, typename F> + Object& Bind(const cm::string_view& name, M U::*member, F func, + bool required = true) + { + return this->BindPrivate(name, + [func, member](T& out, const Json::Value* value, + CallState&&... state) -> E { + return func(out.*member, value, + std::forward(state)...); + }, + required); + } + template <typename M, typename F> + Object& Bind(const cm::string_view& name, std::nullptr_t, F func, + bool required = true) + { + return this->BindPrivate(name, + [func](T& /*out*/, const Json::Value* value, + CallState&&... state) -> E { + M dummy; + return func(dummy, value, + std::forward(state)...); + }, + required); + } + template <typename F> + Object& Bind(const cm::string_view& name, F func, bool required = true) + { + return this->BindPrivate(name, MemberFunction(func), required); + } -template <typename T, typename E> -template <typename M, typename F> -cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind( - const cm::string_view& name, std::nullptr_t, F func, bool required) -{ - return this->BindPrivate(name, - [func](T& /*out*/, const Json::Value* value) -> E { - M dummy; - return func(dummy, value); - }, - required); -} + E operator()(T& out, const Json::Value* value, CallState&&... state) const + { + if (!value && this->AnyRequired) { + return this->Fail; + } + if (value && !value->isObject()) { + return this->Fail; + } + Json::Value::Members extraFields; + if (value) { + extraFields = value->getMemberNames(); + } -template <typename T, typename E> -template <typename F> -cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind( - const cm::string_view& name, F func, bool required) -{ - return this->BindPrivate(name, MemberFunction(func), required); -} + for (auto const& m : this->Members) { + std::string name(m.Name.data(), m.Name.size()); + if (value && value->isMember(name)) { + E result = m.Function(out, &(*value)[name], std::forward(state)...); + if (result != this->Success) { + return result; + } + extraFields.erase( + std::find(extraFields.begin(), extraFields.end(), name)); + } else if (!m.Required) { + E result = m.Function(out, nullptr, std::forward(state)...); + if (result != this->Success) { + return result; + } + } else { + return this->Fail; + } + } -template <typename T, typename E> -cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::BindPrivate( - const cm::string_view& name, MemberFunction&& func, bool required) -{ - Member m; - m.Name = name; - m.Function = std::move(func); - m.Required = required; - this->Members.push_back(std::move(m)); - if (required) { - this->AnyRequired = true; - } - return *this; -} + return this->AllowExtra || extraFields.empty() ? this->Success + : this->Fail; + } -template <typename T, typename E> -E cmJSONObjectHelper<T, E>::operator()(T& out, const Json::Value* value) const -{ - if (!value && this->AnyRequired) { - return this->Fail; - } - if (value && !value->isObject()) { - return this->Fail; - } - Json::Value::Members extraFields; - if (value) { - extraFields = value->getMemberNames(); - } + private: + // Not a true cmJSONHelper, it just happens to match the signature + using MemberFunction = + std::function<E(T& out, const Json::Value* value, CallState&&... state)>; + struct Member + { + cm::string_view Name; + MemberFunction Function; + bool Required; + }; + std::vector<Member> Members; + bool AnyRequired = false; + E Success; + E Fail; + bool AllowExtra; - for (auto const& m : this->Members) { - std::string name(m.Name.data(), m.Name.size()); - if (value && value->isMember(name)) { - E result = m.Function(out, &(*value)[name]); - if (result != this->Success) { - return result; - } - extraFields.erase( - std::find(extraFields.begin(), extraFields.end(), name)); - } else if (!m.Required) { - E result = m.Function(out, nullptr); - if (result != this->Success) { - return result; + Object& BindPrivate(const cm::string_view& name, MemberFunction&& func, + bool required) + { + Member m; + m.Name = name; + m.Function = std::move(func); + m.Required = required; + this->Members.push_back(std::move(m)); + if (required) { + this->AnyRequired = true; } - } else { - return this->Fail; + return *this; } - } - - return this->AllowExtra || extraFields.empty() ? this->Success : this->Fail; -} - -template <typename E> -cmJSONHelper<std::string, E> cmJSONStringHelper(E success, E fail, - const std::string& defval = "") -{ - return - [success, fail, defval](std::string& out, const Json::Value* value) -> E { + }; + static cmJSONHelper<std::string, E, CallState...> String( + E success, E fail, const std::string& defval = "") + { + return [success, fail, defval](std::string& out, const Json::Value* value, + CallState&&... /*state*/) -> E { if (!value) { out = defval; return success; @@ -164,30 +144,30 @@ cmJSONHelper<std::string, E> cmJSONStringHelper(E success, E fail, out = value->asString(); return success; }; -} + } -template <typename E> -cmJSONHelper<int, E> cmJSONIntHelper(E success, E fail, int defval = 0) -{ - return [success, fail, defval](int& out, const Json::Value* value) -> E { - if (!value) { - out = defval; + static cmJSONHelper<int, E, CallState...> Int(E success, E fail, + int defval = 0) + { + return [success, fail, defval](int& out, const Json::Value* value, + CallState&&... /*state*/) -> E { + if (!value) { + out = defval; + return success; + } + if (!value->isInt()) { + return fail; + } + out = value->asInt(); return success; - } - if (!value->isInt()) { - return fail; - } - out = value->asInt(); - return success; - }; -} + }; + } -template <typename E> -cmJSONHelper<unsigned int, E> cmJSONUIntHelper(E success, E fail, - unsigned int defval = 0) -{ - return - [success, fail, defval](unsigned int& out, const Json::Value* value) -> E { + static cmJSONHelper<unsigned int, E, CallState...> UInt( + E success, E fail, unsigned int defval = 0) + { + return [success, fail, defval](unsigned int& out, const Json::Value* value, + CallState&&... /*state*/) -> E { if (!value) { out = defval; return success; @@ -198,118 +178,126 @@ cmJSONHelper<unsigned int, E> cmJSONUIntHelper(E success, E fail, out = value->asUInt(); return success; }; -} + } -template <typename E> -cmJSONHelper<bool, E> cmJSONBoolHelper(E success, E fail, bool defval = false) -{ - return [success, fail, defval](bool& out, const Json::Value* value) -> E { - if (!value) { - out = defval; + static cmJSONHelper<bool, E, CallState...> Bool(E success, E fail, + bool defval = false) + { + return [success, fail, defval](bool& out, const Json::Value* value, + CallState&&... /*state*/) -> E { + if (!value) { + out = defval; + return success; + } + if (!value->isBool()) { + return fail; + } + out = value->asBool(); return success; - } - if (!value->isBool()) { - return fail; - } - out = value->asBool(); - return success; - }; -} + }; + } -template <typename T, typename E, typename F, typename Filter> -cmJSONHelper<std::vector<T>, E> cmJSONVectorFilterHelper(E success, E fail, - F func, Filter filter) -{ - return [success, fail, func, filter](std::vector<T>& out, - const Json::Value* value) -> E { - if (!value) { - out.clear(); - return success; - } - if (!value->isArray()) { - return fail; - } - out.clear(); - for (auto const& item : *value) { - T t; - E result = func(t, &item); - if (result != success) { - return result; + template <typename T, typename F, typename Filter> + static cmJSONHelper<std::vector<T>, E, CallState...> VectorFilter( + E success, E fail, F func, Filter filter) + { + return [success, fail, func, filter](std::vector<T>& out, + const Json::Value* value, + CallState&&... state) -> E { + if (!value) { + out.clear(); + return success; } - if (!filter(t)) { - continue; + if (!value->isArray()) { + return fail; } - out.push_back(std::move(t)); - } - return success; - }; -} - -template <typename T, typename E, typename F> -cmJSONHelper<std::vector<T>, E> cmJSONVectorHelper(E success, E fail, F func) -{ - return cmJSONVectorFilterHelper<T, E, F>(success, fail, func, - [](const T&) { return true; }); -} - -template <typename T, typename E, typename F, typename Filter> -cmJSONHelper<std::map<std::string, T>, E> cmJSONMapFilterHelper(E success, - E fail, F func, - Filter filter) -{ - return [success, fail, func, filter](std::map<std::string, T>& out, - const Json::Value* value) -> E { - if (!value) { out.clear(); + for (auto const& item : *value) { + T t; + E result = func(t, &item, std::forward(state)...); + if (result != success) { + return result; + } + if (!filter(t)) { + continue; + } + out.push_back(std::move(t)); + } return success; - } - if (!value->isObject()) { - return fail; - } - out.clear(); - for (auto const& key : value->getMemberNames()) { - if (!filter(key)) { - continue; + }; + } + + template <typename T, typename F> + static cmJSONHelper<std::vector<T>, E, CallState...> Vector(E success, + E fail, F func) + { + return VectorFilter<T, F>(success, fail, func, + [](const T&) { return true; }); + } + + template <typename T, typename F, typename Filter> + static cmJSONHelper<std::map<std::string, T>, E, CallState...> MapFilter( + E success, E fail, F func, Filter filter) + { + return [success, fail, func, filter](std::map<std::string, T>& out, + const Json::Value* value, + CallState&&... state) -> E { + if (!value) { + out.clear(); + return success; } - T t; - E result = func(t, &(*value)[key]); - if (result != success) { - return result; + if (!value->isObject()) { + return fail; } - out[key] = std::move(t); - } - return success; - }; -} + out.clear(); + for (auto const& key : value->getMemberNames()) { + if (!filter(key)) { + continue; + } + T t; + E result = func(t, &(*value)[key], std::forward(state)...); + if (result != success) { + return result; + } + out[key] = std::move(t); + } + return success; + }; + } -template <typename T, typename E, typename F> -cmJSONHelper<std::map<std::string, T>, E> cmJSONMapHelper(E success, E fail, - F func) -{ - return cmJSONMapFilterHelper<T, E, F>( - success, fail, func, [](const std::string&) { return true; }); -} + template <typename T, typename F> + static cmJSONHelper<std::map<std::string, T>, E, CallState...> Map(E success, + E fail, + F func) + { + return MapFilter<T, F>(success, fail, func, + [](const std::string&) { return true; }); + } -template <typename T, typename E, typename F> -cmJSONHelper<cm::optional<T>, E> cmJSONOptionalHelper(E success, F func) -{ - return [success, func](cm::optional<T>& out, const Json::Value* value) -> E { - if (!value) { - out.reset(); - return success; - } - out.emplace(); - return func(*out, value); - }; -} + template <typename T, typename F> + static cmJSONHelper<cm::optional<T>, E, CallState...> Optional(E success, + F func) + { + return [success, func](cm::optional<T>& out, const Json::Value* value, + CallState&&... state) -> E { + if (!value) { + out.reset(); + return success; + } + out.emplace(); + return func(*out, value, std::forward(state)...); + }; + } -template <typename T, typename E, typename F> -cmJSONHelper<T, E> cmJSONRequiredHelper(E fail, F func) -{ - return [fail, func](T& out, const Json::Value* value) -> E { - if (!value) { - return fail; - } - return func(out, value); - }; -} + template <typename T, typename F> + static cmJSONHelper<T, E, CallState...> Required(E fail, F func) + { + return [fail, func](T& out, const Json::Value* value, + CallState&&... state) -> E { + if (!value) { + return fail; + } + return func(out, value, std::forward(state)...); + }; + } +}; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index c54d5bf..e2bcea8 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1025,6 +1025,14 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, flags.emplace_back(std::move(compReqFlag)); } + // Add Warning as errors flags + const cmValue wError = target->GetProperty("COMPILE_WARNING_AS_ERROR"); + const cmValue wErrorFlag = this->Makefile->GetDefinition( + cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_WARNING_AS_ERROR")); + if (wError.IsOn() && wErrorFlag.IsSet()) { + flags.emplace_back(wErrorFlag); + } + // Add compile flag for the MSVC compiler only. cmMakefile* mf = this->GetMakefile(); if (cmValue jmc = @@ -1919,6 +1927,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, std::string compilerSimulateId = this->Makefile->GetSafeDefinition( cmStrCat("CMAKE_", lang, "_SIMULATE_ID")); + if (lang == "Swift") { if (cmValue v = target->GetProperty("Swift_LANGUAGE_VERSION")) { if (cmSystemTools::VersionCompare( @@ -1994,6 +2003,38 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, } } } + + // Add Watcom runtime library flags. This is activated by the presence + // of a default selection whether or not it is overridden by a property. + cmValue watcomRuntimeLibraryDefault = + this->Makefile->GetDefinition("CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT"); + if (cmNonempty(watcomRuntimeLibraryDefault)) { + cmValue watcomRuntimeLibraryValue = + target->GetProperty("WATCOM_RUNTIME_LIBRARY"); + if (!watcomRuntimeLibraryValue) { + watcomRuntimeLibraryValue = watcomRuntimeLibraryDefault; + } + std::string const watcomRuntimeLibrary = cmGeneratorExpression::Evaluate( + *watcomRuntimeLibraryValue, this, config, target); + if (!watcomRuntimeLibrary.empty()) { + if (cmValue watcomRuntimeLibraryOptions = this->Makefile->GetDefinition( + "CMAKE_" + lang + "_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_" + + watcomRuntimeLibrary)) { + this->AppendCompileOptions(flags, *watcomRuntimeLibraryOptions); + } else if ((this->Makefile->GetSafeDefinition( + "CMAKE_" + lang + "_COMPILER_ID") == "OpenWatcom" || + this->Makefile->GetSafeDefinition( + "CMAKE_" + lang + "_SIMULATE_ID") == "OpenWatcom") && + !cmSystemTools::GetErrorOccuredFlag()) { + // The compiler uses the Watcom ABI so it needs a known runtime + // library. + this->IssueMessage(MessageType::FATAL_ERROR, + "WATCOM_RUNTIME_LIBRARY value '" + + watcomRuntimeLibrary + "' not known for this " + + lang + " compiler."); + } + } + } } void cmLocalGenerator::AddLanguageFlagsForLinking( diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 7d06607..4977083 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -408,7 +408,10 @@ class cmMakefile; SELECT(POLICY, CMP0135, \ "ExternalProject ignores timestamps in archives by default for the " \ "URL download method", \ - 3, 24, 0, cmPolicies::WARN) + 3, 24, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0136, \ + "Watcom runtime library flags are selected by an abstraction.", 3, \ + 24, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index feb2ee3..80d1940 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -543,6 +543,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("LINK_DEPENDS_NO_SHARED"); initProp("LINK_INTERFACE_LIBRARIES"); initProp("MSVC_RUNTIME_LIBRARY"); + initProp("WATCOM_RUNTIME_LIBRARY"); initProp("WIN32_EXECUTABLE"); initProp("MACOSX_BUNDLE"); initProp("MACOSX_RPATH"); @@ -587,6 +588,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("UNITY_BUILD_UNIQUE_ID"); initProp("OPTIMIZE_DEPENDENCIES"); initProp("EXPORT_COMPILE_COMMANDS"); + initProp("COMPILE_WARNING_AS_ERROR"); initPropValue("UNITY_BUILD_BATCH_SIZE", "8"); initPropValue("UNITY_BUILD_MODE", "BATCH"); initPropValue("PCH_WARN_INVALID", "ON"); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 1c027ad..a8dc963 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2103,6 +2103,21 @@ int cmake::ActualConfigure() cmStateEnums::INTERNAL); } + // We want to create the package redirects directory as early as possible, + // but not before pre-configure checks have passed. This ensures we get + // errors about inappropriate source/binary directories first. + const auto redirectsDir = + cmStrCat(this->GetHomeOutputDirectory(), "/CMakeFiles/pkgRedirects"); + cmSystemTools::RemoveADirectory(redirectsDir); + if (!cmSystemTools::MakeDirectory(redirectsDir)) { + cmSystemTools::Error( + "Unable to (re)create the private pkgRedirects directory:\n" + + redirectsDir); + return -1; + } + this->AddCacheEntry("CMAKE_FIND_PACKAGE_REDIRECTS_DIR", redirectsDir, + "Value Computed by CMake.", cmStateEnums::STATIC); + // no generator specified on the command line if (!this->GlobalGenerator) { cmValue genName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR"); diff --git a/Tests/CMakeLib/testJSONHelpers.cxx b/Tests/CMakeLib/testJSONHelpers.cxx index a45d320..2cd3f75 100644 --- a/Tests/CMakeLib/testJSONHelpers.cxx +++ b/Tests/CMakeLib/testJSONHelpers.cxx @@ -43,32 +43,33 @@ enum class ErrorCode MissingRequired, }; +using JSONHelperBuilder = cmJSONHelperBuilder<ErrorCode>; + auto const IntHelper = - cmJSONIntHelper<ErrorCode>(ErrorCode::Success, ErrorCode::InvalidInt, 1); + JSONHelperBuilder::Int(ErrorCode::Success, ErrorCode::InvalidInt, 1); auto const RequiredIntHelper = - cmJSONRequiredHelper<int, ErrorCode>(ErrorCode::MissingRequired, IntHelper); + JSONHelperBuilder::Required<int>(ErrorCode::MissingRequired, IntHelper); auto const UIntHelper = - cmJSONUIntHelper<ErrorCode>(ErrorCode::Success, ErrorCode::InvalidInt, 1); -auto const BoolHelper = cmJSONBoolHelper<ErrorCode>( - ErrorCode::Success, ErrorCode::InvalidBool, false); -auto const StringHelper = cmJSONStringHelper<ErrorCode>( + JSONHelperBuilder::UInt(ErrorCode::Success, ErrorCode::InvalidInt, 1); +auto const BoolHelper = + JSONHelperBuilder::Bool(ErrorCode::Success, ErrorCode::InvalidBool, false); +auto const StringHelper = JSONHelperBuilder::String( ErrorCode::Success, ErrorCode::InvalidString, "default"); -auto const RequiredStringHelper = cmJSONRequiredHelper<std::string, ErrorCode>( +auto const RequiredStringHelper = JSONHelperBuilder::Required<std::string>( ErrorCode::MissingRequired, StringHelper); -auto const StringVectorHelper = cmJSONVectorHelper<std::string, ErrorCode>( +auto const StringVectorHelper = JSONHelperBuilder::Vector<std::string>( ErrorCode::Success, ErrorCode::InvalidArray, StringHelper); auto const StringVectorFilterHelper = - cmJSONVectorFilterHelper<std::string, ErrorCode>( + JSONHelperBuilder::VectorFilter<std::string>( ErrorCode::Success, ErrorCode::InvalidArray, StringHelper, [](const std::string& value) { return value != "ignore"; }); -auto const StringMapHelper = cmJSONMapHelper<std::string, ErrorCode>( +auto const StringMapHelper = JSONHelperBuilder::Map<std::string>( ErrorCode::Success, ErrorCode::InvalidObject, StringHelper); -auto const StringMapFilterHelper = - cmJSONMapFilterHelper<std::string, ErrorCode>( - ErrorCode::Success, ErrorCode::InvalidObject, StringHelper, - [](const std::string& key) { return key != "ignore"; }); +auto const StringMapFilterHelper = JSONHelperBuilder::MapFilter<std::string>( + ErrorCode::Success, ErrorCode::InvalidObject, StringHelper, + [](const std::string& key) { return key != "ignore"; }); auto const OptionalStringHelper = - cmJSONOptionalHelper<std::string>(ErrorCode::Success, StringHelper); + JSONHelperBuilder::Optional<std::string>(ErrorCode::Success, StringHelper); bool testInt() { @@ -150,10 +151,10 @@ bool testString() bool testObject() { auto const subhelper = - cmJSONObjectHelper<ObjectStruct, ErrorCode>(ErrorCode::Success, - ErrorCode::InvalidSubObject) + JSONHelperBuilder::Object<ObjectStruct>(ErrorCode::Success, + ErrorCode::InvalidSubObject) .Bind("subfield"_s, &ObjectStruct::Field2, IntHelper); - auto const helper = cmJSONObjectHelper<ObjectStruct, ErrorCode>( + auto const helper = JSONHelperBuilder::Object<ObjectStruct>( ErrorCode::Success, ErrorCode::InvalidObject) .Bind("field1"_s, &ObjectStruct::Field1, StringHelper) .Bind("field2"_s, subhelper) @@ -206,8 +207,8 @@ bool testObject() bool testObjectInherited() { auto const helper = - cmJSONObjectHelper<InheritedStruct, ErrorCode>(ErrorCode::Success, - ErrorCode::InvalidObject) + JSONHelperBuilder::Object<InheritedStruct>(ErrorCode::Success, + ErrorCode::InvalidObject) .Bind("field1"_s, &InheritedStruct::Field1, StringHelper) .Bind("field2"_s, &InheritedStruct::Field2, IntHelper) .Bind("field3"_s, &InheritedStruct::Field3, StringHelper); @@ -253,7 +254,7 @@ bool testObjectInherited() bool testObjectNoExtra() { - auto const helper = cmJSONObjectHelper<ObjectStruct, ErrorCode>( + auto const helper = JSONHelperBuilder::Object<ObjectStruct>( ErrorCode::Success, ErrorCode::InvalidObject, false) .Bind("field1"_s, &ObjectStruct::Field1, StringHelper) .Bind("field2"_s, &ObjectStruct::Field2, IntHelper); @@ -277,8 +278,8 @@ bool testObjectNoExtra() bool testObjectOptional() { auto const helper = - cmJSONObjectHelper<ObjectStruct, ErrorCode>(ErrorCode::Success, - ErrorCode::InvalidObject) + JSONHelperBuilder::Object<ObjectStruct>(ErrorCode::Success, + ErrorCode::InvalidObject) .Bind("field1"_s, &ObjectStruct::Field1, StringHelper, false) .Bind("field2"_s, &ObjectStruct::Field2, IntHelper, false) .Bind<std::string>("field3_s", nullptr, StringHelper, false); diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 9a1cf69..9cee144 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -2077,6 +2077,10 @@ if(BUILD_TESTING) ADD_TEST_MACRO(ModuleDefinition example_exe) endif() + if (CMAKE_C_COMPILER_ID MATCHES "Watcom" AND WIN32) + ADD_TEST_MACRO(WatcomRuntimeLibrary) + endif() + ADD_TEST_MACRO(CheckCompilerRelatedVariables CheckCompilerRelatedVariables) if("${CMAKE_GENERATOR}" MATCHES "Makefile" OR diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 515c6d8..07b256c 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -369,6 +369,7 @@ add_RunCMake_test(TargetProperties) add_RunCMake_test(ToolchainFile) add_RunCMake_test(find_dependency) add_RunCMake_test(CompileDefinitions) +add_RunCMake_test(CompileWarningAsError) add_RunCMake_test(CompileFeatures -DCMake_NO_C_STANDARD=${CMake_NO_C_STANDARD} -DCMake_NO_CXX_STANDARD=${CMake_NO_CXX_STANDARD}) add_RunCMake_test(Policy) add_RunCMake_test(PolicyScope) @@ -785,6 +786,7 @@ if(CMake_TEST_RunCMake_ExternalProject_DOWNLOAD_SERVER_TIMEOUT) endif() add_RunCMake_test(ExternalProject) add_RunCMake_test(FetchContent) +add_RunCMake_test(FetchContent_find_package) set(CTestCommandLine_ARGS -DPython_EXECUTABLE=${Python_EXECUTABLE}) if(NOT CMake_TEST_EXTERNAL_CMAKE) list(APPEND CTestCommandLine_ARGS -DTEST_AFFINITY=$<TARGET_FILE:testAffinity>) diff --git a/Tests/RunCMake/CompileWarningAsError/CMakeLists.txt b/Tests/RunCMake/CompileWarningAsError/CMakeLists.txt new file mode 100644 index 0000000..5ff8d3e --- /dev/null +++ b/Tests/RunCMake/CompileWarningAsError/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.23) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CompileWarningAsError/RunCMakeTest.cmake b/Tests/RunCMake/CompileWarningAsError/RunCMakeTest.cmake new file mode 100644 index 0000000..059c80f --- /dev/null +++ b/Tests/RunCMake/CompileWarningAsError/RunCMakeTest.cmake @@ -0,0 +1,12 @@ +include(RunCMake) + +function(run_compile_warn test) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build) + set(RunCMake_TEST_OUTPUT_MERGE 1) + run_cmake(${test}) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${test}-Build ${CMAKE_COMMAND} --build . ${verbose_args}) +endfunction() + +run_compile_warn(WerrorOn) +run_compile_warn(WerrorOff) diff --git a/Tests/RunCMake/CompileWarningAsError/WarningAsErrorOptions.cmake b/Tests/RunCMake/CompileWarningAsError/WarningAsErrorOptions.cmake new file mode 100644 index 0000000..ccc6cc5 --- /dev/null +++ b/Tests/RunCMake/CompileWarningAsError/WarningAsErrorOptions.cmake @@ -0,0 +1,18 @@ +# add compile options to warning_options to ensure unused-function throws a warning +# if warning_options is NOT DEFINED, assume compiler doesn't support warning as error +macro(get_warning_options warning_options) + if (CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang|XLClang|IBMClang|LCC|NVCC|IntelLLVM)$") + set(${warning_options} "-Wall") + elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" + OR (CMAKE_CXX_COMPILER_ID STREQUAL "Intel" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC")) + set(${warning_options} "-W4") + elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel") + set(${warning_options} "-w3") + elseif (CMAKE_CXX_COMPILER_ID STREQUAL "XL") + set(${warning_options} "-qinfo=all") + elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro") + set(${warning_options} "+w;+w2") + elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Fujitsu") + set(${warning_options} "SHELL:-w 8") + endif() +endmacro() diff --git a/Tests/RunCMake/CompileWarningAsError/WerrorOff.cmake b/Tests/RunCMake/CompileWarningAsError/WerrorOff.cmake new file mode 100644 index 0000000..b05d65e --- /dev/null +++ b/Tests/RunCMake/CompileWarningAsError/WerrorOff.cmake @@ -0,0 +1,8 @@ +enable_language(CXX) + +include(WarningAsErrorOptions.cmake) +get_warning_options(warning_options) + +add_executable(WerrorOff warn.cxx) +target_compile_options(WerrorOff PUBLIC "${warning_options}") +set_target_properties(WerrorOff PROPERTIES COMPILE_WARNING_AS_ERROR OFF) diff --git a/Tests/RunCMake/CompileWarningAsError/WerrorOn-Build-result.txt b/Tests/RunCMake/CompileWarningAsError/WerrorOn-Build-result.txt new file mode 100644 index 0000000..d197c91 --- /dev/null +++ b/Tests/RunCMake/CompileWarningAsError/WerrorOn-Build-result.txt @@ -0,0 +1 @@ +[^0] diff --git a/Tests/RunCMake/CompileWarningAsError/WerrorOn.cmake b/Tests/RunCMake/CompileWarningAsError/WerrorOn.cmake new file mode 100644 index 0000000..4310333 --- /dev/null +++ b/Tests/RunCMake/CompileWarningAsError/WerrorOn.cmake @@ -0,0 +1,13 @@ +enable_language(CXX) + +include(WarningAsErrorOptions.cmake) +get_warning_options(warning_options) + +if (DEFINED warning_options) + add_executable(WerrorOn warn.cxx) + target_compile_options(WerrorOn PUBLIC "${warning_options}") + set_target_properties(WerrorOn PROPERTIES COMPILE_WARNING_AS_ERROR ON) +else() + # if no werror option is set for the environment, use err.cxx so that build fails as expected + add_executable(WerrorOn err.cxx) +endif() diff --git a/Tests/RunCMake/CompileWarningAsError/err.cxx b/Tests/RunCMake/CompileWarningAsError/err.cxx new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/CompileWarningAsError/err.cxx diff --git a/Tests/RunCMake/CompileWarningAsError/warn.cxx b/Tests/RunCMake/CompileWarningAsError/warn.cxx new file mode 100644 index 0000000..64a245a --- /dev/null +++ b/Tests/RunCMake/CompileWarningAsError/warn.cxx @@ -0,0 +1,17 @@ +static void unused_function(); + +#ifdef __SUNPRO_CC +struct A +{ + virtual ~A() throw(); +}; +struct B : public A +{ + virtual ~B() throw(int); +}; +#endif + +int main(int unused_argument, char* []) +{ + return 1; +} diff --git a/Tests/RunCMake/FetchContent_find_package/AddedProject/CMakeLists.txt b/Tests/RunCMake/FetchContent_find_package/AddedProject/CMakeLists.txt new file mode 100644 index 0000000..8be00ed --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/AddedProject/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.13...3.23) +project(AddedProject LANGUAGES NONE) + +message(STATUS "Confirmation project has been added") diff --git a/Tests/RunCMake/FetchContent_find_package/BadArgs_find_package-result.txt b/Tests/RunCMake/FetchContent_find_package/BadArgs_find_package-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/BadArgs_find_package-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/FetchContent_find_package/BadArgs_find_package-stderr.txt b/Tests/RunCMake/FetchContent_find_package/BadArgs_find_package-stderr.txt new file mode 100644 index 0000000..b6996b5 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/BadArgs_find_package-stderr.txt @@ -0,0 +1,3 @@ +CMake Error at .*/FetchContent.cmake:[0-9]+ \(message\): + Cannot specify both OVERRIDE_FIND_PACKAGE and FIND_PACKAGE_ARGS when + declaring details for AddedProject diff --git a/Tests/RunCMake/FetchContent_find_package/BadArgs_find_package.cmake b/Tests/RunCMake/FetchContent_find_package/BadArgs_find_package.cmake new file mode 100644 index 0000000..c1272b4 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/BadArgs_find_package.cmake @@ -0,0 +1,9 @@ +include(FetchContent) + +FetchContent_Declare( + AddedProject + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/AddedProject + # The following two args are mutually exclusive + OVERRIDE_FIND_PACKAGE + FIND_PACKAGE_ARGS +) diff --git a/Tests/RunCMake/FetchContent_find_package/CMAKE_FIND_PACKAGE_REDIRECTS_DIR-AlwaysEmptied-Setup.cmake b/Tests/RunCMake/FetchContent_find_package/CMAKE_FIND_PACKAGE_REDIRECTS_DIR-AlwaysEmptied-Setup.cmake new file mode 100644 index 0000000..ea36bf0 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/CMAKE_FIND_PACKAGE_REDIRECTS_DIR-AlwaysEmptied-Setup.cmake @@ -0,0 +1,3 @@ +file(WRITE "${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/dummy_file.txt" + "This file should be deleted the next time CMake runs" +) diff --git a/Tests/RunCMake/FetchContent_find_package/CMAKE_FIND_PACKAGE_REDIRECTS_DIR-AlwaysEmptied.cmake b/Tests/RunCMake/FetchContent_find_package/CMAKE_FIND_PACKAGE_REDIRECTS_DIR-AlwaysEmptied.cmake new file mode 100644 index 0000000..07c45f2 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/CMAKE_FIND_PACKAGE_REDIRECTS_DIR-AlwaysEmptied.cmake @@ -0,0 +1,9 @@ +file(GLOB contents LIST_DIRECTORIES true "${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/*") + +if(NOT contents STREQUAL "") + list(JOIN contents "\n" fileList) + message(FATAL_ERROR + "CMAKE_FIND_PACKAGE_REDIRECTS_DIR is not empty:\n" + "${fileList}" + ) +endif() diff --git a/Tests/RunCMake/FetchContent_find_package/CMAKE_FIND_PACKAGE_REDIRECTS_DIR-Exists.cmake b/Tests/RunCMake/FetchContent_find_package/CMAKE_FIND_PACKAGE_REDIRECTS_DIR-Exists.cmake new file mode 100644 index 0000000..dd01333 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/CMAKE_FIND_PACKAGE_REDIRECTS_DIR-Exists.cmake @@ -0,0 +1,18 @@ +if(NOT DEFINED CMAKE_FIND_PACKAGE_REDIRECTS_DIR) + message(FATAL_ERROR "CMAKE_FIND_PACKAGE_REDIRECTS_DIR is not defined") +endif() + +if(NOT CMAKE_FIND_PACKAGE_REDIRECTS_DIR STREQUAL "${CMAKE_BINARY_DIR}/CMakeFiles/pkgRedirects") + message(FATAL_ERROR + "CMAKE_FIND_PACKAGE_REDIRECTS_DIR has wrong value\n" + " Expected: ${CMAKE_BINARY_DIR}/CMakeFiles/pkgRedirects\n" + " Actual: ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}" + ) +endif() + +if(NOT EXISTS "${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}") + message(FATAL_ERROR + "Directory CMAKE_FIND_PACKAGE_REDIRECTS_DIR points to does not exist:\n" + "${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}" + ) +endif() diff --git a/Tests/RunCMake/FetchContent_find_package/CMakeLists.txt b/Tests/RunCMake/FetchContent_find_package/CMakeLists.txt new file mode 100644 index 0000000..bd718c7 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.23) +project(${RunCMake_TEST} NONE) + +# Tests assume no previous downloads in the output directory +file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/_deps) + +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/FetchContent_find_package/FatalIfAdded/CMakeLists.txt b/Tests/RunCMake/FetchContent_find_package/FatalIfAdded/CMakeLists.txt new file mode 100644 index 0000000..6a3b931 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/FatalIfAdded/CMakeLists.txt @@ -0,0 +1 @@ +message(FATAL_ERROR "Unexpectedly added directory via FetchContent_MakeAvailable()") diff --git a/Tests/RunCMake/FetchContent_find_package/MissingDetails-result.txt b/Tests/RunCMake/FetchContent_find_package/MissingDetails-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/MissingDetails-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/FetchContent_find_package/MissingDetails-stderr.txt b/Tests/RunCMake/FetchContent_find_package/MissingDetails-stderr.txt new file mode 100644 index 0000000..c4f1daf --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/MissingDetails-stderr.txt @@ -0,0 +1 @@ +No content details recorded for t1 diff --git a/Tests/RunCMake/FetchContent_find_package/MissingDetails.cmake b/Tests/RunCMake/FetchContent_find_package/MissingDetails.cmake new file mode 100644 index 0000000..ba8d121 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/MissingDetails.cmake @@ -0,0 +1,3 @@ +include(FetchContent) + +FetchContent_Populate(t1) diff --git a/Tests/RunCMake/FetchContent_find_package/PackageConfigs/AddedProjectConfig.cmake b/Tests/RunCMake/FetchContent_find_package/PackageConfigs/AddedProjectConfig.cmake new file mode 100644 index 0000000..a38159f --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/PackageConfigs/AddedProjectConfig.cmake @@ -0,0 +1,2 @@ +set(AddedProject_FOUND TRUE) +message(STATUS "Loaded AddedProject from package config") diff --git a/Tests/RunCMake/FetchContent_find_package/PackageConfigs/FirstProjectConfig.cmake b/Tests/RunCMake/FetchContent_find_package/PackageConfigs/FirstProjectConfig.cmake new file mode 100644 index 0000000..3a89969 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/PackageConfigs/FirstProjectConfig.cmake @@ -0,0 +1,2 @@ +set(FirstProject_FOUND TRUE) +message(STATUS "Loaded FirstProject from package config") diff --git a/Tests/RunCMake/FetchContent_find_package/PackageConfigs/SecondProjectConfig.cmake b/Tests/RunCMake/FetchContent_find_package/PackageConfigs/SecondProjectConfig.cmake new file mode 100644 index 0000000..a181ab8 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/PackageConfigs/SecondProjectConfig.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "Unexpectedly found SecondProject via find_package()") diff --git a/Tests/RunCMake/FetchContent_find_package/PackageFindModules/FindFirstProject.cmake b/Tests/RunCMake/FetchContent_find_package/PackageFindModules/FindFirstProject.cmake new file mode 100644 index 0000000..bdd3369 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/PackageFindModules/FindFirstProject.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "First project used Find module") diff --git a/Tests/RunCMake/FetchContent_find_package/PackageFindModules/FindSecondProject.cmake b/Tests/RunCMake/FetchContent_find_package/PackageFindModules/FindSecondProject.cmake new file mode 100644 index 0000000..09a4acf --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/PackageFindModules/FindSecondProject.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "Second project used Find module") diff --git a/Tests/RunCMake/FetchContent_find_package/PreferFetchContent-stdout.txt b/Tests/RunCMake/FetchContent_find_package/PreferFetchContent-stdout.txt new file mode 100644 index 0000000..5413a4b --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/PreferFetchContent-stdout.txt @@ -0,0 +1,3 @@ +Confirmation project has been added +(-- )?Lowercase extra file was read +(-- )?Uppercase extra file was read diff --git a/Tests/RunCMake/FetchContent_find_package/PreferFetchContent.cmake b/Tests/RunCMake/FetchContent_find_package/PreferFetchContent.cmake new file mode 100644 index 0000000..c1030fb --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/PreferFetchContent.cmake @@ -0,0 +1,20 @@ +include(FetchContent) + +FetchContent_Declare( + AddedProject + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/AddedProject + OVERRIDE_FIND_PACKAGE +) + +# The default generated config package files are expected to include these when present +file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/AddedProjectExtra.cmake [[ +message(STATUS "Uppercase extra file was read") +]] +) +file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/addedproject-extra.cmake [[ +message(STATUS "Lowercase extra file was read") +]] +) + +# This is expected to be re-routed to a FetchContent_MakeAvailable() call +find_package(AddedProject REQUIRED) diff --git a/Tests/RunCMake/FetchContent_find_package/Prefer_find_package-stdout.txt b/Tests/RunCMake/FetchContent_find_package/Prefer_find_package-stdout.txt new file mode 100644 index 0000000..dfb4238 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/Prefer_find_package-stdout.txt @@ -0,0 +1,3 @@ +Loaded AddedProject from package config +.*Loaded AddedProject from package config +.*Loaded AddedProject from package config diff --git a/Tests/RunCMake/FetchContent_find_package/Prefer_find_package.cmake b/Tests/RunCMake/FetchContent_find_package/Prefer_find_package.cmake new file mode 100644 index 0000000..f5454ab --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/Prefer_find_package.cmake @@ -0,0 +1,15 @@ +include(FetchContent) + +set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_LIST_DIR}/PackageConfigs) + +FetchContent_Declare( + AddedProject + # Ensure failure if we don't re-route to find_package() + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/FatalIfAdded + FIND_PACKAGE_ARGS REQUIRED +) + +# Cycle through a few calls to exercise global property changes +FetchContent_MakeAvailable(AddedProject) +find_package(AddedProject REQUIRED) +FetchContent_MakeAvailable(AddedProject) # Will re-route to find_package() again diff --git a/Tests/RunCMake/FetchContent_find_package/PreserveEmptyArgs-stdout.txt b/Tests/RunCMake/FetchContent_find_package/PreserveEmptyArgs-stdout.txt new file mode 100644 index 0000000..a72d914 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/PreserveEmptyArgs-stdout.txt @@ -0,0 +1,4 @@ +.*-- Number of arguments: 6 +.*-- Argument 3: 'before' +.*-- Argument 4: '' +.*-- Argument 5: 'after' diff --git a/Tests/RunCMake/FetchContent_find_package/PreserveEmptyArgs.cmake b/Tests/RunCMake/FetchContent_find_package/PreserveEmptyArgs.cmake new file mode 100644 index 0000000..4f35448 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/PreserveEmptyArgs.cmake @@ -0,0 +1,13 @@ +include(FetchContent) + +# Need to see the download command output +set(FETCHCONTENT_QUIET OFF) + +FetchContent_Declare( + t1 + DOWNLOAD_COMMAND ${CMAKE_COMMAND} -P + ${CMAKE_CURRENT_LIST_DIR}/countArgs.cmake + before "" after +) + +FetchContent_Populate(t1) diff --git a/Tests/RunCMake/FetchContent_find_package/ProjectProvidesPackageConfigFiles-stdout.txt b/Tests/RunCMake/FetchContent_find_package/ProjectProvidesPackageConfigFiles-stdout.txt new file mode 100644 index 0000000..76c6916 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/ProjectProvidesPackageConfigFiles-stdout.txt @@ -0,0 +1,4 @@ +(-- )?ConfigForm1 override successful +(-- )?ConfigForm2 override successful +(-- )?ConfigForm1_VERSION = 1.8 +(-- )?ConfigForm2_VERSION = 1.9.7 diff --git a/Tests/RunCMake/FetchContent_find_package/ProjectProvidesPackageConfigFiles.cmake b/Tests/RunCMake/FetchContent_find_package/ProjectProvidesPackageConfigFiles.cmake new file mode 100644 index 0000000..32e3f73 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/ProjectProvidesPackageConfigFiles.cmake @@ -0,0 +1,40 @@ +include(FetchContent) + +FetchContent_Declare( + ConfigForm1 + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/FatalIfAdded + FIND_PACKAGE_ARGS 1.8 EXACT REQUIRED +) +file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/ConfigForm1Config.cmake [[ +set(ConfigForm1_FOUND TRUE) +message(STATUS "ConfigForm1 override successful") +]] +) +file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/ConfigForm1ConfigVersion.cmake [[ +set(PACKAGE_VERSION 1.8) +set(PACKAGE_VERSION_EXACT TRUE) +set(PACKAGE_VERSION_COMPATIBLE TRUE) +]] +) + +FetchContent_Declare( + ConfigForm2 + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/FatalIfAdded + FIND_PACKAGE_ARGS 1.8 REQUIRED +) +file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/configform2-config.cmake [[ +set(ConfigForm2_FOUND TRUE) +message(STATUS "ConfigForm2 override successful") +]] +) +file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/configform2-config-version.cmake [[ +set(PACKAGE_VERSION 1.9.7) +set(PACKAGE_VERSION_EXACT FALSE) +set(PACKAGE_VERSION_COMPATIBLE TRUE) +]] +) + +FetchContent_MakeAvailable(ConfigForm1 ConfigForm2) + +message(STATUS "ConfigForm1_VERSION = ${ConfigForm1_VERSION}") +message(STATUS "ConfigForm2_VERSION = ${ConfigForm2_VERSION}") diff --git a/Tests/RunCMake/FetchContent_find_package/Redirect_find_package_MODULE-stdout.txt b/Tests/RunCMake/FetchContent_find_package/Redirect_find_package_MODULE-stdout.txt new file mode 100644 index 0000000..fbe6e38 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/Redirect_find_package_MODULE-stdout.txt @@ -0,0 +1,9 @@ +(-- )?find_package\(FirstProject\): +(-- )?Confirmation project has been added +(-- )?FirstProject_FOUND = 1 +(-- )?FetchContent_MakeAvailable\(FirstProject\): +(-- )?FetchContent_MakeAvailable\(SecondProject\): +(-- )?Confirmation project has been added +(-- )?find_package\(SecondProject\): +(-- )?SecondProject_FOUND = 1 +(-- )?End of test diff --git a/Tests/RunCMake/FetchContent_find_package/Redirect_find_package_MODULE.cmake b/Tests/RunCMake/FetchContent_find_package/Redirect_find_package_MODULE.cmake new file mode 100644 index 0000000..95bc2dc --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/Redirect_find_package_MODULE.cmake @@ -0,0 +1,39 @@ +include(FetchContent) + +set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_LIST_DIR}/PackageConfigs) + +FetchContent_Declare( + FirstProject + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/AddedProject + OVERRIDE_FIND_PACKAGE +) +FetchContent_Declare( + SecondProject + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/AddedProject + # Allow a call to find_package() that we know will fail. + # This enables redirection of calls to find_package(SecondProject) + # after FetchContent_MakeAvailable() populates. + FIND_PACKAGE_ARGS NAMES I_do_not_exist +) + +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/PackageFindModules) + +# Re-directs to FetchContent_MakeAvailable() +message(STATUS "find_package(FirstProject):") +find_package(FirstProject REQUIRED MODULE) +message(STATUS "FirstProject_FOUND = ${FirstProject_FOUND}") + +# Does nothing, already populated +message(STATUS "FetchContent_MakeAvailable(FirstProject):") +FetchContent_MakeAvailable(FirstProject) + +# Populates as normal +message(STATUS "FetchContent_MakeAvailable(SecondProject):") +FetchContent_MakeAvailable(SecondProject) + +# Redirects to config package file created by previous command +message(STATUS "find_package(SecondProject):") +find_package(SecondProject REQUIRED MODULE) +message(STATUS "SecondProject_FOUND = ${FirstProject_FOUND}") + +message(STATUS "End of test") diff --git a/Tests/RunCMake/FetchContent_find_package/RunCMakeTest.cmake b/Tests/RunCMake/FetchContent_find_package/RunCMakeTest.cmake new file mode 100644 index 0000000..c139f57 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/RunCMakeTest.cmake @@ -0,0 +1,22 @@ +include(RunCMake) + +unset(RunCMake_TEST_NO_CLEAN) + +function(run_FetchContent_pkgRedirects) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMAKE_FIND_PACKAGE_REDIRECTS_DIR-AlwaysEmptied-build) + run_cmake(CMAKE_FIND_PACKAGE_REDIRECTS_DIR-AlwaysEmptied-Setup) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake(CMAKE_FIND_PACKAGE_REDIRECTS_DIR-AlwaysEmptied) +endfunction() + +run_cmake(CMAKE_FIND_PACKAGE_REDIRECTS_DIR-Exists) +run_FetchContent_pkgRedirects() +run_cmake(BadArgs_find_package) +run_cmake(PreferFetchContent) +run_cmake(Prefer_find_package) +run_cmake(ProjectProvidesPackageConfigFiles) +run_cmake(Try_find_package-ALWAYS) +run_cmake(Try_find_package-NEVER) +run_cmake(Try_find_package-OPT_IN) +run_cmake(Try_find_package-BOGUS) +run_cmake(Redirect_find_package_MODULE) diff --git a/Tests/RunCMake/FetchContent_find_package/Try_find_package-ALWAYS-stdout.txt b/Tests/RunCMake/FetchContent_find_package/Try_find_package-ALWAYS-stdout.txt new file mode 100644 index 0000000..d43b8e8 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/Try_find_package-ALWAYS-stdout.txt @@ -0,0 +1,2 @@ +Loaded FirstProject from package config +(-- )?Confirmation project has been added diff --git a/Tests/RunCMake/FetchContent_find_package/Try_find_package-ALWAYS.cmake b/Tests/RunCMake/FetchContent_find_package/Try_find_package-ALWAYS.cmake new file mode 100644 index 0000000..0d7e289 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/Try_find_package-ALWAYS.cmake @@ -0,0 +1,18 @@ +include(FetchContent) + +set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_LIST_DIR}/PackageConfigs) +set(FETCHCONTENT_TRY_FIND_PACKAGE_MODE ALWAYS) + +FetchContent_Declare( + FirstProject + # Ensure failure if we don't re-route to find_package() + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/FatalIfAdded +) + +FetchContent_Declare( + SecondProject + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/AddedProject + OVERRIDE_FIND_PACKAGE # Takes precedence over ALWAYS mode +) + +FetchContent_MakeAvailable(FirstProject SecondProject) diff --git a/Tests/RunCMake/FetchContent_find_package/Try_find_package-BOGUS-result.txt b/Tests/RunCMake/FetchContent_find_package/Try_find_package-BOGUS-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/Try_find_package-BOGUS-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/FetchContent_find_package/Try_find_package-BOGUS-stderr.txt b/Tests/RunCMake/FetchContent_find_package/Try_find_package-BOGUS-stderr.txt new file mode 100644 index 0000000..4cc7347 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/Try_find_package-BOGUS-stderr.txt @@ -0,0 +1,2 @@ +CMake Error at .*/FetchContent.cmake:[0-9]+ \(message\): + Unsupported value for FETCHCONTENT_TRY_FIND_PACKAGE_MODE: BOGUS diff --git a/Tests/RunCMake/FetchContent_find_package/Try_find_package-BOGUS.cmake b/Tests/RunCMake/FetchContent_find_package/Try_find_package-BOGUS.cmake new file mode 100644 index 0000000..f9c8ce7 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/Try_find_package-BOGUS.cmake @@ -0,0 +1,8 @@ +include(FetchContent) + +set(FETCHCONTENT_TRY_FIND_PACKAGE_MODE BOGUS) + +FetchContent_Declare( + AddedProject + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/AddedProject +) diff --git a/Tests/RunCMake/FetchContent_find_package/Try_find_package-NEVER-stdout.txt b/Tests/RunCMake/FetchContent_find_package/Try_find_package-NEVER-stdout.txt new file mode 100644 index 0000000..52398e7 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/Try_find_package-NEVER-stdout.txt @@ -0,0 +1 @@ +Confirmation project has been added diff --git a/Tests/RunCMake/FetchContent_find_package/Try_find_package-NEVER.cmake b/Tests/RunCMake/FetchContent_find_package/Try_find_package-NEVER.cmake new file mode 100644 index 0000000..92cb7d0 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/Try_find_package-NEVER.cmake @@ -0,0 +1,12 @@ +include(FetchContent) + +set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_LIST_DIR}/PackageConfigs) +set(FETCHCONTENT_TRY_FIND_PACKAGE_MODE NEVER) + +FetchContent_Declare( + AddedProject + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/AddedProject + FIND_PACKAGE_ARGS REQUIRED +) + +FetchContent_MakeAvailable(AddedProject) diff --git a/Tests/RunCMake/FetchContent_find_package/Try_find_package-OPT_IN-stdout.txt b/Tests/RunCMake/FetchContent_find_package/Try_find_package-OPT_IN-stdout.txt new file mode 100644 index 0000000..d43b8e8 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/Try_find_package-OPT_IN-stdout.txt @@ -0,0 +1,2 @@ +Loaded FirstProject from package config +(-- )?Confirmation project has been added diff --git a/Tests/RunCMake/FetchContent_find_package/Try_find_package-OPT_IN.cmake b/Tests/RunCMake/FetchContent_find_package/Try_find_package-OPT_IN.cmake new file mode 100644 index 0000000..a549583 --- /dev/null +++ b/Tests/RunCMake/FetchContent_find_package/Try_find_package-OPT_IN.cmake @@ -0,0 +1,20 @@ +include(FetchContent) + +set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_LIST_DIR}/PackageConfigs) +set(FETCHCONTENT_TRY_FIND_PACKAGE_MODE OPT_IN) + +# With opt-in, should call find_package() +FetchContent_Declare( + FirstProject + # Ensure failure if we don't re-route to find_package() + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/FatalIfAdded + FIND_PACKAGE_ARGS REQUIRED +) + +# Without opt-in, shouldn't call find_package() +FetchContent_Declare( + SecondProject + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/AddedProject +) + +FetchContent_MakeAvailable(FirstProject SecondProject) diff --git a/Tests/RunCMake/find_package/FromPATHEnv-stderr.txt b/Tests/RunCMake/find_package/FromPATHEnv-stderr.txt index 691d7f0..fdf098d 100644 --- a/Tests/RunCMake/find_package/FromPATHEnv-stderr.txt +++ b/Tests/RunCMake/find_package/FromPATHEnv-stderr.txt @@ -6,6 +6,11 @@ The file was not found. + The internally managed CMAKE_FIND_PACKAGE_REDIRECTS_DIR. + + [^ +]*/Tests/RunCMake/find_package/FromPATHEnv-build/CMakeFiles/pkgRedirects + <PackageName>_ROOT CMake variable \[CMAKE_FIND_USE_PACKAGE_ROOT_PATH\]. none @@ -69,6 +74,10 @@ module: [^ +]*/Tests/RunCMake/find_package/FromPATHEnv-build/CMakeFiles/pkgRedirects/ResolvedConfig.cmake + [^ +]*/Tests/RunCMake/find_package/FromPATHEnv-build/CMakeFiles/pkgRedirects/resolved-config.cmake + [^ ]*/Tests/RunCMake/find_package/PackageRoot/ResolvedConfig.cmake The file was found at diff --git a/Tests/RunCMake/find_package/FromPATHEnvDebugPkg-stderr.txt b/Tests/RunCMake/find_package/FromPATHEnvDebugPkg-stderr.txt index ef5ec33..5140616 100644 --- a/Tests/RunCMake/find_package/FromPATHEnvDebugPkg-stderr.txt +++ b/Tests/RunCMake/find_package/FromPATHEnvDebugPkg-stderr.txt @@ -6,6 +6,11 @@ The file was not found. + The internally managed CMAKE_FIND_PACKAGE_REDIRECTS_DIR. + + [^ +]*/Tests/RunCMake/find_package/FromPATHEnvDebugPkg-build/CMakeFiles/pkgRedirects + <PackageName>_ROOT CMake variable \[CMAKE_FIND_USE_PACKAGE_ROOT_PATH\]. none @@ -69,6 +74,10 @@ module: [^ +]*/Tests/RunCMake/find_package/FromPATHEnvDebugPkg-build/CMakeFiles/pkgRedirects/ResolvedConfig.cmake + [^ +]*/Tests/RunCMake/find_package/FromPATHEnvDebugPkg-build/CMakeFiles/pkgRedirects/resolved-config.cmake + [^ ]*/Tests/RunCMake/find_package/PackageRoot/ResolvedConfig.cmake The file was found at diff --git a/Tests/RunCMake/find_package/ModuleModeDebugPkg-stderr.txt b/Tests/RunCMake/find_package/ModuleModeDebugPkg-stderr.txt index e4fd7c5..9757803 100644 --- a/Tests/RunCMake/find_package/ModuleModeDebugPkg-stderr.txt +++ b/Tests/RunCMake/find_package/ModuleModeDebugPkg-stderr.txt @@ -97,6 +97,11 @@ Call Stack \(most recent call first\): FindBar processed here. + CMake Debug Log at ModuleModeDebugPkg/FindFoo.cmake:[0-9]+ \(find_package\): + The internally managed CMAKE_FIND_PACKAGE_REDIRECTS_DIR. + + [^ +]*/Tests/RunCMake/find_package/ModuleModeDebugPkg-build/CMakeFiles/pkgRedirects + Paths specified by the find_package HINTS option. none @@ -107,6 +112,11 @@ CMake Debug Log at ModuleModeDebugPkg/FindFoo.cmake:[0-9]+ \(find_package\): find_package considered the following locations for Zot's Config module: + [^ +]*/Tests/RunCMake/find_package/ModuleModeDebugPkg-build/CMakeFiles/pkgRedirects/ZotConfig.cmake + [^ +]*/Tests/RunCMake/find_package/ModuleModeDebugPkg-build/CMakeFiles/pkgRedirects/zot-config.cmake + The file was not found. Call Stack \(most recent call first\): diff --git a/Tests/WatcomRuntimeLibrary/CMakeLists.txt b/Tests/WatcomRuntimeLibrary/CMakeLists.txt new file mode 100644 index 0000000..e8a3edc --- /dev/null +++ b/Tests/WatcomRuntimeLibrary/CMakeLists.txt @@ -0,0 +1,49 @@ +cmake_minimum_required(VERSION 3.23) +cmake_policy(SET CMP0136 NEW) +project(WatcomRuntimeLibrary) + +function(verify_combinations threads lang src) + set(verify_def_MultiThreaded -DVERIFY_MT) + set(verify_def_DLL -DVERIFY_DLL) + foreach(dll "" DLL) + # Construct the name of this runtime library combination. + set(rtl "${threads}${dll}") + + # Test that try_compile builds with this RTL. + set(CMAKE_WATCOM_RUNTIME_LIBRARY "${rtl}") + set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") + try_compile(${rtl}_COMPILES + ${CMAKE_CURRENT_BINARY_DIR}/try_compile/${rtl} + ${CMAKE_CURRENT_SOURCE_DIR}/${src} + COMPILE_DEFINITIONS ${verify_def_${threads}} ${verify_def_${dll}} + OUTPUT_VARIABLE ${rtl}_OUTPUT + ) + if(${rtl}_COMPILES) + message(STATUS "try_compile with ${rtl} worked") + else() + string(REPLACE "\n" "\n " ${rtl}_OUTPUT " ${${rtl}_OUTPUT}") + message(SEND_ERROR "try_compile with ${rtl} failed:\n${${rtl}_OUTPUT}") + endif() + + # Test that targets build with this RTL. + set(CMAKE_WATCOM_RUNTIME_LIBRARY "$<$<BOOL:$<TARGET_PROPERTY:BOOL_TRUE>>:${rtl}>$<$<BOOL:$<TARGET_PROPERTY:BOOL_FALSE>>:BadContent>") + add_library(${rtl}-${lang} ${src}) + set_property(TARGET ${rtl}-${lang} PROPERTY BOOL_TRUE TRUE) + target_compile_definitions(${rtl}-${lang} PRIVATE ${verify_def_${threads}} ${verify_def_${dll}}) + endforeach() +endfunction() + +function(verify lang src) + add_library(default-${lang} ${src}) + target_compile_definitions(default-${lang} PRIVATE VERIFY_MT VERIFY_DLL) + + verify_combinations(SingleThreaded ${lang} ${src}) + verify_combinations(MultiThreaded ${lang} ${src}) + + # Test known default behavior when no flag is given. + set(CMAKE_WATCOM_RUNTIME_LIBRARY "") + add_library(empty-${lang} ${src}) +endfunction() + +verify(C verify.c) +verify(CXX verify.cxx) diff --git a/Tests/WatcomRuntimeLibrary/verify.c b/Tests/WatcomRuntimeLibrary/verify.c new file mode 100644 index 0000000..741bca6 --- /dev/null +++ b/Tests/WatcomRuntimeLibrary/verify.c @@ -0,0 +1 @@ +#include "verify.h" diff --git a/Tests/WatcomRuntimeLibrary/verify.cxx b/Tests/WatcomRuntimeLibrary/verify.cxx new file mode 100644 index 0000000..741bca6 --- /dev/null +++ b/Tests/WatcomRuntimeLibrary/verify.cxx @@ -0,0 +1 @@ +#include "verify.h" diff --git a/Tests/WatcomRuntimeLibrary/verify.h b/Tests/WatcomRuntimeLibrary/verify.h new file mode 100644 index 0000000..6c67e6d --- /dev/null +++ b/Tests/WatcomRuntimeLibrary/verify.h @@ -0,0 +1,31 @@ +#ifdef VERIFY_DLL +# ifndef _DLL +# error "_DLL not defined by DLL runtime library selection" +# endif +# ifndef __SW_BR +# error "__SW_BR not defined by DLL runtime library selection" +# endif +#else +# ifdef _DLL +# error "_DLL defined by non-DLL runtime library selection" +# endif +# ifdef __SW_BR +# error "__SW_BR defined by non-DLL runtime library selection" +# endif +#endif + +#ifdef VERIFY_MT +# ifndef _MT +# error "_MT not defined by multi-threaded runtime library selection" +# endif +# ifndef __SW_BM +# error "__SW_BM not defined by multi-threaded runtime library selection" +# endif +#else +# ifdef _MT +# error "_MT defined by single-threaded runtime library selection" +# endif +# ifdef __SW_BM +# error "__SW_BM defined by single-threaded runtime library selection" +# endif +#endif |