find_* commands: add control over Windows registry views

Fixes: #22775
This commit is contained in:
Marc Chevrier
2022-04-16 10:57:30 +02:00
parent 08941a9a40
commit 8d7e80cf3d
115 changed files with 1926 additions and 57 deletions

View File

@@ -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.

View File

@@ -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.

View File

@@ -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``

View File

@@ -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`+

View File

@@ -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|

View File

@@ -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|

View File

@@ -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``

View File

@@ -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|

View File

@@ -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::

View File

@@ -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>

39
Help/policy/CMP0134.rst Normal file
View File

@@ -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

View File

@@ -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.

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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;

View File

@@ -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,

View File

@@ -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;

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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
}

View File

@@ -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;
};

View File

View File

View File

@@ -0,0 +1 @@
1

View File

@@ -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\)

View File

@@ -0,0 +1,2 @@
find_file(result NAMES input.txt REGISTRY_VIEW)

View File

@@ -0,0 +1 @@
1

View File

@@ -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\)

View File

@@ -0,0 +1,2 @@
find_file(result NAMES input.txt REGISTRY_VIEW WRONG_VIEW)

View File

@@ -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()

View File

@@ -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()

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
1

View File

@@ -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\)

View File

@@ -0,0 +1,2 @@
find_library(result NAMES input.txt REGISTRY_VIEW)

View File

@@ -0,0 +1 @@
1

View File

@@ -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\)

View File

@@ -0,0 +1,2 @@
find_library(result NAMES input.txt REGISTRY_VIEW WRONG_VIEW)

View File

@@ -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()

View File

@@ -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()

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,4 @@
if (NOT EXPECTED_LOCATION STREQUAL "32bit")
message (SEND_ERROR "RegistryViewConfig: location is '32bit' but expects '${EXPECTED_LOCATION}'")
endif()

View File

@@ -0,0 +1,4 @@
if (NOT EXPECTED_LOCATION STREQUAL "32bit")
message (SEND_ERROR "RegistryViewConfig: location is '32bit' but expects '${EXPECTED_LOCATION}'")
endif()

View File

@@ -0,0 +1,4 @@
if (NOT EXPECTED_LOCATION STREQUAL "64bit")
message (SEND_ERROR "RegistryViewConfig: location is '64bit' but expects '${EXPECTED_LOCATION}'")
endif()

View File

@@ -0,0 +1,4 @@
if (NOT EXPECTED_LOCATION STREQUAL "64bit")
message (SEND_ERROR "RegistryViewConfig: location is '64bit' but expects '${EXPECTED_LOCATION}'")
endif()

View File

@@ -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()

View File

@@ -0,0 +1 @@
1

View File

@@ -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\)

View File

@@ -0,0 +1,2 @@
find_package(result NAMES input.txt REGISTRY_VIEW)

View File

@@ -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)

View File

@@ -0,0 +1 @@
1

View File

@@ -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\)

View File

@@ -0,0 +1,2 @@
find_package(result NAMES input.txt REGISTRY_VIEW WRONG_VIEW)

View File

@@ -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()

View File

@@ -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()

View File

@@ -0,0 +1,4 @@
if (NOT EXPECTED_LOCATION STREQUAL "default.32bit")
message (SEND_ERROR "RegistryViewConfig: location is 'default.32bit' but expects '${EXPECTED_LOCATION}'")
endif()

View File

@@ -0,0 +1,4 @@
if (NOT EXPECTED_LOCATION STREQUAL "default.32bit")
message (SEND_ERROR "RegistryViewConfig: location is 'default.32bit' but expects '${EXPECTED_LOCATION}'")
endif()

View File

@@ -0,0 +1,4 @@
if (NOT EXPECTED_LOCATION STREQUAL "default.64bit")
message (SEND_ERROR "RegistryViewConfig: location is 'default.64bit' but expects '${EXPECTED_LOCATION}'")
endif()

View File

@@ -0,0 +1,4 @@
if (NOT EXPECTED_LOCATION STREQUAL "default.64bit")
message (SEND_ERROR "RegistryViewConfig: location is 'default.64bit' but expects '${EXPECTED_LOCATION}'")
endif()

Binary file not shown.

Binary file not shown.

View File

View File

View File

@@ -0,0 +1 @@
1

View File

@@ -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\)

View File

@@ -0,0 +1,2 @@
find_path(result NAMES input.txt REGISTRY_VIEW)

View File

@@ -0,0 +1 @@
1

View File

@@ -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\)

View File

@@ -0,0 +1,2 @@
find_path(result NAMES input.txt REGISTRY_VIEW WRONG_VIEW)

View File

@@ -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()

View File

@@ -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()

Binary file not shown.

Binary file not shown.

View File

View File

Some files were not shown because too many files have changed in this diff Show More