diff options
author | Marc Chevrier <marc.chevrier@gmail.com> | 2022-04-16 08:57:30 (GMT) |
---|---|---|
committer | Marc Chevrier <marc.chevrier@gmail.com> | 2022-04-29 20:00:02 (GMT) |
commit | 8d7e80cf3d39ae24a6c88ee07492b9cfe40defd5 (patch) | |
tree | 3463bda9324fb4bae11d6c470086b4b942246597 | |
parent | 08941a9a40c7786aa2ee8ff8e7c684eaf016513e (diff) | |
download | CMake-8d7e80cf3d39ae24a6c88ee07492b9cfe40defd5.zip CMake-8d7e80cf3d39ae24a6c88ee07492b9cfe40defd5.tar.gz CMake-8d7e80cf3d39ae24a6c88ee07492b9cfe40defd5.tar.bz2 |
find_* commands: add control over Windows registry views
Fixes: #22775
115 files changed, 1926 insertions, 57 deletions
diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt index 1e75dc9..ab5f860 100644 --- a/Help/command/FIND_XXX.txt +++ b/Help/command/FIND_XXX.txt @@ -13,6 +13,7 @@ The general signature is: name | |NAMES| [HINTS [path | ENV var]... ] [PATHS [path | ENV var]... ] + [REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)] [PATH_SUFFIXES suffix1 [suffix2 ...]] [DOC "cache documentation string"] [NO_CACHE] @@ -51,6 +52,18 @@ Options include: The ``ENV var`` sub-option reads paths from a system environment variable. + .. versionchanged:: 3.24 + On ``Windows`` platform, it is possible to include registry queries as part + of the directories. Such specifications will be ignored on all other + platforms. + + .. include:: FIND_XXX_REGISTRY_QUERY.txt + +``REGISTRY_VIEW`` + .. versionadded:: 3.24 + + .. include:: FIND_XXX_REGISTRY_VIEW.txt + ``PATH_SUFFIXES`` Specify additional subdirectories to check below each directory location otherwise considered. diff --git a/Help/command/FIND_XXX_REGISTRY_QUERY.txt b/Help/command/FIND_XXX_REGISTRY_QUERY.txt new file mode 100644 index 0000000..04a087a --- /dev/null +++ b/Help/command/FIND_XXX_REGISTRY_QUERY.txt @@ -0,0 +1,43 @@ +The formal syntax, as specified using +`BNF <https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form>`_ notation with +the regular extensions, for registry query is the following: + +.. parsed-literal:: + + registry_query ::= '[' `sep_definition`_? `root_key`_ + ((`key_separator`_ `sub_key`_)? (`value_separator`_ `value_name`_)?)? ']' + _`sep_definition` ::= '{' `value_separator`_ '}' + _`root_key` ::= 'HKLM' | 'HKEY_LOCAL_MACHINE' | 'HKCU' | 'HKEY_CURRENT_USER' | + 'HKCR' | 'HKEY_CLASSES_ROOT' | 'HKCC' | 'HKEY_CURRENT_CONFIG' | + 'HKU' | 'HKEY_USERS' + _`sub_key` ::= `element`_ (`key_separator`_ `element`_)* + _`key_separator` ::= '/' | '\\' + _`value_separator` ::= `element`_ | ';' + _`value_name` ::= `element`_ | '(default)' + _`element` ::= `character`_\+ + _`character` ::= <any character except `key_separator`_ and `value_separator`_> + +The `sep_definition`_ optional item offers the possibility to specify the +string used to separate the `sub_key`_ from the `value_name`_ item. If +not specified, the character ``;`` is used. + +.. parsed-literal:: + + # example using default separator + |FIND_XXX| (... **PATHS** "/root/[HKLM/Stuff;InstallDir]/lib[HKLM\\\\Stuff;Architecture]") + + # example using different specified separators + |FIND_XXX| (... **HINTS** "/root/[{|}HKCU/Stuff|InstallDir]/lib[{@@}HKCU\\\\Stuff@@Architecture]") + +If the `value_name`_ item is not specified or has the special name +``(default)``, the content of the default value, if any, will be returned. The +supported types for the `value_name`_ are: + +* ``REG_SZ``. +* ``REG_EXPAND_SZ``. The returned data is expanded. +* ``REG_DWORD``. +* ``REG_QWORD``. + +When the registry query failed, typically because the key does not exist or +the data type is not supported, the string ``/REGISTRY-NOTFOUND`` is substituted +to the ``[]`` query expression. diff --git a/Help/command/FIND_XXX_REGISTRY_VIEW.txt b/Help/command/FIND_XXX_REGISTRY_VIEW.txt new file mode 100644 index 0000000..39b156f --- /dev/null +++ b/Help/command/FIND_XXX_REGISTRY_VIEW.txt @@ -0,0 +1,41 @@ +Specify which registry views must be queried. This option is only meaningful +on ``Windows`` platform and will be ignored on other ones. When not +specified, |FIND_XXX_REGISTRY_VIEW_DEFAULT| view is used when :policy:`CMP0134` +policy is ``NEW``. Refer to :policy:`CMP0134` policy for default view when +policy is ``OLD`` or undefined. + +``64`` + Query the 64bit registry. On ``32bit Windows``, returns always the string + ``/REGISTRY-NOTFOUND``. + +``32`` + Query the 32bit registry. + +``64_32`` + Query both views (``64`` and ``32``) and generate a path for each. + +``32_64`` + Query both views (``32`` and ``64``) and generate a path for each. + +``HOST`` + Query the registry matching the architecture of the host: ``64`` on ``64bit + Windows`` and ``32`` on ``32bit Windows``. + +``TARGET`` + Query the registry matching the architecture specified by + :variable:`CMAKE_SIZEOF_VOID_P` variable. If not defined, fallback to + ``HOST`` view. + +``BOTH`` + Query both views (``32`` and ``64``). The order depends of the following + rules: If :variable:`CMAKE_SIZEOF_VOID_P` variable is defined. Use the + following view depending of the content of this variable: + + * ``8``: ``64_32`` + * ``4``: ``32_64`` + + If :variable:`CMAKE_SIZEOF_VOID_P` variable is not defined, rely on + architecture of the host: + + * ``64bit``: ``64_32`` + * ``32bit``: ``32`` diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index ec73f9f..4fe9326 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -288,12 +288,12 @@ The options are: .. productionlist:: depfile depfile: `rule`* - rule: `targets` (`:` (`separator` `dependencies`?)?)? `eol` + rule: `targets` (':' (`separator` `dependencies`?)?)? `eol` targets: `target` (`separator` `target`)* `separator`* target: `pathname` dependencies: `dependency` (`separator` `dependency`)* `separator`* dependency: `pathname` - separator: (space | line_continue)+ + separator: (`space` | `line_continue`)+ line_continue: '\' `eol` space: ' ' | '\t' pathname: `character`+ diff --git a/Help/command/find_file.rst b/Help/command/find_file.rst index 39dfb85..c5c4014 100644 --- a/Help/command/find_file.rst +++ b/Help/command/find_file.rst @@ -8,6 +8,8 @@ find_file .. |prefix_XXX_SUBDIR| replace:: ``<prefix>/include`` .. |entry_XXX_SUBDIR| replace:: ``<entry>/include`` +.. |FIND_XXX_REGISTRY_VIEW_DEFAULT| replace:: ``TARGET`` + .. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace:: ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set, and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR| diff --git a/Help/command/find_library.rst b/Help/command/find_library.rst index ab957ce..c237e7f 100644 --- a/Help/command/find_library.rst +++ b/Help/command/find_library.rst @@ -8,6 +8,8 @@ find_library .. |prefix_XXX_SUBDIR| replace:: ``<prefix>/lib`` .. |entry_XXX_SUBDIR| replace:: ``<entry>/lib`` +.. |FIND_XXX_REGISTRY_VIEW_DEFAULT| replace:: ``TARGET`` + .. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace:: ``<prefix>/lib/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set, and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR| diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index 86e26e9..0d8a166 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -1,6 +1,12 @@ find_package ------------ +.. |FIND_XXX| replace:: find_package +.. |FIND_ARGS_XXX| replace:: <PackageName> +.. |FIND_XXX_REGISTRY_VIEW_DEFAULT| replace:: ``TARGET`` +.. |CMAKE_FIND_ROOT_PATH_MODE_XXX| replace:: + :variable:`CMAKE_FIND_ROOT_PATH_MODE_PACKAGE` + .. only:: html .. contents:: @@ -74,11 +80,12 @@ sections on this page. Basic Signature ^^^^^^^^^^^^^^^ -.. code-block:: cmake +.. parsed-literal:: find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE] [REQUIRED] [[COMPONENTS] [components...]] [OPTIONAL_COMPONENTS components...] + [REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)] [NO_POLICY_SCOPE] [GLOBAL]) @@ -116,6 +123,12 @@ define what occurs in such cases. Common arrangements include assuming it should find all components, no components or some well-defined subset of the available components. +.. versionadded:: 3.24 + The ``REGISTRY_VIEW`` keyword enables to specify which registry views must be + queried. This keyword is only meaningful on ``Windows`` platform and will be + ignored on all other ones. Formally, it is up to the target package how to + interpret the registry view information given to it. + Specifying the ``GLOBAL`` keyword will promote all imported targets to a global scope in the importing project. Alternatively this functionality can be enabled by setting the variable @@ -155,7 +168,7 @@ of the ``NO_POLICY_SCOPE`` option. Full Signature ^^^^^^^^^^^^^^ -.. code-block:: cmake +.. parsed-literal:: find_package(<PackageName> [version] [EXACT] [QUIET] [REQUIRED] [[COMPONENTS] [components...]] @@ -167,6 +180,7 @@ Full Signature [CONFIGS config1 [config2 ...]] [HINTS path1 [path2 ... ]] [PATHS path1 [path2 ... ]] + [REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)] [PATH_SUFFIXES suffix1 [suffix2 ...]] [NO_DEFAULT_PATH] [NO_PACKAGE_ROOT_PATH] @@ -272,6 +286,19 @@ that order). if the :prop_gbl:`FIND_LIBRARY_USE_LIBX32_PATHS` property is set to ``TRUE``. * The ``lib`` path is always searched. +.. versionchanged:: 3.24 + On ``Windows`` platform, it is possible to include registry queries as part + of the directories specified through ``HINTS`` and ``PATHS`` keywords. Such + specifications will be ignored on all other platforms. + +.. include:: FIND_XXX_REGISTRY_QUERY.txt + +.. versionadded:: 3.24 + ``REGISTRY_VIEW`` can be specified to manage ``Windows`` registry queries + specified as part of ``PATHS`` and ``HINTS``. + +.. include:: FIND_XXX_REGISTRY_VIEW.txt + If ``PATH_SUFFIXES`` is specified, the suffixes are appended to each (``W``) or (``U``) directory entry one-by-one. @@ -382,11 +409,6 @@ of the above locations to be ignored. Added the ``CMAKE_FIND_USE_<CATEGORY>`` variables to globally disable various search locations. -.. |FIND_XXX| replace:: find_package -.. |FIND_ARGS_XXX| replace:: <PackageName> -.. |CMAKE_FIND_ROOT_PATH_MODE_XXX| replace:: - :variable:`CMAKE_FIND_ROOT_PATH_MODE_PACKAGE` - .. include:: FIND_XXX_ROOT.txt .. include:: FIND_XXX_ORDER.txt @@ -557,6 +579,8 @@ restores their original state before returning): True if ``REQUIRED`` option was given ``<PackageName>_FIND_QUIETLY`` True if ``QUIET`` option was given +``<PackageName>_FIND_REGISTRY_VIEW`` + The requested view if ``REGISTRY_VIEW`` option was given ``<PackageName>_FIND_VERSION`` Full requested version string ``<PackageName>_FIND_VERSION_MAJOR`` diff --git a/Help/command/find_path.rst b/Help/command/find_path.rst index ec66771..1d7648d 100644 --- a/Help/command/find_path.rst +++ b/Help/command/find_path.rst @@ -8,6 +8,8 @@ find_path .. |prefix_XXX_SUBDIR| replace:: ``<prefix>/include`` .. |entry_XXX_SUBDIR| replace:: ``<entry>/include`` +.. |FIND_XXX_REGISTRY_VIEW_DEFAULT| replace:: ``TARGET`` + .. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace:: ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set, and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR| diff --git a/Help/command/find_program.rst b/Help/command/find_program.rst index e2ff693..f4149be 100644 --- a/Help/command/find_program.rst +++ b/Help/command/find_program.rst @@ -8,6 +8,8 @@ find_program .. |prefix_XXX_SUBDIR| replace:: ``<prefix>/[s]bin`` .. |entry_XXX_SUBDIR| replace:: ``<entry>/[s]bin`` +.. |FIND_XXX_REGISTRY_VIEW_DEFAULT| replace:: ``BOTH`` + .. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace:: |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR| .. |CMAKE_PREFIX_PATH_XXX| replace:: diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 84ef15f..d1fafb5 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 + 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> CMP0132: Do not set compiler environment variables on first run. </policy/CMP0132> CMP0131: LINK_LIBRARIES supports the LINK_ONLY generator expression. </policy/CMP0131> diff --git a/Help/policy/CMP0134.rst b/Help/policy/CMP0134.rst new file mode 100644 index 0000000..2b562bc --- /dev/null +++ b/Help/policy/CMP0134.rst @@ -0,0 +1,39 @@ +CMP0134 +------- + +.. versionadded:: 3.24 + +The default registry view is ``TARGET`` for the :command:`find_file`, +:command:`find_path`, :command:`find_library`, and :command:`find_package` +commands and ``BOTH`` for the :command:`find_program` command. + +The default registry views in CMake 3.23 and below are selected using the +following rules: + +* if :variable:`CMAKE_SIZEOF_VOID_P` has value ``8``: + + * Use view ``64`` for all ``find_*`` commands except :command:`find_program` + command. + * Use view ``64_32`` for :command:`find_program` command. + +* if :variable:`CMAKE_SIZEOF_VOID_P` has value ``4`` or is undefined: + + * Use view ``32`` for all ``find_*`` commands except :command:`find_program` + command. + * Use view ``32_64`` for :command:`find_program` command. + +The ``OLD`` behavior for this policy is to use registry views ``64`` and +``64_32`` or ``32_64`` and ``32`` as default, depending of +:variable:`CMAKE_SIZEOF_VOID_P` variable value. +The ``NEW`` behavior for this policy is to use registry views ``TARGET`` and +``BOTH`` as default. + +This policy was introduced in CMake version 3.24. Use the +:command:`cmake_policy` command to set this policy to ``OLD`` or ``NEW`` +explicitly. Unlike many policies, CMake version |release| does *not* warn +by default when this policy is not set and simply uses ``OLD`` behavior. +See documentation of the +:variable:`CMAKE_POLICY_WARNING_CMP0133 <CMAKE_POLICY_WARNING_CMP<NNNN>>` +variable to control the warning. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/find_item-query-windows-registry.rst b/Help/release/dev/find_item-query-windows-registry.rst new file mode 100644 index 0000000..ff0bd40 --- /dev/null +++ b/Help/release/dev/find_item-query-windows-registry.rst @@ -0,0 +1,6 @@ +find_item-query-windows-registry.rst +------------------------------------ + +* :command:`find_file`, :command:`find_path`, :command:`find_library`, + :command:`find_program`, and :command:`find_package` commands gain the + capability to specify which registry views must be queried. diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index a8db63d..702d9fe 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -7,6 +7,7 @@ #include <map> #include <utility> +#include <cm/optional> #include <cmext/algorithm> #include "cmCMakePath.h" @@ -20,6 +21,7 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" +#include "cmWindowsRegistry.h" #include "cmake.h" class cmExecutionStatus; @@ -123,6 +125,19 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn) doing = DoingNone; this->Required = true; newStyle = true; + } else if (args[j] == "REGISTRY_VIEW") { + if (++j == args.size()) { + this->SetError("missing required argument for \"REGISTRY_VIEW\""); + return false; + } + auto view = cmWindowsRegistry::ToView(args[j]); + if (view) { + this->RegistryView = *view; + } else { + this->SetError( + cmStrCat("given invalid value for \"REGISTRY_VIEW\": ", args[j])); + return false; + } } else if (this->CheckCommonArgument(args[j])) { doing = DoingNone; } else { diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index 9fd712a..c3fb907 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -11,6 +11,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmPolicies.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" @@ -58,6 +59,17 @@ cmFindCommon::cmFindCommon(cmExecutionStatus& status) this->InitializeSearchPathGroups(); this->DebugMode = false; + + // Windows Registry views + // When policy CMP0134 is not NEW, rely on previous behavior: + if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0134) != + cmPolicies::NEW) { + if (this->Makefile->GetDefinition("CMAKE_SIZEOF_VOID_P") == "8") { + this->RegistryView = cmWindowsRegistry::View::Reg64; + } else { + this->RegistryView = cmWindowsRegistry::View::Reg32; + } + } } void cmFindCommon::SetError(std::string const& e) diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h index 4c02df0..41de797 100644 --- a/Source/cmFindCommon.h +++ b/Source/cmFindCommon.h @@ -11,6 +11,7 @@ #include "cmPathLabel.h" #include "cmSearchPath.h" +#include "cmWindowsRegistry.h" class cmExecutionStatus; class cmMakefile; @@ -131,6 +132,7 @@ protected: bool NoSystemEnvironmentPath; bool NoCMakeSystemPath; bool NoCMakeInstallPath; + cmWindowsRegistry::View RegistryView = cmWindowsRegistry::View::Target; std::vector<std::string> SearchPathSuffixes; diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 9a89935..e23ed0b 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -13,6 +13,7 @@ #include <utility> #include <cm/memory> +#include <cm/optional> #include <cmext/string_view> #include "cmsys/Directory.hxx" @@ -33,6 +34,7 @@ #include "cmSystemTools.h" #include "cmValue.h" #include "cmVersion.h" +#include "cmWindowsRegistry.h" #if defined(__HAIKU__) # include <FindDirectory.h> @@ -317,6 +319,20 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) // Ignore legacy option. configArgs.insert(i); doing = DoingNone; + } else if (args[i] == "REGISTRY_VIEW") { + if (++i == args.size()) { + this->SetError("missing required argument for \"REGISTRY_VIEW\""); + return false; + } + auto view = cmWindowsRegistry::ToView(args[i]); + if (view) { + this->RegistryView = *view; + this->RegistryViewDefined = true; + } else { + this->SetError( + cmStrCat("given invalid value for \"REGISTRY_VIEW\": ", args[i])); + return false; + } } else if (this->CheckCommonArgument(args[i])) { configArgs.insert(i); doing = DoingNone; @@ -767,6 +783,11 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components) id = cmStrCat(this->Name, "_FIND_VERSION_RANGE_MAX"); this->AddFindDefinition(id, this->VersionRangeMax); } + + if (this->RegistryViewDefined) { + this->AddFindDefinition(cmStrCat(this->Name, "_FIND_REGISTRY_VIEW"), + cmWindowsRegistry::FromView(this->RegistryView)); + } } void cmFindPackageCommand::AddFindDefinition(const std::string& var, diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index b9f19e4..03f29b6 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -200,6 +200,7 @@ private: bool UseRealPath = false; bool PolicyScope = true; bool GlobalScope = false; + bool RegistryViewDefined = false; std::string LibraryArchitecture; std::vector<std::string> Names; std::vector<std::string> Configs; diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index 780b256..a64e0e4 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -12,6 +12,8 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" +#include "cmWindowsRegistry.h" class cmExecutionStatus; @@ -172,6 +174,18 @@ cmFindProgramCommand::cmFindProgramCommand(cmExecutionStatus& status) this->NamesPerDirAllowed = true; this->VariableDocumentation = "Path to a program."; this->VariableType = cmStateEnums::FILEPATH; + // Windows Registry views + // When policy CMP0134 is not NEW, rely on previous behavior: + if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0134) != + cmPolicies::NEW) { + if (this->Makefile->GetDefinition("CMAKE_SIZEOF_VOID_P") == "8") { + this->RegistryView = cmWindowsRegistry::View::Reg64_32; + } else { + this->RegistryView = cmWindowsRegistry::View::Reg32_64; + } + } else { + this->RegistryView = cmWindowsRegistry::View::Both; + } } // cmFindProgramCommand diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 5393747..8739c55 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -400,6 +400,10 @@ class cmMakefile; SELECT(POLICY, CMP0133, \ "The CPack module disables SLA by default in the CPack DragNDrop " \ "Generator.", \ + 3, 24, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0134, \ + "Fallback to \"HOST\" Windows registry view when \"TARGET\" view " \ + "is not usable.", \ 3, 24, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx index bfee64c..6c53b85 100644 --- a/Source/cmSearchPath.cxx +++ b/Source/cmSearchPath.cxx @@ -6,11 +6,14 @@ #include <cassert> #include <utility> +#include <cm/optional> + #include "cmFindCommon.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" +#include "cmWindowsRegistry.h" cmSearchPath::cmSearchPath(cmFindCommon* findCmd) : FC(findCmd) @@ -46,26 +49,13 @@ void cmSearchPath::AddUserPath(const std::string& path) std::vector<std::string> outPaths; - // We should view the registry as the target application would view - // it. - cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32; - cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64; - if (this->FC->Makefile->PlatformIs64Bit()) { - view = cmSystemTools::KeyWOW64_64; - other_view = cmSystemTools::KeyWOW64_32; - } - - // Expand using the view of the target application. - std::string expanded = path; - cmSystemTools::ExpandRegistryValues(expanded, view); - cmSystemTools::GlobDirs(expanded, outPaths); - - // Executables can be either 32-bit or 64-bit, so expand using the - // alternative view. - if (expanded != path && this->FC->CMakePathName == "PROGRAM") { - expanded = path; - cmSystemTools::ExpandRegistryValues(expanded, other_view); - cmSystemTools::GlobDirs(expanded, outPaths); + cmWindowsRegistry registry(*this->FC->Makefile, + cmWindowsRegistry::SimpleTypes); + auto expandedPaths = registry.ExpandExpression(path, this->FC->RegistryView); + if (expandedPaths) { + for (const auto& expandedPath : expandedPaths.value()) { + cmSystemTools::GlobDirs(expandedPath, outPaths); + } } // Process them all from the current directory diff --git a/Source/cmWindowsRegistry.cxx b/Source/cmWindowsRegistry.cxx index 9048334..6dba863 100644 --- a/Source/cmWindowsRegistry.cxx +++ b/Source/cmWindowsRegistry.cxx @@ -1,33 +1,61 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmConfigure.h" // IWYU pragma: keep #include "cmWindowsRegistry.h" +#include <cctype> +#include <cstddef> +#include <functional> +#include <type_traits> #include <unordered_map> +#include <utility> + +#include <cmext/string_view> + +#include "cmsys/RegularExpression.hxx" #if defined(_WIN32) && !defined(__CYGWIN__) # include <algorithm> -# include <cstdint> +# include <cstring> # include <exception> # include <iterator> -# include <utility> # include <vector> # include <cm/memory> -# include <cmext/string_view> # include <windows.h> -# include "cmsys/Encoding.hxx" -# include "cmsys/SystemTools.hxx" - # include "cmMakefile.h" # include "cmStringAlgorithms.h" # include "cmValue.h" #endif -#if defined(_WIN32) && !defined(__CYGWIN__) namespace { +// Case-independent string comparison +int Strucmp(cm::string_view l, cm::string_view r) +{ + if (l.empty() && r.empty()) { + return 0; + } + if (l.empty() || r.empty()) { + return static_cast<int>(l.size() - r.size()); + } + + int lc; + int rc; + cm::string_view::size_type li = 0; + cm::string_view::size_type ri = 0; + + do { + lc = std::tolower(l[li++]); + rc = std::tolower(r[ri++]); + } while (lc == rc && li < l.size() && ri < r.size()); + + return lc == rc ? static_cast<int>(l.size() - r.size()) : lc - rc; +} + +#if defined(_WIN32) && !defined(__CYGWIN__) bool Is64BitWindows() { # if defined(_WIN64) @@ -40,6 +68,26 @@ bool Is64BitWindows() # endif } +// Helper to translate Windows registry value type to enum ValueType +cm::optional<cmWindowsRegistry::ValueType> ToValueType(DWORD type) +{ + using ValueType = cmWindowsRegistry::ValueType; + + static std::unordered_map<DWORD, ValueType> ValueTypes{ + { REG_SZ, ValueType::Reg_SZ }, + { REG_EXPAND_SZ, ValueType::Reg_EXPAND_SZ }, + { REG_MULTI_SZ, ValueType::Reg_MULTI_SZ }, + { REG_DWORD, ValueType::Reg_DWORD }, + { REG_QWORD, ValueType::Reg_QWORD } + }; + + auto it = ValueTypes.find(type); + + return it == ValueTypes.end() + ? cm::nullopt + : cm::optional<cmWindowsRegistry::ValueType>{ it->second }; +} + // class registry_exception class registry_error : public std::exception { @@ -61,6 +109,7 @@ class KeyHandler { public: using View = cmWindowsRegistry::View; + using ValueTypeSet = cmWindowsRegistry::ValueTypeSet; KeyHandler(HKEY hkey) : Handler(hkey) @@ -68,9 +117,14 @@ public: } ~KeyHandler() { RegCloseKey(this->Handler); } + static KeyHandler OpenKey(cm::string_view rootKey, cm::string_view subKey, + View view); static KeyHandler OpenKey(cm::string_view key, View view); - std::string ReadValue(cm::string_view name, cm::string_view separator); + std::string ReadValue( + cm::string_view name, + ValueTypeSet supportedTypes = cmWindowsRegistry::AllTypes, + cm::string_view separator = "\0"_s); std::vector<std::string> GetValueNames(); std::vector<std::string> GetSubKeys(); @@ -83,16 +137,14 @@ private: HKEY Handler; }; -KeyHandler KeyHandler::OpenKey(cm::string_view key, View view) +KeyHandler KeyHandler::OpenKey(cm::string_view rootKey, cm::string_view subKey, + View view) { if (view == View::Reg64 && !Is64BitWindows()) { throw registry_error("No 64bit registry on Windows32."); } - auto start = key.find_first_of("\\/"_s); - auto rootKey = key.substr(0, start); HKEY hRootKey; - if (rootKey == "HKCU"_s || rootKey == "HKEY_CURRENT_USER"_s) { hRootKey = HKEY_CURRENT_USER; } else if (rootKey == "HKLM"_s || rootKey == "HKEY_LOCAL_MACHINE"_s) { @@ -106,12 +158,9 @@ KeyHandler KeyHandler::OpenKey(cm::string_view key, View view) } else { throw registry_error(cmStrCat(rootKey, ": invalid root key.")); } - std::wstring subKey; - if (start != cm::string_view::npos) { - subKey = ToWide(key.substr(start + 1)); - } // Update path format - std::replace(subKey.begin(), subKey.end(), L'/', L'\\'); + auto key = ToWide(subKey); + std::replace(key.begin(), key.end(), L'/', L'\\'); REGSAM options = KEY_READ; if (Is64BitWindows()) { @@ -119,14 +168,25 @@ KeyHandler KeyHandler::OpenKey(cm::string_view key, View view) } HKEY hKey; - if (LSTATUS status = RegOpenKeyExW(hRootKey, subKey.c_str(), 0, options, - &hKey) != ERROR_SUCCESS) { + LSTATUS status; + if ((status = RegOpenKeyExW(hRootKey, key.c_str(), 0, options, &hKey)) != + ERROR_SUCCESS) { throw registry_error(FormatSystemError(status)); } return KeyHandler(hKey); } +KeyHandler KeyHandler::OpenKey(cm::string_view key, View view) +{ + auto start = key.find_first_of("\\/"_s); + + return OpenKey(key.substr(0, start), + start == cm::string_view::npos ? cm::string_view{ ""_s } + : key.substr(start + 1), + view); +} + std::string KeyHandler::FormatSystemError(LSTATUS status) { std::string formattedMessage{ "Windows Registry: unexpected error." }; @@ -208,6 +268,7 @@ std::string KeyHandler::ToNarrow(const wchar_t* wstr, int size) } std::string KeyHandler::ReadValue(cm::string_view name, + ValueTypeSet supportedTypes, cm::string_view separator) { LSTATUS status; @@ -225,6 +286,12 @@ std::string KeyHandler::ReadValue(cm::string_view name, &type, data.get(), &size)) != ERROR_SUCCESS) { throw registry_error(this->FormatSystemError(status)); } + + auto valueType = ToValueType(type); + if (!valueType || !supportedTypes.contains(*valueType)) { + throw registry_error(cmStrCat(type, ": unsupported type.")); + } + switch (type) { case REG_SZ: return this->ToNarrow(reinterpret_cast<wchar_t*>(data.get())); @@ -319,12 +386,109 @@ std::vector<std::string> KeyHandler::GetSubKeys() return subKeys; } -} #endif +// ExpressionParser: Helper to parse expression holding multiple +// registry specifications +class ExpressionParser +{ +public: + ExpressionParser(cm::string_view expression) + : Expression(expression) + , Separator(";"_s) + , RegistryFormat{ + "\\[({.+})?(HKCU|HKEY_CURRENT_USER|HKLM|HKEY_LOCAL_MACHINE|HKCR|HKEY_" + "CLASSES_" + "ROOT|HKCC|HKEY_CURRENT_CONFIG|HKU|HKEY_USERS)[/\\]?([^]]*)\\]" + } + { + } + + bool Find() + { + // reset result members + this->RootKey = cm::string_view{}; + this->SubKey = cm::string_view{}; + this->ValueName = cm::string_view{}; + + auto result = this->RegistryFormat.find(this->Expression); + + if (result) { + auto separator = cm::string_view{ + this->Expression.data() + this->RegistryFormat.start(1), + this->RegistryFormat.end(1) - this->RegistryFormat.start(1) + }; + if (separator.empty()) { + separator = this->Separator; + } else { + separator = separator.substr(1, separator.length() - 2); + } + + this->RootKey = cm::string_view{ + this->Expression.data() + this->RegistryFormat.start(2), + this->RegistryFormat.end(2) - this->RegistryFormat.start(2) + }; + this->SubKey = cm::string_view{ + this->Expression.data() + this->RegistryFormat.start(3), + this->RegistryFormat.end(3) - this->RegistryFormat.start(3) + }; + + auto pos = this->SubKey.find(separator); + if (pos != cm::string_view::npos) { + // split in ValueName and SubKey + this->ValueName = this->SubKey.substr(pos + separator.size()); + if (Strucmp(this->ValueName, "(default)") == 0) { + // handle magic name for default value + this->ValueName = ""_s; + } + this->SubKey = this->SubKey.substr(0, pos); + } else { + this->ValueName = ""_s; + } + } + return result; + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + void Replace(const std::string& value) + { + this->Expression.replace( + this->RegistryFormat.start(), + this->RegistryFormat.end() - this->RegistryFormat.start(), value); + } + + cm::string_view GetRootKey() const { return this->RootKey; } + + cm::string_view GetSubKey() const { return this->SubKey; } + cm::string_view GetValueName() const { return this->ValueName; } + + const std::string& GetExpression() const { return this->Expression; } +#endif + +private: + std::string Expression; + cm::string_view Separator; + cmsys::RegularExpression RegistryFormat; + cm::string_view RootKey; + cm::string_view SubKey; + cm::string_view ValueName; +}; +} + // class cmWindowsRegistry -cmWindowsRegistry::cmWindowsRegistry(cmMakefile& makefile) -#if !defined(_WIN32) || defined(__CYGWIN__) +const cmWindowsRegistry::ValueTypeSet cmWindowsRegistry::SimpleTypes = + cmWindowsRegistry::ValueTypeSet{ cmWindowsRegistry::ValueType::Reg_SZ, + cmWindowsRegistry::ValueType::Reg_EXPAND_SZ, + cmWindowsRegistry::ValueType::Reg_DWORD, + cmWindowsRegistry::ValueType::Reg_QWORD }; +const cmWindowsRegistry::ValueTypeSet cmWindowsRegistry::AllTypes = + cmWindowsRegistry::SimpleTypes + cmWindowsRegistry::ValueType::Reg_MULTI_SZ; + +cmWindowsRegistry::cmWindowsRegistry(cmMakefile& makefile, + const ValueTypeSet& supportedTypes) +#if defined(_WIN32) && !defined(__CYGWIN__) + : SupportedTypes(supportedTypes) +#else : LastError("No Registry on this platform.") #endif { @@ -334,6 +498,7 @@ cmWindowsRegistry::cmWindowsRegistry(cmMakefile& makefile) } #else (void)makefile; + (void)supportedTypes; #endif } @@ -350,8 +515,22 @@ cm::optional<cmWindowsRegistry::View> cmWindowsRegistry::ToView( auto it = ViewDefinitions.find(name); - return it == ViewDefinitions.end() ? cm::nullopt - : cm::optional{ it->second }; + return it == ViewDefinitions.end() + ? cm::nullopt + : cm::optional<cmWindowsRegistry::View>{ it->second }; +} + +// define hash structure required by std::unordered_map +namespace std { +template <> +struct hash<cmWindowsRegistry::View> +{ + size_t operator()(cmWindowsRegistry::View const& v) const noexcept + { + return static_cast< + typename underlying_type<cmWindowsRegistry::View>::type>(v); + } +}; } cm::string_view cmWindowsRegistry::FromView(View view) @@ -434,7 +613,7 @@ cm::optional<std::string> cmWindowsRegistry::ReadValue( // compute list of registry views auto views = this->ComputeViews(view); - if (cmsys::SystemTools::Strucmp(name.data(), "(default)") == 0) { + if (Strucmp(name, "(default)") == 0) { // handle magic name for default value name = ""_s; } @@ -446,7 +625,7 @@ cm::optional<std::string> cmWindowsRegistry::ReadValue( try { this->LastError.clear(); auto handler = KeyHandler::OpenKey(key, v); - return handler.ReadValue(name, separator); + return handler.ReadValue(name, this->SupportedTypes, separator); } catch (const registry_error& e) { this->LastError = e.what(); continue; @@ -539,3 +718,53 @@ cm::optional<std::vector<std::string>> cmWindowsRegistry::GetSubKeys( #endif return cm::nullopt; } + +cm::optional<std::vector<std::string>> cmWindowsRegistry::ExpandExpression( + cm::string_view expression, View view, cm::string_view separator) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + static std::string NOTFOUND{ "/REGISTRY-NOTFOUND" }; + + this->LastError.clear(); + + // compute list of registry views + auto views = this->ComputeViews(view); + std::vector<std::string> result; + + for (auto v : views) { + ExpressionParser parser(expression); + + while (parser.Find()) { + try { + auto handler = + KeyHandler::OpenKey(parser.GetRootKey(), parser.GetSubKey(), v); + auto data = handler.ReadValue(parser.GetValueName(), + this->SupportedTypes, separator); + parser.Replace(data); + } catch (const registry_error& e) { + this->LastError = e.what(); + parser.Replace(NOTFOUND); + continue; + } + } + result.emplace_back(parser.GetExpression()); + if (expression == parser.GetExpression()) { + // there no substitutions, so can ignore other views + break; + } + } + + return result; +#else + (void)view; + (void)separator; + + ExpressionParser parser(expression); + if (parser.Find()) { + // expression holds unsupported registry access + // so the expression cannot be used on this platform + return cm::nullopt; + } + return std::vector<std::string>{ std::string{ expression } }; +#endif +} diff --git a/Source/cmWindowsRegistry.h b/Source/cmWindowsRegistry.h index e04ce87..bb9090e 100644 --- a/Source/cmWindowsRegistry.h +++ b/Source/cmWindowsRegistry.h @@ -7,6 +7,7 @@ #include <cm/optional> #include <cm/string_view> +#include <cmext/enum_set> #include <cmext/string_view> class cmMakefile; @@ -14,8 +15,6 @@ class cmMakefile; class cmWindowsRegistry { public: - cmWindowsRegistry(cmMakefile&); - enum class View { Both, @@ -27,6 +26,25 @@ public: Reg64 }; + // Registry supported types + enum class ValueType : std::uint8_t + { + Reg_SZ, + Reg_EXPAND_SZ, + Reg_MULTI_SZ, + Reg_DWORD, + Reg_QWORD + }; + using ValueTypeSet = cm::enum_set<ValueType>; + + // All types as defined by enum ValueType + static const ValueTypeSet AllTypes; + // same as AllTYpes but without type REG_MULTI_SZ + static const ValueTypeSet SimpleTypes; + + cmWindowsRegistry(cmMakefile&, + const ValueTypeSet& supportedTypes = AllTypes); + // Helper routine to convert string to enum value static cm::optional<View> ToView(cm::string_view name); // Helper routine to convert enum to string @@ -48,6 +66,12 @@ public: cm::optional<std::vector<std::string>> GetSubKeys(cm::string_view key, View view = View::Both); + // Expand an expression which may contains multiple references + // to registry keys. + // Depending of the view specified, one or two expansions can be done. + cm::optional<std::vector<std::string>> ExpandExpression( + cm::string_view expression, View view, cm::string_view separator = "\0"_s); + cm::string_view GetLastError() const; private: @@ -55,6 +79,7 @@ private: std::vector<View> ComputeViews(View view); int TargetSize = 0; + ValueTypeSet SupportedTypes = AllTypes; #endif std::string LastError; }; diff --git a/Tests/RunCMake/find_file/32bit/file.txt b/Tests/RunCMake/find_file/32bit/file.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_file/32bit/file.txt diff --git a/Tests/RunCMake/find_file/32bit/file32bit.txt b/Tests/RunCMake/find_file/32bit/file32bit.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_file/32bit/file32bit.txt diff --git a/Tests/RunCMake/find_file/64bit/file.txt b/Tests/RunCMake/find_file/64bit/file.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_file/64bit/file.txt diff --git a/Tests/RunCMake/find_file/64bit/file64bit.txt b/Tests/RunCMake/find_file/64bit/file64bit.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_file/64bit/file64bit.txt diff --git a/Tests/RunCMake/find_file/REGISTRY_VIEW-no-view-result.txt b/Tests/RunCMake/find_file/REGISTRY_VIEW-no-view-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_file/REGISTRY_VIEW-no-view-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_file/REGISTRY_VIEW-no-view-stderr.txt b/Tests/RunCMake/find_file/REGISTRY_VIEW-no-view-stderr.txt new file mode 100644 index 0000000..28e3e12 --- /dev/null +++ b/Tests/RunCMake/find_file/REGISTRY_VIEW-no-view-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at REGISTRY_VIEW-no-view.cmake:[0-9]+ \(find_file\): + find_file missing required argument for "REGISTRY_VIEW" +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_file/REGISTRY_VIEW-no-view.cmake b/Tests/RunCMake/find_file/REGISTRY_VIEW-no-view.cmake new file mode 100644 index 0000000..fc24f7b --- /dev/null +++ b/Tests/RunCMake/find_file/REGISTRY_VIEW-no-view.cmake @@ -0,0 +1,2 @@ + +find_file(result NAMES input.txt REGISTRY_VIEW) diff --git a/Tests/RunCMake/find_file/REGISTRY_VIEW-wrong-view-result.txt b/Tests/RunCMake/find_file/REGISTRY_VIEW-wrong-view-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_file/REGISTRY_VIEW-wrong-view-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_file/REGISTRY_VIEW-wrong-view-stderr.txt b/Tests/RunCMake/find_file/REGISTRY_VIEW-wrong-view-stderr.txt new file mode 100644 index 0000000..42843f3 --- /dev/null +++ b/Tests/RunCMake/find_file/REGISTRY_VIEW-wrong-view-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at REGISTRY_VIEW-wrong-view.cmake:[0-9]+ \(find_file\): + find_file given invalid value for "REGISTRY_VIEW": WRONG_VIEW +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_file/REGISTRY_VIEW-wrong-view.cmake b/Tests/RunCMake/find_file/REGISTRY_VIEW-wrong-view.cmake new file mode 100644 index 0000000..a2c73d6 --- /dev/null +++ b/Tests/RunCMake/find_file/REGISTRY_VIEW-wrong-view.cmake @@ -0,0 +1,2 @@ + +find_file(result NAMES input.txt REGISTRY_VIEW WRONG_VIEW) diff --git a/Tests/RunCMake/find_file/Registry-query.cmake b/Tests/RunCMake/find_file/Registry-query.cmake new file mode 100644 index 0000000..ea2f0f1 --- /dev/null +++ b/Tests/RunCMake/find_file/Registry-query.cmake @@ -0,0 +1,218 @@ + +# helper function for test validation +function(CHECK query result expression) + cmake_language(EVAL CODE + "if (NOT (${expression})) + message(SEND_ERROR \"wrong value for query '${query}': '${result}'\") + endif()") +endfunction() + + +cmake_policy(SET CMP0134 NEW) + +# HKCU/Software/Classes/CLSID/CMake-Tests/find_file: Query default value +set(FILE_DIR "[HKCU/Software/Classes/CLSID/CMake-Tests/find_file]") +set(FILE_DIR2 "[HKCU/Software/Classes/CLSID/CMake-Tests/find_file;(default)]") + +unset(result) +find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"default.${ARCH}/file.txt$\"") + +# query value using special name should be identical to default value +unset(result) +find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR2}" REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR2}" "${result}" "result MATCHES \"default.${ARCH}/file.txt$\"") + +unset(result) +find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"default.${ARCH}/file.txt$\"") +# VIEW TARGET should have same value as VIEW HOST +unset(result2) +find_file(result2 NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result2}" "result2 STREQUAL result") + +if (ARCH STREQUAL "64bit") + + unset(result) + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/file.txt$\"") + + unset(result) + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.txt$\"") + + unset(result) + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/file.txt$\"") + unset(result) + + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.txt$\"") + + # check the second view is taken into account + unset(result) + find_file(result NAMES file32bit.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file32bit.txt$\"") + + unset(result) + find_file(result NAMES file64bit.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/file64bit.txt$\"") + + # check the both views are taken into account + unset(result) + find_file(result NAMES file32bit.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file32bit.txt$\"") + + unset(result) + find_file(result NAMES file64bit.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/file64bit.txt$\"") + +else() # 32bit + + # no 64bit registry: file not found + unset(result) + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"result-NOTFOUND$\"") + + unset(result) + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.txt$\"") + + # views 64_32 and 32_64 give same result + unset(result) + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.txt$\"") + + unset(result) + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.txt$\"") + + # check the both views are usable on 32bit platforms + unset(result) + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.txt$\"") + +endif() + +# HKCU/Software/Classes/CLSID/CMake-Tests/find_file: Query specific value +set(FILE_DIR "[{|}HKCU/Software/Classes/CLSID/CMake-Tests/find_file|FILE_DIR]") +set(FILE_DIR2 "[HKCU\\Software\\Classes\\CLSID\\CMake-Tests\\find_file;FILE_DIR]") + +unset(result) +find_file(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.txt$\"") + +# query value using special name should be identical to default value +unset(result) +find_file(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR2}" REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR2}" "${result}" "result MATCHES \"/${ARCH}/file.txt$\"") + +unset(result) +find_file(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.txt$\"") +# VIEW TARGET should have same value as VIEW HOST +unset(result2) +find_file(result2 NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result2}" "result2 STREQUAL result") + +if (ARCH STREQUAL "64bit") + + unset(result) + find_file(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file.txt$\"") + + unset(result) + find_file(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.txt$\"") + + unset(result) + find_file(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file.txt$\"") + unset(result) + + find_file(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.txt$\"") + + # check the second view is taken into account + unset(result) + find_file(result NAMES file32bit.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file32bit.txt$\"") + + unset(result) + find_file(result NAMES file64bit.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file64bit.txt$\"") + + # check the both views are taken into account + unset(result) + find_file(result NAMES file32bit.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file32bit.txt$\"") + + unset(result) + find_file(result NAMES file64bit.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file64bit.txt$\"") + +else() # 32bit + + # no 64bit registry: file not found + unset(result) + find_file(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"result-NOTFOUND$\"") + + unset(result) + find_file(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.txt$\"") + + unset(result) + find_file(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.txt$\"") + + unset(result) + find_file(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.txt$\"") + + # check the both views are taken into account + unset(result) + find_file(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.txt$\"") + +endif() + +if (ARCH STREQUAL "64bit") + + # Check influence of variable CMAKE_SIZEOF_VOID_P + set(CMAKE_SIZEOF_VOID_P 8) + unset(result) + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file.txt$\"") + + unset(result) + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.txt$\"") + + + set(CMAKE_SIZEOF_VOID_P 4) + unset(result) + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.txt$\"") + + unset(result) + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.txt$\"") + + unset(CMAKE_SIZEOF_VOID_P) + + + # Check influence of CMP0134 policy with OLD value + cmake_policy(SET CMP0134 OLD) + # CMAKE_SIZEOF_VOID_P is not set, so search first 32bit registry + unset(result) + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.txt$\"") + + cmake_policy(SET CMP0134 NEW) + # CMAKE_SIZEOF_VOID_P is not set, so search first the HOST architecture registry + unset(result) + find_file(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.txt$\"") + +endif() diff --git a/Tests/RunCMake/find_file/RunCMakeTest.cmake b/Tests/RunCMake/find_file/RunCMakeTest.cmake index c5cd5fa..23765d4 100644 --- a/Tests/RunCMake/find_file/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_file/RunCMakeTest.cmake @@ -5,5 +5,33 @@ run_cmake(FromPrefixPath) run_cmake(PrefixInPATH) run_cmake(Required) run_cmake(NO_CACHE) +run_cmake(REGISTRY_VIEW-no-view) +run_cmake(REGISTRY_VIEW-wrong-view) run_cmake_with_options(FromPATHEnvDebugVar --debug-find-var=PrefixInPATH_File) + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + # Tests using the Windows registry + find_program(REG NAMES "reg.exe" NO_CACHE) + if (REG) + ## check host architecture + cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "HKCU" SUBKEYS VIEW 64 ERROR_VARIABLE status) + if (status STREQUAL "") + set(ARCH "64bit") + else() + set(ARCH "32bit") + endif() + + # crete some entries in the registry + cmake_path(CONVERT "${RunCMake_SOURCE_DIR}/registry_host${ARCH}.reg" TO_NATIVE_PATH_LIST registry_data) + execute_process(COMMAND "${REG}" import "${registry_data}" OUTPUT_QUIET ERROR_QUIET) + + run_cmake_with_options(Registry-query -DARCH=${ARCH}) + + # clean-up registry + execute_process(COMMAND "${REG}" delete "HKCU\\SOFTWARE\\Classes\\CLSID\\CMake-Tests\\find_file" /f OUTPUT_QUIET ERROR_QUIET) + if (ARCH STREQUAL "64bit") + execute_process(COMMAND "${REG}" delete "HKCU\\SOFTWARE\\Classes\\WOW6432Node\\CLSID\\CMake-Tests\\find_file" /f OUTPUT_QUIET ERROR_QUIET) + endif() + endif() +endif() diff --git a/Tests/RunCMake/find_file/default.32bit/file.txt b/Tests/RunCMake/find_file/default.32bit/file.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_file/default.32bit/file.txt diff --git a/Tests/RunCMake/find_file/default.32bit/file32bit.txt b/Tests/RunCMake/find_file/default.32bit/file32bit.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_file/default.32bit/file32bit.txt diff --git a/Tests/RunCMake/find_file/default.64bit/file.txt b/Tests/RunCMake/find_file/default.64bit/file.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_file/default.64bit/file.txt diff --git a/Tests/RunCMake/find_file/default.64bit/file64bit.txt b/Tests/RunCMake/find_file/default.64bit/file64bit.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_file/default.64bit/file64bit.txt diff --git a/Tests/RunCMake/find_file/registry_host32bit.reg b/Tests/RunCMake/find_file/registry_host32bit.reg Binary files differnew file mode 100644 index 0000000..2987185 --- /dev/null +++ b/Tests/RunCMake/find_file/registry_host32bit.reg diff --git a/Tests/RunCMake/find_file/registry_host64bit.reg b/Tests/RunCMake/find_file/registry_host64bit.reg Binary files differnew file mode 100644 index 0000000..2d70fa9 --- /dev/null +++ b/Tests/RunCMake/find_file/registry_host64bit.reg diff --git a/Tests/RunCMake/find_library/32bit/file.lib b/Tests/RunCMake/find_library/32bit/file.lib new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_library/32bit/file.lib diff --git a/Tests/RunCMake/find_library/32bit/file32bit.lib b/Tests/RunCMake/find_library/32bit/file32bit.lib new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_library/32bit/file32bit.lib diff --git a/Tests/RunCMake/find_library/64bit/file.lib b/Tests/RunCMake/find_library/64bit/file.lib new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_library/64bit/file.lib diff --git a/Tests/RunCMake/find_library/64bit/file64bit.lib b/Tests/RunCMake/find_library/64bit/file64bit.lib new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_library/64bit/file64bit.lib diff --git a/Tests/RunCMake/find_library/REGISTRY_VIEW-no-view-result.txt b/Tests/RunCMake/find_library/REGISTRY_VIEW-no-view-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_library/REGISTRY_VIEW-no-view-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_library/REGISTRY_VIEW-no-view-stderr.txt b/Tests/RunCMake/find_library/REGISTRY_VIEW-no-view-stderr.txt new file mode 100644 index 0000000..ec1877c --- /dev/null +++ b/Tests/RunCMake/find_library/REGISTRY_VIEW-no-view-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at REGISTRY_VIEW-no-view.cmake:[0-9]+ \(find_library\): + find_library missing required argument for "REGISTRY_VIEW" +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_library/REGISTRY_VIEW-no-view.cmake b/Tests/RunCMake/find_library/REGISTRY_VIEW-no-view.cmake new file mode 100644 index 0000000..e87a6c3 --- /dev/null +++ b/Tests/RunCMake/find_library/REGISTRY_VIEW-no-view.cmake @@ -0,0 +1,2 @@ + +find_library(result NAMES input.txt REGISTRY_VIEW) diff --git a/Tests/RunCMake/find_library/REGISTRY_VIEW-wrong-view-result.txt b/Tests/RunCMake/find_library/REGISTRY_VIEW-wrong-view-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_library/REGISTRY_VIEW-wrong-view-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_library/REGISTRY_VIEW-wrong-view-stderr.txt b/Tests/RunCMake/find_library/REGISTRY_VIEW-wrong-view-stderr.txt new file mode 100644 index 0000000..3e7f814 --- /dev/null +++ b/Tests/RunCMake/find_library/REGISTRY_VIEW-wrong-view-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at REGISTRY_VIEW-wrong-view.cmake:[0-9]+ \(find_library\): + find_library given invalid value for "REGISTRY_VIEW": WRONG_VIEW +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_library/REGISTRY_VIEW-wrong-view.cmake b/Tests/RunCMake/find_library/REGISTRY_VIEW-wrong-view.cmake new file mode 100644 index 0000000..e4a636a --- /dev/null +++ b/Tests/RunCMake/find_library/REGISTRY_VIEW-wrong-view.cmake @@ -0,0 +1,2 @@ + +find_library(result NAMES input.txt REGISTRY_VIEW WRONG_VIEW) diff --git a/Tests/RunCMake/find_library/Registry-query.cmake b/Tests/RunCMake/find_library/Registry-query.cmake new file mode 100644 index 0000000..22968aa --- /dev/null +++ b/Tests/RunCMake/find_library/Registry-query.cmake @@ -0,0 +1,218 @@ + +# helper function for test validation +function(CHECK query result expression) + cmake_language(EVAL CODE + "if (NOT (${expression})) + message(SEND_ERROR \"wrong value for query '${query}': '${result}'\") + endif()") +endfunction() + +cmake_policy(SET CMP0134 NEW) + +# HKCU/Software/Classes/CLSID/CMake-Tests/find_library: Query default value +set(FILE_DIR "[HKCU/Software/Classes/CLSID/CMake-Tests/find_library]") +set(FILE_DIR2 "[HKCU/Software/Classes/CLSID/CMake-Tests/find_library;(default)]") + +unset(result) +find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"default.${ARCH}/file.lib$\"") + +# query value using special name should be identical to default value +unset(result) +find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR2}" REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR2}" "${result}" "result MATCHES \"default.${ARCH}/file.lib$\"") + +unset(result) +find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"default.${ARCH}/file.lib$\"") +# VIEW TARGET should have same value as VIEW HOST +unset(result2) +find_library(result2 NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result2}" "result2 STREQUAL result") + +if (ARCH STREQUAL "64bit") + + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/file.lib$\"") + + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.lib$\"") + + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/file.lib$\"") + + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.lib$\"") + + # check the second view is taken into account + unset(result) + find_library(result NAMES file32bit.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file32bit.lib$\"") + + unset(result) + find_library(result NAMES file64bit.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/file64bit.lib$\"") + unset(result) + + # check the both views are taken into account + unset(result) + find_library(result NAMES file32bit.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file32bit.lib$\"") + + unset(result) + find_library(result NAMES file64bit.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/file64bit.lib$\"") + unset(result) + +else() # 32bit + + # no 64bit registry: file not found + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"result-NOTFOUND$\"") + + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.lib$\"") + + # views 64_32 and 32_64 give same result + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.lib$\"") + + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.lib$\"") + + # check the both views are usable on 32bit platforms + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.lib$\"") + +endif() + +# HKCU/Software/Classes/CLSID/CMake-Tests/find_library: Query specific value +set(FILE_DIR "[{|}HKCU/Software/Classes/CLSID/CMake-Tests/find_library|FILE_DIR]") +set(FILE_DIR2 "[HKCU\\Software\\Classes\\CLSID\\CMake-Tests\\find_library;FILE_DIR]") + +unset(result) +find_library(result NAMES file.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.lib$\"") + +# query value using special name should be identical to default value +unset(result) +find_library(result NAMES file.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR2}" REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR2}" "${result}" "result MATCHES \"/${ARCH}/file.lib$\"") + +unset(result) +find_library(result NAMES file.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.lib$\"") +# VIEW TARGET should have same value as VIEW HOST +unset(result2) +find_library(result2 NAMES file.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result2}" "result2 STREQUAL result") + +if (ARCH STREQUAL "64bit") + + unset(result) + find_library(result NAMES file.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file.lib$\"") + + unset(result) + find_library(result NAMES file.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.lib$\"") + + unset(result) + find_library(result NAMES file.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file.lib$\"") + + unset(result) + find_library(result NAMES file.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.lib$\"") + + # check the second view is taken into account + unset(result) + find_library(result NAMES file32bit.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file32bit.lib$\"") + + unset(result) + find_library(result NAMES file64bit.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file64bit.lib$\"") + + # check the both views are taken into account + unset(result) + find_library(result NAMES file32bit.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file32bit.lib$\"") + + unset(result) + find_library(result NAMES file64bit.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file64bit.lib$\"") + +else() # 32bit + + # no 64bit registry: file not found + unset(result) + find_library(result NAMES file.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"result-NOTFOUND$\"") + + unset(result) + find_library(result NAMES file.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.lib$\"") + + unset(result) + find_library(result NAMES file.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.lib$\"") + + unset(result) + find_library(result NAMES file.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.lib$\"") + + unset(result) + find_library(result NAMES file.lib HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.lib$\"") + +endif() + +if (ARCH STREQUAL "64bit") + + # Check influence of variable CMAKE_SIZEOF_VOID_P + set(CMAKE_SIZEOF_VOID_P 8) + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file.lib$\"") + + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.lib$\"") + + + set(CMAKE_SIZEOF_VOID_P 4) + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.lib$\"") + + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.lib$\"") + + unset(CMAKE_SIZEOF_VOID_P) + + + # Check influence of CMP0134 policy with OLD value + cmake_policy(SET CMP0134 OLD) + # CMAKE_SIZEOF_VOID_P is not set, so search first 32bit registry + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.lib$\"") + + cmake_policy(SET CMP0134 NEW) + # CMAKE_SIZEOF_VOID_P is not set, so search first the HOST architecture registry + unset(result) + find_library(result NAMES file.lib PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.lib$\"") + +endif() diff --git a/Tests/RunCMake/find_library/RunCMakeTest.cmake b/Tests/RunCMake/find_library/RunCMakeTest.cmake index ef1ede6..de0ee14 100644 --- a/Tests/RunCMake/find_library/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_library/RunCMakeTest.cmake @@ -11,7 +11,35 @@ endif() run_cmake(PrefixInPATH) run_cmake(Required) run_cmake(NO_CACHE) +run_cmake(REGISTRY_VIEW-no-view) +run_cmake(REGISTRY_VIEW-wrong-view) run_cmake_script(FromScriptMode "-DTEMP_DIR=${RunCMake_BINARY_DIR}/FromScriptMode-temp") run_cmake_with_options(FromPATHEnvDebugVar --debug-find-var=CREATED_LIBRARY) + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + # Tests using the Windows registry + find_program(REG NAMES "reg.exe" NO_CACHE) + if (REG) + ## check host architecture + cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "HKCU" SUBKEYS VIEW 64 ERROR_VARIABLE status) + if (status STREQUAL "") + set(ARCH "64bit") + else() + set(ARCH "32bit") + endif() + + # crete some entries in the registry + cmake_path(CONVERT "${RunCMake_SOURCE_DIR}/registry_host${ARCH}.reg" TO_NATIVE_PATH_LIST registry_data) + execute_process(COMMAND "${REG}" import "${registry_data}" OUTPUT_QUIET ERROR_QUIET) + + run_cmake_with_options(Registry-query -DARCH=${ARCH}) + + # clean-up registry + execute_process(COMMAND "${REG}" delete "HKCU\\SOFTWARE\\Classes\\CLSID\\CMake-Tests\\find_library" /f OUTPUT_QUIET ERROR_QUIET) + if (ARCH STREQUAL "64bit") + execute_process(COMMAND "${REG}" delete "HKCU\\SOFTWARE\\Classes\\WOW6432Node\\CLSID\\CMake-Tests\\find_library" /f OUTPUT_QUIET ERROR_QUIET) + endif() + endif() +endif() diff --git a/Tests/RunCMake/find_library/default.32bit/file.lib b/Tests/RunCMake/find_library/default.32bit/file.lib new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_library/default.32bit/file.lib diff --git a/Tests/RunCMake/find_library/default.32bit/file32bit.lib b/Tests/RunCMake/find_library/default.32bit/file32bit.lib new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_library/default.32bit/file32bit.lib diff --git a/Tests/RunCMake/find_library/default.64bit/file.lib b/Tests/RunCMake/find_library/default.64bit/file.lib new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_library/default.64bit/file.lib diff --git a/Tests/RunCMake/find_library/default.64bit/file64bit.lib b/Tests/RunCMake/find_library/default.64bit/file64bit.lib new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_library/default.64bit/file64bit.lib diff --git a/Tests/RunCMake/find_library/registry_host32bit.reg b/Tests/RunCMake/find_library/registry_host32bit.reg Binary files differnew file mode 100644 index 0000000..cf36b34 --- /dev/null +++ b/Tests/RunCMake/find_library/registry_host32bit.reg diff --git a/Tests/RunCMake/find_library/registry_host64bit.reg b/Tests/RunCMake/find_library/registry_host64bit.reg Binary files differnew file mode 100644 index 0000000..8a87c98 --- /dev/null +++ b/Tests/RunCMake/find_library/registry_host64bit.reg diff --git a/Tests/RunCMake/find_package/32bit/RegistryView32Config.cmake b/Tests/RunCMake/find_package/32bit/RegistryView32Config.cmake new file mode 100644 index 0000000..63f9622 --- /dev/null +++ b/Tests/RunCMake/find_package/32bit/RegistryView32Config.cmake @@ -0,0 +1,4 @@ + +if (NOT EXPECTED_LOCATION STREQUAL "32bit") + message (SEND_ERROR "RegistryViewConfig: location is '32bit' but expects '${EXPECTED_LOCATION}'") +endif() diff --git a/Tests/RunCMake/find_package/32bit/RegistryViewConfig.cmake b/Tests/RunCMake/find_package/32bit/RegistryViewConfig.cmake new file mode 100644 index 0000000..63f9622 --- /dev/null +++ b/Tests/RunCMake/find_package/32bit/RegistryViewConfig.cmake @@ -0,0 +1,4 @@ + +if (NOT EXPECTED_LOCATION STREQUAL "32bit") + message (SEND_ERROR "RegistryViewConfig: location is '32bit' but expects '${EXPECTED_LOCATION}'") +endif() diff --git a/Tests/RunCMake/find_package/64bit/RegistryView64Config.cmake b/Tests/RunCMake/find_package/64bit/RegistryView64Config.cmake new file mode 100644 index 0000000..3d64301 --- /dev/null +++ b/Tests/RunCMake/find_package/64bit/RegistryView64Config.cmake @@ -0,0 +1,4 @@ + +if (NOT EXPECTED_LOCATION STREQUAL "64bit") + message (SEND_ERROR "RegistryViewConfig: location is '64bit' but expects '${EXPECTED_LOCATION}'") +endif() diff --git a/Tests/RunCMake/find_package/64bit/RegistryViewConfig.cmake b/Tests/RunCMake/find_package/64bit/RegistryViewConfig.cmake new file mode 100644 index 0000000..3d64301 --- /dev/null +++ b/Tests/RunCMake/find_package/64bit/RegistryViewConfig.cmake @@ -0,0 +1,4 @@ + +if (NOT EXPECTED_LOCATION STREQUAL "64bit") + message (SEND_ERROR "RegistryViewConfig: location is '64bit' but expects '${EXPECTED_LOCATION}'") +endif() diff --git a/Tests/RunCMake/find_package/FindRegistryView.cmake b/Tests/RunCMake/find_package/FindRegistryView.cmake new file mode 100644 index 0000000..e4080a6 --- /dev/null +++ b/Tests/RunCMake/find_package/FindRegistryView.cmake @@ -0,0 +1,11 @@ + +if (EXPECTED_REGISTRY_VIEW STREQUAL "UNDEFINED") + if (DEFINED ${CMAKE_FIND_PACKAGE_NAME}_FIND_REGISTRY_VIEW) + message(SEND_ERROR "${CMAKE_FIND_PACKAGE_NAME}_FIND_REGISTRY_VIEW: unexpectedly defined as '${${CMAKE_FIND_PACKAGE_NAME}_FIND_REGISTRY_VIEW}' instead of '${EXPECTED_REGISTRY_VIEW}'") + endif() + return() +endif() + +if (NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_REGISTRY_VIEW STREQUAL EXPECTED_REGISTRY_VIEW) + message(SEND_ERROR "${CMAKE_FIND_PACKAGE_NAME}_FIND_REGISTRY_VIEW: '${${CMAKE_FIND_PACKAGE_NAME}_FIND_REGISTRY_VIEW}' instead of '${EXPECTED_REGISTRY_VIEW}'") +endif() diff --git a/Tests/RunCMake/find_package/REGISTRY_VIEW-no-view-result.txt b/Tests/RunCMake/find_package/REGISTRY_VIEW-no-view-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_package/REGISTRY_VIEW-no-view-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_package/REGISTRY_VIEW-no-view-stderr.txt b/Tests/RunCMake/find_package/REGISTRY_VIEW-no-view-stderr.txt new file mode 100644 index 0000000..9dbcc93 --- /dev/null +++ b/Tests/RunCMake/find_package/REGISTRY_VIEW-no-view-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at REGISTRY_VIEW-no-view.cmake:[0-9]+ \(find_package\): + find_package missing required argument for "REGISTRY_VIEW" +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_package/REGISTRY_VIEW-no-view.cmake b/Tests/RunCMake/find_package/REGISTRY_VIEW-no-view.cmake new file mode 100644 index 0000000..866cc54 --- /dev/null +++ b/Tests/RunCMake/find_package/REGISTRY_VIEW-no-view.cmake @@ -0,0 +1,2 @@ + +find_package(result NAMES input.txt REGISTRY_VIEW) diff --git a/Tests/RunCMake/find_package/REGISTRY_VIEW-propagated.cmake b/Tests/RunCMake/find_package/REGISTRY_VIEW-propagated.cmake new file mode 100644 index 0000000..8d8fec7 --- /dev/null +++ b/Tests/RunCMake/find_package/REGISTRY_VIEW-propagated.cmake @@ -0,0 +1,16 @@ + +set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}") + +# when REGISTRY_VIEW is not specified, should not be defined in module +set (EXPECTED_REGISTRY_VIEW "UNDEFINED") +find_package(RegistryView) + +# query package to check if variable is propagated correctly +set(EXPECTED_REGISTRY_VIEW "TARGET") +find_package(RegistryView REGISTRY_VIEW TARGET) + +set(EXPECTED_REGISTRY_VIEW "64_32") +find_package(RegistryView REGISTRY_VIEW 64_32) + +set(EXPECTED_REGISTRY_VIEW "32") +find_package(RegistryView REGISTRY_VIEW 32) diff --git a/Tests/RunCMake/find_package/REGISTRY_VIEW-wrong-view-result.txt b/Tests/RunCMake/find_package/REGISTRY_VIEW-wrong-view-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_package/REGISTRY_VIEW-wrong-view-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_package/REGISTRY_VIEW-wrong-view-stderr.txt b/Tests/RunCMake/find_package/REGISTRY_VIEW-wrong-view-stderr.txt new file mode 100644 index 0000000..e65af62 --- /dev/null +++ b/Tests/RunCMake/find_package/REGISTRY_VIEW-wrong-view-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at REGISTRY_VIEW-wrong-view.cmake:[0-9]+ \(find_package\): + find_package given invalid value for "REGISTRY_VIEW": WRONG_VIEW +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_package/REGISTRY_VIEW-wrong-view.cmake b/Tests/RunCMake/find_package/REGISTRY_VIEW-wrong-view.cmake new file mode 100644 index 0000000..e2aff3cf --- /dev/null +++ b/Tests/RunCMake/find_package/REGISTRY_VIEW-wrong-view.cmake @@ -0,0 +1,2 @@ + +find_package(result NAMES input.txt REGISTRY_VIEW WRONG_VIEW) diff --git a/Tests/RunCMake/find_package/Registry-query.cmake b/Tests/RunCMake/find_package/Registry-query.cmake new file mode 100644 index 0000000..181c479 --- /dev/null +++ b/Tests/RunCMake/find_package/Registry-query.cmake @@ -0,0 +1,216 @@ + +# helper macro for test clean-up +macro(CLEAN) + unset(RegistryView_DIR CACHE) + unset(RegistryView_FOUND) + unset(RegistryView64_DIR CACHE) + unset(RegistryView64_FOUND) + unset(RegistryView32_DIR CACHE) + unset(RegistryView32_FOUND) +endmacro() + + +cmake_policy(SET CMP0134 NEW) + +# HKCU/Software/Classes/CLSID/CMake-Tests/find_package: Query default value +set(FILE_DIR "[HKCU/Software/Classes/CLSID/CMake-Tests/find_package]") +set(FILE_DIR2 "[HKCU/Software/Classes/CLSID/CMake-Tests/find_package;(default)]") + +set(EXPECTED_LOCATION "default.${ARCH}") + +find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_DEFAULT_PATH) +clean() + +# query value using special name should be identical to default value +find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR2}" REQUIRED NO_DEFAULT_PATH) +clean() + +find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_DEFAULT_PATH) +clean() + +# VIEW TARGET should have same value as VIEW HOST +find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_DEFAULT_PATH) +clean() + +if (ARCH STREQUAL "64bit") + + set(EXPECTED_LOCATION "default.64bit") + find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 REQUIRED NO_DEFAULT_PATH) + clean() + + set(EXPECTED_LOCATION "default.32bit") + find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_DEFAULT_PATH) + clean() + + set(EXPECTED_LOCATION "default.64bit") + find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_DEFAULT_PATH) + clean() + + set(EXPECTED_LOCATION "default.32bit") + find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_DEFAULT_PATH) + clean() + + # check the second view is taken into account + set(EXPECTED_LOCATION "default.32bit") + find_package(RegistryView32 PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_DEFAULT_PATH) + clean() + + set(EXPECTED_LOCATION "default.64bit") + find_package(RegistryView64 PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_DEFAULT_PATH) + clean() + + # check the both views are taken into account + set(EXPECTED_LOCATION "default.32bit") + find_package(RegistryView32 PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_DEFAULT_PATH) + clean() + + set(EXPECTED_LOCATION "default.64bit") + find_package(RegistryView64 PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_DEFAULT_PATH) + clean() + +else() # 32bit + + # no 64bit registry: file not found + find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 NO_DEFAULT_PATH) + if (RegistryView_FOUND) + message (SEND_ERROR "Unexpectedly found file '${RegistryView_DIR}/RegistryViewConfog.cmake'") + endif() + clean() + + set(EXPECTED_LOCATION "default.32bit") + + find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_DEFAULT_PATH) + clean() + + # views 64_32 and 32_64 give same result + find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_DEFAULT_PATH) + clean() + + find_package(RegistryView PATHS "${CMAKE_ CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_DEFAULT_PATH) + clean() + + # check the both views are usable on 32bit platforms + find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_DEFAULT_PATH) + clean() + +endif() + + +# HKCU/Software/Classes/CLSID/CMake-Tests/find_package: Query specific value +set(FILE_DIR "[{|}HKCU/Software/Classes/CLSID/CMake-Tests/find_package|FILE_DIR]") +set(FILE_DIR2 "[HKCU\\Software\\Classes\\CLSID\\CMake-Tests\\find_package;FILE_DIR]") + +set(EXPECTED_LOCATION "${ARCH}") + +find_package(RegistryView HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_DEFAULT_PATH) +clean() + +# query value using special name should be identical to default value +find_package(RegistryView HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR2}" REQUIRED NO_DEFAULT_PATH) +clean() + +find_package(RegistryView HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_DEFAULT_PATH) +clean() +# VIEW TARGET should have same value as VIEW HOST +find_package(RegistryView HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_DEFAULT_PATH) +clean() + +if (ARCH STREQUAL "64bit") + + set(EXPECTED_LOCATION "64bit") + find_package(RegistryView HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 REQUIRED NO_DEFAULT_PATH) + clean() + + set(EXPECTED_LOCATION "32bit") + find_package(RegistryView HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_DEFAULT_PATH) + clean() + + set(EXPECTED_LOCATION "64bit") + find_package(RegistryView HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_DEFAULT_PATH) + clean() + + set(EXPECTED_LOCATION "32bit") + find_package(RegistryView HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_DEFAULT_PATH) + clean() + + # check the second view is taken into account + find_package(RegistryView32 HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_DEFAULT_PATH) + clean() + + set(EXPECTED_LOCATION "64bit") + find_package(RegistryView64 HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_DEFAULT_PATH) + clean() + + # check the both views are taken into account + set(EXPECTED_LOCATION "32bit") + find_package(RegistryView32 HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_DEFAULT_PATH) + clean() + + set(EXPECTED_LOCATION "64bit") + find_package(RegistryView64 NAMES HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_DEFAULT_PATH) + clean() + +else() # 32bit + + # no 64bit registry: file not found + find_package(RegistryView HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 NO_DEFAULT_PATH) + if (RegistryView_FOUND) + message (SEND_ERROR "Unexpectedly found file '${RegistryView_DIR}/RegistryViewConfog.cmake'") + endif() + clean() + + set(EXPECTED_LOCATION "32bit") + + find_package(RegistryView HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_DEFAULT_PATH) + clean() + + find_package(RegistryView HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_DEFAULT_PATH) + clean() + + find_package(RegistryView HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_DEFAULT_PATH) + clean() + + # check the both views are taken into account + find_package(RegistryView HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_DEFAULT_PATH) + clean() + +endif() + +if (ARCH STREQUAL "64bit") + + # Check influence of variable CMAKE_SIZEOF_VOID_P + set(CMAKE_SIZEOF_VOID_P 8) + set(EXPECTED_LOCATION "64bit") + find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET) + clean() + + find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST) + clean() + + + set(CMAKE_SIZEOF_VOID_P 4) + set(EXPECTED_LOCATION "32bit") + find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET) + clean() + + set(EXPECTED_LOCATION "64bit") + find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST) + clean() + + unset(CMAKE_SIZEOF_VOID_P) + + + # Check influence of CMP0134 policy with OLD value + cmake_policy(SET CMP0134 OLD) + # CMAKE_SIZEOF_VOID_P is not set, so search first 32bit registry + set(EXPECTED_LOCATION "32bit") + find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}") + clean() + + cmake_policy(SET CMP0134 NEW) + # CMAKE_SIZEOF_VOID_P is not set, so search first the HOST architecture registry + set(EXPECTED_LOCATION "64bit") + find_package(RegistryView PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}") + clean() + +endif() diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake index b2d1bf6..32e54d5 100644 --- a/Tests/RunCMake/find_package/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake @@ -51,8 +51,38 @@ run_cmake(VersionRangeConfigStd2) run_cmake_with_options(IgnoreInstallPrefix "-DCMAKE_INSTALL_PREFIX=${RunCMake_SOURCE_DIR}/PackageRoot/foo/cmake_root") run_cmake(IgnorePath) run_cmake(IgnorePrefixPath) +run_cmake(REGISTRY_VIEW-no-view) +run_cmake(REGISTRY_VIEW-wrong-view) +run_cmake(REGISTRY_VIEW-propagated) + if(UNIX AND NOT MSYS # FIXME: This works on CYGWIN but not on MSYS ) run_cmake(SetFoundResolved) endif() + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + # Tests using the Windows registry + find_program(REG NAMES "reg.exe" NO_CACHE) + if (REG) + ## check host architecture + cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "HKCU" SUBKEYS VIEW 64 ERROR_VARIABLE status) + if (status STREQUAL "") + set(ARCH "64bit") + else() + set(ARCH "32bit") + endif() + + # crete some entries in the registry + cmake_path(CONVERT "${RunCMake_SOURCE_DIR}/registry_host${ARCH}.reg" TO_NATIVE_PATH_LIST registry_data) + execute_process(COMMAND "${REG}" import "${registry_data}" OUTPUT_QUIET ERROR_QUIET) + + run_cmake_with_options(Registry-query -DARCH=${ARCH}) + + # clean-up registry + execute_process(COMMAND "${REG}" delete "HKCU\\SOFTWARE\\Classes\\CLSID\\CMake-Tests\\find_package" /f OUTPUT_QUIET ERROR_QUIET) + if (ARCH STREQUAL "64bit") + execute_process(COMMAND "${REG}" delete "HKCU\\SOFTWARE\\Classes\\WOW6432Node\\CLSID\\CMake-Tests\\find_package" /f OUTPUT_QUIET ERROR_QUIET) + endif() + endif() +endif() diff --git a/Tests/RunCMake/find_package/default.32bit/RegistryView32Config.cmake b/Tests/RunCMake/find_package/default.32bit/RegistryView32Config.cmake new file mode 100644 index 0000000..8d13254 --- /dev/null +++ b/Tests/RunCMake/find_package/default.32bit/RegistryView32Config.cmake @@ -0,0 +1,4 @@ + +if (NOT EXPECTED_LOCATION STREQUAL "default.32bit") + message (SEND_ERROR "RegistryViewConfig: location is 'default.32bit' but expects '${EXPECTED_LOCATION}'") +endif() diff --git a/Tests/RunCMake/find_package/default.32bit/RegistryViewConfig.cmake b/Tests/RunCMake/find_package/default.32bit/RegistryViewConfig.cmake new file mode 100644 index 0000000..8d13254 --- /dev/null +++ b/Tests/RunCMake/find_package/default.32bit/RegistryViewConfig.cmake @@ -0,0 +1,4 @@ + +if (NOT EXPECTED_LOCATION STREQUAL "default.32bit") + message (SEND_ERROR "RegistryViewConfig: location is 'default.32bit' but expects '${EXPECTED_LOCATION}'") +endif() diff --git a/Tests/RunCMake/find_package/default.64bit/RegistryView64Config.cmake b/Tests/RunCMake/find_package/default.64bit/RegistryView64Config.cmake new file mode 100644 index 0000000..1d3d78c --- /dev/null +++ b/Tests/RunCMake/find_package/default.64bit/RegistryView64Config.cmake @@ -0,0 +1,4 @@ + +if (NOT EXPECTED_LOCATION STREQUAL "default.64bit") + message (SEND_ERROR "RegistryViewConfig: location is 'default.64bit' but expects '${EXPECTED_LOCATION}'") +endif() diff --git a/Tests/RunCMake/find_package/default.64bit/RegistryViewConfig.cmake b/Tests/RunCMake/find_package/default.64bit/RegistryViewConfig.cmake new file mode 100644 index 0000000..1d3d78c --- /dev/null +++ b/Tests/RunCMake/find_package/default.64bit/RegistryViewConfig.cmake @@ -0,0 +1,4 @@ + +if (NOT EXPECTED_LOCATION STREQUAL "default.64bit") + message (SEND_ERROR "RegistryViewConfig: location is 'default.64bit' but expects '${EXPECTED_LOCATION}'") +endif() diff --git a/Tests/RunCMake/find_package/registry_host32bit.reg b/Tests/RunCMake/find_package/registry_host32bit.reg Binary files differnew file mode 100644 index 0000000..3b2fb50 --- /dev/null +++ b/Tests/RunCMake/find_package/registry_host32bit.reg diff --git a/Tests/RunCMake/find_package/registry_host64bit.reg b/Tests/RunCMake/find_package/registry_host64bit.reg Binary files differnew file mode 100644 index 0000000..07eb9b7 --- /dev/null +++ b/Tests/RunCMake/find_package/registry_host64bit.reg diff --git a/Tests/RunCMake/find_path/32bit/file.txt b/Tests/RunCMake/find_path/32bit/file.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_path/32bit/file.txt diff --git a/Tests/RunCMake/find_path/32bit/file32bit.txt b/Tests/RunCMake/find_path/32bit/file32bit.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_path/32bit/file32bit.txt diff --git a/Tests/RunCMake/find_path/64bit/file.txt b/Tests/RunCMake/find_path/64bit/file.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_path/64bit/file.txt diff --git a/Tests/RunCMake/find_path/64bit/file64bit.txt b/Tests/RunCMake/find_path/64bit/file64bit.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_path/64bit/file64bit.txt diff --git a/Tests/RunCMake/find_path/REGISTRY_VIEW-no-view-result.txt b/Tests/RunCMake/find_path/REGISTRY_VIEW-no-view-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_path/REGISTRY_VIEW-no-view-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_path/REGISTRY_VIEW-no-view-stderr.txt b/Tests/RunCMake/find_path/REGISTRY_VIEW-no-view-stderr.txt new file mode 100644 index 0000000..662d2d3 --- /dev/null +++ b/Tests/RunCMake/find_path/REGISTRY_VIEW-no-view-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at REGISTRY_VIEW-no-view.cmake:[0-9]+ \(find_path\): + find_path missing required argument for "REGISTRY_VIEW" +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_path/REGISTRY_VIEW-no-view.cmake b/Tests/RunCMake/find_path/REGISTRY_VIEW-no-view.cmake new file mode 100644 index 0000000..e76d9dc --- /dev/null +++ b/Tests/RunCMake/find_path/REGISTRY_VIEW-no-view.cmake @@ -0,0 +1,2 @@ + +find_path(result NAMES input.txt REGISTRY_VIEW) diff --git a/Tests/RunCMake/find_path/REGISTRY_VIEW-wrong-view-result.txt b/Tests/RunCMake/find_path/REGISTRY_VIEW-wrong-view-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_path/REGISTRY_VIEW-wrong-view-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_path/REGISTRY_VIEW-wrong-view-stderr.txt b/Tests/RunCMake/find_path/REGISTRY_VIEW-wrong-view-stderr.txt new file mode 100644 index 0000000..075d6af --- /dev/null +++ b/Tests/RunCMake/find_path/REGISTRY_VIEW-wrong-view-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at REGISTRY_VIEW-wrong-view.cmake:[0-9]+ \(find_path\): + find_path given invalid value for "REGISTRY_VIEW": WRONG_VIEW +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_path/REGISTRY_VIEW-wrong-view.cmake b/Tests/RunCMake/find_path/REGISTRY_VIEW-wrong-view.cmake new file mode 100644 index 0000000..9f46538 --- /dev/null +++ b/Tests/RunCMake/find_path/REGISTRY_VIEW-wrong-view.cmake @@ -0,0 +1,2 @@ + +find_path(result NAMES input.txt REGISTRY_VIEW WRONG_VIEW) diff --git a/Tests/RunCMake/find_path/Registry-query.cmake b/Tests/RunCMake/find_path/Registry-query.cmake new file mode 100644 index 0000000..6d26cd0 --- /dev/null +++ b/Tests/RunCMake/find_path/Registry-query.cmake @@ -0,0 +1,218 @@ + +# helper function for test validation +function(CHECK query result expression) + cmake_language(EVAL CODE + "if (NOT (${expression})) + message(SEND_ERROR \"wrong value for query '${query}': '${result}'\") + endif()") +endfunction() + +cmake_policy(SET CMP0134 NEW) + +# HKCU/Software/Classes/CLSID/CMake-Tests/find_path: Query default value +set(FILE_DIR "[HKCU/Software/Classes/CLSID/CMake-Tests/find_path]") +set(FILE_DIR2 "[HKCU/Software/Classes/CLSID/CMake-Tests/find_path;(default)]") + +unset(result) +find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"default.${ARCH}/$\"") + +# query value using special name should be identical to default value +unset(result) +find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR2}" REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR2}" "${result}" "result MATCHES \"default.${ARCH}/$\"") + +unset(result) +find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"default.${ARCH}/$\"") +# VIEW TARGET should have same value as VIEW HOST +unset(result2) +find_path(result2 NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result2}" "result2 STREQUAL result") + +if (ARCH STREQUAL "64bit") + + unset(result) + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/$\"") + + unset(result) + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/$\"") + + unset(result) + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/$\"") + unset(result) + + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/$\"") + + # check the second view is taken into account + unset(result) + find_path(result NAMES file32bit.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/$\"") + + unset(result) + find_path(result NAMES file64bit.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/$\"") + + # check the both views are taken into account + unset(result) + find_path(result NAMES file32bit.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/$\"") + + unset(result) + find_path(result NAMES file64bit.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/$\"") + +else() # 32bit + + # no 64bit registry: file not found + unset(result) + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"result-NOTFOUND$\"") + + unset(result) + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/$\"") + + # views 64_32 and 32_64 give same result + unset(result) + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/$\"") + + unset(result) + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/$\"") + + # check the both views are usable on 32bit platforms + unset(result) + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/$\"") + +endif() + + +# HKCU/Software/Classes/CLSID/CMake-Tests/find_path: Query specific value +set(FILE_DIR "[{|}HKCU/Software/Classes/CLSID/CMake-Tests/find_path|FILE_DIR]") +set(FILE_DIR2 "[HKCU\\Software\\Classes\\CLSID\\CMake-Tests\\find_path;FILE_DIR]") + +unset(result) +find_path(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" NO_CACHE REQUIRED NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/$\"") + +# query value using special name should be identical to default value +unset(result) +find_path(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR2}" NO_CACHE REQUIRED NO_DEFAULT_PATH) +check("${FILE_DIR2}" "${result}" "result MATCHES \"/${ARCH}/$\"") + +unset(result) +find_path(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/$\"") +# VIEW TARGET should have same value as VIEW HOST +unset(result2) +find_path(result2 NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result2}" "result2 STREQUAL result") + +if (ARCH STREQUAL "64bit") + +unset(result) +find_path(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/$\"") + +unset(result) +find_path(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/$\"") + +unset(result) +find_path(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/$\"") + +unset(result) +find_path(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/$\"") + +# check the second view is taken into account +unset(result) +find_path(result NAMES file32bit.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/$\"") + +unset(result) +find_path(result NAMES file64bit.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/$\"") + +# check the both views are taken into account +unset(result) +find_path(result NAMES file32bit.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/$\"") + +unset(result) +find_path(result NAMES file64bit.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/$\"") + +else() # 32bit + + # no 64bit registry: file not found + unset(result) + find_path(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"result-NOTFOUND$\"") + + unset(result) + find_path(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/$\"") + + unset(result) + find_path(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/$\"") + + unset(result) + find_path(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/$\"") + + unset(result) + find_path(result NAMES file.txt HINTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/$\"") + +endif() + + +if (ARCH STREQUAL "64bit") + + # Check influence of variable CMAKE_SIZEOF_VOID_P + set(CMAKE_SIZEOF_VOID_P 8) + unset(result) + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/$\"") + + unset(result) + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/$\"") + + + set(CMAKE_SIZEOF_VOID_P 4) + unset(result) + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/$\"") + + unset(result) + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/$\"") + + unset(CMAKE_SIZEOF_VOID_P) + + + # Check influence of CMP0134 policy with OLD value + cmake_policy(SET CMP0134 OLD) + # CMAKE_SIZEOF_VOID_P is not set, so search first 32bit registry + unset(result) + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" NO_CACHE REQUIRED NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/$\"") + + cmake_policy(SET CMP0134 NEW) + # CMAKE_SIZEOF_VOID_P is not set, so search first the HOST architecture registry + unset(result) + find_path(result NAMES file.txt PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" NO_CACHE REQUIRED NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/$\"") + +endif() diff --git a/Tests/RunCMake/find_path/RunCMakeTest.cmake b/Tests/RunCMake/find_path/RunCMakeTest.cmake index 5b52f90..63cadc2 100644 --- a/Tests/RunCMake/find_path/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_path/RunCMakeTest.cmake @@ -5,9 +5,37 @@ run_cmake(FromPATHEnv) run_cmake(PrefixInPATH) run_cmake(Required) run_cmake(NO_CACHE) +run_cmake(REGISTRY_VIEW-no-view) +run_cmake(REGISTRY_VIEW-wrong-view) if(APPLE) run_cmake(FrameworksWithSubdirs) endif() run_cmake_with_options(FromPATHEnvDebugVar --debug-find-var=PATH_IN_ENV_PATH) + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + # Tests using the Windows registry + find_program(REG NAMES "reg.exe" NO_CACHE) + if (REG) + ## check host architecture + cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "HKCU" SUBKEYS VIEW 64 ERROR_VARIABLE status) + if (status STREQUAL "") + set(ARCH "64bit") + else() + set(ARCH "32bit") + endif() + + # crete some entries in the registry + cmake_path(CONVERT "${RunCMake_SOURCE_DIR}/registry_host${ARCH}.reg" TO_NATIVE_PATH_LIST registry_data) + execute_process(COMMAND "${REG}" import "${registry_data}" OUTPUT_QUIET ERROR_QUIET) + + run_cmake_with_options(Registry-query -DARCH=${ARCH}) + + # clean-up registry + execute_process(COMMAND "${REG}" delete "HKCU\\SOFTWARE\\Classes\\CLSID\\CMake-Tests\\find_path" /f OUTPUT_QUIET ERROR_QUIET) + if (ARCH STREQUAL "64bit") + execute_process(COMMAND "${REG}" delete "HKCU\\SOFTWARE\\Classes\\WOW6432Node\\CLSID\\CMake-Tests\\find_path" /f OUTPUT_QUIET ERROR_QUIET) + endif() + endif() +endif() diff --git a/Tests/RunCMake/find_path/default.32bit/file.txt b/Tests/RunCMake/find_path/default.32bit/file.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_path/default.32bit/file.txt diff --git a/Tests/RunCMake/find_path/default.32bit/file32bit.txt b/Tests/RunCMake/find_path/default.32bit/file32bit.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_path/default.32bit/file32bit.txt diff --git a/Tests/RunCMake/find_path/default.64bit/file.txt b/Tests/RunCMake/find_path/default.64bit/file.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_path/default.64bit/file.txt diff --git a/Tests/RunCMake/find_path/default.64bit/file64bit.txt b/Tests/RunCMake/find_path/default.64bit/file64bit.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_path/default.64bit/file64bit.txt diff --git a/Tests/RunCMake/find_path/registry_host32bit.reg b/Tests/RunCMake/find_path/registry_host32bit.reg Binary files differnew file mode 100644 index 0000000..a56d79c --- /dev/null +++ b/Tests/RunCMake/find_path/registry_host32bit.reg diff --git a/Tests/RunCMake/find_path/registry_host64bit.reg b/Tests/RunCMake/find_path/registry_host64bit.reg Binary files differnew file mode 100644 index 0000000..705b073 --- /dev/null +++ b/Tests/RunCMake/find_path/registry_host64bit.reg diff --git a/Tests/RunCMake/find_program/32bit/file.exe b/Tests/RunCMake/find_program/32bit/file.exe new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_program/32bit/file.exe diff --git a/Tests/RunCMake/find_program/32bit/file32bit.exe b/Tests/RunCMake/find_program/32bit/file32bit.exe new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_program/32bit/file32bit.exe diff --git a/Tests/RunCMake/find_program/64bit/file.exe b/Tests/RunCMake/find_program/64bit/file.exe new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_program/64bit/file.exe diff --git a/Tests/RunCMake/find_program/64bit/file64bit.exe b/Tests/RunCMake/find_program/64bit/file64bit.exe new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_program/64bit/file64bit.exe diff --git a/Tests/RunCMake/find_program/REGISTRY_VIEW-no-view-result.txt b/Tests/RunCMake/find_program/REGISTRY_VIEW-no-view-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_program/REGISTRY_VIEW-no-view-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_program/REGISTRY_VIEW-no-view-stderr.txt b/Tests/RunCMake/find_program/REGISTRY_VIEW-no-view-stderr.txt new file mode 100644 index 0000000..dbe38a1 --- /dev/null +++ b/Tests/RunCMake/find_program/REGISTRY_VIEW-no-view-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at REGISTRY_VIEW-no-view.cmake:[0-9]+ \(find_program\): + find_program missing required argument for "REGISTRY_VIEW" +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_program/REGISTRY_VIEW-no-view.cmake b/Tests/RunCMake/find_program/REGISTRY_VIEW-no-view.cmake new file mode 100644 index 0000000..1dc6659 --- /dev/null +++ b/Tests/RunCMake/find_program/REGISTRY_VIEW-no-view.cmake @@ -0,0 +1,2 @@ + +find_program(result NAMES input.txt REGISTRY_VIEW) diff --git a/Tests/RunCMake/find_program/REGISTRY_VIEW-wrong-view-result.txt b/Tests/RunCMake/find_program/REGISTRY_VIEW-wrong-view-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_program/REGISTRY_VIEW-wrong-view-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_program/REGISTRY_VIEW-wrong-view-stderr.txt b/Tests/RunCMake/find_program/REGISTRY_VIEW-wrong-view-stderr.txt new file mode 100644 index 0000000..de07095 --- /dev/null +++ b/Tests/RunCMake/find_program/REGISTRY_VIEW-wrong-view-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at REGISTRY_VIEW-wrong-view.cmake:[0-9]+ \(find_program\): + find_program given invalid value for "REGISTRY_VIEW": WRONG_VIEW +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_program/REGISTRY_VIEW-wrong-view.cmake b/Tests/RunCMake/find_program/REGISTRY_VIEW-wrong-view.cmake new file mode 100644 index 0000000..110fd9a --- /dev/null +++ b/Tests/RunCMake/find_program/REGISTRY_VIEW-wrong-view.cmake @@ -0,0 +1,2 @@ + +find_program(result NAMES input.txt REGISTRY_VIEW WRONG_VIEW) diff --git a/Tests/RunCMake/find_program/Registry-query.cmake b/Tests/RunCMake/find_program/Registry-query.cmake new file mode 100644 index 0000000..0e1f2a5 --- /dev/null +++ b/Tests/RunCMake/find_program/Registry-query.cmake @@ -0,0 +1,236 @@ + +# helper function for test validation +function(CHECK query result expression) + cmake_language(EVAL CODE + "if (NOT (${expression})) + message(SEND_ERROR \"wrong value for query '${query}': '${result}'\") + endif()") +endfunction() + + +cmake_policy(SET CMP0134 NEW) + +# HKCU/Software/Classes/CLSID/CMake-Tests/find_program: Query default value +set(FILE_DIR "[HKCU/Software/Classes/CLSID/CMake-Tests/find_program]") +set(FILE_DIR2 "[HKCU/Software/Classes/CLSID/CMake-Tests/find_program;(default)]") + +unset(result) +find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"default.${ARCH}/file.exe$\"") + +# query value using special name should be identical to default value +unset(result) +find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR2}" REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR2}" "${result}" "result MATCHES \"default.${ARCH}/file.exe$\"") + +unset(result) +find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"default.${ARCH}/file.exe$\"") +# VIEW TARGET should have same value as VIEW HOST +unset(result2) +find_program(result2 NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result2}" "result2 STREQUAL result") + +if (ARCH STREQUAL "64bit") + + # default view is BOTH so querying any value specific to 32 or 64bit must be found + unset(result) + find_program(result NAMES file64bit.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/file64bit.exe$\"") + + unset(result) + find_program(result NAMES file32bit.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file32bit.exe$\"") + + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/file.exe$\"") + + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.exe$\"") + + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/file.exe$\"") + unset(result) + + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.exe$\"") + + # check the second view is taken into account + unset(result) + find_program(result NAMES file32bit.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file32bit.exe$\"") + + unset(result) + find_program(result NAMES file64bit.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/file64bit.exe$\"") + + # check the both views are taken into account + unset(result) + find_program(result NAMES file32bit.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file32bit.exe$\"") + + unset(result) + find_program(result NAMES file64bit.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.64bit/file64bit.exe$\"") + +else() # 32bit + + # no 64bit registry: file not found + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"result-NOTFOUND$\"") + + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.exe$\"") + + # views 64_32 and 32_64 give same result + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.exe$\"") + + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.exe$\"") + + # check the both views are usable on 32bit platforms + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"default.32bit/file.exe$\"") + +endif() + +# HKCU/Software/Classes/CLSID/CMake-Tests/find_program: Query specific value +set(FILE_DIR "[{|}HKCU/Software/Classes/CLSID/CMake-Tests/find_program|FILE_DIR]") +set(FILE_DIR2 "[HKCU\\Software\\Classes\\CLSID\\CMake-Tests\\find_program;FILE_DIR]") + +unset(result) +find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.exe$\"") + +# query value using special name should be identical to default value +unset(result) +find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR2}" REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR2}" "${result}" "result MATCHES \"/${ARCH}/file.exe$\"") + +unset(result) +find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.exe$\"") +# VIEW TARGET should have same value as VIEW HOST +unset(result2) +find_program(result2 NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) +check("${FILE_DIR}" "${result2}" "result2 STREQUAL result") + +if (ARCH STREQUAL "64bit") + + # default view is BOTH so querying any value specific to 32 or 64bit must be found + unset(result) + find_program(result NAMES file64bit.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file64bit.exe$\"") + + unset(result) + find_program(result NAMES file32bit.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file32bit.exe$\"") + + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file.exe$\"") + + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.exe$\"") + + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file.exe$\"") + unset(result) + + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.exe$\"") + + # check the second view is taken into account + unset(result) + find_program(result NAMES file32bit.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file32bit.exe$\"") + + unset(result) + find_program(result NAMES file64bit.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file64bit.exe$\"") + + # check the both views are taken into account + unset(result) + find_program(result NAMES file32bit.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file32bit.exe$\"") + + unset(result) + find_program(result NAMES file64bit.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file64bit.exe$\"") + +else() # 32bit + + # no 64bit registry: file not found + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64 NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"result-NOTFOUND$\"") + + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.exe$\"") + + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 64_32 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.exe$\"") + + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW 32_64 REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.exe$\"") + + # check the both views are taken into account + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW BOTH REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.exe$\"") + +endif() + +if (ARCH STREQUAL "64bit") + + # Check influence of variable CMAKE_SIZEOF_VOID_P + set(CMAKE_SIZEOF_VOID_P 8) + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/64bit/file.exe$\"") + + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.exe$\"") + + + set(CMAKE_SIZEOF_VOID_P 4) + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW TARGET REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.exe$\"") + + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" REGISTRY_VIEW HOST REQUIRED NO_CACHE NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.exe$\"") + + unset(CMAKE_SIZEOF_VOID_P) + + + # Check influence of CMP0134 policy with OLD value + cmake_policy(SET CMP0134 OLD) + # CMAKE_SIZEOF_VOID_P is not set, so search first 32bit registry + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" NO_CACHE REQUIRED NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/32bit/file.exe$\"") + + cmake_policy(SET CMP0134 NEW) + # CMAKE_SIZEOF_VOID_P is not set, so search first the HOST architecture registry + unset(result) + find_program(result NAMES file.exe PATHS "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_DIR}" NO_CACHE REQUIRED NO_DEFAULT_PATH) + check("${FILE_DIR}" "${result}" "result MATCHES \"/${ARCH}/file.exe$\"") + +endif() diff --git a/Tests/RunCMake/find_program/RunCMakeTest.cmake b/Tests/RunCMake/find_program/RunCMakeTest.cmake index c2c07af..d0ce8fc 100644 --- a/Tests/RunCMake/find_program/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_program/RunCMakeTest.cmake @@ -7,6 +7,8 @@ run_cmake(RelAndAbsPath) run_cmake(Required) run_cmake(NO_CACHE) run_cmake(IgnorePrefixPath) +run_cmake(REGISTRY_VIEW-no-view) +run_cmake(REGISTRY_VIEW-wrong-view) if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN|MSYS)$") run_cmake(WindowsCom) @@ -30,3 +32,29 @@ if(APPLE) endif() run_cmake_with_options(EnvAndHintsDebugVar --debug-find-var=PROG) + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + # Tests using the Windows registry + find_program(REG NAMES "reg.exe" NO_CACHE) + if (REG) + ## check host architecture + cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "HKCU" SUBKEYS VIEW 64 ERROR_VARIABLE status) + if (status STREQUAL "") + set(ARCH "64bit") + else() + set(ARCH "32bit") + endif() + + # crete some entries in the registry + cmake_path(CONVERT "${RunCMake_SOURCE_DIR}/registry_host${ARCH}.reg" TO_NATIVE_PATH_LIST registry_data) + execute_process(COMMAND "${REG}" import "${registry_data}" OUTPUT_QUIET ERROR_QUIET) + + run_cmake_with_options(Registry-query -DARCH=${ARCH}) + + # clean-up registry + execute_process(COMMAND "${REG}" delete "HKCU\\SOFTWARE\\Classes\\CLSID\\CMake-Tests\\find_program" /f OUTPUT_QUIET ERROR_QUIET) + if (ARCH STREQUAL "64bit") + execute_process(COMMAND "${REG}" delete "HKCU\\SOFTWARE\\Classes\\WOW6432Node\\CLSID\\CMake-Tests\\find_program" /f OUTPUT_QUIET ERROR_QUIET) + endif() + endif() +endif() diff --git a/Tests/RunCMake/find_program/default.32bit/file.exe b/Tests/RunCMake/find_program/default.32bit/file.exe new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_program/default.32bit/file.exe diff --git a/Tests/RunCMake/find_program/default.32bit/file32bit.exe b/Tests/RunCMake/find_program/default.32bit/file32bit.exe new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_program/default.32bit/file32bit.exe diff --git a/Tests/RunCMake/find_program/default.64bit/file.exe b/Tests/RunCMake/find_program/default.64bit/file.exe new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_program/default.64bit/file.exe diff --git a/Tests/RunCMake/find_program/default.64bit/file64bit.exe b/Tests/RunCMake/find_program/default.64bit/file64bit.exe new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_program/default.64bit/file64bit.exe diff --git a/Tests/RunCMake/find_program/registry_host32bit.reg b/Tests/RunCMake/find_program/registry_host32bit.reg Binary files differnew file mode 100644 index 0000000..4c904c9 --- /dev/null +++ b/Tests/RunCMake/find_program/registry_host32bit.reg diff --git a/Tests/RunCMake/find_program/registry_host64bit.reg b/Tests/RunCMake/find_program/registry_host64bit.reg Binary files differnew file mode 100644 index 0000000..1a8fe54 --- /dev/null +++ b/Tests/RunCMake/find_program/registry_host64bit.reg @@ -490,6 +490,7 @@ CMAKE_CXX_SOURCES="\ cmUVProcessChain \ cmVersion \ cmWhileCommand \ + cmWindowsRegistry \ cmWorkingDirectory \ cmake \ cmakemain \ @@ -1612,6 +1613,9 @@ if ${cmake_system_mingw}; then cmake_report cmConfigure.h${_tmp} "#if defined(_WIN32) && !defined(NOMINMAX)" cmake_report cmConfigure.h${_tmp} "# define NOMINMAX" cmake_report cmConfigure.h${_tmp} "#endif" + cmake_report cmConfigure.h${_tmp} "#if defined(_WIN32) && !defined(KWSYS_ENCODING_DEFAULT_CODEPAGE)" + cmake_report cmConfigure.h${_tmp} "# define KWSYS_ENCODING_DEFAULT_CODEPAGE CP_UTF8" + cmake_report cmConfigure.h${_tmp} "#endif" fi # Regenerate configured headers |