summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2021-08-24 14:04:03 (GMT)
committerKitware Robot <kwrobot@kitware.com>2021-08-24 14:04:15 (GMT)
commitcf90aa5595eac39029f7516e0bc5790fe398ea3d (patch)
tree1eeb86857a1a7adcf70618b21e773f90f062f846
parent91d5bf68ae2bee13bc29ce89732844047c687334 (diff)
parentb9698f89df275a33b01cfc7b4f88a510ad9d8bbe (diff)
downloadCMake-cf90aa5595eac39029f7516e0bc5790fe398ea3d.zip
CMake-cf90aa5595eac39029f7516e0bc5790fe398ea3d.tar.gz
CMake-cf90aa5595eac39029f7516e0bc5790fe398ea3d.tar.bz2
Merge topic 'host-distro-info'
b9698f89df cmake_host_system_information: Make it available for all systems 5469c71a82 Refactor: Simplify `GetValue()` function calls 6c92f80f2e cmake_host_system_information: Also set `USED_FALLBACK_SCRIPT` efe139d1b8 cmake_host_system_information: Can run fallback scripts 1e65e4a6e5 cmake_host_system_information: Can read `/etc/os-release` file e808cbb1dd Testing: Convert `cmake_host_system_information` tests into `RunCMake` 9e831284e5 Documentation: Use definition list instead of tables 346f3de005 Refactor: Deduplicate code for `VS_nn_DIR` keys processing ... Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: buildbot <buildbot@kitware.com> Merge-request: !6410
-rw-r--r--Help/command/cmake_host_system_information.rst268
-rw-r--r--Help/release/dev/os-release.rst6
-rw-r--r--Modules/Internal/OSRelease/010-TryOldCentOS.cmake41
-rw-r--r--Modules/Internal/OSRelease/020-TryDebianVersion.cmake38
-rw-r--r--Source/cmCMakeHostSystemInformationCommand.cxx606
-rw-r--r--Tests/CMakeTests/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake21
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt4
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg1.cmake (renamed from Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake)0
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt4
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg2.cmake (renamed from Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake)0
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt4
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg3.cmake (renamed from Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake)0
-rw-r--r--Tests/RunCMake/cmake_host_system_information/CMakeLists.txt7
-rw-r--r--Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt7
-rw-r--r--Tests/RunCMake/cmake_host_system_information/CentOS6.cmake5
-rw-r--r--Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt5
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Debian6.cmake5
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt9
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Exherbo.cmake11
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release7
-rw-r--r--Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt27
-rw-r--r--Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake (renamed from Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in)24
-rw-r--r--Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/QueryList.cmake (renamed from Tests/CMakeTests/CMakeHostSystemInformation-QueryList.cmake)2
-rw-r--r--Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake17
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt14
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake11
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release12
-rw-r--r--Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt7
-rw-r--r--Tests/RunCMake/cmake_host_system_information/UnitTest.cmake5
-rw-r--r--Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release9
-rw-r--r--Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt5
-rw-r--r--Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt7
-rw-r--r--Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake12
42 files changed, 991 insertions, 218 deletions
diff --git a/Help/command/cmake_host_system_information.rst b/Help/command/cmake_host_system_information.rst
index 2b902a9..998e146 100644
--- a/Help/command/cmake_host_system_information.rst
+++ b/Help/command/cmake_host_system_information.rst
@@ -13,46 +13,236 @@ queried. The list of queried values is stored in ``<variable>``.
``<key>`` can be one of the following values:
-============================= ================================================
-Key Description
-============================= ================================================
-``NUMBER_OF_LOGICAL_CORES`` Number of logical cores
-``NUMBER_OF_PHYSICAL_CORES`` Number of physical cores
-``HOSTNAME`` Hostname
-``FQDN`` Fully qualified domain name
-``TOTAL_VIRTUAL_MEMORY`` Total virtual memory in MiB [#mebibytes]_
-``AVAILABLE_VIRTUAL_MEMORY`` Available virtual memory in MiB [#mebibytes]_
-``TOTAL_PHYSICAL_MEMORY`` Total physical memory in MiB [#mebibytes]_
-``AVAILABLE_PHYSICAL_MEMORY`` Available physical memory in MiB [#mebibytes]_
-============================= ================================================
-
-.. versionadded:: 3.10
- Additional ``<key>`` values are available:
-
-============================= ================================================
-Key Description
-============================= ================================================
-``IS_64BIT`` One if processor is 64Bit
-``HAS_FPU`` One if processor has floating point unit
-``HAS_MMX`` One if processor supports MMX instructions
-``HAS_MMX_PLUS`` One if processor supports Ext. MMX instructions
-``HAS_SSE`` One if processor supports SSE instructions
-``HAS_SSE2`` One if processor supports SSE2 instructions
-``HAS_SSE_FP`` One if processor supports SSE FP instructions
-``HAS_SSE_MMX`` One if processor supports SSE MMX instructions
-``HAS_AMD_3DNOW`` One if processor supports 3DNow instructions
-``HAS_AMD_3DNOW_PLUS`` One if processor supports 3DNow+ instructions
-``HAS_IA64`` One if IA64 processor emulating x86
-``HAS_SERIAL_NUMBER`` One if processor has serial number
-``PROCESSOR_SERIAL_NUMBER`` Processor serial number
-``PROCESSOR_NAME`` Human readable processor name
-``PROCESSOR_DESCRIPTION`` Human readable full processor description
-``OS_NAME`` See :variable:`CMAKE_HOST_SYSTEM_NAME`
-``OS_RELEASE`` The OS sub-type e.g. on Windows ``Professional``
-``OS_VERSION`` The OS build ID
-``OS_PLATFORM`` See :variable:`CMAKE_HOST_SYSTEM_PROCESSOR`
-============================= ================================================
+``NUMBER_OF_LOGICAL_CORES``
+ Number of logical cores
+
+``NUMBER_OF_PHYSICAL_CORES``
+ Number of physical cores
+
+``HOSTNAME``
+ Hostname
+
+``FQDN``
+ Fully qualified domain name
+
+``TOTAL_VIRTUAL_MEMORY``
+ Total virtual memory in MiB [#mebibytes]_
+
+``AVAILABLE_VIRTUAL_MEMORY``
+ Available virtual memory in MiB [#mebibytes]_
+
+``TOTAL_PHYSICAL_MEMORY``
+ Total physical memory in MiB [#mebibytes]_
+
+``AVAILABLE_PHYSICAL_MEMORY``
+ Available physical memory in MiB [#mebibytes]_
+
+``IS_64BIT``
+ .. versionadded:: 3.10
+
+ One if processor is 64Bit
+
+``HAS_FPU``
+ .. versionadded:: 3.10
+
+ One if processor has floating point unit
+
+``HAS_MMX``
+ .. versionadded:: 3.10
+
+ One if processor supports MMX instructions
+
+``HAS_MMX_PLUS``
+ .. versionadded:: 3.10
+
+ One if processor supports Ext. MMX instructions
+
+``HAS_SSE``
+ .. versionadded:: 3.10
+
+ One if processor supports SSE instructions
+
+``HAS_SSE2``
+ .. versionadded:: 3.10
+
+ One if processor supports SSE2 instructions
+
+``HAS_SSE_FP``
+ .. versionadded:: 3.10
+
+ One if processor supports SSE FP instructions
+
+``HAS_SSE_MMX``
+ .. versionadded:: 3.10
+
+ One if processor supports SSE MMX instructions
+
+``HAS_AMD_3DNOW``
+ .. versionadded:: 3.10
+
+ One if processor supports 3DNow instructions
+
+``HAS_AMD_3DNOW_PLUS``
+ .. versionadded:: 3.10
+
+ One if processor supports 3DNow+ instructions
+
+``HAS_IA64``
+ .. versionadded:: 3.10
+
+ One if IA64 processor emulating x86
+
+``HAS_SERIAL_NUMBER``
+ .. versionadded:: 3.10
+
+ One if processor has serial number
+
+``PROCESSOR_SERIAL_NUMBER``
+ .. versionadded:: 3.10
+
+ Processor serial number
+
+``PROCESSOR_NAME``
+ .. versionadded:: 3.10
+
+ Human readable processor name
+
+``PROCESSOR_DESCRIPTION``
+ .. versionadded:: 3.10
+
+ Human readable full processor description
+
+``OS_NAME``
+ .. versionadded:: 3.10
+
+ See :variable:`CMAKE_HOST_SYSTEM_NAME`
+
+``OS_RELEASE``
+ .. versionadded:: 3.10
+
+ The OS sub-type e.g. on Windows ``Professional``
+
+``OS_VERSION``
+ .. versionadded:: 3.10
+
+ The OS build ID
+
+``OS_PLATFORM``
+ .. versionadded:: 3.10
+
+ See :variable:`CMAKE_HOST_SYSTEM_PROCESSOR`
+
+``DISTRIB_INFO``
+ .. versionadded:: 3.22
+
+ Read :file:`/etc/os-release` file and define the given ``<variable>``
+ into a list of read variables
+
+``DISTRIB_<name>``
+ .. versionadded:: 3.22
+
+ Get the ``<name>`` variable (see `man 5 os-release`_) if it exists in the
+ :file:`/etc/os-release` file
+
+ Example:
+
+ .. code-block:: cmake
+
+ cmake_host_system_information(RESULT PRETTY_NAME QUERY DISTRIB_PRETTY_NAME)
+ message(STATUS "${PRETTY_NAME}")
+
+ cmake_host_system_information(RESULT DISTRO QUERY DISTRIB_INFO)
+
+ foreach(VAR IN LISTS DISTRO)
+ message(STATUS "${VAR}=`${${VAR}}`")
+ endforeach()
+
+
+ Output::
+
+ -- Ubuntu 20.04.2 LTS
+ -- DISTRO_BUG_REPORT_URL=`https://bugs.launchpad.net/ubuntu/`
+ -- DISTRO_HOME_URL=`https://www.ubuntu.com/`
+ -- DISTRO_ID=`ubuntu`
+ -- DISTRO_ID_LIKE=`debian`
+ -- DISTRO_NAME=`Ubuntu`
+ -- DISTRO_PRETTY_NAME=`Ubuntu 20.04.2 LTS`
+ -- DISTRO_PRIVACY_POLICY_URL=`https://www.ubuntu.com/legal/terms-and-policies/privacy-policy`
+ -- DISTRO_SUPPORT_URL=`https://help.ubuntu.com/`
+ -- DISTRO_UBUNTU_CODENAME=`focal`
+ -- DISTRO_VERSION=`20.04.2 LTS (Focal Fossa)`
+ -- DISTRO_VERSION_CODENAME=`focal`
+ -- DISTRO_VERSION_ID=`20.04`
+
+If :file:`/etc/os-release` file is not found, the command tries to gather OS
+identification via fallback scripts. The fallback script can use `various
+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
+
+ In addition to the scripts shipped with CMake, a user may append full
+ paths to his script(s) to the this list. The script filename has the
+ following format: ``NNN-<name>.cmake``, where ``NNN`` is three digits
+ used to apply collected scripts in a specific order.
+
+.. variable:: CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_<varname>
+
+ Variables collected by the user provided fallback script
+ ought to be assigned to CMake variables using this naming
+ convention. Example, the ``ID`` variable from the manual becomes
+ ``CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID``.
+
+.. variable:: CMAKE_GET_OS_RELEASE_FALLBACK_RESULT
+
+ The fallback script ought to store names of all assigned
+ ``CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_<varname>`` variables in this list.
+
+Example:
+
+.. code-block:: cmake
+
+ # Try to detect some old distribution
+ # See also
+ # - http://linuxmafia.com/faq/Admin/release-files.html
+ #
+ if(NOT EXISTS "${CMAKE_SYSROOT}/etc/foobar-release")
+ return()
+ endif()
+ # Get the first string only
+ file(
+ STRINGS "${CMAKE_SYSROOT}/etc/foobar-release" CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT
+ LIMIT_COUNT 1
+ )
+ #
+ # Example:
+ #
+ # Foobar distribution release 1.2.3 (server)
+ #
+ if(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT MATCHES "Foobar distribution release ([0-9\.]+) .*")
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME Foobar)
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME "${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT}")
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID foobar)
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION ${CMAKE_MATCH_1})
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID ${CMAKE_MATCH_1})
+ list(
+ APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID
+ )
+ endif()
+ unset(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT)
+
.. rubric:: Footnotes
.. [#mebibytes] One MiB (mebibyte) is equal to 1024x1024 bytes.
+
+.. _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
diff --git a/Help/release/dev/os-release.rst b/Help/release/dev/os-release.rst
new file mode 100644
index 0000000..cce6aee
--- /dev/null
+++ b/Help/release/dev/os-release.rst
@@ -0,0 +1,6 @@
+os-release
+----------
+
+* The :command:`cmake_host_system_information` command query operating system
+ identification `variables <https://www.freedesktop.org/software/systemd/man/os-release.html>`_
+ from the :file:`/etc/os-release` file.
diff --git a/Modules/Internal/OSRelease/010-TryOldCentOS.cmake b/Modules/Internal/OSRelease/010-TryOldCentOS.cmake
new file mode 100644
index 0000000..ff35897
--- /dev/null
+++ b/Modules/Internal/OSRelease/010-TryOldCentOS.cmake
@@ -0,0 +1,41 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+# Author: Alex Turbov
+
+if(NOT EXISTS "${CMAKE_SYSROOT}/etc/centos-release")
+ return()
+endif()
+
+# Get the first string only
+file(
+ STRINGS "${CMAKE_SYSROOT}/etc/centos-release" CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT
+ LIMIT_COUNT 1
+ )
+
+#
+# Example:
+# CentOS release 6.10 (Final)
+#
+if(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT MATCHES "CentOS release ([0-9\.]+) .*")
+
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME CentOS)
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME "${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT}")
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID centos)
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE rhel)
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION ${CMAKE_MATCH_1})
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID ${CMAKE_MATCH_1})
+
+ list(
+ APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID
+ )
+
+endif()
+
+unset(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT)
diff --git a/Modules/Internal/OSRelease/020-TryDebianVersion.cmake b/Modules/Internal/OSRelease/020-TryDebianVersion.cmake
new file mode 100644
index 0000000..8ebe19a
--- /dev/null
+++ b/Modules/Internal/OSRelease/020-TryDebianVersion.cmake
@@ -0,0 +1,38 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+# Author: Alex Turbov
+
+if(NOT EXISTS "${CMAKE_SYSROOT}/etc/debian_version")
+ return()
+endif()
+
+# Get the first string only
+file(
+ STRINGS "${CMAKE_SYSROOT}/etc/debian_version" CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT
+ LIMIT_COUNT 1
+ )
+
+#
+# Example:
+# 6.0.10 # Old debian
+# wheezy/sid # Ubuntu
+#
+if(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT MATCHES "[0-9]+(\.[0-9]+)*")
+
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME Debian)
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID debian)
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION ${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT})
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID ${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT})
+
+ list(
+ APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID
+ )
+
+endif()
+
+unset(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT)
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index 0550568..74071ff 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -2,214 +2,510 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCMakeHostSystemInformationCommand.h"
-#include <cstddef>
+#include <algorithm>
+#include <cassert>
+#include <cctype>
+#include <initializer_list>
+#include <map>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <cm/optional>
+#include <cm/string_view>
+#include <cmext/string_view>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
#include "cmsys/SystemInformation.hxx"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
-#if defined(_WIN32)
+#ifdef _WIN32
# include "cmAlgorithms.h"
# include "cmGlobalGenerator.h"
# include "cmGlobalVisualStudioVersionedGenerator.h"
-# include "cmSystemTools.h"
# include "cmVSSetupHelper.h"
# define HAVE_VS_SETUP_HELPER
#endif
namespace {
-bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info,
- std::string const& key, std::string& value);
-std::string ValueToString(size_t value);
-std::string ValueToString(const char* value);
-std::string ValueToString(std::string const& value);
-}
+std::string const DELIM[2] = { {}, ";" };
-// cmCMakeHostSystemInformation
-bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args,
- cmExecutionStatus& status)
+// BEGIN Private functions
+std::string ValueToString(std::size_t const value)
{
- size_t current_index = 0;
-
- if (args.size() < (current_index + 2) || args[current_index] != "RESULT") {
- status.SetError("missing RESULT specification.");
- return false;
- }
-
- std::string const& variable = args[current_index + 1];
- current_index += 2;
-
- if (args.size() < (current_index + 2) || args[current_index] != "QUERY") {
- status.SetError("missing QUERY specification");
- return false;
- }
-
- cmsys::SystemInformation info;
- info.RunCPUCheck();
- info.RunOSCheck();
- info.RunMemoryCheck();
-
- std::string result_list;
- for (size_t i = current_index + 1; i < args.size(); ++i) {
- std::string const& key = args[i];
- if (i != current_index + 1) {
- result_list += ";";
- }
- std::string value;
- if (!GetValue(status, info, key, value)) {
- return false;
- }
- result_list += value;
- }
-
- status.GetMakefile().AddDefinition(variable, result_list);
+ return std::to_string(value);
+}
- return true;
+std::string ValueToString(const char* const value)
+{
+ return value ? value : std::string{};
}
-namespace {
+std::string ValueToString(std::string const& value)
+{
+ return value;
+}
-bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info,
- std::string const& key, std::string& value)
+cm::optional<std::string> GetValue(cmsys::SystemInformation& info,
+ std::string const& key)
{
- if (key == "NUMBER_OF_LOGICAL_CORES") {
- value = ValueToString(info.GetNumberOfLogicalCPU());
- } else if (key == "NUMBER_OF_PHYSICAL_CORES") {
- value = ValueToString(info.GetNumberOfPhysicalCPU());
- } else if (key == "HOSTNAME") {
- value = ValueToString(info.GetHostname());
- } else if (key == "FQDN") {
- value = ValueToString(info.GetFullyQualifiedDomainName());
- } else if (key == "TOTAL_VIRTUAL_MEMORY") {
- value = ValueToString(info.GetTotalVirtualMemory());
- } else if (key == "AVAILABLE_VIRTUAL_MEMORY") {
- value = ValueToString(info.GetAvailableVirtualMemory());
- } else if (key == "TOTAL_PHYSICAL_MEMORY") {
- value = ValueToString(info.GetTotalPhysicalMemory());
- } else if (key == "AVAILABLE_PHYSICAL_MEMORY") {
- value = ValueToString(info.GetAvailablePhysicalMemory());
- } else if (key == "IS_64BIT") {
- value = ValueToString(info.Is64Bits());
- } else if (key == "HAS_FPU") {
- value = ValueToString(
+ if (key == "NUMBER_OF_LOGICAL_CORES"_s) {
+ return ValueToString(info.GetNumberOfLogicalCPU());
+ }
+ if (key == "NUMBER_OF_PHYSICAL_CORES"_s) {
+ return ValueToString(info.GetNumberOfPhysicalCPU());
+ }
+ if (key == "HOSTNAME"_s) {
+ return ValueToString(info.GetHostname());
+ }
+ if (key == "FQDN"_s) {
+ return ValueToString(info.GetFullyQualifiedDomainName());
+ }
+ if (key == "TOTAL_VIRTUAL_MEMORY"_s) {
+ return ValueToString(info.GetTotalVirtualMemory());
+ }
+ if (key == "AVAILABLE_VIRTUAL_MEMORY"_s) {
+ return ValueToString(info.GetAvailableVirtualMemory());
+ }
+ if (key == "TOTAL_PHYSICAL_MEMORY"_s) {
+ return ValueToString(info.GetTotalPhysicalMemory());
+ }
+ if (key == "AVAILABLE_PHYSICAL_MEMORY"_s) {
+ return ValueToString(info.GetAvailablePhysicalMemory());
+ }
+ if (key == "IS_64BIT"_s) {
+ return ValueToString(info.Is64Bits());
+ }
+ if (key == "HAS_FPU"_s) {
+ return ValueToString(
info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_FPU));
- } else if (key == "HAS_MMX") {
- value = ValueToString(
+ }
+ if (key == "HAS_MMX"_s) {
+ return ValueToString(
info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_MMX));
- } else if (key == "HAS_MMX_PLUS") {
- value = ValueToString(info.DoesCPUSupportFeature(
+ }
+ if (key == "HAS_MMX_PLUS"_s) {
+ return ValueToString(info.DoesCPUSupportFeature(
cmsys::SystemInformation::CPU_FEATURE_MMX_PLUS));
- } else if (key == "HAS_SSE") {
- value = ValueToString(
+ }
+ if (key == "HAS_SSE"_s) {
+ return ValueToString(
info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE));
- } else if (key == "HAS_SSE2") {
- value = ValueToString(
+ }
+ if (key == "HAS_SSE2"_s) {
+ return ValueToString(
info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE2));
- } else if (key == "HAS_SSE_FP") {
- value = ValueToString(info.DoesCPUSupportFeature(
+ }
+ if (key == "HAS_SSE_FP"_s) {
+ return ValueToString(info.DoesCPUSupportFeature(
cmsys::SystemInformation::CPU_FEATURE_SSE_FP));
- } else if (key == "HAS_SSE_MMX") {
- value = ValueToString(info.DoesCPUSupportFeature(
+ }
+ if (key == "HAS_SSE_MMX"_s) {
+ return ValueToString(info.DoesCPUSupportFeature(
cmsys::SystemInformation::CPU_FEATURE_SSE_MMX));
- } else if (key == "HAS_AMD_3DNOW") {
- value = ValueToString(info.DoesCPUSupportFeature(
+ }
+ if (key == "HAS_AMD_3DNOW"_s) {
+ return ValueToString(info.DoesCPUSupportFeature(
cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW));
- } else if (key == "HAS_AMD_3DNOW_PLUS") {
- value = ValueToString(info.DoesCPUSupportFeature(
+ }
+ if (key == "HAS_AMD_3DNOW_PLUS"_s) {
+ return ValueToString(info.DoesCPUSupportFeature(
cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW_PLUS));
- } else if (key == "HAS_IA64") {
- value = ValueToString(
+ }
+ if (key == "HAS_IA64"_s) {
+ return ValueToString(
info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_IA64));
- } else if (key == "HAS_SERIAL_NUMBER") {
- value = ValueToString(info.DoesCPUSupportFeature(
+ }
+ if (key == "HAS_SERIAL_NUMBER"_s) {
+ return ValueToString(info.DoesCPUSupportFeature(
cmsys::SystemInformation::CPU_FEATURE_SERIALNUMBER));
- } else if (key == "PROCESSOR_NAME") {
- value = ValueToString(info.GetExtendedProcessorName());
- } else if (key == "PROCESSOR_DESCRIPTION") {
- value = info.GetCPUDescription();
- } else if (key == "PROCESSOR_SERIAL_NUMBER") {
- value = ValueToString(info.GetProcessorSerialNumber());
- } else if (key == "OS_NAME") {
- value = ValueToString(info.GetOSName());
- } else if (key == "OS_RELEASE") {
- value = ValueToString(info.GetOSRelease());
- } else if (key == "OS_VERSION") {
- value = ValueToString(info.GetOSVersion());
- } else if (key == "OS_PLATFORM") {
- value = ValueToString(info.GetOSPlatform());
-#ifdef HAVE_VS_SETUP_HELPER
- } else if (key == "VS_15_DIR") {
- // If generating for the VS 15 IDE, use the same instance.
- cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator();
- if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 15 ")) {
- cmGlobalVisualStudioVersionedGenerator* vs15gen =
- static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
- if (vs15gen->GetVSInstance(value)) {
- return true;
- }
+ }
+ if (key == "PROCESSOR_NAME"_s) {
+ return ValueToString(info.GetExtendedProcessorName());
+ }
+ if (key == "PROCESSOR_DESCRIPTION"_s) {
+ return info.GetCPUDescription();
+ }
+ if (key == "PROCESSOR_SERIAL_NUMBER"_s) {
+ return ValueToString(info.GetProcessorSerialNumber());
+ }
+ if (key == "OS_NAME"_s) {
+ return ValueToString(info.GetOSName());
+ }
+ if (key == "OS_RELEASE"_s) {
+ return ValueToString(info.GetOSRelease());
+ }
+ if (key == "OS_VERSION"_s) {
+ return ValueToString(info.GetOSVersion());
+ }
+ if (key == "OS_PLATFORM"_s) {
+ return ValueToString(info.GetOSPlatform());
+ }
+ return {};
+}
+
+cm::optional<std::pair<std::string, std::string>> ParseOSReleaseLine(
+ std::string const& line)
+{
+ std::string key;
+ std::string value;
+
+ char prev = 0;
+ enum ParserState
+ {
+ PARSE_KEY_1ST,
+ PARSE_KEY,
+ FOUND_EQ,
+ PARSE_SINGLE_QUOTE_VALUE,
+ PARSE_DBL_QUOTE_VALUE,
+ PARSE_VALUE,
+ IGNORE_REST
+ } state = PARSE_KEY_1ST;
+
+ for (auto ch : line) {
+ switch (state) {
+ case PARSE_KEY_1ST:
+ if (std::isalpha(ch) || ch == '_') {
+ key += ch;
+ state = PARSE_KEY;
+ } else if (!std::isspace(ch)) {
+ state = IGNORE_REST;
+ }
+ break;
+
+ case PARSE_KEY:
+ if (ch == '=') {
+ state = FOUND_EQ;
+ } else if (std::isalnum(ch) || ch == '_') {
+ key += ch;
+ } else {
+ state = IGNORE_REST;
+ }
+ break;
+
+ case FOUND_EQ:
+ switch (ch) {
+ case '\'':
+ state = PARSE_SINGLE_QUOTE_VALUE;
+ break;
+ case '"':
+ state = PARSE_DBL_QUOTE_VALUE;
+ break;
+ case '#':
+ case '\\':
+ state = IGNORE_REST;
+ break;
+ default:
+ value += ch;
+ state = PARSE_VALUE;
+ }
+ break;
+
+ case PARSE_SINGLE_QUOTE_VALUE:
+ if (ch == '\'') {
+ if (prev != '\\') {
+ state = IGNORE_REST;
+ } else {
+ assert(!value.empty());
+ value[value.size() - 1] = ch;
+ }
+ } else {
+ value += ch;
+ }
+ break;
+
+ case PARSE_DBL_QUOTE_VALUE:
+ if (ch == '"') {
+ if (prev != '\\') {
+ state = IGNORE_REST;
+ } else {
+ assert(!value.empty());
+ value[value.size() - 1] = ch;
+ }
+ } else {
+ value += ch;
+ }
+ break;
+
+ case PARSE_VALUE:
+ if (ch == '#' || std::isspace(ch)) {
+ state = IGNORE_REST;
+ } else {
+ value += ch;
+ }
+ break;
+
+ default:
+ // Unexpected os-release parser state!
+ state = IGNORE_REST;
+ break;
}
- // Otherwise, find a VS 15 instance ourselves.
- cmVSSetupAPIHelper vsSetupAPIHelper(15);
- if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
- cmSystemTools::ConvertToUnixSlashes(value);
+ if (state == IGNORE_REST) {
+ break;
}
- } else if (key == "VS_16_DIR") {
- // If generating for the VS 16 IDE, use the same instance.
- cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator();
- if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 16 ")) {
- cmGlobalVisualStudioVersionedGenerator* vs16gen =
- static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
- if (vs16gen->GetVSInstance(value)) {
- return true;
+ prev = ch;
+ }
+ if (!(key.empty() || value.empty())) {
+ return std::make_pair(key, value);
+ }
+ return {};
+}
+
+std::map<std::string, std::string> GetOSReleaseVariables(
+ cmExecutionStatus& status)
+{
+ auto& makefile = status.GetMakefile();
+ const auto& sysroot = makefile.GetSafeDefinition("CMAKE_SYSROOT");
+
+ std::map<std::string, std::string> data;
+ // Based on
+ // https://www.freedesktop.org/software/systemd/man/os-release.html
+ for (auto name : { "/etc/os-release"_s, "/usr/lib/os-release"_s }) {
+ const auto& filename = cmStrCat(sysroot, name);
+ if (cmSystemTools::FileExists(filename)) {
+ cmsys::ifstream fin(filename.c_str());
+ for (std::string line; !std::getline(fin, line).fail();) {
+ auto kv = ParseOSReleaseLine(line);
+ if (kv.has_value()) {
+ data.emplace(kv.value());
+ }
}
+ break;
}
+ }
+ // Got smth?
+ if (!data.empty()) {
+ return data;
+ }
+
+ // Ugh, it could be some pre-os-release distro.
+ // Lets try some fallback getters.
+ // See also:
+ // - http://linuxmafia.com/faq/Admin/release-files.html
+
+ // 1. CMake provided
+ cmsys::Glob gl;
+ std::vector<std::string> scripts;
+ auto const findExpr = cmStrCat(cmSystemTools::GetCMakeRoot(),
+ "/Modules/Internal/OSRelease/*.cmake");
+ if (gl.FindFiles(findExpr)) {
+ scripts = gl.GetFiles();
+ }
+
+ // 2. User provided (append to the CMake prvided)
+ makefile.GetDefExpandList("CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS", scripts);
+
+ // Filter out files that are not in format `NNN-name.cmake`
+ auto checkName = [](std::string const& filepath) -> bool {
+ auto const& filename = cmSystemTools::GetFilenameName(filepath);
+ // NOTE Minimum filename length expected:
+ // NNN-<at-least-one-char-name>.cmake --> 11
+ return (filename.size() < 11) || !std::isdigit(filename[0]) ||
+ !std::isdigit(filename[1]) || !std::isdigit(filename[2]) ||
+ filename[3] != '-';
+ };
+ scripts.erase(std::remove_if(scripts.begin(), scripts.end(), checkName),
+ scripts.end());
- // Otherwise, find a VS 16 instance ourselves.
- cmVSSetupAPIHelper vsSetupAPIHelper(16);
- if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
- cmSystemTools::ConvertToUnixSlashes(value);
+ // Make sure scripts are running in desired order
+ std::sort(scripts.begin(), scripts.end(),
+ [](std::string const& lhs, std::string const& rhs) -> bool {
+ long lhs_order;
+ cmStrToLong(cmSystemTools::GetFilenameName(lhs).substr(0u, 3u),
+ &lhs_order);
+ long rhs_order;
+ cmStrToLong(cmSystemTools::GetFilenameName(rhs).substr(0u, 3u),
+ &rhs_order);
+ return lhs_order < rhs_order;
+ });
+
+ // Name of the variable to put the results
+ auto const result_variable = "CMAKE_GET_OS_RELEASE_FALLBACK_RESULT"_s;
+
+ for (auto const& script : scripts) {
+ // Unset the result variable
+ makefile.RemoveDefinition(result_variable.data());
+
+ // include FATAL_ERROR and ERROR in the return status
+ if (!makefile.ReadListFile(script) ||
+ cmSystemTools::GetErrorOccuredFlag()) {
+ // Ok, no worries... go try the next script.
+ continue;
+ }
+
+ std::vector<std::string> variables;
+ if (!makefile.GetDefExpandList(result_variable.data(), variables)) {
+ // Heh, this script didn't found anything... go try the next one.
+ continue;
}
- } else if (key == "VS_17_DIR") {
- // If generating for the VS 17 IDE, use the same instance.
- cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator();
- if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 17 ")) {
- cmGlobalVisualStudioVersionedGenerator* vs17gen =
- static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
- if (vs17gen->GetVSInstance(value)) {
- return true;
+
+ for (auto const& variable : variables) {
+ auto value = makefile.GetSafeDefinition(variable);
+ makefile.RemoveDefinition(variable);
+
+ if (!cmHasPrefix(variable, cmStrCat(result_variable, '_'))) {
+ // Ignore unknown variable set by the script
+ continue;
}
+
+ auto key = variable.substr(result_variable.size() + 1,
+ variable.size() - result_variable.size() - 1);
+ data.emplace(std::move(key), std::move(value));
}
- // Otherwise, find a VS 17 instance ourselves.
- cmVSSetupAPIHelper vsSetupAPIHelper(17);
- if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
- cmSystemTools::ConvertToUnixSlashes(value);
+ // Try 'till some script can get anything
+ if (!data.empty()) {
+ data.emplace("USED_FALLBACK_SCRIPT", script);
+ break;
}
-#endif
- } else {
- std::string e = "does not recognize <key> " + key;
- status.SetError(e);
- return false;
}
- return true;
+ makefile.RemoveDefinition(result_variable.data());
+
+ return data;
}
-std::string ValueToString(size_t value)
+cm::optional<std::string> GetValue(cmExecutionStatus& status,
+ std::string const& key,
+ std::string const& variable)
{
- return std::to_string(value);
+ const auto prefix = "DISTRIB_"_s;
+ if (!cmHasPrefix(key, prefix)) {
+ return {};
+ }
+
+ static const std::map<std::string, std::string> s_os_release =
+ GetOSReleaseVariables(status);
+
+ auto& makefile = status.GetMakefile();
+
+ const std::string subkey =
+ key.substr(prefix.size(), key.size() - prefix.size());
+ if (subkey == "INFO"_s) {
+ std::string vars;
+ for (const auto& kv : s_os_release) {
+ auto cmake_var_name = cmStrCat(variable, '_', kv.first);
+ vars += DELIM[!vars.empty()] + cmake_var_name;
+ makefile.AddDefinition(cmake_var_name, kv.second);
+ }
+ return cm::optional<std::string>(std::move(vars));
+ }
+
+ // Query individual variable
+ const auto it = s_os_release.find(subkey);
+ if (it != s_os_release.cend()) {
+ return it->second;
+ }
+
+ // NOTE Empty string means requested variable not set
+ return std::string{};
+}
+
+#ifdef HAVE_VS_SETUP_HELPER
+cm::optional<std::string> GetValue(cmExecutionStatus& status,
+ std::string const& key)
+{
+ auto* const gg = status.GetMakefile().GetGlobalGenerator();
+ for (auto vs : { 15, 16, 17 }) {
+ if (key == cmStrCat("VS_"_s, vs, "_DIR"_s)) {
+ std::string value;
+ // If generating for the VS nn IDE, use the same instance.
+
+ if (cmHasPrefix(gg->GetName(), cmStrCat("Visual Studio "_s, vs, ' '))) {
+ cmGlobalVisualStudioVersionedGenerator* vsNNgen =
+ static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
+ if (vsNNgen->GetVSInstance(value)) {
+ return value;
+ }
+ }
+
+ // Otherwise, find a VS nn instance ourselves.
+ cmVSSetupAPIHelper vsSetupAPIHelper(vs);
+ if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
+ cmSystemTools::ConvertToUnixSlashes(value);
+ }
+ return value;
+ }
+ }
+
+ return {};
}
+#endif
-std::string ValueToString(const char* value)
+cm::optional<std::string> GetValueChained()
{
- std::string safe_string = value ? value : "";
- return safe_string;
+ return {};
}
-std::string ValueToString(std::string const& value)
+template <typename GetterFn, typename... Next>
+cm::optional<std::string> GetValueChained(GetterFn current, Next... chain)
{
- return value;
+ auto value = current();
+ if (value.has_value()) {
+ return value;
+ }
+ return GetValueChained(chain...);
}
+// END Private functions
+} // anonymous namespace
+
+// cmCMakeHostSystemInformation
+bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ std::size_t current_index = 0;
+
+ if (args.size() < (current_index + 2) || args[current_index] != "RESULT"_s) {
+ status.SetError("missing RESULT specification.");
+ return false;
+ }
+
+ auto const& variable = args[current_index + 1];
+ current_index += 2;
+
+ if (args.size() < (current_index + 2) || args[current_index] != "QUERY"_s) {
+ status.SetError("missing QUERY specification");
+ return false;
+ }
+
+ static cmsys::SystemInformation info;
+ static auto initialized = false;
+ if (!initialized) {
+ info.RunCPUCheck();
+ info.RunOSCheck();
+ info.RunMemoryCheck();
+ initialized = true;
+ }
+
+ std::string result_list;
+ for (auto i = current_index + 1; i < args.size(); ++i) {
+ result_list += DELIM[!result_list.empty()];
+
+ auto const& key = args[i];
+ // clang-format off
+ auto value =
+ GetValueChained(
+ [&]() { return GetValue(info, key); }
+ , [&]() { return GetValue(status, key, variable); }
+#ifdef HAVE_VS_SETUP_HELPER
+ , [&]() { return GetValue(status, key); }
+#endif
+ );
+ // clang-format on
+ if (!value) {
+ status.SetError("does not recognize <key> " + key);
+ return false;
+ }
+ result_list += value.value();
+ }
+
+ status.GetMakefile().AddDefinition(variable, result_list);
+
+ return true;
}
diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt
index 52959e6..9e0b891 100644
--- a/Tests/CMakeTests/CMakeLists.txt
+++ b/Tests/CMakeTests/CMakeLists.txt
@@ -31,7 +31,6 @@ AddCMakeTest(CompilerIdVendor "")
AddCMakeTest(ProcessorCount "-DKWSYS_TEST_EXE=$<TARGET_FILE:cmsysTestsCxx>")
AddCMakeTest(PushCheckState "")
AddCMakeTest(While "")
-AddCMakeTest(CMakeHostSystemInformation "")
AddCMakeTest(FileDownload "")
set_tests_properties(CMake.FileDownload PROPERTIES
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index ef797f7..eb2c2d9 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -349,6 +349,7 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE)
endif()
add_RunCMake_test(execute_process)
add_RunCMake_test(export)
+add_RunCMake_test(cmake_host_system_information)
add_RunCMake_test(cmake_language)
add_RunCMake_test(cmake_minimum_required)
add_RunCMake_test(cmake_parse_arguments)
diff --git a/Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake b/Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake
new file mode 100644
index 0000000..ad873eb
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake
@@ -0,0 +1 @@
+message(WARNING "The warning text to match just to make sure the script get executed")
diff --git a/Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake b/Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake
new file mode 100644
index 0000000..08d8da8
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake
@@ -0,0 +1,21 @@
+if(DEFINED CMAKE_GET_OS_RELEASE_FALLBACK_RESULT)
+ message(FATAL_ERROR "The `CMAKE_GET_OS_RELEASE_FALLBACK_RESULT` expected to be unset at this moment")
+endif()
+
+set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME UnitTest)
+set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME "Just a Unit Test")
+set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID unittest)
+set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE nothing)
+set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION 0.0.1)
+set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID 0.0.1)
+
+list(
+ APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME
+ IGNORED_VARIABLE_NAME_WHICH_IS_NOT_STARTED_WITH_EXPECTED_PREFIX
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID
+ )
diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt b/Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt b/Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt
new file mode 100644
index 0000000..ed995e6
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at BadArg1\.cmake:1 \(cmake_host_system_information\):
+ cmake_host_system_information missing RESULT specification.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:7 \(include\)
diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake b/Tests/RunCMake/cmake_host_system_information/BadArg1.cmake
index 1655eb4..1655eb4 100644
--- a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg1.cmake
diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt b/Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt b/Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt
new file mode 100644
index 0000000..b78c927
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at BadArg2\.cmake:1 \(cmake_host_system_information\):
+ cmake_host_system_information missing QUERY specification
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:7 \(include\)
diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake b/Tests/RunCMake/cmake_host_system_information/BadArg2.cmake
index 1f056d5..1f056d5 100644
--- a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg2.cmake
diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt b/Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt b/Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt
new file mode 100644
index 0000000..c3f1314
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at BadArg3\.cmake:1 \(cmake_host_system_information\):
+ cmake_host_system_information does not recognize <key> FOOBAR
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:7 \(include\)
diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake b/Tests/RunCMake/cmake_host_system_information/BadArg3.cmake
index 9c5a558..9c5a558 100644
--- a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg3.cmake
diff --git a/Tests/RunCMake/cmake_host_system_information/CMakeLists.txt b/Tests/RunCMake/cmake_host_system_information/CMakeLists.txt
new file mode 100644
index 0000000..0198f9b
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.21)
+
+project(${RunCMake_TEST} NONE)
+
+set(CMAKE_SYSROOT ${PROJECT_SOURCE_DIR}/${RunCMake_TEST})
+
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt b/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt
new file mode 100644
index 0000000..50dbb08
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt
@@ -0,0 +1,7 @@
+-- CENTOS6_ID=`centos`
+-- CENTOS6_ID_LIKE=`rhel`
+-- CENTOS6_NAME=`CentOS`
+-- CENTOS6_PRETTY_NAME=`CentOS release 6\.10 \(Final\)`
+-- CENTOS6_USED_FALLBACK_SCRIPT=`.*/Modules/Internal/OSRelease/010-TryOldCentOS.cmake`
+-- CENTOS6_VERSION=`6\.10`
+-- CENTOS6_VERSION_ID=`6\.10`
diff --git a/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake b/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake
new file mode 100644
index 0000000..3bc632b
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake
@@ -0,0 +1,5 @@
+cmake_host_system_information(RESULT CENTOS6 QUERY DISTRIB_INFO)
+
+foreach(VAR IN LISTS CENTOS6)
+ message(STATUS "${VAR}=`${${VAR}}`")
+endforeach()
diff --git a/Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release b/Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release
new file mode 100644
index 0000000..294ccc9
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release
@@ -0,0 +1 @@
+CentOS release 6.10 (Final)
diff --git a/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt b/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt
new file mode 100644
index 0000000..4193d6f
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt
@@ -0,0 +1,5 @@
+-- DEBIAN6_ID=`debian`
+-- DEBIAN6_NAME=`Debian`
+-- DEBIAN6_USED_FALLBACK_SCRIPT=`.*/Modules/Internal/OSRelease/020-TryDebianVersion.cmake`
+-- DEBIAN6_VERSION=`6\.0\.10`
+-- DEBIAN6_VERSION_ID=`6\.0\.10`
diff --git a/Tests/RunCMake/cmake_host_system_information/Debian6.cmake b/Tests/RunCMake/cmake_host_system_information/Debian6.cmake
new file mode 100644
index 0000000..cbf83a9
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Debian6.cmake
@@ -0,0 +1,5 @@
+cmake_host_system_information(RESULT DEBIAN6 QUERY DISTRIB_INFO)
+
+foreach(VAR IN LISTS DEBIAN6)
+ message(STATUS "${VAR}=`${${VAR}}`")
+endforeach()
diff --git a/Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version b/Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version
new file mode 100644
index 0000000..c7d48f0
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version
@@ -0,0 +1 @@
+6.0.10
diff --git a/Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt b/Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt
new file mode 100644
index 0000000..11ae71f
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt
@@ -0,0 +1,9 @@
+-- TEST1_ANSI_COLOR=`0;32`
+-- TEST1_BUG_REPORT_URL=`https://bugs.exherbo.org/`
+-- TEST1_HOME_URL=`https://www.exherbo.org/`
+-- TEST1_ID=`exherbo`
+-- TEST1_NAME=`Exherbo`
+-- TEST1_PRETTY_NAME=`Exherbo Linux`
+-- TEST1_SUPPORT_URL=`irc://irc.freenode.net/#exherbo`
+-- TEST2_ID=`exherbo`
+-- TEST2_VERSION=``
diff --git a/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake b/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake
new file mode 100644
index 0000000..7fc26d8
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake
@@ -0,0 +1,11 @@
+cmake_host_system_information(RESULT TEST1 QUERY DISTRIB_INFO)
+
+foreach(VAR IN LISTS TEST1)
+ message(STATUS "${VAR}=`${${VAR}}`")
+endforeach()
+
+# Query individual variables
+cmake_host_system_information(RESULT TEST2 QUERY DISTRIB_ID DISTRIB_VERSION)
+list(POP_FRONT TEST2 TEST2_ID TEST2_VERSION)
+message(STATUS "TEST2_ID=`${TEST2_ID}`")
+message(STATUS "TEST2_VERSION=`${TEST2_VERSION}`")
diff --git a/Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release b/Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release
new file mode 100644
index 0000000..944c9b4
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release
@@ -0,0 +1,7 @@
+NAME="Exherbo"
+PRETTY_NAME="Exherbo Linux"
+ID="exherbo"
+ANSI_COLOR="0;32"
+HOME_URL="https://www.exherbo.org/"
+SUPPORT_URL="irc://irc.freenode.net/#exherbo"
+BUG_REPORT_URL="https://bugs.exherbo.org/"
diff --git a/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt b/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt
new file mode 100644
index 0000000..f583deb
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt
@@ -0,0 +1,27 @@
+-- NUMBER_OF_LOGICAL_CORES=`[0-9]+`
+-- NUMBER_OF_PHYSICAL_CORES=`[0-9]+`
+-- HOSTNAME=`.*`
+-- FQDN=`.*`
+-- TOTAL_VIRTUAL_MEMORY=`[0-9]+`
+-- AVAILABLE_VIRTUAL_MEMORY=`[0-9]+`
+-- TOTAL_PHYSICAL_MEMORY=`[0-9]+`
+-- AVAILABLE_PHYSICAL_MEMORY=`[0-9]+`
+-- IS_64BIT=`[01]`
+-- HAS_FPU=`[01]`
+-- HAS_MMX=`[01]`
+-- HAS_MMX_PLUS=`[01]`
+-- HAS_SSE=`[01]`
+-- HAS_SSE2=`[01]`
+-- HAS_SSE_FP=`[01]`
+-- HAS_SSE_MMX=`[01]`
+-- HAS_AMD_3DNOW=`[01]`
+-- HAS_AMD_3DNOW_PLUS=`[01]`
+-- HAS_IA64=`[01]`
+-- HAS_SERIAL_NUMBER=`[01]`
+-- PROCESSOR_SERIAL_NUMBER=`.*`
+-- PROCESSOR_NAME=`.*`
+-- PROCESSOR_DESCRIPTION=`.*`
+-- OS_NAME=`.*`
+-- OS_RELEASE=`.*`
+-- OS_VERSION=`.*`
+-- OS_PLATFORM=`.*`
diff --git a/Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in b/Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake
index a3c2b05..f22a0ae 100644
--- a/Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in
+++ b/Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake
@@ -1,19 +1,8 @@
-set(BadArg1-RESULT 1)
-set(BadArg1-STDERR "missing RESULT specification")
-set(BadArg2-RESULT 1)
-set(BadArg2-STDERR "missing QUERY specification")
-set(BadArg3-RESULT 1)
-set(BadArg3-STDERR "does not recognize <key> FOOBAR")
-set(QueryList-RESULT 0)
-set(QueryList-STDERR "\\[[0-9]+;[0-9]+\\]")
-
function(try_and_print key)
- cmake_host_system_information(RESULT RESULT QUERY ${key})
- message(STATUS "[${key}] [${RESULT}]")
+ cmake_host_system_information(RESULT RESULT QUERY ${key})
+ message(STATUS "${key}=`${RESULT}`")
endfunction()
-message("CTEST_FULL_OUTPUT (Avoid ctest truncation of output)")
-
try_and_print(NUMBER_OF_LOGICAL_CORES)
try_and_print(NUMBER_OF_PHYSICAL_CORES)
try_and_print(HOSTNAME)
@@ -41,12 +30,3 @@ try_and_print(OS_NAME)
try_and_print(OS_RELEASE)
try_and_print(OS_VERSION)
try_and_print(OS_PLATFORM)
-
-include("@CMAKE_CURRENT_SOURCE_DIR@/CheckCMakeTest.cmake")
-
-check_cmake_test(CMakeHostSystemInformation
- BadArg1
- BadArg2
- BadArg3
- QueryList
-)
diff --git a/Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt b/Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt
new file mode 100644
index 0000000..eebe0d4
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt
@@ -0,0 +1 @@
+-- \[[0-9]+;[0-9]+\]
diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-QueryList.cmake b/Tests/RunCMake/cmake_host_system_information/QueryList.cmake
index 1c3156d..f24aa2b 100644
--- a/Tests/CMakeTests/CMakeHostSystemInformation-QueryList.cmake
+++ b/Tests/RunCMake/cmake_host_system_information/QueryList.cmake
@@ -2,4 +2,4 @@ cmake_host_system_information(RESULT RESULT
QUERY NUMBER_OF_LOGICAL_CORES NUMBER_OF_PHYSICAL_CORES
)
-message("[${RESULT}]")
+message(STATUS "[${RESULT}]")
diff --git a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake
new file mode 100644
index 0000000..189013f
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake
@@ -0,0 +1,17 @@
+include(RunCMake)
+
+run_cmake(BadArg1)
+run_cmake(BadArg2)
+run_cmake(BadArg3)
+
+run_cmake(QueryList)
+run_cmake(QueryKeys)
+
+run_cmake(UnitTest)
+run_cmake(Exherbo)
+run_cmake(Ubuntu)
+
+run_cmake(CentOS6)
+run_cmake(Debian6)
+
+run_cmake(UserFallbackScript)
diff --git a/Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt b/Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt
new file mode 100644
index 0000000..d1a18da
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt
@@ -0,0 +1,14 @@
+-- TEST1_BUG_REPORT_URL=`https://bugs\.launchpad\.net/ubuntu/`
+-- TEST1_HOME_URL=`https://www\.ubuntu\.com/`
+-- TEST1_ID=`ubuntu`
+-- TEST1_ID_LIKE=`debian`
+-- TEST1_NAME=`Ubuntu`
+-- TEST1_PRETTY_NAME=`Ubuntu 20\.04\.2 LTS`
+-- TEST1_PRIVACY_POLICY_URL=`https://www\.ubuntu\.com/legal/terms-and-policies/privacy-policy`
+-- TEST1_SUPPORT_URL=`https://help\.ubuntu\.com/`
+-- TEST1_UBUNTU_CODENAME=`focal`
+-- TEST1_VERSION=`20\.04\.2 LTS \(Focal Fossa\)`
+-- TEST1_VERSION_CODENAME=`focal`
+-- TEST1_VERSION_ID=`20\.04`
+-- TEST2_ID=`ubuntu`
+-- TEST2_VERSION=`20\.04\.2 LTS \(Focal Fossa\)`
diff --git a/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake b/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake
new file mode 100644
index 0000000..7fc26d8
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake
@@ -0,0 +1,11 @@
+cmake_host_system_information(RESULT TEST1 QUERY DISTRIB_INFO)
+
+foreach(VAR IN LISTS TEST1)
+ message(STATUS "${VAR}=`${${VAR}}`")
+endforeach()
+
+# Query individual variables
+cmake_host_system_information(RESULT TEST2 QUERY DISTRIB_ID DISTRIB_VERSION)
+list(POP_FRONT TEST2 TEST2_ID TEST2_VERSION)
+message(STATUS "TEST2_ID=`${TEST2_ID}`")
+message(STATUS "TEST2_VERSION=`${TEST2_VERSION}`")
diff --git a/Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release b/Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release
new file mode 100644
index 0000000..f228f22
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release
@@ -0,0 +1,12 @@
+NAME="Ubuntu"
+VERSION="20.04.2 LTS (Focal Fossa)"
+ID=ubuntu
+ID_LIKE=debian
+PRETTY_NAME="Ubuntu 20.04.2 LTS"
+VERSION_ID="20.04"
+HOME_URL="https://www.ubuntu.com/"
+SUPPORT_URL="https://help.ubuntu.com/"
+BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
+PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
+VERSION_CODENAME=focal
+UBUNTU_CODENAME=focal
diff --git a/Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt b/Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt
new file mode 100644
index 0000000..db6f487
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt
@@ -0,0 +1,7 @@
+-- UNIT_TEST_A_LIST_LIKE_VARIABLE=`satu;dua;tiga`
+-- UNIT_TEST_DBL_QUOTED_VALUE=`"The" value in double "quotes"`
+-- UNIT_TEST_DBL_QUOTED_VALUE_STIPPED_COMMENT=`Blah blah blah`
+-- UNIT_TEST_NON_SPACE_VALUE=`Blah-blah-blah`
+-- UNIT_TEST_QUOTED_VALUE=`'The' value in single 'quotes'`
+-- UNIT_TEST_QUOTED_VALUE_STIPPED_COMMENT=`The value in single quotes`
+-- UNIT_TEST_THE_URL_WITH_ANCHOR_TEST=`https://blah.blah/resource#anchor`
diff --git a/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake b/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake
new file mode 100644
index 0000000..d9a0aca
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake
@@ -0,0 +1,5 @@
+cmake_host_system_information(RESULT UNIT_TEST QUERY DISTRIB_INFO)
+
+foreach(VAR IN LISTS UNIT_TEST)
+ message(STATUS "${VAR}=`${${VAR}}`")
+endforeach()
diff --git a/Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release b/Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release
new file mode 100644
index 0000000..66c33b5
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release
@@ -0,0 +1,9 @@
+# Comment string gonna be ignored
+NON_SPACE_VALUE=Blah-blah-blah
+QUOTED_VALUE='\'The\' value in single \'quotes\''
+QUOTED_VALUE_STIPPED_COMMENT='The value in single quotes'# The comment right after `'`
+DBL_QUOTED_VALUE="\"The\" value in double \"quotes\""
+DBL_QUOTED_VALUE_STIPPED_COMMENT="Blah blah blah"# The comment right after `'`
+THE_URL_WITH_ANCHOR_TEST="https://blah.blah/resource#anchor" # And a comment after
+A_LIST_LIKE_VARIABLE='satu;dua;tiga'
+INCORRECT_ESCAPE_IGNORED=\'This line gonna be ignored'
diff --git a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt
new file mode 100644
index 0000000..78acea2
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt
@@ -0,0 +1,5 @@
+CMake Warning at 000-FirstFallbackScript\.cmake:[0-9]+ \(message\):
+ The warning text to match just to make sure the script get executed
+Call Stack \(most recent call first\):
+ UserFallbackScript\.cmake:[0-9]+ \(cmake_host_system_information\)
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt
new file mode 100644
index 0000000..acaf47e
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt
@@ -0,0 +1,7 @@
+-- UFS_ID=`unittest`
+-- UFS_ID_LIKE=`nothing`
+-- UFS_NAME=`UnitTest`
+-- UFS_PRETTY_NAME=`Just a Unit Test`
+-- UFS_USED_FALLBACK_SCRIPT=`.*/999-LastFallbackScript\.cmake`
+-- UFS_VERSION=`0\.0\.1`
+-- UFS_VERSION_ID=`0\.0\.1`
diff --git a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake
new file mode 100644
index 0000000..660aa1c
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake
@@ -0,0 +1,12 @@
+list(
+ APPEND CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS
+ ${CMAKE_CURRENT_SOURCE_DIR}/000-FirstFallbackScript.cmake
+ ${CMAKE_CURRENT_SOURCE_DIR}/Ignored-Script.cmake
+ ${CMAKE_CURRENT_SOURCE_DIR}/999-LastFallbackScript.cmake
+ )
+
+cmake_host_system_information(RESULT UFS QUERY DISTRIB_INFO)
+
+foreach(VAR IN LISTS UFS)
+ message(STATUS "${VAR}=`${${VAR}}`")
+endforeach()