From 52c8b8104bdc2c2751ae910e54530adfe7d43f95 Mon Sep 17 00:00:00 2001 From: Daksh Mamodiya Date: Sat, 29 Aug 2026 16:16:19 +0200 Subject: [PATCH] cmake_host_system_information: select host vs sysroot for DISTRIB_* `DISTRIB_*` read os-release under `CMAKE_SYSROOT`, so cross builds got the target distro from a host-oriented command, and a process-wide static froze the first result. Add a `FROM_SYSROOT ` option and policy `CMP0221` to default to the host, parse per call, and scope `CMAKE_SYSROOT` so the fallback scripts follow the same choice. Fixes: #27640 --- .../command/cmake_host_system_information.rst | 26 ++- Help/manual/cmake-policies.7.rst | 1 + Help/policy/CMP0221.rst | 44 ++++++ ...e_host_system_information-distrib-host.rst | 7 + .../cmCMakeHostSystemInformationCommand.cxx | 149 ++++++++++++++++-- Source/cmPolicies.h | 4 + .../CentOS6.cmake | 2 +- .../Debian6.cmake | 2 +- .../DistribFallbackSelector.cmake | 28 ++++ .../DistribHost.cmake | 15 ++ .../DistribPolicyNew.cmake | 14 ++ .../DistribPolicyNonDistrib.cmake | 5 + .../DistribPolicyOld.cmake | 9 ++ .../DistribPolicyWarn-stderr.txt | 8 + .../DistribPolicyWarn.cmake | 8 + .../DistribRegistrySelector-result.txt | 1 + .../DistribRegistrySelector-stderr.txt | 3 + .../DistribRegistrySelector.cmake | 4 + .../DistribSysrootBadValue-result.txt | 1 + .../DistribSysrootBadValue-stderr.txt | 4 + .../DistribSysrootBadValue.cmake | 3 + .../DistribSysrootDuplicate-result.txt | 1 + .../DistribSysrootDuplicate-stderr.txt | 3 + .../DistribSysrootDuplicate.cmake | 2 + .../DistribSysrootPosition.cmake | 17 ++ .../DistribTarget.cmake | 10 ++ .../Exherbo.cmake | 4 +- .../RunCMakeTest.cmake | 13 ++ .../Sentinel/etc/os-release | 4 + .../Ubuntu.cmake | 4 +- .../UnitTest.cmake | 2 +- .../UserFallbackScript.cmake | 2 +- 32 files changed, 375 insertions(+), 25 deletions(-) create mode 100644 Help/policy/CMP0221.rst create mode 100644 Help/release/dev/cmake_host_system_information-distrib-host.rst create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribFallbackSelector.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribHost.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribPolicyNew.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribPolicyNonDistrib.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribPolicyOld.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribPolicyWarn-stderr.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribPolicyWarn.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribRegistrySelector-result.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribRegistrySelector-stderr.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribRegistrySelector.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribSysrootBadValue-result.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribSysrootBadValue-stderr.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribSysrootBadValue.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribSysrootDuplicate-result.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribSysrootDuplicate-stderr.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribSysrootDuplicate.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribSysrootPosition.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/DistribTarget.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/Sentinel/etc/os-release diff --git a/Help/command/cmake_host_system_information.rst b/Help/command/cmake_host_system_information.rst index 35360c28fe..a020211f56 100644 --- a/Help/command/cmake_host_system_information.rst +++ b/Help/command/cmake_host_system_information.rst @@ -9,7 +9,7 @@ Synopsis .. parsed-literal:: `Query host system specific information`_ - cmake_host_system_information(RESULT `QUERY`_ ...) + cmake_host_system_information(RESULT `QUERY`_ [FROM_SYSROOT ] ...) `Query the Windows registry`_ cmake_host_system_information(RESULT `QUERY WINDOWS_REGISTRY`_ ...) @@ -18,7 +18,7 @@ Query host system specific information ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. signature:: - cmake_host_system_information(RESULT QUERY ...) + cmake_host_system_information(RESULT QUERY [FROM_SYSROOT ] ...) :target: QUERY @@ -26,6 +26,19 @@ Queries system information of the host system on which cmake runs. One or more ```` can be provided to select the information to be queried. The list of queried values is stored in ````. +.. versionadded:: 4.5 + + The ``FROM_SYSROOT `` option controls whether ``DISTRIB_*`` keys read + the os-release under :variable:`CMAKE_SYSROOT` or the host os-release: + + * A true value reads the os-release under :variable:`CMAKE_SYSROOT`, i.e. the + target distribution. This is useful, for example, to label packages for + the target system. + * A false value reads the host os-release, ignoring :variable:`CMAKE_SYSROOT`. + This is the default. See policy :policy:`CMP0221`. + + It affects only ``DISTRIB_*`` keys. + ```` can be one of the following values: ``NUMBER_OF_LOGICAL_CORES`` @@ -270,6 +283,15 @@ 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. +.. versionadded:: 4.5 + + The ``DISTRIB_*`` keys, including the fallback scripts, read the os-release + under the selected root (see ``FROM_SYSROOT`` above and policy + :policy:`CMP0221`): the host root, or the :variable:`CMAKE_SYSROOT` (target) + root. For ``DISTRIB_INFO``, only the names in the returned list are + authoritative; reusing ```` across queries may leave stale + ``_`` definitions from a previous root. + Fallback Interface Variables """""""""""""""""""""""""""" diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 505ecd1a00..05f1678c94 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -100,6 +100,7 @@ Policies Introduced by CMake 4.5 .. toctree:: :maxdepth: 1 + CMP0221: cmake_host_system_information() DISTRIB_* queries read the host os-release. CMP0220: Languages enabled in subdirectories propagate to the top-level directory. Policies Introduced by CMake 4.4 diff --git a/Help/policy/CMP0221.rst b/Help/policy/CMP0221.rst new file mode 100644 index 0000000000..871eab4922 --- /dev/null +++ b/Help/policy/CMP0221.rst @@ -0,0 +1,44 @@ +CMP0221 +------- + +.. versionadded:: 4.5 + +:command:`cmake_host_system_information` ``DISTRIB_*`` queries read the host +os-release. + +The :command:`cmake_host_system_information` command is documented to query +information about the host system on which CMake runs. However, its +``DISTRIB_*`` queries read the :file:`/etc/os-release` (or +:file:`/usr/lib/os-release`) file under the :variable:`CMAKE_SYSROOT`, if set. +During cross compilation this reports the *target* distribution rather than +the host, contradicting the rest of the command. + +The ``OLD`` behavior of this policy is for ``DISTRIB_*`` queries with no +``FROM_SYSROOT`` to read the os-release under :variable:`CMAKE_SYSROOT`. +The ``NEW`` behavior is for such queries to read the host os-release, +ignoring :variable:`CMAKE_SYSROOT`. + +Either behavior may be requested explicitly, regardless of this policy, with +the ``FROM_SYSROOT `` option: + +* A false value reads the host os-release. +* A true value reads the os-release under :variable:`CMAKE_SYSROOT`, which is + useful for querying the target distribution (e.g. for packaging). + +.. code-block:: cmake + + # Always the host distribution: + cmake_host_system_information(RESULT host QUERY FROM_SYSROOT OFF DISTRIB_ID) + + # Always the target (CMAKE_SYSROOT) distribution: + cmake_host_system_information(RESULT target QUERY FROM_SYSROOT ON DISTRIB_ID) + +The warning is issued only when it can matter: a ``DISTRIB_*`` query with no +``FROM_SYSROOT`` while :variable:`CMAKE_SYSROOT` is non-empty. Passing +``FROM_SYSROOT``, or leaving :variable:`CMAKE_SYSROOT` empty, is silent. + +.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.5 +.. |WARNS_OR_DOES_NOT_WARN| replace:: warns +.. include:: include/STANDARD_ADVICE.rst + +.. include:: include/DEPRECATED.rst diff --git a/Help/release/dev/cmake_host_system_information-distrib-host.rst b/Help/release/dev/cmake_host_system_information-distrib-host.rst new file mode 100644 index 0000000000..c407b081a2 --- /dev/null +++ b/Help/release/dev/cmake_host_system_information-distrib-host.rst @@ -0,0 +1,7 @@ +cmake_host_system_information-distrib-host +------------------------------------------ + +* The :command:`cmake_host_system_information` command's ``DISTRIB_*`` queries + now read the host os-release by default. See policy :policy:`CMP0221`. + A new ``FROM_SYSROOT `` option explicitly enables or disables reading + the target os-release from :variable:`CMAKE_SYSROOT`. diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 55e93ee0cc..4e67ba7c99 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,7 @@ #include "cmExecutionStatus.h" #include "cmList.h" #include "cmMakefile.h" +#include "cmPolicies.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -325,17 +327,49 @@ cm::optional> ParseOSReleaseLine( return {}; } +// Fallback os-release scripts read ${CMAKE_SYSROOT} directly, so point it at +// the effective root while they run; restored on destruction even if one +// fails. +class SysrootOverride +{ +public: + SysrootOverride(cmMakefile& makefile, std::string const& root) + : Makefile(makefile) + { + cmValue value = this->Makefile.GetDefinition("CMAKE_SYSROOT"); + this->Existed = static_cast(value); + if (this->Existed) { + this->Saved = *value; + } + this->Makefile.AddDefinition("CMAKE_SYSROOT", root); + } + ~SysrootOverride() + { + if (this->Existed) { + this->Makefile.AddDefinition("CMAKE_SYSROOT", this->Saved); + } else { + this->Makefile.RemoveDefinition("CMAKE_SYSROOT"); + } + } + SysrootOverride(SysrootOverride const&) = delete; + SysrootOverride& operator=(SysrootOverride const&) = delete; + +private: + cmMakefile& Makefile; + std::string Saved; + bool Existed; +}; + std::map GetOSReleaseVariables( - cmExecutionStatus& status) + cmExecutionStatus& status, std::string const& root) { auto& makefile = status.GetMakefile(); - auto const& sysroot = makefile.GetSafeDefinition("CMAKE_SYSROOT"); std::map data; // Based on // https://www.freedesktop.org/software/systemd/man/latest/os-release.html for (auto name : { "/etc/os-release"_s, "/usr/lib/os-release"_s }) { - auto const& filename = cmStrCat(sysroot, name); + auto const& filename = cmStrCat(root, name); if (cmSystemTools::FileExists(filename)) { cmsys::ifstream fin(filename.c_str()); for (std::string line; !std::getline(fin, line).fail();) { @@ -397,6 +431,8 @@ std::map GetOSReleaseVariables( // Name of the variable to put the results std::string const result_variable{ "CMAKE_GET_OS_RELEASE_FALLBACK_RESULT" }; + SysrootOverride const sysrootOverride(makefile, root); + for (auto const& script : scripts) { // Unset the result variable makefile.RemoveDefinition(result_variable); @@ -440,17 +476,21 @@ std::map GetOSReleaseVariables( return data; } -cm::optional GetDistribValue(cmExecutionStatus& status, - std::string const& key, - std::string const& variable) +cm::optional GetDistribValue( + cmExecutionStatus& status, std::string const& key, + std::string const& variable, std::string const& root, + cm::optional>& os_release) { auto const prefix = "DISTRIB_"_s; if (!cmHasPrefix(key, prefix)) { return {}; } - static std::map const s_os_release = - GetOSReleaseVariables(status); + // Parse once per call, not in a static: a static would freeze the first + // call's result and ignore a later change of root. + if (!os_release.has_value()) { + os_release = GetOSReleaseVariables(status, root); + } auto& makefile = status.GetMakefile(); @@ -458,7 +498,7 @@ cm::optional GetDistribValue(cmExecutionStatus& status, key.substr(prefix.size(), key.size() - prefix.size()); if (subkey == "INFO"_s) { std::string vars; - for (auto const& kv : s_os_release) { + for (auto const& kv : *os_release) { auto cmake_var_name = cmStrCat(variable, '_', kv.first); vars += DELIM[!vars.empty()] + cmake_var_name; makefile.AddDefinition(cmake_var_name, kv.second); @@ -467,8 +507,8 @@ cm::optional GetDistribValue(cmExecutionStatus& status, } // Query individual variable - auto const it = s_os_release.find(subkey); - if (it != s_os_release.cend()) { + auto const it = os_release->find(subkey); + if (it != os_release->cend()) { return it->second; } @@ -739,6 +779,82 @@ bool cmCMakeHostSystemInformationCommand(std::vector const& args, status, variable); } + // FROM_SYSROOT selects the CMAKE_SYSROOT (target) or host root for + // DISTRIB_* keys. Handled after the registry signature above, since a + // registry argument could itself be "FROM_SYSROOT". + enum class SysrootMode + { + Default, + Host, + Target, + }; + auto mode = SysrootMode::Default; + std::vector keys; + for (size_t i = current_index + 1; i < args.size(); ++i) { + if (args[i] != "FROM_SYSROOT"_s) { + keys.push_back(args[i]); + continue; + } + if (mode != SysrootMode::Default) { + status.SetError("FROM_SYSROOT may be given at most once."); + return false; + } + if (i + 1 >= args.size()) { + status.SetError("FROM_SYSROOT requires a boolean value."); + return false; + } + std::string const& value = args[++i]; + if (cmIsOn(value)) { + mode = SysrootMode::Target; + } else if (cmIsOff(value)) { + mode = SysrootMode::Host; + } else { + status.SetError(cmStrCat("FROM_SYSROOT requires a boolean value, got \"", + value, "\".")); + return false; + } + } + + cmMakefile& makefile = status.GetMakefile(); + + bool anyDistrib = false; + for (std::string const& key : keys) { + if (cmHasPrefix(key, "DISTRIB_"_s)) { + anyDistrib = true; + break; + } + } + + std::string const& sysroot = makefile.GetSafeDefinition("CMAKE_SYSROOT"); + + bool selectHost = false; + switch (mode) { + case SysrootMode::Host: + selectHost = true; + break; + case SysrootMode::Target: + selectHost = false; + break; + case SysrootMode::Default: + switch (makefile.GetPolicyStatus(cmPolicies::CMP0221)) { + case cmPolicies::NEW: + selectHost = true; + break; + case cmPolicies::WARN: + // Warn only where OLD and NEW diverge: a DISTRIB_* query with a + // real sysroot. Empty sysroot or non-DISTRIB keys stay silent. + if (anyDistrib && !sysroot.empty()) { + makefile.IssuePolicyWarning(cmPolicies::CMP0221); + } + CM_FALLTHROUGH; + case cmPolicies::OLD: + selectHost = false; + break; + } + break; + } + std::string const effectiveRoot = selectHost ? std::string{} : sysroot; + static cmsys::SystemInformation info; static auto initialized = false; if (!initialized) { @@ -748,16 +864,19 @@ bool cmCMakeHostSystemInformationCommand(std::vector const& args, initialized = true; } + cm::optional> os_release; std::string result_list; - for (auto i = current_index + 1; i < args.size(); ++i) { + for (std::string const& key : keys) { result_list += DELIM[!result_list.empty()]; - auto const& key = args[i]; // clang-format off auto value = GetValueChained( [&]() { return GetValue(info, key); } - , [&]() { return GetDistribValue(status, key, variable); } + , [&]() { + return GetDistribValue(status, key, variable, effectiveRoot, + os_release); + } #ifdef _WIN32 , [&]() { return GetWindowsValue(status, key); } #endif @@ -770,7 +889,7 @@ bool cmCMakeHostSystemInformationCommand(std::vector const& args, result_list += value.value(); } - status.GetMakefile().AddDefinition(variable, result_list); + makefile.AddDefinition(variable, result_list); return true; } diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 4c0c5cc960..746ed45568 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -662,6 +662,10 @@ class cmMakefile; SELECT(POLICY, CMP0220, \ "Languages enabled in subdirectories propagate to the top-level " \ "directory.", \ + 4, 5, 0, WARN) \ + SELECT(POLICY, CMP0221, \ + "cmake_host_system_information() DISTRIB_* queries read the host " \ + "os-release.", \ 4, 5, 0, WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) diff --git a/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake b/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake index 3bc632b9b9..3c9886e836 100644 --- a/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake +++ b/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake @@ -1,4 +1,4 @@ -cmake_host_system_information(RESULT CENTOS6 QUERY DISTRIB_INFO) +cmake_host_system_information(RESULT CENTOS6 QUERY FROM_SYSROOT ON DISTRIB_INFO) foreach(VAR IN LISTS CENTOS6) message(STATUS "${VAR}=`${${VAR}}`") diff --git a/Tests/RunCMake/cmake_host_system_information/Debian6.cmake b/Tests/RunCMake/cmake_host_system_information/Debian6.cmake index cbf83a9f1f..8e40a341c4 100644 --- a/Tests/RunCMake/cmake_host_system_information/Debian6.cmake +++ b/Tests/RunCMake/cmake_host_system_information/Debian6.cmake @@ -1,4 +1,4 @@ -cmake_host_system_information(RESULT DEBIAN6 QUERY DISTRIB_INFO) +cmake_host_system_information(RESULT DEBIAN6 QUERY FROM_SYSROOT ON DISTRIB_INFO) foreach(VAR IN LISTS DEBIAN6) message(STATUS "${VAR}=`${${VAR}}`") diff --git a/Tests/RunCMake/cmake_host_system_information/DistribFallbackSelector.cmake b/Tests/RunCMake/cmake_host_system_information/DistribFallbackSelector.cmake new file mode 100644 index 0000000000..9fb3229c48 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribFallbackSelector.cmake @@ -0,0 +1,28 @@ +# Pre-os-release fallback scripts read ${CMAKE_SYSROOT}; FROM_SYSROOT must +# scope-override it so target/host selection is honored, and the original +# CMAKE_SYSROOT must be restored after each call. +cmake_policy(SET CMP0221 NEW) + +# Host baseline with no sysroot in effect (the host itself may be CentOS). +cmake_host_system_information(RESULT baseline QUERY DISTRIB_ID) + +set(sysroot "${CMAKE_CURRENT_LIST_DIR}/CentOS6") +set(CMAKE_SYSROOT "${sysroot}") + +# Target: the CentOS fallback script detects the fixture under CMAKE_SYSROOT. +cmake_host_system_information(RESULT tgt QUERY FROM_SYSROOT ON DISTRIB_ID) +if(NOT tgt STREQUAL "centos") + message(FATAL_ERROR "FROM_SYSROOT ON fallback read ID '${tgt}', expected 'centos'") +endif() +if(NOT CMAKE_SYSROOT STREQUAL "${sysroot}") + message(FATAL_ERROR "CMAKE_SYSROOT not restored after target fallback: '${CMAKE_SYSROOT}'") +endif() + +# Host: must read the host os-release, not the target fixture. +cmake_host_system_information(RESULT host QUERY FROM_SYSROOT OFF DISTRIB_ID) +if(NOT host STREQUAL baseline) + message(FATAL_ERROR "FROM_SYSROOT OFF read '${host}', expected host baseline '${baseline}'") +endif() +if(NOT CMAKE_SYSROOT STREQUAL "${sysroot}") + message(FATAL_ERROR "CMAKE_SYSROOT not restored after host fallback: '${CMAKE_SYSROOT}'") +endif() diff --git a/Tests/RunCMake/cmake_host_system_information/DistribHost.cmake b/Tests/RunCMake/cmake_host_system_information/DistribHost.cmake new file mode 100644 index 0000000000..dbf98be2a1 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribHost.cmake @@ -0,0 +1,15 @@ +# Explicit host selection must ignore CMAKE_SYSROOT and read the host os-release. +cmake_policy(SET CMP0221 NEW) + +# Baseline: query the host with no sysroot in effect. +cmake_host_system_information(RESULT baseline QUERY DISTRIB_ID) + +set(CMAKE_SYSROOT "${CMAKE_CURRENT_LIST_DIR}/Sentinel") +cmake_host_system_information(RESULT host QUERY FROM_SYSROOT OFF DISTRIB_ID) + +if(NOT host STREQUAL baseline) + message(FATAL_ERROR "FROM_SYSROOT OFF read '${host}', expected host baseline '${baseline}'") +endif() +if(host STREQUAL "sentineltarget") + message(FATAL_ERROR "FROM_SYSROOT OFF leaked the target sentinel") +endif() diff --git a/Tests/RunCMake/cmake_host_system_information/DistribPolicyNew.cmake b/Tests/RunCMake/cmake_host_system_information/DistribPolicyNew.cmake new file mode 100644 index 0000000000..014b3d51d9 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribPolicyNew.cmake @@ -0,0 +1,14 @@ +# With CMP0221 NEW, the no-keyword default ignores CMAKE_SYSROOT (host). +cmake_policy(SET CMP0221 NEW) + +cmake_host_system_information(RESULT baseline QUERY DISTRIB_ID) + +set(CMAKE_SYSROOT "${CMAKE_CURRENT_LIST_DIR}/Sentinel") +cmake_host_system_information(RESULT def QUERY DISTRIB_ID) + +if(NOT def STREQUAL baseline) + message(FATAL_ERROR "CMP0221 NEW default read '${def}', expected host baseline '${baseline}'") +endif() +if(def STREQUAL "sentineltarget") + message(FATAL_ERROR "CMP0221 NEW default leaked the target sentinel") +endif() diff --git a/Tests/RunCMake/cmake_host_system_information/DistribPolicyNonDistrib.cmake b/Tests/RunCMake/cmake_host_system_information/DistribPolicyNonDistrib.cmake new file mode 100644 index 0000000000..4ebcdf1fbe --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribPolicyNonDistrib.cmake @@ -0,0 +1,5 @@ +# CMP0221 unset (WARN): a non-DISTRIB_* query must not warn, even with a +# non-empty CMAKE_SYSROOT. Also proves the os-release is not read lazily when +# no DISTRIB_* key is requested (no stderr, no side effects). +set(CMAKE_SYSROOT "${CMAKE_CURRENT_LIST_DIR}/Sentinel") +cmake_host_system_information(RESULT cores QUERY NUMBER_OF_LOGICAL_CORES) diff --git a/Tests/RunCMake/cmake_host_system_information/DistribPolicyOld.cmake b/Tests/RunCMake/cmake_host_system_information/DistribPolicyOld.cmake new file mode 100644 index 0000000000..3b09b4fa46 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribPolicyOld.cmake @@ -0,0 +1,9 @@ +# With CMP0221 OLD, the no-keyword default follows CMAKE_SYSROOT (target). +cmake_policy(SET CMP0221 OLD) + +set(CMAKE_SYSROOT "${CMAKE_CURRENT_LIST_DIR}/Sentinel") +cmake_host_system_information(RESULT def QUERY DISTRIB_ID) + +if(NOT def STREQUAL "sentineltarget") + message(FATAL_ERROR "CMP0221 OLD default read '${def}', expected target 'sentineltarget'") +endif() diff --git a/Tests/RunCMake/cmake_host_system_information/DistribPolicyWarn-stderr.txt b/Tests/RunCMake/cmake_host_system_information/DistribPolicyWarn-stderr.txt new file mode 100644 index 0000000000..67aa7e57e9 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribPolicyWarn-stderr.txt @@ -0,0 +1,8 @@ +^CMake Warning \(policy\) at [^ +]*/DistribPolicyWarn\.cmake:[0-9]+ \(cmake_host_system_information\): + Policy CMP0221 is not set: cmake_host_system_information\(\) DISTRIB_\* + queries read the host os-release\. Run "cmake --help-policy CMP0221" for + policy details\. Use the cmake_policy command to set the policy and + suppress this warning\. +This warning is for project developers\. Use -Wno-author or -Wno-policy to +suppress it\.$ diff --git a/Tests/RunCMake/cmake_host_system_information/DistribPolicyWarn.cmake b/Tests/RunCMake/cmake_host_system_information/DistribPolicyWarn.cmake new file mode 100644 index 0000000000..7e9df7fdc2 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribPolicyWarn.cmake @@ -0,0 +1,8 @@ +# CMP0221 unset (WARN): a DISTRIB_* query with a non-empty CMAKE_SYSROOT and no +# selector keyword warns once and uses the OLD behavior (target). +set(CMAKE_SYSROOT "${CMAKE_CURRENT_LIST_DIR}/Sentinel") +cmake_host_system_information(RESULT def QUERY DISTRIB_ID) + +if(NOT def STREQUAL "sentineltarget") + message(FATAL_ERROR "CMP0221 WARN read '${def}', expected target 'sentineltarget'") +endif() diff --git a/Tests/RunCMake/cmake_host_system_information/DistribRegistrySelector-result.txt b/Tests/RunCMake/cmake_host_system_information/DistribRegistrySelector-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribRegistrySelector-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/DistribRegistrySelector-stderr.txt b/Tests/RunCMake/cmake_host_system_information/DistribRegistrySelector-stderr.txt new file mode 100644 index 0000000000..8ef80435a3 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribRegistrySelector-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at [^ +]*/DistribRegistrySelector\.cmake:[0-9]+ \(cmake_host_system_information\): + cmake_host_system_information does not recognize WINDOWS_REGISTRY$ diff --git a/Tests/RunCMake/cmake_host_system_information/DistribRegistrySelector.cmake b/Tests/RunCMake/cmake_host_system_information/DistribRegistrySelector.cmake new file mode 100644 index 0000000000..de540e1ee6 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribRegistrySelector.cmake @@ -0,0 +1,4 @@ +# FROM_SYSROOT before QUERY's content makes WINDOWS_REGISTRY no longer the +# registry signature, so it is rejected as an unknown . This guards the +# registry-first dispatch: registry queries never see FROM_SYSROOT. +cmake_host_system_information(RESULT r QUERY FROM_SYSROOT ON WINDOWS_REGISTRY "HKLM") diff --git a/Tests/RunCMake/cmake_host_system_information/DistribSysrootBadValue-result.txt b/Tests/RunCMake/cmake_host_system_information/DistribSysrootBadValue-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribSysrootBadValue-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/DistribSysrootBadValue-stderr.txt b/Tests/RunCMake/cmake_host_system_information/DistribSysrootBadValue-stderr.txt new file mode 100644 index 0000000000..4f87702c22 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribSysrootBadValue-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at [^ +]*/DistribSysrootBadValue\.cmake:[0-9]+ \(cmake_host_system_information\): + cmake_host_system_information FROM_SYSROOT requires a boolean value, got + "bogus"\.$ diff --git a/Tests/RunCMake/cmake_host_system_information/DistribSysrootBadValue.cmake b/Tests/RunCMake/cmake_host_system_information/DistribSysrootBadValue.cmake new file mode 100644 index 0000000000..1c85f6e57d --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribSysrootBadValue.cmake @@ -0,0 +1,3 @@ +# FROM_SYSROOT requires a boolean value. A non-boolean is rejected, which also +# guards the "forgot the value, ate the next key" mistake. +cmake_host_system_information(RESULT r QUERY FROM_SYSROOT bogus DISTRIB_ID) diff --git a/Tests/RunCMake/cmake_host_system_information/DistribSysrootDuplicate-result.txt b/Tests/RunCMake/cmake_host_system_information/DistribSysrootDuplicate-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribSysrootDuplicate-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/DistribSysrootDuplicate-stderr.txt b/Tests/RunCMake/cmake_host_system_information/DistribSysrootDuplicate-stderr.txt new file mode 100644 index 0000000000..ba21cbccb0 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribSysrootDuplicate-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at [^ +]*/DistribSysrootDuplicate\.cmake:[0-9]+ \(cmake_host_system_information\): + cmake_host_system_information FROM_SYSROOT may be given at most once\.$ diff --git a/Tests/RunCMake/cmake_host_system_information/DistribSysrootDuplicate.cmake b/Tests/RunCMake/cmake_host_system_information/DistribSysrootDuplicate.cmake new file mode 100644 index 0000000000..b787590c94 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribSysrootDuplicate.cmake @@ -0,0 +1,2 @@ +# FROM_SYSROOT may be given at most once. +cmake_host_system_information(RESULT r QUERY FROM_SYSROOT ON FROM_SYSROOT OFF DISTRIB_ID) diff --git a/Tests/RunCMake/cmake_host_system_information/DistribSysrootPosition.cmake b/Tests/RunCMake/cmake_host_system_information/DistribSysrootPosition.cmake new file mode 100644 index 0000000000..073ffba4b0 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribSysrootPosition.cmake @@ -0,0 +1,17 @@ +# FROM_SYSROOT is accepted after and between keys, not just as the first token. +cmake_policy(SET CMP0221 NEW) + +set(CMAKE_SYSROOT "${CMAKE_CURRENT_LIST_DIR}/Sentinel") + +# After a key. +cmake_host_system_information(RESULT after QUERY DISTRIB_ID FROM_SYSROOT ON) +if(NOT after STREQUAL "sentineltarget") + message(FATAL_ERROR "FROM_SYSROOT after a key read '${after}', expected 'sentineltarget'") +endif() + +# Between keys. +cmake_host_system_information(RESULT between QUERY DISTRIB_ID FROM_SYSROOT ON DISTRIB_NAME) +list(GET between 0 between_id) +if(NOT between_id STREQUAL "sentineltarget") + message(FATAL_ERROR "FROM_SYSROOT between keys read '${between_id}', expected 'sentineltarget'") +endif() diff --git a/Tests/RunCMake/cmake_host_system_information/DistribTarget.cmake b/Tests/RunCMake/cmake_host_system_information/DistribTarget.cmake new file mode 100644 index 0000000000..07fa92eead --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/DistribTarget.cmake @@ -0,0 +1,10 @@ +# Explicit target selection must read the CMAKE_SYSROOT os-release, even when +# the policy default is host. +cmake_policy(SET CMP0221 NEW) + +set(CMAKE_SYSROOT "${CMAKE_CURRENT_LIST_DIR}/Sentinel") +cmake_host_system_information(RESULT tgt QUERY FROM_SYSROOT ON DISTRIB_ID) + +if(NOT tgt STREQUAL "sentineltarget") + message(FATAL_ERROR "FROM_SYSROOT ON read '${tgt}', expected target 'sentineltarget'") +endif() diff --git a/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake b/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake index 7fc26d812a..7513a7c754 100644 --- a/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake +++ b/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake @@ -1,11 +1,11 @@ -cmake_host_system_information(RESULT TEST1 QUERY DISTRIB_INFO) +cmake_host_system_information(RESULT TEST1 QUERY FROM_SYSROOT ON 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) +cmake_host_system_information(RESULT TEST2 QUERY FROM_SYSROOT ON 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/RunCMakeTest.cmake b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake index 89a5f51cec..9c17e31963 100644 --- a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake +++ b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake @@ -30,6 +30,19 @@ run_cmake(Ubuntu) run_cmake(CentOS6) run_cmake(Debian6) +# DISTRIB_* host/target selection (CMP0221) and the FROM_SYSROOT option. +run_cmake_script(DistribHost) +run_cmake_script(DistribTarget) +run_cmake_script(DistribPolicyOld) +run_cmake_script(DistribPolicyNew) +run_cmake_script(DistribPolicyWarn) +run_cmake_script(DistribPolicyNonDistrib) +run_cmake_script(DistribSysrootBadValue) +run_cmake_script(DistribSysrootDuplicate) +run_cmake_script(DistribSysrootPosition) +run_cmake_script(DistribRegistrySelector) +run_cmake_script(DistribFallbackSelector) + if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") run_cmake(MacOS) endif() diff --git a/Tests/RunCMake/cmake_host_system_information/Sentinel/etc/os-release b/Tests/RunCMake/cmake_host_system_information/Sentinel/etc/os-release new file mode 100644 index 0000000000..dbc9838698 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Sentinel/etc/os-release @@ -0,0 +1,4 @@ +NAME="Sentinel Target" +PRETTY_NAME="Sentinel Target 9.9" +ID=sentineltarget +VERSION_ID="9.9" diff --git a/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake b/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake index 7fc26d812a..7513a7c754 100644 --- a/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake +++ b/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake @@ -1,11 +1,11 @@ -cmake_host_system_information(RESULT TEST1 QUERY DISTRIB_INFO) +cmake_host_system_information(RESULT TEST1 QUERY FROM_SYSROOT ON 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) +cmake_host_system_information(RESULT TEST2 QUERY FROM_SYSROOT ON 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/UnitTest.cmake b/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake index d9a0acae84..88035fb2a4 100644 --- a/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake +++ b/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake @@ -1,4 +1,4 @@ -cmake_host_system_information(RESULT UNIT_TEST QUERY DISTRIB_INFO) +cmake_host_system_information(RESULT UNIT_TEST QUERY FROM_SYSROOT ON DISTRIB_INFO) foreach(VAR IN LISTS UNIT_TEST) message(STATUS "${VAR}=`${${VAR}}`") diff --git a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake index 660aa1ca31..6c5815edc4 100644 --- a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake +++ b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake @@ -5,7 +5,7 @@ list( ${CMAKE_CURRENT_SOURCE_DIR}/999-LastFallbackScript.cmake ) -cmake_host_system_information(RESULT UFS QUERY DISTRIB_INFO) +cmake_host_system_information(RESULT UFS QUERY FROM_SYSROOT ON DISTRIB_INFO) foreach(VAR IN LISTS UFS) message(STATUS "${VAR}=`${${VAR}}`")