diff options
87 files changed, 1519 insertions, 257 deletions
diff --git a/.gitlab/ci/cmake.ps1 b/.gitlab/ci/cmake.ps1 index 5d01e3f..fd8e29f 100755 --- a/.gitlab/ci/cmake.ps1 +++ b/.gitlab/ci/cmake.ps1 @@ -1,7 +1,7 @@ $erroractionpreference = "stop" -$version = "3.21.0" -$sha256sum = "C7B88C907A753F4EC86E43DDC89F91F70BF1B011859142F7F29E6D51EA4ABB3C" +$version = "3.23.1" +$sha256sum = "9B509CC4EB7191DC128CFA3F2170036F9CBC7D9D5F93FF7FAFC5B2D77B3B40DC" $filename = "cmake-$version-windows-x86_64" $tarball = "$filename.zip" diff --git a/.gitlab/ci/cmake.sh b/.gitlab/ci/cmake.sh index c37f6dc..7d964ee 100755 --- a/.gitlab/ci/cmake.sh +++ b/.gitlab/ci/cmake.sh @@ -2,22 +2,22 @@ set -e -readonly version="3.21.0" +readonly version="3.23.1" case "$(uname -s)-$(uname -m)" in Linux-x86_64) shatool="sha256sum" - sha256sum="d54ef6909f519740bc85cec07ff54574cd1e061f9f17357d9ace69f61c6291ce" + sha256sum="f3c654b2e226b9d43369e0bd8487c51618d4dbe5a1af929dd32af7e6ca432d60" platform="linux-x86_64" ;; Linux-aarch64) shatool="sha256sum" - sha256sum="b1e46825bf370f45f8f47c3a497b1122759ee41fbd60187e525f517a4b0934eb" + sha256sum="74062efddeb935bce3d33694a4db534cef9a650f77a9a153a9f217d9dc385c75" platform="linux-aarch64" ;; Darwin-*) shatool="shasum -a 256" - sha256sum="c1c6f19dfc9c658a48b5aed22806595b2337bb3aedb71ab826552f74f568719f" + sha256sum="f794ed92ccb4e9b6619a77328f313497d7decf8fb7e047ba35a348b838e0e1e2" platform="macos-universal" ;; *) diff --git a/Help/command/cmake_host_system_information.rst b/Help/command/cmake_host_system_information.rst index 998e146..f47615a 100644 --- a/Help/command/cmake_host_system_information.rst +++ b/Help/command/cmake_host_system_information.rst @@ -1,9 +1,23 @@ cmake_host_system_information ----------------------------- -Query host system specific information. +Query various host system information. -.. code-block:: cmake +Synopsis +^^^^^^^^ + +.. parsed-literal:: + + `Query host system specific information`_ + cmake_host_system_information(RESULT <variable> QUERY <key> ...) + + `Query Windows registry`_ + cmake_host_system_information(RESULT <variable> QUERY WINDOWS_REGISTRY <key> ...) + +Query host system specific information +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: cmake_host_system_information(RESULT <variable> QUERY <key> ...) @@ -180,7 +194,7 @@ distribution-specific files`_ to collect OS identification data and map it into `man 5 os-release`_ variables. Fallback Interface Variables -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +"""""""""""""""""""""""""""" .. variable:: CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS @@ -246,3 +260,135 @@ Example: .. _man 5 os-release: https://www.freedesktop.org/software/systemd/man/os-release.html .. _various distribution-specific files: http://linuxmafia.com/faq/Admin/release-files.html + +Query Windows registry +^^^^^^^^^^^^^^^^^^^^^^ + +.. versionadded:: 3.24 + +:: + + cmake_host_system_information(RESULT <variable> + QUERY WINDOWS_REGISTRY <key> [VALUE_NAMES|SUBKEYS|VALUE <name>] + [VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)] + [SEPARATOR <separator>] + [ERROR_VARIABLE <result>]) + +Performs query operations on local computer registry subkey. Returns a list of +subkeys or value names that are located under the specified subkey in the +registry or the data of the specified value name. The result of the queried +entity is stored in ``<variable>``. + +.. note:: + + Querying registry for any other platforms than ``Windows``, including + ``CYGWIN``, will always returns an empty string and sets an error message in + the variable specified with sub-option ``ERROR_VARIABLE``. + +``<key>`` specify the full path of a subkey on the local computer. The +``<key>`` must include a valid root key. Valid root keys for the local computer +are: + +* ``HKLM`` or ``HKEY_LOCAL_MACHINE`` +* ``HKCU`` or ``HKEY_CURRENT_USER`` +* ``HKCR`` or ``HKEY_CLASSES_ROOT`` +* ``HKU`` or ``HKEY_USERS`` +* ``HKCC`` or ``HKEY_CURRENT_CONFIG`` + +And, optionally, the path to a subkey under the specified root key. The path +separator can be the slash or the backslash. ``<key>`` is not case sensitive. +For example: + +.. code-block:: cmake + + cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "HKLM") + cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "HKLM/SOFTWARE/Kitware") + cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "HKCU\\SOFTWARE\\Kitware") + +``VALUE_NAMES`` + Request the list of value names defined under ``<key>``. If a default value + is defined, it will be identified with the special name ``(default)``. + +``SUBKEYS`` + Request the list of subkeys defined under ``<key>``. + +``VALUE <name>`` + Request the data stored in value named ``<name>``. If ``VALUE`` is not + specified or argument is the special name ``(default)``, the content of the + default value, if any, will be returned. + + .. code-block:: cmake + + # query default value for HKLM/SOFTWARE/Kitware key + cmake_host_system_information(RESULT result + QUERY WINDOWS_REGISTRY "HKLM/SOFTWARE/Kitware") + + # query default value for HKLM/SOFTWARE/Kitware key using special value name + cmake_host_system_information(RESULT result + QUERY WINDOWS_REGISTRY "HKLM/SOFTWARE/Kitware" + VALUE "(default)") + + Supported types are: + + * ``REG_SZ``. + * ``REG_EXPAND_SZ``. The returned data is expanded. + * ``REG_MULTI_SZ``. The returned is expressed as a CMake list. See also + ``SEPARATOR`` sub-option. + * ``REG_DWORD``. + * ``REG_QWORD``. + + For all other types, an empty string is returned. + +``VIEW`` + Specify which registry views must be queried. When not specified, ``BOTH`` + view is used. + + ``64`` + Query the 64bit registry. On ``32bit Windows``, returns always an empty + string. + + ``32`` + Query the 32bit registry. + + ``64_32`` + For ``VALUE`` sub-option or default value, query the registry using view + ``64``, and if the request failed, query the registry using view ``32``. + For ``VALUE_NAMES`` and ``SUBKEYS`` sub-options, query both views (``64`` + and ``32``) and merge the results (sorted and duplicates removed). + + ``32_64`` + For ``VALUE`` sub-option or default value, query the registry using view + ``32``, and if the request failed, query the registry using view ``64``. + For ``VALUE_NAMES`` and ``SUBKEYS`` sub-options, query both views (``32`` + and ``64``) and merge the results (sorted and duplicates removed). + + ``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`` + +``SEPARATOR`` + Specify the separator character for ``REG_MULTI_SZ`` type. When not + specified, the character ``\0`` is used. + +``ERROR_VARIABLE <result>`` + Returns any error raised during query operation. In case of success, the + variable holds an empty string. diff --git a/Help/prop_tgt/HEADER_SETS.rst b/Help/prop_tgt/HEADER_SETS.rst index fcf723e..ceb1df5 100644 --- a/Help/prop_tgt/HEADER_SETS.rst +++ b/Help/prop_tgt/HEADER_SETS.rst @@ -3,14 +3,13 @@ HEADER_SETS .. versionadded:: 3.23 -List of the target's ``PRIVATE`` and ``PUBLIC`` header sets (i.e. all -file sets with the type ``HEADERS``). Files listed in these file sets -are treated as source files for the purpose of IDE integration. -The files also have their :prop_sf:`HEADER_FILE_ONLY` property set to -``TRUE``. +Read-only list of the target's ``PRIVATE`` and ``PUBLIC`` header sets (i.e. +all file sets with the type ``HEADERS``). Files listed in these file sets are +treated as source files for the purpose of IDE integration. The files also +have their :prop_sf:`HEADER_FILE_ONLY` property set to ``TRUE``. -This property is normally only set by :command:`target_sources(FILE_SET)` -rather than being manipulated directly. +Header sets may be defined using the :command:`target_sources` command +``FILE_SET`` option with type ``HEADERS``. See also :prop_tgt:`HEADER_SET_<NAME>`, :prop_tgt:`HEADER_SET` and :prop_tgt:`INTERFACE_HEADER_SETS`. diff --git a/Help/prop_tgt/INTERFACE_HEADER_SETS.rst b/Help/prop_tgt/INTERFACE_HEADER_SETS.rst index 62db5b3..2d3bdac 100644 --- a/Help/prop_tgt/INTERFACE_HEADER_SETS.rst +++ b/Help/prop_tgt/INTERFACE_HEADER_SETS.rst @@ -3,12 +3,12 @@ INTERFACE_HEADER_SETS .. versionadded:: 3.23 -List of the target's ``INTERFACE`` and ``PUBLIC`` header sets (i.e. all -file sets with the type ``HEADERS``). Files listed in these header sets +Read-only list of the target's ``INTERFACE`` and ``PUBLIC`` header sets (i.e. +all file sets with the type ``HEADERS``). Files listed in these header sets can be installed with :command:`install(TARGETS)` and exported with :command:`install(EXPORT)` and :command:`export`. -This property is normally only set by :command:`target_sources(FILE_SET)` -rather than being manipulated directly. +Header sets may be defined using the :command:`target_sources` command +``FILE_SET`` option with type ``HEADERS``. See also :prop_tgt:`HEADER_SETS`. diff --git a/Help/release/3.22.rst b/Help/release/3.22.rst index efac925..00e93f6 100644 --- a/Help/release/3.22.rst +++ b/Help/release/3.22.rst @@ -151,9 +151,9 @@ Changes made since CMake 3.22.0 include the following. 3.22.1 ------ -This version made no changes to documented features or interfaces. -Some implementation updates were made to support ecosystem changes -and/or fix regressions. +* This version made no changes to documented features or interfaces. + Some implementation updates were made to support ecosystem changes + and/or fix regressions. 3.22.2 ------ @@ -169,3 +169,10 @@ and/or fix regressions. errors in existing projects. The fix has been reverted to restore compatibility. The fix may be restored in a future version of CMake via a policy. + +3.22.4 +------ + +* This version made no changes to documented features or interfaces. + Some implementation updates were made to support ecosystem changes + and/or fix regressions. diff --git a/Help/release/3.23.rst b/Help/release/3.23.rst index 257c3d5..2febbec 100644 --- a/Help/release/3.23.rst +++ b/Help/release/3.23.rst @@ -114,8 +114,8 @@ Variables Properties ---------- -* The :prop_tgt:`HEADER_SETS` and :prop_tgt:`INTERFACE_HEADER_SETS` target - properties were added to list header sets associated with a target. +* The :prop_tgt:`HEADER_SETS` and :prop_tgt:`INTERFACE_HEADER_SETS` read-only + target properties were added to list header sets associated with a target. * The :prop_tgt:`HEADER_SET` and :prop_tgt:`HEADER_SET_<NAME>` target properties were added to list files in the default header set @@ -278,3 +278,7 @@ Changes made since CMake 3.23.0 include the following. targets. Pending further work in a future version of CMake, it is now an error to add a ``FILE_SET`` of type ``HEADERS`` to such targets on Apple platforms. + +* The :prop_tgt:`HEADER_SETS` and :prop_tgt:`INTERFACE_HEADER_SETS` target + properties added in CMake 3.23.0 are now read-only records of the header + sets created by the :command:`target_sources` command. diff --git a/Help/release/dev/chsi-query-windows-registry.rst b/Help/release/dev/chsi-query-windows-registry.rst new file mode 100644 index 0000000..e75bbd8 --- /dev/null +++ b/Help/release/dev/chsi-query-windows-registry.rst @@ -0,0 +1,5 @@ +chsi-query-windows-registry +--------------------------- + +* :command:`cmake_host_system_information` command gains the capability, on + ``Windows`` platform, to query the registry. diff --git a/Modules/CheckPIESupported.cmake b/Modules/CheckPIESupported.cmake index 6424472..452348b 100644 --- a/Modules/CheckPIESupported.cmake +++ b/Modules/CheckPIESupported.cmake @@ -22,10 +22,13 @@ property for executables will be honored at link time. Options are: ``OUTPUT_VARIABLE <output>`` - Set ``<output>`` variable with details about any error. + Set ``<output>`` variable with details about any error. If the check is + bypassed because it uses cached results from a previous call, the output + will be empty even if errors were present in the previous call. ``LANGUAGES <lang>...`` Check the linkers used for each of the specified languages. + If this option is not provided, the command checks all enabled languages. ``C``, ``CXX``, ``Fortran`` are supported. @@ -43,9 +46,9 @@ Variables For each language checked, two boolean cache variables are defined. ``CMAKE_<lang>_LINK_PIE_SUPPORTED`` - Set to ``YES`` if ``PIE`` is supported by the linker and ``NO`` otherwise. + Set to true if ``PIE`` is supported by the linker and false otherwise. ``CMAKE_<lang>_LINK_NO_PIE_SUPPORTED`` - Set to ``YES`` if ``NO_PIE`` is supported by the linker and ``NO`` otherwise. + Set to true if ``NO_PIE`` is supported by the linker and false otherwise. Examples ^^^^^^^^ @@ -139,7 +142,7 @@ function (check_pie_supported) # no support at link time. Set cache variables to NO set(CMAKE_${lang}_LINK_PIE_SUPPORTED NO CACHE INTERNAL "PIE (${lang})") set(CMAKE_${lang}_LINK_NO_PIE_SUPPORTED NO CACHE INTERNAL "NO_PIE (${lang})") - string (APPEND outputs "PIE and NO_PIE are not supported by linker for ${lang}") + string (APPEND outputs "PIE and NO_PIE are not supported by linker for ${lang}\n") endif() endforeach() diff --git a/Modules/FindGLUT.cmake b/Modules/FindGLUT.cmake index 7a16048..43041c5 100644 --- a/Modules/FindGLUT.cmake +++ b/Modules/FindGLUT.cmake @@ -97,6 +97,9 @@ endfunction() find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(GLUT QUIET glut) + if(NOT GLUT_FOUND) + pkg_check_modules(GLUT QUIET freeglut) + endif() if(GLUT_FOUND) # GLUT_INCLUDE_DIRS is now the official result variable, but # older versions of CMake only provided GLUT_INCLUDE_DIR. @@ -111,7 +114,7 @@ if(WIN32) find_path( GLUT_INCLUDE_DIR NAMES GL/glut.h PATHS ${GLUT_ROOT_PATH}/include ) mark_as_advanced(GLUT_INCLUDE_DIR) - find_library( GLUT_glut_LIBRARY_RELEASE NAMES glut glut32 freeglut + find_library( GLUT_glut_LIBRARY_RELEASE NAMES freeglut glut glut32 PATHS ${OPENGL_LIBRARY_DIR} ${GLUT_ROOT_PATH}/Release diff --git a/Modules/FindGit.cmake b/Modules/FindGit.cmake index 99850b4..08a386a 100644 --- a/Modules/FindGit.cmake +++ b/Modules/FindGit.cmake @@ -31,16 +31,16 @@ Example usage: endif() #]=======================================================================] -# Look for 'git' or 'eg' (easy git) +# Look for 'git' # -set(git_names git eg) +set(git_names git) # Prefer .cmd variants on Windows unless running in a Makefile # in the MSYS shell. # if(CMAKE_HOST_WIN32) if(NOT CMAKE_GENERATOR MATCHES "MSYS") - set(git_names git.cmd git eg.cmd eg) + set(git_names git.cmd git) # GitHub search path for Windows file(GLOB github_path "$ENV{LOCALAPPDATA}/Github/PortableGit*/cmd" diff --git a/Modules/FindPostgreSQL.cmake b/Modules/FindPostgreSQL.cmake index 25c5c09..2233aa0 100644 --- a/Modules/FindPostgreSQL.cmake +++ b/Modules/FindPostgreSQL.cmake @@ -53,7 +53,7 @@ is set regardless of the presence of the ``Server`` component in find_package ca # In Windows the default installation of PostgreSQL uses that as part of the path. # E.g C:\Program Files\PostgreSQL\8.4. # Currently, the following version numbers are known to this module: -# "13" "12" "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0" +# "14" "13" "12" "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0" # # To use this variable just do something like this: # set(PostgreSQL_ADDITIONAL_VERSIONS "9.2" "8.4.4") @@ -102,7 +102,7 @@ set(PostgreSQL_ROOT_DIR_MESSAGE "Set the PostgreSQL_ROOT system variable to wher set(PostgreSQL_KNOWN_VERSIONS ${PostgreSQL_ADDITIONAL_VERSIONS} - "13" "12" "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0") + "14" "13" "12" "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0") # Define additional search paths for root directories. set( PostgreSQL_ROOT_DIRECTORIES diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake index 63af9b6..f7996ba 100644 --- a/Modules/FindwxWidgets.cmake +++ b/Modules/FindwxWidgets.cmake @@ -218,7 +218,7 @@ endif() #===================================================================== # Determine whether unix or win32 paths should be used #===================================================================== -if(WIN32 AND NOT CYGWIN AND NOT MSYS AND NOT CMAKE_CROSSCOMPILING) +if(WIN32 AND NOT CYGWIN AND NOT MSYS AND NOT MINGW AND NOT CMAKE_CROSSCOMPILING) set(wxWidgets_FIND_STYLE "win32") else() set(wxWidgets_FIND_STYLE "unix") diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 7661235..c245f68 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -460,6 +460,8 @@ set(SRCS cmVariableWatch.h cmVersion.cxx cmVersion.h + cmWindowsRegistry.cxx + cmWindowsRegistry.h cmWorkerPool.cxx cmWorkerPool.h cmWorkingDirectory.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index c85060b..9bcb3bf 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 23) -set(CMake_VERSION_PATCH 20220411) +set(CMake_VERSION_PATCH 20220414) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 3922c56..0c41c68 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -9,6 +9,7 @@ #include <map> #include <string> #include <type_traits> +#include <unordered_map> #include <utility> #include <cm/optional> @@ -19,10 +20,13 @@ #include "cmsys/Glob.hxx" #include "cmsys/SystemInformation.hxx" +#include "cmArgumentParser.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmWindowsRegistry.h" #ifdef _WIN32 # include "cmAlgorithms.h" @@ -459,6 +463,105 @@ cm::optional<std::string> GetValueChained(GetterFn current, Next... chain) } return GetValueChained(chain...); } + +template <typename Range> +bool QueryWindowsRegistry(Range args, cmExecutionStatus& status, + std::string const& variable) +{ + using View = cmWindowsRegistry::View; + static std::unordered_map<cm::string_view, cmWindowsRegistry::View> + ViewDefinitions{ + { "BOTH"_s, View::Both }, { "HOST"_s, View::Host }, + { "TARGET"_s, View::Target }, { "32"_s, View::Reg32 }, + { "64"_s, View::Reg64 }, { "32_64"_s, View::Reg32_64 }, + { "64_32"_s, View::Reg64_32 } + }; + + if (args.empty()) { + status.SetError("missing <key> specification."); + return false; + } + std::string const& key = *args.begin(); + + struct Arguments + { + std::string ValueName; + bool ValueNames = false; + bool SubKeys = false; + std::string View; + std::string Separator; + std::string ErrorVariable; + }; + cmArgumentParser<Arguments> parser; + parser.Bind("VALUE"_s, &Arguments::ValueName) + .Bind("VALUE_NAMES"_s, &Arguments::ValueNames) + .Bind("SUBKEYS"_s, &Arguments::SubKeys) + .Bind("VIEW"_s, &Arguments::View) + .Bind("SEPARATOR"_s, &Arguments::Separator) + .Bind("ERROR_VARIABLE"_s, &Arguments::ErrorVariable); + std::vector<std::string> invalidArgs; + std::vector<std::string> keywordsMissingValue; + + Arguments const arguments = + parser.Parse(args.advance(1), &invalidArgs, &keywordsMissingValue); + if (!invalidArgs.empty()) { + status.SetError(cmStrCat("given invalid argument(s) \"", + cmJoin(invalidArgs, ", "_s), "\".")); + return false; + } + if (!keywordsMissingValue.empty()) { + status.SetError(cmStrCat("missing expected value for argument(s) \"", + cmJoin(keywordsMissingValue, ", "_s), "\".")); + return false; + } + if ((!arguments.ValueName.empty() && + (arguments.ValueNames || arguments.SubKeys)) || + (arguments.ValueName.empty() && arguments.ValueNames && + arguments.SubKeys)) { + status.SetError("given mutually exclusive sub-options \"VALUE\", " + "\"VALUE_NAMES\" or \"SUBKEYS\"."); + return false; + } + if (!arguments.View.empty() && + ViewDefinitions.find(arguments.View) == ViewDefinitions.end()) { + status.SetError( + cmStrCat("given invalid value for \"VIEW\": ", arguments.View, '.')); + return false; + } + + auto& makefile = status.GetMakefile(); + + makefile.AddDefinition(variable, ""_s); + + auto view = + arguments.View.empty() ? View::Both : ViewDefinitions[arguments.View]; + cmWindowsRegistry registry(makefile); + if (arguments.ValueNames) { + auto result = registry.GetValueNames(key, view); + if (result) { + makefile.AddDefinition(variable, cmJoin(*result, ";"_s)); + } + } else if (arguments.SubKeys) { + auto result = registry.GetSubKeys(key, view); + if (result) { + makefile.AddDefinition(variable, cmJoin(*result, ";"_s)); + } + } else { + auto result = + registry.ReadValue(key, arguments.ValueName, view, arguments.Separator); + if (result) { + makefile.AddDefinition(variable, *result); + } + } + + // return error message if requested + if (!arguments.ErrorVariable.empty()) { + makefile.AddDefinition(arguments.ErrorVariable, registry.GetLastError()); + } + + return true; +} + // END Private functions } // anonymous namespace @@ -481,6 +584,11 @@ bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, return false; } + if (args[current_index + 1] == "WINDOWS_REGISTRY"_s) { + return QueryWindowsRegistry(cmMakeRange(args).advance(current_index + 2), + status, variable); + } + static cmsys::SystemInformation info; static auto initialized = false; if (!initialized) { diff --git a/Source/cmCMakePresetsGraphReadJSON.cxx b/Source/cmCMakePresetsGraphReadJSON.cxx index e68f0fa..0d3a91f 100644 --- a/Source/cmCMakePresetsGraphReadJSON.cxx +++ b/Source/cmCMakePresetsGraphReadJSON.cxx @@ -569,7 +569,7 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile( } // Support for TestOutputTruncation added in version 5. - if (v < 5 && preset.Output) { + if (v < 5 && preset.Output && preset.Output->TestOutputTruncation) { return ReadFileResult::TEST_OUTPUT_TRUNCATION_UNSUPPORTED; } diff --git a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx index 43eccfe..b874575 100644 --- a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx +++ b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx @@ -58,10 +58,10 @@ auto const TestPresetOptionalOutputVerbosityHelper = TestPresetOutputVerbosityHelper); ReadFileResult TestPresetOutputTruncationHelper( - cmCTestTypes::TruncationMode& out, const Json::Value* value) + cm::optional<cmCTestTypes::TruncationMode>& out, const Json::Value* value) { if (!value) { - out = cmCTestTypes::TruncationMode::Tail; + out = cm::nullopt; return ReadFileResult::READ_OK; } @@ -87,10 +87,6 @@ ReadFileResult TestPresetOutputTruncationHelper( return ReadFileResult::INVALID_PRESET; } -auto const TestPresetOptionalTruncationHelper = - cmJSONOptionalHelper<cmCTestTypes::TruncationMode, ReadFileResult>( - ReadFileResult::READ_OK, TestPresetOutputTruncationHelper); - auto const TestPresetOptionalOutputHelper = cmJSONOptionalHelper<TestPreset::OutputOptions, ReadFileResult>( ReadFileResult::READ_OK, @@ -121,7 +117,7 @@ auto const TestPresetOptionalOutputHelper = cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false) .Bind("testOutputTruncation"_s, &TestPreset::OutputOptions::TestOutputTruncation, - TestPresetOptionalTruncationHelper, false) + TestPresetOutputTruncationHelper, false) .Bind("maxTestNameWidth"_s, &TestPreset::OutputOptions::MaxTestNameWidth, cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false)); diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index f22c716..a306fdd 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -190,7 +190,7 @@ cmStateEnums::TargetType cmExportBuildFileGenerator::GetExportTargetType( // to support transitive usage requirements on other targets that // use the object library. if (targetType == cmStateEnums::OBJECT_LIBRARY && - !this->LG->GetGlobalGenerator()->HasKnownObjectFileLocation(nullptr)) { + !target->Target->HasKnownObjectFileLocation(nullptr)) { targetType = cmStateEnums::INTERFACE_LIBRARY; } return targetType; diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 40e1d2e..dd0540c 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -1728,7 +1728,7 @@ Json::Value Target::DumpArtifacts() // Object libraries have only object files as artifacts. if (this->GT->GetType() == cmStateEnums::OBJECT_LIBRARY) { - if (!this->GT->GetGlobalGenerator()->HasKnownObjectFileLocation(nullptr)) { + if (!this->GT->Target->HasKnownObjectFileLocation(nullptr)) { return artifacts; } std::vector<cmSourceFile const*> objectSources; diff --git a/Source/cmFileSet.cxx b/Source/cmFileSet.cxx index 2c06dc6..1d1d29e 100644 --- a/Source/cmFileSet.cxx +++ b/Source/cmFileSet.cxx @@ -7,19 +7,79 @@ #include <utility> #include <vector> +#include <cmext/string_view> + #include "cmsys/RegularExpression.hxx" #include "cmGeneratorExpression.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" +#include "cmMakefile.h" #include "cmMessageType.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" -cmFileSet::cmFileSet(std::string name, std::string type) +cm::static_string_view cmFileSetVisibilityToName(cmFileSetVisibility vis) +{ + switch (vis) { + case cmFileSetVisibility::Interface: + return "INTERFACE"_s; + case cmFileSetVisibility::Public: + return "PUBLIC"_s; + case cmFileSetVisibility::Private: + return "PRIVATE"_s; + } + return ""_s; +} + +cmFileSetVisibility cmFileSetVisibilityFromName(cm::string_view name, + cmMakefile* mf) +{ + if (name == "INTERFACE"_s) { + return cmFileSetVisibility::Interface; + } + if (name == "PUBLIC"_s) { + return cmFileSetVisibility::Public; + } + if (name == "PRIVATE"_s) { + return cmFileSetVisibility::Private; + } + mf->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("File set visibility \"", name, "\" is not valid.")); + return cmFileSetVisibility::Private; +} + +bool cmFileSetVisibilityIsForSelf(cmFileSetVisibility vis) +{ + switch (vis) { + case cmFileSetVisibility::Interface: + return false; + case cmFileSetVisibility::Public: + case cmFileSetVisibility::Private: + return true; + } + return false; +} + +bool cmFileSetVisibilityIsForInterface(cmFileSetVisibility vis) +{ + switch (vis) { + case cmFileSetVisibility::Interface: + case cmFileSetVisibility::Public: + return true; + case cmFileSetVisibility::Private: + return false; + } + return false; +} + +cmFileSet::cmFileSet(std::string name, std::string type, + cmFileSetVisibility visibility) : Name(std::move(name)) , Type(std::move(type)) + , Visibility(visibility) { } diff --git a/Source/cmFileSet.h b/Source/cmFileSet.h index 3aad75f..5357e77 100644 --- a/Source/cmFileSet.h +++ b/Source/cmFileSet.h @@ -7,20 +7,38 @@ #include <string> #include <vector> +#include <cm/string_view> +#include <cmext/string_view> + #include "cmListFileCache.h" class cmCompiledGeneratorExpression; struct cmGeneratorExpressionDAGChecker; class cmGeneratorTarget; class cmLocalGenerator; +class cmMakefile; + +enum class cmFileSetVisibility +{ + Private, + Public, + Interface, +}; +cm::static_string_view cmFileSetVisibilityToName(cmFileSetVisibility vis); +cmFileSetVisibility cmFileSetVisibilityFromName(cm::string_view name, + cmMakefile* mf); +bool cmFileSetVisibilityIsForSelf(cmFileSetVisibility vis); +bool cmFileSetVisibilityIsForInterface(cmFileSetVisibility vis); class cmFileSet { public: - cmFileSet(std::string name, std::string type); + cmFileSet(std::string name, std::string type, + cmFileSetVisibility visibility); const std::string& GetName() const { return this->Name; } const std::string& GetType() const { return this->Type; } + cmFileSetVisibility GetVisibility() const { return this->Visibility; } void ClearDirectoryEntries(); void AddDirectoryEntry(BT<std::string> directories); @@ -61,6 +79,7 @@ public: private: std::string Name; std::string Type; + cmFileSetVisibility Visibility; std::vector<BT<std::string>> DirectoryEntries; std::vector<BT<std::string>> FileEntries; }; diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 3d1cfbf..a9bc435 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1785,7 +1785,7 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode { std::string reason; if (!context->EvaluateForBuildsystem && - !gg->HasKnownObjectFileLocation(&reason)) { + !gt->Target->HasKnownObjectFileLocation(&reason)) { std::ostringstream e; e << "The evaluation of the TARGET_OBJECTS generator expression " "is only suitable for consumption by CMake (limited" diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 5965a16..dcef070 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -459,10 +459,13 @@ public: virtual bool IsNinja() const { return false; } - /** Return true if we know the exact location of object files. - If false, store the reason in the given string. - This is meaningful only after EnableLanguage has been called. */ - virtual bool HasKnownObjectFileLocation(std::string*) const { return true; } + /** Return true if we know the exact location of object files for the given + cmTarget. If false, store the reason in the given string. This is + meaningful only after EnableLanguage has been called. */ + virtual bool HasKnownObjectFileLocation(cmTarget const&, std::string*) const + { + return true; + } virtual bool UseFolderProperty() const; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 3ce3d59..d53c3d5 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1167,6 +1167,20 @@ std::string GetSourcecodeValueFromFileExtension( return sourcecode; } +template <class T> +std::string GetTargetObjectDirArch(T const& target, + const std::string& defaultVal) +{ + auto archs = cmExpandedList(target.GetSafeProperty("OSX_ARCHITECTURES")); + if (archs.size() > 1) { + return "$(CURRENT_ARCH)"; + } else if (archs.size() == 1) { + return archs.front(); + } else { + return defaultVal; + } +} + } // anonymous // Extracts the framework directory, if path matches the framework syntax @@ -4924,9 +4938,11 @@ bool cmGlobalXCodeGenerator::IsMultiConfig() const } bool cmGlobalXCodeGenerator::HasKnownObjectFileLocation( - std::string* reason) const + cmTarget const& target, std::string* reason) const { - if (this->ObjectDirArch.find('$') != std::string::npos) { + auto objectDirArch = GetTargetObjectDirArch(target, this->ObjectDirArch); + + if (objectDirArch.find('$') != std::string::npos) { if (reason != nullptr) { *reason = " under Xcode with multiple architectures"; } @@ -4957,10 +4973,12 @@ void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { std::string configName = this->GetCMakeCFGIntDir(); + auto objectDirArch = GetTargetObjectDirArch(*gt, this->ObjectDirArch); + std::string dir = cmStrCat(this->GetObjectsDirectory("$(PROJECT_NAME)", configName, gt, "$(OBJECT_FILE_DIR_normal:base)/"), - this->ObjectDirArch, '/'); + objectDirArch, '/'); gt->ObjectDirectory = dir; } diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 1159d1f..92e4528 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -107,7 +107,8 @@ public: bool IsXcode() const override { return true; } - bool HasKnownObjectFileLocation(std::string* reason) const override; + bool HasKnownObjectFileLocation(cmTarget const&, + std::string* reason) const override; bool IsIPOSupported() const override { return true; } diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 1ed698d..7de2cb1 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -919,8 +919,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, if (!objectArgs.GetDestination().empty()) { // Verify that we know where the objects are to install them. std::string reason; - if (!helper.Makefile->GetGlobalGenerator() - ->HasKnownObjectFileLocation(&reason)) { + if (!target.HasKnownObjectFileLocation(&reason)) { status.SetError( cmStrCat("TARGETS given OBJECT library \"", target.GetName(), "\" whose objects may not be installed", reason, ".")); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 4fa7d4f..c54d5bf 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2493,12 +2493,12 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) static const std::array<std::string, 4> langs = { { "C", "CXX", "OBJC", "OBJCXX" } }; - bool haveAnyPch = false; + std::set<std::string> pchLangSet; if (this->GetGlobalGenerator()->IsXcode()) { for (const std::string& lang : langs) { const std::string pchHeader = target->GetPchHeader(config, lang, ""); if (!pchHeader.empty()) { - haveAnyPch = true; + pchLangSet.emplace(lang); } } } @@ -2543,9 +2543,11 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) const std::string pchHeader = target->GetPchHeader(config, lang, arch); if (pchSource.empty() || pchHeader.empty()) { - if (this->GetGlobalGenerator()->IsXcode() && haveAnyPch) { + if (this->GetGlobalGenerator()->IsXcode() && !pchLangSet.empty()) { for (auto* sf : sources) { - sf->SetProperty("SKIP_PRECOMPILE_HEADERS", "ON"); + if (pchLangSet.find(sf->GetLanguage()) == pchLangSet.end()) { + sf->SetProperty("SKIP_PRECOMPILE_HEADERS", "ON"); + } } } continue; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index e2314e2..a01321d 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -691,6 +691,11 @@ bool cmTarget::IsAndroidGuiExecutable() const this->impl->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")); } +bool cmTarget::HasKnownObjectFileLocation(std::string* reason) const +{ + return this->GetGlobalGenerator()->HasKnownObjectFileLocation(*this, reason); +} + std::vector<cmCustomCommand> const& cmTarget::GetPreBuildCommands() const { return this->impl->PreBuildCommands; @@ -1484,37 +1489,14 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value) BT<std::string>(value, this->impl->Makefile->GetBacktrace())); } } else if (prop == propHEADER_SETS) { - if (value) { - for (auto const& name : cmExpandedList(value)) { - if (!this->GetFileSet(name)) { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat("Header set \"", name, "\" has not yet been created.")); - return; - } - } - } - this->impl->HeaderSetsEntries.clear(); - if (!StringIsEmpty(value)) { - this->impl->HeaderSetsEntries.emplace_back( - value, this->impl->Makefile->GetBacktrace()); - } + this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, + "HEADER_SETS property is read-only\n"); + return; } else if (prop == propINTERFACE_HEADER_SETS) { - if (value) { - for (auto const& name : cmExpandedList(value)) { - if (!this->GetFileSet(name)) { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat("Header set \"", name, "\" has not yet been created.")); - return; - } - } - } - this->impl->InterfaceHeaderSetsEntries.clear(); - if (!StringIsEmpty(value)) { - this->impl->InterfaceHeaderSetsEntries.emplace_back( - value, this->impl->Makefile->GetBacktrace()); - } + this->impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "INTERFACE_HEADER_SETS property is read-only\n"); + return; } else { this->impl->Properties.SetProperty(prop, value); } @@ -1680,27 +1662,14 @@ void cmTarget::AppendProperty(const std::string& prop, fileSet->AddFileEntry( BT<std::string>(value, this->impl->Makefile->GetBacktrace())); } else if (prop == "HEADER_SETS") { - for (auto const& name : cmExpandedList(value)) { - if (!this->GetFileSet(name)) { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat("Header set \"", name, "\" has not yet been created.")); - return; - } - } - this->impl->HeaderSetsEntries.emplace_back( - value, this->impl->Makefile->GetBacktrace()); + this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, + "HEADER_SETS property is read-only\n"); + return; } else if (prop == "INTERFACE_HEADER_SETS") { - for (auto const& name : cmExpandedList(value)) { - if (!this->GetFileSet(name)) { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat("Header set \"", name, "\" has not yet been created.")); - return; - } - } - this->impl->InterfaceHeaderSetsEntries.emplace_back( - value, this->impl->Makefile->GetBacktrace()); + this->impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "INTERFACE_HEADER_SETS property is read-only\n"); + return; } else { this->impl->Properties.AppendProperty(prop, value, asString); } @@ -2125,13 +2094,26 @@ cmValue cmTarget::GetProperty(const std::string& prop) const return cmValue(output); } if (prop == propHEADER_SETS) { + std::vector<std::string> set_names; + for (auto const& file_set : this->impl->FileSets) { + if (cmFileSetVisibilityIsForSelf(file_set.second.GetVisibility())) { + set_names.push_back(file_set.second.GetName()); + } + } static std::string output; - output = cmJoin(this->impl->HeaderSetsEntries, ";"_s); + output = cmJoin(set_names, ";"_s); return cmValue(output); } if (prop == propINTERFACE_HEADER_SETS) { + std::vector<std::string> set_names; + for (auto const& file_set : this->impl->FileSets) { + if (cmFileSetVisibilityIsForInterface( + file_set.second.GetVisibility())) { + set_names.push_back(file_set.second.GetName()); + } + } static std::string output; - output = cmJoin(this->impl->InterfaceHeaderSetsEntries, ";"_s); + output = cmJoin(set_names, ";"_s); return cmValue(output); } } @@ -2429,10 +2411,20 @@ cmFileSet* cmTarget::GetFileSet(const std::string& name) } std::pair<cmFileSet*, bool> cmTarget::GetOrCreateFileSet( - const std::string& name, const std::string& type) + const std::string& name, const std::string& type, cmFileSetVisibility vis) { - auto result = - this->impl->FileSets.emplace(std::make_pair(name, cmFileSet(name, type))); + auto result = this->impl->FileSets.emplace( + std::make_pair(name, cmFileSet(name, type, vis))); + if (result.second) { + if (cmFileSetVisibilityIsForSelf(vis)) { + this->impl->HeaderSetsEntries.emplace_back( + name, this->impl->Makefile->GetBacktrace()); + } + if (cmFileSetVisibilityIsForInterface(vis)) { + this->impl->InterfaceHeaderSetsEntries.emplace_back( + name, this->impl->Makefile->GetBacktrace()); + } + } return std::make_pair(&result.first->second, result.second); } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 0cdd2fc..72497b3 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -12,6 +12,7 @@ #include <vector> #include "cmAlgorithms.h" +#include "cmFileSet.h" #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -19,7 +20,6 @@ #include "cmValue.h" class cmCustomCommand; -class cmFileSet; class cmGlobalGenerator; class cmInstallTargetGenerator; class cmListFileBacktrace; @@ -220,6 +220,8 @@ public: //! Return whether this target is a GUI executable on Android. bool IsAndroidGuiExecutable() const; + bool HasKnownObjectFileLocation(std::string* reason = nullptr) const; + //! Get a backtrace from the creation of the target. cmListFileBacktrace const& GetBacktrace() const; @@ -287,7 +289,8 @@ public: const cmFileSet* GetFileSet(const std::string& name) const; cmFileSet* GetFileSet(const std::string& name); std::pair<cmFileSet*, bool> GetOrCreateFileSet(const std::string& name, - const std::string& type); + const std::string& type, + cmFileSetVisibility vis); std::vector<std::string> GetAllInterfaceFileSets() const; diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx index 9173a34..b1367e1 100644 --- a/Source/cmTargetSourcesCommand.cxx +++ b/Source/cmTargetSourcesCommand.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTargetSourcesCommand.h" -#include <algorithm> #include <sstream> #include <utility> @@ -239,7 +238,11 @@ bool TargetSourcesImpl::HandleOneFileSet( (args.Type.empty() && args.FileSet[0] >= 'A' && args.FileSet[0] <= 'Z'); std::string type = isDefault ? args.FileSet : args.Type; - auto fileSet = this->Target->GetOrCreateFileSet(args.FileSet, type); + cmFileSetVisibility visibility = + cmFileSetVisibilityFromName(scope, this->Makefile); + + auto fileSet = + this->Target->GetOrCreateFileSet(args.FileSet, type, visibility); if (fileSet.second) { if (!isDefault) { if (!cmFileSet::IsValidName(args.FileSet)) { @@ -261,15 +264,6 @@ bool TargetSourcesImpl::HandleOneFileSet( if (args.BaseDirs.empty()) { args.BaseDirs.emplace_back(this->Makefile->GetCurrentSourceDirectory()); } - - if (scope == "PRIVATE"_s || scope == "PUBLIC"_s) { - this->Target->AppendProperty(cmTarget::GetFileSetsPropertyName(type), - args.FileSet); - } - if (scope == "INTERFACE"_s || scope == "PUBLIC"_s) { - this->Target->AppendProperty( - cmTarget::GetInterfaceFileSetsPropertyName(type), args.FileSet); - } } else { type = fileSet.first->GetType(); if (!args.Type.empty() && args.Type != type) { @@ -279,37 +273,11 @@ bool TargetSourcesImpl::HandleOneFileSet( return false; } - std::string existingScope = "PRIVATE"; - - auto const fileSetsProperty = cmTarget::GetFileSetsPropertyName(type); - auto const interfaceFileSetsProperty = - cmTarget::GetInterfaceFileSetsPropertyName(type); - std::vector<std::string> fileSets; - std::vector<std::string> interfaceFileSets; - cmExpandList(this->Target->GetSafeProperty(fileSetsProperty), fileSets); - cmExpandList(this->Target->GetSafeProperty(interfaceFileSetsProperty), - interfaceFileSets); - - if (std::find(interfaceFileSets.begin(), interfaceFileSets.end(), - args.FileSet) != interfaceFileSets.end()) { - existingScope = "INTERFACE"; - } - if (std::find(fileSets.begin(), fileSets.end(), args.FileSet) != - fileSets.end()) { - if (existingScope == "INTERFACE"_s) { - existingScope = "PUBLIC"; - } - } else if (existingScope != "INTERFACE"_s) { - this->SetError(cmStrCat("File set \"", args.FileSet, "\" is not in ", - fileSetsProperty, " or ", - interfaceFileSetsProperty)); - return false; - } - - if (scope != existingScope) { + if (visibility != fileSet.first->GetVisibility()) { this->SetError( cmStrCat("Scope ", scope, " for file set \"", args.FileSet, - "\" does not match original scope ", existingScope)); + "\" does not match original scope ", + cmFileSetVisibilityToName(fileSet.first->GetVisibility()))); return false; } } @@ -330,11 +298,11 @@ bool TargetSourcesImpl::HandleOneFileSet( for (auto const& dir : cmExpandedList(baseDirectories)) { auto interfaceDirectoriesGenex = cmStrCat("$<BUILD_INTERFACE:", dir, ">"); - if (scope == "PRIVATE"_s || scope == "PUBLIC"_s) { + if (cmFileSetVisibilityIsForSelf(visibility)) { this->Target->AppendProperty("INCLUDE_DIRECTORIES", interfaceDirectoriesGenex); } - if (scope == "INTERFACE"_s || scope == "PUBLIC"_s) { + if (cmFileSetVisibilityIsForInterface(visibility)) { this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES", interfaceDirectoriesGenex); } diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx index cbd241b..1a3e72e 100644 --- a/Source/cmVSSetupHelper.cxx +++ b/Source/cmVSSetupHelper.cxx @@ -4,6 +4,11 @@ #include <utility> +#if !defined(CMAKE_BOOTSTRAP) +# include <cm3p/json/reader.h> +# include <cm3p/json/value.h> +#endif + #include "cmsys/Encoding.hxx" #include "cmsys/FStream.hxx" @@ -295,6 +300,87 @@ bool cmVSSetupAPIHelper::IsEWDKEnabled() return false; } +bool cmVSSetupAPIHelper::EnumerateVSInstancesWithVswhere( + std::vector<VSInstanceInfo>& VSInstances) +{ +#if !defined(CMAKE_BOOTSTRAP) + // Construct vswhere command to get installed VS instances in JSON format + std::string vswhereExe = getenv("ProgramFiles(x86)") + + std::string(R"(\Microsoft Visual Studio\Installer\vswhere.exe)"); + std::vector<std::string> vswhereCmd = { vswhereExe, "-format", "json" }; + + // Execute vswhere command and capture JSON output + std::string json_output; + int retVal = 1; + if (!cmSystemTools::RunSingleCommand(vswhereCmd, &json_output, &json_output, + &retVal, nullptr, + cmSystemTools::OUTPUT_NONE)) { + return false; + } + + // Parse JSON output and iterate over elements + Json::CharReaderBuilder builder; + auto jsonReader = std::unique_ptr<Json::CharReader>(builder.newCharReader()); + Json::Value json; + std::string error; + + if (!jsonReader->parse(json_output.data(), + json_output.data() + json_output.size(), &json, + &error)) { + return false; + } + + for (const auto& item : json) { + VSInstanceInfo instance; + instance.Version = item["installationVersion"].asString(); + instance.VSInstallLocation = item["installationPath"].asString(); + instance.IsWin10SDKInstalled = true; + instance.IsWin81SDKInstalled = false; + cmSystemTools::ConvertToUnixSlashes(instance.VSInstallLocation); + if (LoadVSInstanceVCToolsetVersion(instance)) { + VSInstances.push_back(instance); + } + } + return true; +#else + static_cast<void>(VSInstances); + return false; +#endif +} + +bool cmVSSetupAPIHelper::EnumerateVSInstancesWithCOM( + std::vector<VSInstanceInfo>& VSInstances) +{ + if (initializationFailure || setupConfig == NULL || setupConfig2 == NULL || + setupHelper == NULL) + return false; + + SmartCOMPtr<IEnumSetupInstances> enumInstances = NULL; + if (FAILED( + setupConfig2->EnumInstances((IEnumSetupInstances**)&enumInstances)) || + !enumInstances) { + return false; + } + + SmartCOMPtr<ISetupInstance> instance; + while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) { + SmartCOMPtr<ISetupInstance2> instance2 = NULL; + if (FAILED( + instance->QueryInterface(IID_ISetupInstance2, (void**)&instance2)) || + !instance2) { + instance = NULL; + continue; + } + + VSInstanceInfo instanceInfo; + bool isInstalled = GetVSInstanceInfo(instance2, instanceInfo); + instance = instance2 = NULL; + if (isInstalled) + VSInstances.push_back(instanceInfo); + } + return true; +} + bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() { bool isVSInstanceExists = false; @@ -321,10 +407,6 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() return true; } - if (initializationFailure || setupConfig == NULL || setupConfig2 == NULL || - setupHelper == NULL) - return false; - std::string envVSCommonToolsDir; std::string envVSCommonToolsDirEnvName = "VS" + std::to_string(this->Version) + "0COMNTOOLS"; @@ -334,72 +416,60 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() cmSystemTools::ConvertToUnixSlashes(envVSCommonToolsDir); } - std::vector<VSInstanceInfo> vecVSInstances; - SmartCOMPtr<IEnumSetupInstances> enumInstances = NULL; - if (FAILED( - setupConfig2->EnumInstances((IEnumSetupInstances**)&enumInstances)) || - !enumInstances) { - return false; - } - std::string const wantVersion = std::to_string(this->Version) + '.'; bool specifiedLocationNotSpecifiedVersion = false; SmartCOMPtr<ISetupInstance> instance; - while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) { - SmartCOMPtr<ISetupInstance2> instance2 = NULL; - if (FAILED( - instance->QueryInterface(IID_ISetupInstance2, (void**)&instance2)) || - !instance2) { - instance = NULL; + + std::vector<VSInstanceInfo> vecVSInstancesAll; + + // Enumerate VS instances with either COM interface or Vswhere + if (!EnumerateVSInstancesWithCOM(vecVSInstancesAll) && + !EnumerateVSInstancesWithVswhere(vecVSInstancesAll)) { + return false; + } + + std::vector<VSInstanceInfo> vecVSInstances; + for (const auto& instanceInfo : vecVSInstancesAll) { + // We are looking for a specific major version. + if (instanceInfo.Version.size() < wantVersion.size() || + instanceInfo.Version.substr(0, wantVersion.size()) != wantVersion) { continue; } - VSInstanceInfo instanceInfo; - bool isInstalled = GetVSInstanceInfo(instance2, instanceInfo); - instance = instance2 = NULL; - - if (isInstalled) { - // We are looking for a specific major version. - if (instanceInfo.Version.size() < wantVersion.size() || - instanceInfo.Version.substr(0, wantVersion.size()) != wantVersion) { - continue; + if (!this->SpecifiedVSInstallLocation.empty()) { + // We are looking for a specific instance. + std::string currentVSLocation = instanceInfo.GetInstallLocation(); + if (cmSystemTools::ComparePath(currentVSLocation, + this->SpecifiedVSInstallLocation)) { + if (this->SpecifiedVSInstallVersion.empty() || + instanceInfo.Version == this->SpecifiedVSInstallVersion) { + chosenInstanceInfo = instanceInfo; + return true; + } + specifiedLocationNotSpecifiedVersion = true; } - - if (!this->SpecifiedVSInstallLocation.empty()) { - // We are looking for a specific instance. - std::string currentVSLocation = instanceInfo.GetInstallLocation(); + } else if (!this->SpecifiedVSInstallVersion.empty()) { + // We are looking for a specific version. + if (instanceInfo.Version == this->SpecifiedVSInstallVersion) { + chosenInstanceInfo = instanceInfo; + return true; + } + } else { + // We are not looking for a specific instance. + // If we've been given a hint then use it. + if (!envVSCommonToolsDir.empty()) { + std::string currentVSLocation = + cmStrCat(instanceInfo.GetInstallLocation(), "/Common7/Tools"); if (cmSystemTools::ComparePath(currentVSLocation, - this->SpecifiedVSInstallLocation)) { - if (this->SpecifiedVSInstallVersion.empty() || - instanceInfo.Version == this->SpecifiedVSInstallVersion) { - chosenInstanceInfo = instanceInfo; - return true; - } - specifiedLocationNotSpecifiedVersion = true; - } - } else if (!this->SpecifiedVSInstallVersion.empty()) { - // We are looking for a specific version. - if (instanceInfo.Version == this->SpecifiedVSInstallVersion) { + envVSCommonToolsDir)) { chosenInstanceInfo = instanceInfo; return true; } - } else { - // We are not looking for a specific instance. - // If we've been given a hint then use it. - if (!envVSCommonToolsDir.empty()) { - std::string currentVSLocation = - cmStrCat(instanceInfo.GetInstallLocation(), "/Common7/Tools"); - if (cmSystemTools::ComparePath(currentVSLocation, - envVSCommonToolsDir)) { - chosenInstanceInfo = instanceInfo; - return true; - } - } - // Otherwise, add this to the list of candidates. - vecVSInstances.push_back(instanceInfo); } + // Otherwise, add this to the list of candidates. + vecVSInstances.push_back(instanceInfo); } } diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h index 44c883b..a16f00b 100644 --- a/Source/cmVSSetupHelper.h +++ b/Source/cmVSSetupHelper.h @@ -118,6 +118,9 @@ private: int ChooseVSInstance(const std::vector<VSInstanceInfo>& vecVSInstances); bool EnumerateAndChooseVSInstance(); bool LoadSpecifiedVSInstanceFromDisk(); + bool EnumerateVSInstancesWithVswhere( + std::vector<VSInstanceInfo>& VSInstances); + bool EnumerateVSInstancesWithCOM(std::vector<VSInstanceInfo>& VSInstances); unsigned int Version; diff --git a/Source/cmWindowsRegistry.cxx b/Source/cmWindowsRegistry.cxx new file mode 100644 index 0000000..c857a3b --- /dev/null +++ b/Source/cmWindowsRegistry.cxx @@ -0,0 +1,442 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmWindowsRegistry.h" + +#if defined(_WIN32) && !defined(__CYGWIN__) +# include <algorithm> +# include <cstdint> +# 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 { +bool Is64BitWindows() +{ +# if defined(_WIN64) + // 64-bit programs run only on Win64 + return true; +# else + // 32-bit programs run on both 32-bit and 64-bit Windows, so we must check. + BOOL isWow64 = false; + return IsWow64Process(GetCurrentProcess(), &isWow64) && isWow64; +# endif +} + +// class registry_exception +class registry_error : public std::exception +{ +public: + registry_error(std::string msg) + : What(std::move(msg)) + { + } + ~registry_error() override = default; + + const char* what() const noexcept override { return What.c_str(); } + +private: + std::string What; +}; + +// Class KeyHandler +class KeyHandler +{ +public: + using View = cmWindowsRegistry::View; + + KeyHandler(HKEY hkey) + : Handler(hkey) + { + } + ~KeyHandler() { RegCloseKey(this->Handler); } + + static KeyHandler OpenKey(cm::string_view key, View view); + + std::string ReadValue(cm::string_view name, cm::string_view separator); + + std::vector<std::string> GetValueNames(); + std::vector<std::string> GetSubKeys(); + +private: + static std::string FormatSystemError(LSTATUS status); + + HKEY Handler; +}; + +KeyHandler KeyHandler::OpenKey(cm::string_view key, 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) { + hRootKey = HKEY_LOCAL_MACHINE; + } else if (rootKey == "HKCR"_s || rootKey == "HKEY_CLASSES_ROOT"_s) { + hRootKey = HKEY_CLASSES_ROOT; + } else if (rootKey == "HKCC"_s || rootKey == "HKEY_CURRENT_CONFIG"_s) { + hRootKey = HKEY_CURRENT_CONFIG; + } else if (rootKey == "HKU"_s || rootKey == "HKEY_USERS"_s) { + hRootKey = HKEY_USERS; + } else { + throw registry_error(cmStrCat(rootKey, ": invalid root key.")); + } + std::wstring subKey; + if (start != cm::string_view::npos) { + subKey = cmsys::Encoding::ToWide(key.substr(start + 1).data()); + } + // Update path format + std::replace(subKey.begin(), subKey.end(), L'/', L'\\'); + + REGSAM options = KEY_READ; + if (Is64BitWindows()) { + options |= view == View::Reg64 ? KEY_WOW64_64KEY : KEY_WOW64_32KEY; + } + + HKEY hKey; + if (LSTATUS status = RegOpenKeyExW(hRootKey, subKey.c_str(), 0, options, + &hKey) != ERROR_SUCCESS) { + throw registry_error(FormatSystemError(status)); + } + + return KeyHandler(hKey); +} + +std::string KeyHandler::FormatSystemError(LSTATUS status) +{ + std::string formattedMessage; + LPWSTR message = nullptr; + DWORD size = 1024; + if (FormatMessageW( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, nullptr, + status, 0, reinterpret_cast<LPWSTR>(&message), size, nullptr) == 0) { + formattedMessage = "Windows Registry: unexpected error."; + } else { + formattedMessage = cmTrimWhitespace(cmsys::Encoding::ToNarrow(message)); + } + LocalFree(message); + + return formattedMessage; +} + +std::string KeyHandler::ReadValue(cm::string_view name, + cm::string_view separator) +{ + LSTATUS status; + DWORD size; + // pick-up maximum size for value + if ((status = RegQueryInfoKeyW(this->Handler, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, + &size, nullptr, nullptr)) != ERROR_SUCCESS) { + throw registry_error(this->FormatSystemError(status)); + } + auto data = cm::make_unique<BYTE[]>(size); + DWORD type; + auto valueName = cmsys::Encoding::ToWide(name.data()); + if ((status = RegQueryValueExW(this->Handler, valueName.c_str(), nullptr, + &type, data.get(), &size)) != ERROR_SUCCESS) { + throw registry_error(this->FormatSystemError(status)); + } + switch (type) { + case REG_SZ: + return cmsys::Encoding::ToNarrow(reinterpret_cast<wchar_t*>(data.get())); + break; + case REG_EXPAND_SZ: { + auto expandSize = ExpandEnvironmentStringsW( + reinterpret_cast<wchar_t*>(data.get()), nullptr, 0); + auto expandData = cm::make_unique<wchar_t[]>(expandSize + 1); + if (ExpandEnvironmentStringsW(reinterpret_cast<wchar_t*>(data.get()), + expandData.get(), expandSize + 1) == 0) { + throw registry_error(this->FormatSystemError(GetLastError())); + } else { + return cmsys::Encoding::ToNarrow(expandData.get()); + } + } break; + case REG_DWORD: + return std::to_string(*reinterpret_cast<std::uint32_t*>(data.get())); + break; + case REG_QWORD: + return std::to_string(*reinterpret_cast<std::uint64_t*>(data.get())); + break; + case REG_MULTI_SZ: { + // replace separator with semicolon + auto sep = cmsys::Encoding::ToWide(separator.data())[0]; + std::replace(reinterpret_cast<wchar_t*>(data.get()), + reinterpret_cast<wchar_t*>(data.get()) + + (size / sizeof(wchar_t)) - 1, + sep, L';'); + return cmsys::Encoding::ToNarrow(reinterpret_cast<wchar_t*>(data.get())); + } break; + default: + throw registry_error(cmStrCat(type, ": unsupported type.")); + } +} + +std::vector<std::string> KeyHandler::GetValueNames() +{ + LSTATUS status; + DWORD maxSize; + // pick-up maximum size for value names + if ((status = RegQueryInfoKeyW( + this->Handler, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, &maxSize, nullptr, nullptr, nullptr)) != ERROR_SUCCESS) { + throw registry_error(this->FormatSystemError(status)); + } + // increment size for final null + auto data = cm::make_unique<wchar_t[]>(++maxSize); + DWORD index = 0; + DWORD size = maxSize; + + std::vector<std::string> valueNames; + + while ((status = RegEnumValueW(this->Handler, index, data.get(), &size, + nullptr, nullptr, nullptr, nullptr)) == + ERROR_SUCCESS) { + auto name = cmsys::Encoding::ToNarrow(data.get()); + valueNames.push_back(name.empty() ? "(default)" : name); + size = maxSize; + ++index; + } + + if (status != ERROR_NO_MORE_ITEMS) { + throw registry_error(this->FormatSystemError(status)); + } + + return valueNames; +} + +std::vector<std::string> KeyHandler::GetSubKeys() +{ + LSTATUS status; + DWORD size; + // pick-up maximum size for subkeys + if ((status = RegQueryInfoKeyW( + this->Handler, nullptr, nullptr, nullptr, nullptr, &size, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr)) != ERROR_SUCCESS) { + throw registry_error(this->FormatSystemError(status)); + } + // increment size for final null + auto data = cm::make_unique<wchar_t[]>(++size); + DWORD index = 0; + std::vector<std::string> subKeys; + + while ((status = RegEnumKeyW(this->Handler, index, data.get(), size)) == + ERROR_SUCCESS) { + subKeys.push_back(cmsys::Encoding::ToNarrow(data.get())); + ++index; + } + if (status != ERROR_NO_MORE_ITEMS) { + throw registry_error(this->FormatSystemError(status)); + } + + return subKeys; +} +} +#endif + +// class cmWindowsRegistry +cmWindowsRegistry::cmWindowsRegistry(cmMakefile& makefile) +#if !defined(_WIN32) || defined(__CYGWIN__) + : LastError("No Registry on this platform.") +#endif +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + if (cmValue targetSize = makefile.GetDefinition("CMAKE_SIZEOF_VOID_P")) { + this->TargetSize = targetSize == "8" ? 64 : 32; + } +#else + (void)makefile; +#endif +} + +cm::string_view cmWindowsRegistry::GetLastError() const +{ + return this->LastError; +} + +#if defined(_WIN32) && !defined(__CYGWIN__) +std::vector<cmWindowsRegistry::View> cmWindowsRegistry::ComputeViews(View view) +{ + switch (view) { + case View::Both: + switch (this->TargetSize) { + case 64: + return std::vector<View>{ View::Reg64, View::Reg32 }; + break; + case 32: + return Is64BitWindows() + ? std::vector<View>{ View::Reg32, View::Reg64 } + : std::vector<View>{ View::Reg32 }; + break; + default: + // No language specified, fallback to host architecture + return Is64BitWindows() + ? std::vector<View>{ View::Reg64, View::Reg32 } + : std::vector<View>{ View::Reg32 }; + break; + } + break; + case View::Target: + switch (this->TargetSize) { + case 64: + return std::vector<View>{ View::Reg64 }; + break; + case 32: + return std::vector<View>{ View::Reg32 }; + break; + default: + break; + } + CM_FALLTHROUGH; + case View::Host: + return std::vector<View>{ Is64BitWindows() ? View::Reg64 : View::Reg32 }; + break; + case View::Reg64_32: + return Is64BitWindows() ? std::vector<View>{ View::Reg64, View::Reg32 } + : std::vector<View>{ View::Reg32 }; + break; + case View::Reg32_64: + return Is64BitWindows() ? std::vector<View>{ View::Reg32, View::Reg64 } + : std::vector<View>{ View::Reg32 }; + break; + default: + return std::vector<View>{ view }; + break; + } +} +#endif + +cm::optional<std::string> cmWindowsRegistry::ReadValue( + cm::string_view key, cm::string_view name, View view, + cm::string_view separator) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + // compute list of registry views + auto views = this->ComputeViews(view); + + if (cmsys::SystemTools::Strucmp(name.data(), "(default)") == 0) { + // handle magic name for default value + name = ""_s; + } + if (separator.empty()) { + separator = "\0"_s; + } + + for (auto v : views) { + try { + this->LastError.clear(); + auto handler = KeyHandler::OpenKey(key, v); + return handler.ReadValue(name, separator); + } catch (const registry_error& e) { + this->LastError = e.what(); + continue; + } + } +#else + (void)key; + (void)name; + (void)view; + (void)separator; +#endif + return cm::nullopt; +} + +cm::optional<std::vector<std::string>> cmWindowsRegistry::GetValueNames( + cm::string_view key, View view) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + this->LastError.clear(); + // compute list of registry views + auto views = this->ComputeViews(view); + std::vector<std::string> valueNames; + bool querySuccessful = false; + + for (auto v : views) { + try { + auto handler = KeyHandler::OpenKey(key, v); + auto list = handler.GetValueNames(); + std::move(list.begin(), list.end(), std::back_inserter(valueNames)); + querySuccessful = true; + } catch (const registry_error& e) { + this->LastError = e.what(); + continue; + } + } + if (!valueNames.empty()) { + // value names must be unique and sorted + std::sort(valueNames.begin(), valueNames.end()); + valueNames.erase(std::unique(valueNames.begin(), valueNames.end()), + valueNames.end()); + } + + if (querySuccessful) { + // At least one query was successful, so clean-up any error message + this->LastError.clear(); + return valueNames; + } +#else + (void)key; + (void)view; +#endif + return cm::nullopt; +} + +cm::optional<std::vector<std::string>> cmWindowsRegistry::GetSubKeys( + cm::string_view key, View view) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + this->LastError.clear(); + // compute list of registry views + auto views = this->ComputeViews(view); + std::vector<std::string> subKeys; + bool querySuccessful = false; + + for (auto v : views) { + try { + auto handler = KeyHandler::OpenKey(key, v); + auto list = handler.GetSubKeys(); + std::move(list.begin(), list.end(), std::back_inserter(subKeys)); + querySuccessful = true; + } catch (const registry_error& e) { + this->LastError = e.what(); + continue; + } + } + if (!subKeys.empty()) { + // keys must be unique and sorted + std::sort(subKeys.begin(), subKeys.end()); + subKeys.erase(std::unique(subKeys.begin(), subKeys.end()), subKeys.end()); + } + + if (querySuccessful) { + // At least one query was successful, so clean-up any error message + this->LastError.clear(); + return subKeys; + } +#else + (void)key; + (void)view; +#endif + return cm::nullopt; +} diff --git a/Source/cmWindowsRegistry.h b/Source/cmWindowsRegistry.h new file mode 100644 index 0000000..6f10b3a --- /dev/null +++ b/Source/cmWindowsRegistry.h @@ -0,0 +1,55 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include <string> +#include <vector> + +#include <cm/optional> +#include <cm/string_view> +#include <cmext/string_view> + +class cmMakefile; + +class cmWindowsRegistry +{ +public: + cmWindowsRegistry(cmMakefile&); + + enum class View + { + Both, + Target, + Host, + Reg64_32, + Reg32_64, + Reg32, + Reg64 + }; + + cm::optional<std::string> ReadValue(cm::string_view key, + View view = View::Both, + cm::string_view separator = "\0"_s) + { + return this->ReadValue(key, ""_s, view, separator); + } + cm::optional<std::string> ReadValue(cm::string_view key, + cm::string_view name, + View view = View::Both, + cm::string_view separator = "\0"_s); + + cm::optional<std::vector<std::string>> GetValueNames(cm::string_view key, + View view = View::Both); + cm::optional<std::vector<std::string>> GetSubKeys(cm::string_view key, + View view = View::Both); + + cm::string_view GetLastError() const; + +private: +#if defined(_WIN32) && !defined(__CYGWIN__) + std::vector<View> ComputeViews(View view); + + int TargetSize = 0; +#endif + std::string LastError; +}; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 96bf845..28be166 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -308,10 +308,11 @@ int do_cmake(int ac, char const* const* av) parsedArgs.emplace_back("--find-package"); return true; } }, - CommandArgument{ "--list-presets", CommandArgument::Values::Zero, - [&](std::string const&) -> bool { + CommandArgument{ "--list-presets", CommandArgument::Values::ZeroOrOne, + [&](std::string const& value) -> bool { workingMode = cmake::HELP_MODE; parsedArgs.emplace_back("--list-presets"); + parsedArgs.emplace_back(value); return true; } }, }; diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index dbff293..024c388 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -352,6 +352,9 @@ if(MSVC) add_RunCMake_test(MSVCRuntimeTypeInfo) add_RunCMake_test(MSVCWarningFlags) endif() +if(XCODE_VERSION) + set(ObjectLibrary_ARGS -DXCODE_VERSION=${XCODE_VERSION}) +endif() add_RunCMake_test(ObjectLibrary) add_RunCMake_test(ParseImplicitIncludeInfo) add_RunCMake_test(ParseImplicitLinkInfo) diff --git a/Tests/RunCMake/CMakePresets/ListConfigurePresetsWorkingDir-stdout.txt b/Tests/RunCMake/CMakePresets/ListConfigurePresetsWorkingDir-stdout.txt new file mode 100644 index 0000000..97eedae --- /dev/null +++ b/Tests/RunCMake/CMakePresets/ListConfigurePresetsWorkingDir-stdout.txt @@ -0,0 +1,7 @@ +^Not searching for unused variables given on the command line\. +Available configure presets: + + "zzzzzz" - Sleepy + "aaaaaaaa" - Screaming + "mmmmmm" + "no-generator"$ diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index 449132a..5867efd 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake @@ -71,13 +71,18 @@ function(run_cmake_presets name) set(_unused_cli) endif() + set(_preset "--preset=${name}") + if(CMakePresets_NO_PRESET) + set(_preset) + endif() + set(RunCMake_TEST_COMMAND ${CMAKE_COMMAND} ${_source_args} -DRunCMake_TEST=${name} -DRunCMake_GENERATOR=${RunCMake_GENERATOR} -DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM} ${_unused_cli} - --preset=${name} + ${_preset} ${ARGN} ) run_cmake(${name}) @@ -288,7 +293,10 @@ run_cmake_presets(ListPresets --list-presets) set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/ListPresetsWorkingDir") set(RunCMake_TEST_NO_CLEAN 1) set(CMakePresets_NO_SOURCE_ARGS 1) +set(CMakePresets_NO_PRESET 1) run_cmake_presets(ListPresetsWorkingDir --list-presets) +run_cmake_presets(ListConfigurePresetsWorkingDir --list-presets=configure) +unset(CMakePresets_NO_PRESET) unset(CMakePresets_NO_SOURCE_ARGS) unset(RunCMake_TEST_NO_CLEAN) unset(RunCMake_TEST_BINARY_DIR) diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake index 8515ba5..0e31b78 100644 --- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake +++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake @@ -8,12 +8,21 @@ run_cmake(BadObjSource2) if(RunCMake_GENERATOR STREQUAL "Xcode" AND "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]") run_cmake(ImportMultiArch) run_cmake(InstallNotSupported) + + set(osx_archs $ENV{CMAKE_OSX_ARCHITECTURES}) + list(GET osx_archs 0 osx_arch) + run_cmake_with_options(TargetOverrideSingleArch -Dosx_arch=${osx_arch}) else() run_cmake(Import) run_cmake(Install) run_cmake(InstallLinkedObj1) run_cmake(InstallLinkedObj2) + + if(RunCMake_GENERATOR STREQUAL "Xcode" AND XCODE_VERSION VERSION_GREATER_EQUAL 13) + run_cmake(TargetOverrideMultiArch) + endif() endif() + run_cmake(Export) function (run_object_lib_build name) diff --git a/Tests/RunCMake/target_sources/FileSetNoScope-result.txt b/Tests/RunCMake/ObjectLibrary/TargetOverrideMultiArch-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/target_sources/FileSetNoScope-result.txt +++ b/Tests/RunCMake/ObjectLibrary/TargetOverrideMultiArch-result.txt diff --git a/Tests/RunCMake/ObjectLibrary/TargetOverrideMultiArch-stderr.txt b/Tests/RunCMake/ObjectLibrary/TargetOverrideMultiArch-stderr.txt new file mode 100644 index 0000000..eb0593c --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/TargetOverrideMultiArch-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at TargetOverrideMultiArch.cmake:[0-9]+ \(install\): + install TARGETS given OBJECT library "A" whose objects may not be installed + under Xcode with multiple architectures. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/TargetOverrideMultiArch.cmake b/Tests/RunCMake/ObjectLibrary/TargetOverrideMultiArch.cmake new file mode 100644 index 0000000..ada77f8 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/TargetOverrideMultiArch.cmake @@ -0,0 +1,3 @@ +add_library(A OBJECT a.c) +set_target_properties(A PROPERTIES OSX_ARCHITECTURES "x86_64;arm64") +install(TARGETS A DESTINATION lib) diff --git a/Tests/RunCMake/ObjectLibrary/TargetOverrideSingleArch.cmake b/Tests/RunCMake/ObjectLibrary/TargetOverrideSingleArch.cmake new file mode 100644 index 0000000..3f400e8 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/TargetOverrideSingleArch.cmake @@ -0,0 +1,3 @@ +add_library(A OBJECT a.c) +set_target_properties(A PROPERTIES OSX_ARCHITECTURES ${osx_arch}) +install(TARGETS A DESTINATION lib) diff --git a/Tests/RunCMake/PrecompileHeaders/PchIncludedOneLanguage.cmake b/Tests/RunCMake/PrecompileHeaders/PchIncludedOneLanguage.cmake new file mode 100644 index 0000000..dd582ac --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchIncludedOneLanguage.cmake @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.16) +project(PchIncludedAllLanguages C CXX) + +if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH) + add_definitions(-DHAVE_PCH_SUPPORT) +endif() + +add_executable(main + main.cpp + empty.c + pch-included.cpp +) + +target_precompile_headers(main PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_SOURCE_DIR}/pch.h>) + +enable_testing() +add_test(NAME main COMMAND main) diff --git a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake index a7b3126..fd41e2f 100644 --- a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake +++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake @@ -30,4 +30,5 @@ if(RunCMake_GENERATOR MATCHES "Make|Ninja") endif() run_test(PchReuseFromObjLib) run_test(PchIncludedAllLanguages) +run_test(PchIncludedOneLanguage) run_test(PchLibObjLibExe) diff --git a/Tests/RunCMake/target_sources/FileSetNoExistPrivate-result.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadKey1-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/target_sources/FileSetNoExistPrivate-result.txt +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadKey1-result.txt diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadKey1-stderr.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadKey1-stderr.txt new file mode 100644 index 0000000..1832ada --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadKey1-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at Registry_BadKey1.cmake:[0-9]+ \(message\): + WRONG_ROOT: invalid root key. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadKey1.cmake b/Tests/RunCMake/cmake_host_system_information/Registry_BadKey1.cmake new file mode 100644 index 0000000..6299f85 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadKey1.cmake @@ -0,0 +1,4 @@ +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY WRONG_ROOT/SUBKEY ERROR_VARIABLE error) +if (NOT error STREQUAL "") + message(FATAL_ERROR "${error}") +endif() diff --git a/Tests/RunCMake/target_sources/FileSetNoExistInterface-result.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadKey2-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/target_sources/FileSetNoExistInterface-result.txt +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadKey2-result.txt diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadKey2-stderr.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadKey2-stderr.txt new file mode 100644 index 0000000..4be55bf --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadKey2-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at Registry_BadKey2.cmake:[0-9]+ \(message\): + HKLM-SUBKEY: invalid root key. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadKey2.cmake b/Tests/RunCMake/cmake_host_system_information/Registry_BadKey2.cmake new file mode 100644 index 0000000..1750078 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadKey2.cmake @@ -0,0 +1,4 @@ +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY HKLM-SUBKEY ERROR_VARIABLE error) +if (NOT error STREQUAL "") + message(FATAL_ERROR "${error}") +endif() diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery1-result.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery1-stderr.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery1-stderr.txt new file mode 100644 index 0000000..9510327 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery1-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at Registry_BadQuery1.cmake:[0-9]+ \(cmake_host_system_information\): + cmake_host_system_information given invalid argument\(s\) "BAD_OPTION". +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery1.cmake b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery1.cmake new file mode 100644 index 0000000..a92f35c --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery1.cmake @@ -0,0 +1 @@ +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY HKLM/SOFTWARE BAD_OPTION) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-result.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt new file mode 100644 index 0000000..6a430f1 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at Registry_BadQuery2.cmake:[0-9]+ \(cmake_host_system_information\): + cmake_host_system_information missing expected value for argument\(s\) + "VALUE". +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2.cmake b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2.cmake new file mode 100644 index 0000000..7c751cc --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2.cmake @@ -0,0 +1 @@ +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY HKLM/SOFTWARE VALUE) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-result.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt new file mode 100644 index 0000000..5eda4ff --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at Registry_BadView1.cmake:[0-9]+ \(cmake_host_system_information\): + cmake_host_system_information missing expected value for argument\(s\) + "VIEW". +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadView1.cmake b/Tests/RunCMake/cmake_host_system_information/Registry_BadView1.cmake new file mode 100644 index 0000000..6527784 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadView1.cmake @@ -0,0 +1 @@ +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY HKLM/SOFTWARE VIEW) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadView2-result.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadView2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadView2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadView2-stderr.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadView2-stderr.txt new file mode 100644 index 0000000..201d93a --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadView2-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at Registry_BadView2.cmake:[0-9]+ \(cmake_host_system_information\): + cmake_host_system_information given invalid value for "VIEW": BAD_VIEW. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadView2.cmake b/Tests/RunCMake/cmake_host_system_information/Registry_BadView2.cmake new file mode 100644 index 0000000..d116c76 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadView2.cmake @@ -0,0 +1 @@ +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY HKLM/SOFTWARE VIEW BAD_VIEW) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadView3-result.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadView3-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadView3-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadView3-stderr.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadView3-stderr.txt new file mode 100644 index 0000000..5b7f7c7 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadView3-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at Registry_BadView3.cmake:[0-9]+ \(cmake_host_system_information\): + cmake_host_system_information given invalid argument\(s\) "64". +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadView3.cmake b/Tests/RunCMake/cmake_host_system_information/Registry_BadView3.cmake new file mode 100644 index 0000000..7c5f272 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadView3.cmake @@ -0,0 +1 @@ +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY HKLM/SOFTWARE VIEW 32 64) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_NoArgs-result.txt b/Tests/RunCMake/cmake_host_system_information/Registry_NoArgs-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_NoArgs-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_NoArgs-stderr.txt b/Tests/RunCMake/cmake_host_system_information/Registry_NoArgs-stderr.txt new file mode 100644 index 0000000..ff55fcb --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_NoArgs-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at Registry_NoArgs.cmake:[0-9]+ \(cmake_host_system_information\): + cmake_host_system_information missing <key> specification. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_NoArgs.cmake b/Tests/RunCMake/cmake_host_system_information/Registry_NoArgs.cmake new file mode 100644 index 0000000..87e253d --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_NoArgs.cmake @@ -0,0 +1 @@ +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_Query.cmake b/Tests/RunCMake/cmake_host_system_information/Registry_Query.cmake new file mode 100644 index 0000000..9f9fb14 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Registry_Query.cmake @@ -0,0 +1,232 @@ + +# check Windows architecture +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "HKCU" SUBKEYS VIEW 64 ERROR_VARIABLE status) +if (status STREQUAL "") + set(HOST_64BIT TRUE) +else() + set(HOST_64BIT FALSE) +endif() + +# helper function for test validation +function(CHECK key result status expression) + if(status STREQUAL "") + cmake_language(EVAL CODE + "if (NOT (${expression})) + message(SEND_ERROR \"wrong value for key '${key}': '${result}'\") + endif()") + else() + message(SEND_ERROR "query failed for key '${key}': '${status}'") + endif() +endfunction() + + +# HKCU/Software/Classes/CLSID/CMake-Tests/chsi-registry: Query default value +set(KEY "HKCU/Software/Classes/CLSID/CMake-Tests/chsi-registry") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" ERROR_VARIABLE status) +check("${KEY}" "${result}" "${status}" + "(HOST_64BIT AND result STREQUAL \"default 64bit\") + OR (NOT HOST_64BIT AND result STREQUAL \"default 32bit\")") +# query value using special name should be identical to default value +cmake_host_system_information(RESULT result2 QUERY WINDOWS_REGISTRY "${KEY}" VALUE "(default)" ERROR_VARIABLE status) +check("${KEY}{(default)}" "${result2}" "${status}" "result2 STREQUAL result") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VIEW HOST ERROR_VARIABLE status) +check("${KEY}" "${result}" "${status}" + "(HOST_64BIT AND result STREQUAL \"default 64bit\") + OR (NOT HOST_64BIT AND result STREQUAL \"default 32bit\")") +# VIEW TARGET should have same value as VIEW HOST +cmake_host_system_information(RESULT result2 QUERY WINDOWS_REGISTRY "${KEY}" VIEW TARGET ERROR_VARIABLE status) +check("${KEY}" "${result2}" "${status}" "result2 STREQUAL result") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VIEW 64 ERROR_VARIABLE status) +check("${KEY}" "${result}" "${status}" "result STREQUAL \"default 64bit\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VIEW 32 ERROR_VARIABLE status) +check("${KEY}" "${result}" "${status}" "result STREQUAL \"default 32bit\"") + +# reg 64bit is read first +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VIEW 64_32 ERROR_VARIABLE status) +check("${KEY}" "${result}" "${status}" "result STREQUAL \"default 64bit\"") + +# reg 32bit is read first +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VIEW 32_64 ERROR_VARIABLE status) +check("${KEY}" "${result}" "${status}" "result STREQUAL \"default 32bit\"") + + +# HKCU/Software/CMake-Tests/chsi-registry: Query named value +set(KEY "HKCU/Software/Classes/CLSID/CMake-Tests/chsi-registry") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE BYTE_SIZE + ERROR_VARIABLE status) +check("${KEY}{BYTE_SIZE}" "${result}" "${status}" + "(HOST_64BIT AND result STREQUAL \"64bit\") + OR (NOT HOST_64BIT AND result STREQUAL \"32bit\")") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE BYTE_SIZE + VIEW HOST ERROR_VARIABLE status) +check("${KEY}{BYTE_SIZE}" "${result}" "${status}" + "(HOST_64BIT AND result STREQUAL \"64bit\") + OR (NOT HOST_64BIT AND result STREQUAL \"32bit\")") +# VIEW TARGET should have same value as VIEW HOST +cmake_host_system_information(RESULT result2 QUERY WINDOWS_REGISTRY "${KEY}" VALUE BYTE_SIZE + VIEW TARGET ERROR_VARIABLE status) +check("${KEY}{BYTE_SIZE}" "${result2}" "${status}" "result2 STREQUAL result") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE BYTE_SIZE + VIEW 64 ERROR_VARIABLE status) +check("${KEY}{BYTE_SIZE}" "${result}" "${status}" "result STREQUAL \"64bit\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE BYTE_SIZE + VIEW 32 ERROR_VARIABLE status) +check("${KEY}{BYTE_SIZE}" "${result}" "${status}" "result STREQUAL \"32bit\"") + +# reg 64bit is read first +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE BYTE_SIZE + VIEW 64_32 ERROR_VARIABLE status) +check("${KEY}{BYTE_SIZE}" "${result}" "${status}" "result STREQUAL \"64bit\"") + +# reg 32bit is read first +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE BYTE_SIZE + VIEW 32_64 ERROR_VARIABLE status) +check("${KEY}{BYTE_SIZE}" "${result}" "${status}" "result STREQUAL \"32bit\"") + + +# HKCU/Software/CMake-Tests/chsi-registry: check retrieval of various types +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE VALUE_SZ ERROR_VARIABLE status) +check("${KEY}{VALUE_SZ}" "${result}" "${status}" "result STREQUAL \"data with space\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE VALUE_EXPAND_SZ ERROR_VARIABLE status) +check("${KEY}{VALUE_EXPAND_SZ}" "${result}" "${status}" + "(NOT result STREQUAL \"PATH=%PATH%\") AND (result MATCHES \"^PATH=\")") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE VALUE_MULTI_SZ ERROR_VARIABLE status) +check("${KEY}{VALUE_MULTI_SZ}" "${result}" "${status}" "result STREQUAL \"data1;data2\"") +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE VALUE2_MULTI_SZ + SEPARATOR "|" ERROR_VARIABLE status) +check("${KEY}{VALUE2_MULTI_SZ}" "${result}" "${status}" "result STREQUAL \"data1;data2\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE VALUE_DWORD ERROR_VARIABLE status) +check("${KEY}{VALUE_DWORD}" "${result}" "${status}" "result EQUAL \"129\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE VALUE_QWORD ERROR_VARIABLE status) +check("${KEY}{VALUE_QWORD}" "${result}" "${status}" "result EQUAL \"513\"") + + +# HKCU/Software/CMake-Tests/chsi-registry: check retrieval of value names +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE_NAMES + ERROR_VARIABLE status) +check("${KEY}[VALUE_NAMES]" "${result}" "${status}" "result STREQUAL \"(default);BYTE_SIZE;VALUE2_MULTI_SZ;VALUE2_SZ;VALUE_DWORD;VALUE_EXPAND_SZ;VALUE_MULTI_SZ;VALUE_QWORD;VALUE_SZ\"") +# VIEW BOTH should have same result as default view +cmake_host_system_information(RESULT result2 QUERY WINDOWS_REGISTRY "${KEY}" VALUE_NAMES + VIEW BOTH ERROR_VARIABLE status) +check("${KEY}[VALUE_NAMES]" "${result2}" "${status}" "result STREQUAL \"(default);BYTE_SIZE;VALUE2_MULTI_SZ;VALUE2_SZ;VALUE_DWORD;VALUE_EXPAND_SZ;VALUE_MULTI_SZ;VALUE_QWORD;VALUE_SZ\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE_NAMES + VIEW HOST ERROR_VARIABLE status) +check("${KEY}[VALUE_NAMES]" "${result}" "${status}" + "(HOST_64BIT AND result STREQUAL \"(default);BYTE_SIZE;VALUE2_MULTI_SZ;VALUE_DWORD;VALUE_EXPAND_SZ;VALUE_MULTI_SZ;VALUE_QWORD;VALUE_SZ\") + OR (NOT HOST_64BIT AND result STREQUAL \"(default);BYTE_SIZE;VALUE2_SZ\")") +# VIEW TARGET should have same result as VIEW HOST +cmake_host_system_information(RESULT result2 QUERY WINDOWS_REGISTRY "${KEY}" VALUE_NAMES + VIEW TARGET ERROR_VARIABLE status) +check("${KEY}[VALUE_NAMES]" "${result2}" "${status}" + "(HOST_64BIT AND result STREQUAL \"(default);BYTE_SIZE;VALUE2_MULTI_SZ;VALUE_DWORD;VALUE_EXPAND_SZ;VALUE_MULTI_SZ;VALUE_QWORD;VALUE_SZ\") + OR (NOT HOST_64BIT AND result STREQUAL \"(default);BYTE_SIZE;VALUE2_SZ\")") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE_NAMES + VIEW 64 ERROR_VARIABLE status) +check("${KEY}[VALUE_NAMES]" "${result}" "${status}" + "result STREQUAL \"(default);BYTE_SIZE;VALUE2_MULTI_SZ;VALUE_DWORD;VALUE_EXPAND_SZ;VALUE_MULTI_SZ;VALUE_QWORD;VALUE_SZ\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE_NAMES + VIEW 32 ERROR_VARIABLE status) +check("${KEY}[VALUE_NAMES]" "${result}" "${status}" "result STREQUAL \"(default);BYTE_SIZE;VALUE2_SZ\"") + +# reg 64bit is read first +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE_NAMES + VIEW 64_32 ERROR_VARIABLE status) +check("${KEY}[VALUE_NAMES]" "${result}" "${status}" + "result STREQUAL \"(default);BYTE_SIZE;VALUE2_MULTI_SZ;VALUE2_SZ;VALUE_DWORD;VALUE_EXPAND_SZ;VALUE_MULTI_SZ;VALUE_QWORD;VALUE_SZ\"") + +# reg 32bit is read first. Result is the same as with view 64_32 +cmake_host_system_information(RESULT result2 QUERY WINDOWS_REGISTRY "${KEY}" VALUE_NAMES + VIEW 32_64 ERROR_VARIABLE status) +check("${KEY}[VALUE_NAMES]" "${result2}" "${status}" "result2 STREQUAL result") + + +# HKCU/Software/CMake-Tests/chsi-registry: check retrieval of sub keys +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" SUBKEYS + ERROR_VARIABLE status) +check("${KEY}[SUBKEYS]" "${result}" "${status}" "result STREQUAL \"subkey1;subkey2;subkey3\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" SUBKEYS + VIEW HOST ERROR_VARIABLE status) +check("${KEY}[SUBKEYS]" "${result}" "${status}" + "(HOST_64BIT AND result STREQUAL \"subkey1;subkey2\") + OR (NOT HOST_64BIT AND result STREQUAL \"subkey1;subkey3\")") +# VIEW TARGET should have same result as VIEW HOST +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" SUBKEYS + VIEW TARGET ERROR_VARIABLE status) +check("${KEY}[SUBKEYS]" "${result}" "${status}" + "(HOST_64BIT AND result STREQUAL \"subkey1;subkey2\") + OR (NOT HOST_64BIT AND result STREQUAL \"subkey1;subkey3\")") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" SUBKEYS + VIEW 64 ERROR_VARIABLE status) +check("${KEY}[SUBKEYS]" "${result}" "${status}" + "result STREQUAL \"subkey1;subkey2\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" SUBKEYS + VIEW 32 ERROR_VARIABLE status) +check("${KEY}[SUBKEYS]" "${result}" "${status}" + "result STREQUAL \"subkey1;subkey3\"") + +# reg 64bit is read first +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" SUBKEYS + VIEW 64_32 ERROR_VARIABLE status) +check("${KEY}[SUBLEYS]" "${result}" "${status}" "result STREQUAL \"subkey1;subkey2;subkey3\"") + +# reg 32bit is read first. Result is the same as with view 64_32 +cmake_host_system_information(RESULT result2 QUERY WINDOWS_REGISTRY "${KEY}" SUBKEYS + VIEW 32_64 ERROR_VARIABLE status) +check("${KEY}[SUBKEYS]" "${result2}" "${status}" "result2 STREQUAL result") + + +# Check influence of variable CMAKE_SIZEOF_VOID_P +set(CMAKE_SIZEOF_VOID_P 8) + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" + VIEW TARGET ERROR_VARIABLE status) +check("${KEY}" "${result}" "${status}" "result STREQUAL \"default 64bit\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE BYTE_SIZE + VIEW TARGET ERROR_VARIABLE status) +check("${KEY}" "${result}" "${status}" "result STREQUAL \"64bit\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE_NAMES + VIEW TARGET ERROR_VARIABLE status) +check("${KEY}" "${result}" "${status}" "result STREQUAL \"(default);BYTE_SIZE;VALUE2_MULTI_SZ;VALUE_DWORD;VALUE_EXPAND_SZ;VALUE_MULTI_SZ;VALUE_QWORD;VALUE_SZ\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" SUBKEYS + VIEW TARGET ERROR_VARIABLE status) +check("${KEY}" "${result}" "${status}" "result STREQUAL \"subkey1;subkey2\"") + + +set(CMAKE_SIZEOF_VOID_P 4) + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" + VIEW TARGET ERROR_VARIABLE status) +check("${KEY}" "${result}" "${status}" "result STREQUAL \"default 32bit\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE BYTE_SIZE + VIEW TARGET ERROR_VARIABLE status) +check("${KEY}" "${result}" "${status}" "result STREQUAL \"32bit\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" VALUE_NAMES + VIEW TARGET ERROR_VARIABLE status) +check("${KEY}" "${result}" "${status}" "result STREQUAL \"(default);BYTE_SIZE;VALUE2_SZ\"") + +cmake_host_system_information(RESULT result QUERY WINDOWS_REGISTRY "${KEY}" SUBKEYS + VIEW TARGET ERROR_VARIABLE status) +check("${KEY}" "${result}" "${status}" "result STREQUAL \"subkey1;subkey3\"") diff --git a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake index 87b6944..d857bee 100644 --- a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake +++ b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake @@ -21,3 +21,27 @@ if(RunCMake_GENERATOR MATCHES "^Visual Studio " AND NOT RunCMake_GENERATOR STREQ else() run_cmake(VsMSBuildMissing) endif() + +# WINDOWS_REGISTRY tests +run_cmake(Registry_NoArgs) +run_cmake(Registry_BadQuery1) +run_cmake(Registry_BadQuery2) +run_cmake(Registry_BadView1) +run_cmake(Registry_BadView2) +run_cmake(Registry_BadView3) +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + run_cmake(Registry_BadKey1) + run_cmake(Registry_BadKey2) + + # Tests using the Windows registry + find_program(REG NAMES "reg.exe" NO_CACHE) + if (REG) + # crete some entries in the registry + cmake_path(CONVERT "${RunCMake_SOURCE_DIR}/registry_data.reg" TO_NATIVE_PATH_LIST registry_data) + execute_process(COMMAND "${REG}" import "${registry_data}" OUTPUT_QUIET ERROR_QUIET) + run_cmake(Registry_Query) + # clean-up registry + execute_process(COMMAND "${REG}" delete "HKCU\\SOFTWARE\\Classes\\CLSID\\CMake-Tests" /f OUTPUT_QUIET ERROR_QUIET) + execute_process(COMMAND "${REG}" delete "HKCU\\SOFTWARE\\Classes\\WOW6432Node\\CLSID\\CMake-Tests" /f OUTPUT_QUIET ERROR_QUIET) + endif() +endif() diff --git a/Tests/RunCMake/cmake_host_system_information/registry_data.reg b/Tests/RunCMake/cmake_host_system_information/registry_data.reg Binary files differnew file mode 100644 index 0000000..8596648 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/registry_data.reg diff --git a/Tests/RunCMake/target_sources/FileSetImport.cmake b/Tests/RunCMake/target_sources/FileSetImport.cmake index 9c7358a..7e790c7 100644 --- a/Tests/RunCMake/target_sources/FileSetImport.cmake +++ b/Tests/RunCMake/target_sources/FileSetImport.cmake @@ -17,7 +17,7 @@ include("${export_build_dir}/export.cmake") include("${export_build_dir}/install/lib/cmake/export.cmake") assert_prop_eq(export::lib1 HEADER_SETS "") -assert_prop_eq(export::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;e;f;g;dir3") +assert_prop_eq(export::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;dir3;e;f;g") assert_prop_eq(export::lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/error.c") assert_prop_eq(export::lib1 HEADER_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") assert_prop_eq(export::lib1 HEADER_SET_b "${CMAKE_CURRENT_SOURCE_DIR}/h2.h") @@ -35,7 +35,7 @@ assert_prop_eq(export::lib1 HEADER_DIRS_g "${CMAKE_CURRENT_SOURCE_DIR}/dir1;${CM assert_prop_eq(export::lib1 INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR};$<1:${CMAKE_CURRENT_SOURCE_DIR}/dir>;${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/$<IF:$<CONFIG:Debug>,debug,release>;${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/dir1;${CMAKE_CURRENT_SOURCE_DIR}/dir2;${CMAKE_CURRENT_SOURCE_DIR}/dir3;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:$<1:${CMAKE_CURRENT_SOURCE_DIR}/dir>>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/$<IF:$<CONFIG:Debug>,debug,release>>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir1>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir2>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir3>") assert_prop_eq(install::lib1 HEADER_SETS "") -assert_prop_eq(install::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;e;f;g;dir3") +assert_prop_eq(install::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;dir3;e;f;g") assert_prop_eq(install::lib1 HEADER_SET "${export_build_dir}/install/include/error.c") assert_prop_eq(install::lib1 HEADER_DIRS "${export_build_dir}/install/include") assert_prop_eq(install::lib1 HEADER_SET_b "${export_build_dir}/install/include/h2.h") diff --git a/Tests/RunCMake/target_sources/FileSetNoExistInterface-stderr.txt b/Tests/RunCMake/target_sources/FileSetNoExistInterface-stderr.txt deleted file mode 100644 index 3972c89..0000000 --- a/Tests/RunCMake/target_sources/FileSetNoExistInterface-stderr.txt +++ /dev/null @@ -1,4 +0,0 @@ -^CMake Error at FileSetNoExistInterface\.cmake:[0-9]+ \(set_property\): - Header set "a" has not yet been created\. -Call Stack \(most recent call first\): - CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/target_sources/FileSetNoExistPrivate-stderr.txt b/Tests/RunCMake/target_sources/FileSetNoExistPrivate-stderr.txt deleted file mode 100644 index 336bafe..0000000 --- a/Tests/RunCMake/target_sources/FileSetNoExistPrivate-stderr.txt +++ /dev/null @@ -1,4 +0,0 @@ -^CMake Error at FileSetNoExistPrivate\.cmake:[0-9]+ \(set_property\): - Header set "a" has not yet been created\. -Call Stack \(most recent call first\): - CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/target_sources/FileSetNoExistPrivate.cmake b/Tests/RunCMake/target_sources/FileSetNoExistPrivate.cmake deleted file mode 100644 index f501912..0000000 --- a/Tests/RunCMake/target_sources/FileSetNoExistPrivate.cmake +++ /dev/null @@ -1,7 +0,0 @@ -enable_language(C) - -add_library(lib1 STATIC empty.c) -set_property(TARGET lib1 PROPERTY HEADER_SETS "a") - -# Error happens at configure-time, so this doesn't help. -target_sources(lib1 PRIVATE FILE_SET a TYPE HEADERS) diff --git a/Tests/RunCMake/target_sources/FileSetNoScope-stderr.txt b/Tests/RunCMake/target_sources/FileSetNoScope-stderr.txt deleted file mode 100644 index 835ffe7..0000000 --- a/Tests/RunCMake/target_sources/FileSetNoScope-stderr.txt +++ /dev/null @@ -1,4 +0,0 @@ -^CMake Error at FileSetNoScope\.cmake:[0-9]+ \(target_sources\): - target_sources File set "a" is not in HEADER_SETS or INTERFACE_HEADER_SETS -Call Stack \(most recent call first\): - CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/target_sources/FileSetNoScope.cmake b/Tests/RunCMake/target_sources/FileSetNoScope.cmake deleted file mode 100644 index 79ff341..0000000 --- a/Tests/RunCMake/target_sources/FileSetNoScope.cmake +++ /dev/null @@ -1,6 +0,0 @@ -enable_language(C) - -add_library(lib1 STATIC empty.c) -target_sources(lib1 PRIVATE FILE_SET a TYPE HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES h1.h) -set_property(TARGET lib1 PROPERTY HEADER_SETS) -target_sources(lib1 PRIVATE FILE_SET a TYPE HEADERS FILES h2.h) diff --git a/Tests/RunCMake/target_sources/FileSetProperties.cmake b/Tests/RunCMake/target_sources/FileSetProperties.cmake index a671ab3..74487fe 100644 --- a/Tests/RunCMake/target_sources/FileSetProperties.cmake +++ b/Tests/RunCMake/target_sources/FileSetProperties.cmake @@ -57,14 +57,14 @@ assert_prop_eq(lib1 INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURC assert_prop_eq(lib1 INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>") target_sources(lib1 PUBLIC FILE_SET HEADERS BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}" FILES h1.h) -assert_prop_eq(lib1 INTERFACE_HEADER_SETS "a;c;d;HEADERS") +assert_prop_eq(lib1 INTERFACE_HEADER_SETS "HEADERS;a;c;d") assert_prop_eq(lib1 HEADER_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") assert_prop_eq(lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/h1.h") assert_prop_eq(lib1 INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>") assert_prop_eq(lib1 INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>") target_sources(lib1 PUBLIC FILE_SET HEADERS FILES h2.h) -assert_prop_eq(lib1 INTERFACE_HEADER_SETS "a;c;d;HEADERS") +assert_prop_eq(lib1 INTERFACE_HEADER_SETS "HEADERS;a;c;d") assert_prop_eq(lib1 HEADER_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") assert_prop_eq(lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/h1.h;${CMAKE_CURRENT_SOURCE_DIR}/h2.h") assert_prop_eq(lib1 INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>") diff --git a/Tests/RunCMake/target_sources/FileSetReadOnlyInterface-result.txt b/Tests/RunCMake/target_sources/FileSetReadOnlyInterface-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/target_sources/FileSetReadOnlyInterface-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/target_sources/FileSetReadOnlyInterface-stderr.txt b/Tests/RunCMake/target_sources/FileSetReadOnlyInterface-stderr.txt new file mode 100644 index 0000000..2307d13 --- /dev/null +++ b/Tests/RunCMake/target_sources/FileSetReadOnlyInterface-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at FileSetReadOnlyInterface\.cmake:[0-9]+ \(set_property\): + INTERFACE_HEADER_SETS property is read-only + +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/target_sources/FileSetNoExistInterface.cmake b/Tests/RunCMake/target_sources/FileSetReadOnlyInterface.cmake index 266bc61..468ef91 100644 --- a/Tests/RunCMake/target_sources/FileSetNoExistInterface.cmake +++ b/Tests/RunCMake/target_sources/FileSetReadOnlyInterface.cmake @@ -2,6 +2,3 @@ enable_language(C) add_library(lib1 STATIC empty.c) set_property(TARGET lib1 PROPERTY INTERFACE_HEADER_SETS "a") - -# Error happens at configure-time, so this doesn't help. -target_sources(lib1 INTERFACE FILE_SET a TYPE HEADERS) diff --git a/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate-result.txt b/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate-stderr.txt b/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate-stderr.txt new file mode 100644 index 0000000..5f955da --- /dev/null +++ b/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at FileSetReadOnlyPrivate\.cmake:[0-9]+ \(set_property\): + HEADER_SETS property is read-only + +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate.cmake b/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate.cmake new file mode 100644 index 0000000..eda92c1 --- /dev/null +++ b/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate.cmake @@ -0,0 +1,4 @@ +enable_language(C) + +add_library(lib1 STATIC empty.c) +set_property(TARGET lib1 PROPERTY HEADER_SETS "a") diff --git a/Tests/RunCMake/target_sources/RunCMakeTest.cmake b/Tests/RunCMake/target_sources/RunCMakeTest.cmake index 743879e..8429c96 100644 --- a/Tests/RunCMake/target_sources/RunCMakeTest.cmake +++ b/Tests/RunCMake/target_sources/RunCMakeTest.cmake @@ -33,9 +33,8 @@ run_cmake(FileSetWrongBaseDirsRelative) run_cmake(FileSetOverlappingBaseDirs) run_cmake(FileSetInstallMissingSetsPrivate) run_cmake(FileSetInstallMissingSetsInterface) -run_cmake(FileSetNoScope) -run_cmake(FileSetNoExistPrivate) -run_cmake(FileSetNoExistInterface) +run_cmake(FileSetReadOnlyPrivate) +run_cmake(FileSetReadOnlyInterface) run_cmake(FileSetNoExistInstall) run_cmake(FileSetDirectories) run_cmake(FileSetCustomTarget) |