cmake_host_system_information: Can run fallback scripts
This commit is contained in:
parent
1e65e4a6e5
commit
efe139d1b8
@ -176,8 +176,75 @@ system identification as described in the `man 5 os-release`_.
|
||||
-- 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
|
||||
|
41
Modules/Internal/OSRelease/010-TryOldCentOS.cmake
Normal file
41
Modules/Internal/OSRelease/010-TryOldCentOS.cmake
Normal file
@ -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)
|
38
Modules/Internal/OSRelease/020-TryDebianVersion.cmake
Normal file
38
Modules/Internal/OSRelease/020-TryDebianVersion.cmake
Normal file
@ -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)
|
@ -2,6 +2,7 @@
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmCMakeHostSystemInformationCommand.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <initializer_list>
|
||||
@ -15,6 +16,7 @@
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmsys/FStream.hxx"
|
||||
#include "cmsys/Glob.hxx"
|
||||
#include "cmsys/SystemInformation.hxx"
|
||||
|
||||
#include "cmExecutionStatus.h"
|
||||
@ -259,8 +261,8 @@ cm::optional<std::pair<std::string, std::string>> ParseOSReleaseLine(
|
||||
std::map<std::string, std::string> GetOSReleaseVariables(
|
||||
cmExecutionStatus& status)
|
||||
{
|
||||
const auto& sysroot =
|
||||
status.GetMakefile().GetSafeDefinition("CMAKE_SYSROOT");
|
||||
auto& makefile = status.GetMakefile();
|
||||
const auto& sysroot = makefile.GetSafeDefinition("CMAKE_SYSROOT");
|
||||
|
||||
std::map<std::string, std::string> data;
|
||||
// Based on
|
||||
@ -278,6 +280,92 @@ std::map<std::string, std::string> GetOSReleaseVariables(
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Got smth?
|
||||
if (!data.empty()) {
|
||||
return data;
|
||||
}
|
||||
|
||||
// Ugh, it could be some pre-os-release distro.
|
||||
// Lets try some fallback getters.
|
||||
|
||||
// 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());
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
if (!data.empty()) {
|
||||
// Try 'till some script can get anything
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
makefile.RemoveDefinition(result_variable.data());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
message(WARNING "The warning text to match just to make sure the script get executed")
|
@ -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
|
||||
)
|
@ -0,0 +1,6 @@
|
||||
-- CENTOS6_ID=`centos`
|
||||
-- CENTOS6_ID_LIKE=`rhel`
|
||||
-- CENTOS6_NAME=`CentOS`
|
||||
-- CENTOS6_PRETTY_NAME=`CentOS release 6\.10 \(Final\)`
|
||||
-- CENTOS6_VERSION=`6\.10`
|
||||
-- CENTOS6_VERSION_ID=`6\.10`
|
@ -0,0 +1,5 @@
|
||||
cmake_host_system_information(RESULT CENTOS6 QUERY DISTRIB_INFO)
|
||||
|
||||
foreach(VAR IN LISTS CENTOS6)
|
||||
message(STATUS "${VAR}=`${${VAR}}`")
|
||||
endforeach()
|
@ -0,0 +1 @@
|
||||
CentOS release 6.10 (Final)
|
@ -0,0 +1,4 @@
|
||||
-- DEBIAN6_ID=`debian`
|
||||
-- DEBIAN6_NAME=`Debian`
|
||||
-- DEBIAN6_VERSION=`6\.0\.10`
|
||||
-- DEBIAN6_VERSION_ID=`6\.0\.10`
|
@ -0,0 +1,5 @@
|
||||
cmake_host_system_information(RESULT DEBIAN6 QUERY DISTRIB_INFO)
|
||||
|
||||
foreach(VAR IN LISTS DEBIAN6)
|
||||
message(STATUS "${VAR}=`${${VAR}}`")
|
||||
endforeach()
|
@ -0,0 +1 @@
|
||||
6.0.10
|
@ -13,4 +13,9 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
run_cmake_with_options(Exherbo)
|
||||
run_cmake_with_options(Ubuntu)
|
||||
|
||||
run_cmake_with_options(CentOS6)
|
||||
run_cmake_with_options(Debian6)
|
||||
|
||||
run_cmake_with_options(UserFallbackScript)
|
||||
|
||||
endif()
|
||||
|
@ -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\)
|
@ -0,0 +1,6 @@
|
||||
-- UFS_ID=`unittest`
|
||||
-- UFS_ID_LIKE=`nothing`
|
||||
-- UFS_NAME=`UnitTest`
|
||||
-- UFS_PRETTY_NAME=`Just a Unit Test`
|
||||
-- UFS_VERSION=`0\.0\.1`
|
||||
-- UFS_VERSION_ID=`0\.0\.1`
|
@ -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()
|
Loading…
Reference in New Issue
Block a user