cmake_host_system_information: Add MSYSTEM_PREFIX query

Add a query on Windows hosts for the installation prefix of a
MSYS or MinGW development environment.

Issue: #24216
This commit is contained in:
Brad King 2023-09-08 20:06:13 -04:00
parent cdcff0a0f0
commit 84a25fc263
13 changed files with 146 additions and 0 deletions

View File

@ -1,5 +1,8 @@
set(CMake_TEST_Java OFF CACHE BOOL "")
get_filename_component(mingw_dir "${CMAKE_CURRENT_LIST_DIR}/../mingw" ABSOLUTE)
set(CMake_TEST_MSYSTEM_PREFIX "${mingw_dir}" CACHE STRING "")
set(configure_no_sccache 1)
include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")

View File

@ -146,6 +146,13 @@ queried. The list of queried values is stored in ``<variable>``.
See :variable:`CMAKE_HOST_SYSTEM_PROCESSOR`
``MSYSTEM_PREFIX``
.. versionadded:: 3.28
Available only on Windows hosts. In a MSYS or MinGW development
environment that sets the ``MSYSTEM`` environment variable, this
is its installation prefix. Otherwise, this is the empty string.
``DISTRIB_INFO``
.. versionadded:: 3.22

View File

@ -0,0 +1,6 @@
host-msystem-prefix
-------------------
* The :command:`cmake_host_system_information` command gained a
``MSYSTEM_PREFIX`` query for the installation prefix of a MSYS
or MinGW development environment on Windows hosts.

View File

@ -414,6 +414,86 @@ cm::optional<std::string> GetDistribValue(cmExecutionStatus& status,
}
#ifdef _WIN32
std::string FindMSYSTEM_PREFIX(std::vector<std::string> prefixes)
{
for (std::string const& prefix : prefixes) {
std::string out;
std::string err;
int ret;
// In a modern MSYSTEM environment we expect cygpath to be in PATH.
std::vector<std::string> cygpath_cmd{ "cygpath", "-w", prefix };
if (cmSystemTools::RunSingleCommand(cygpath_cmd, &out, &err, &ret, nullptr,
cmSystemTools::OUTPUT_NONE)) {
if (ret == 0) {
out = cmTrimWhitespace(out);
cmSystemTools::ConvertToUnixSlashes(out);
if (cmSystemTools::FileIsDirectory(out)) {
return out;
}
}
} else {
// In a legacy MSYSTEM environment (MinGW/MSYS 1.0) there is no
// cygpath but we expect 'sh' to be in PATH.
std::vector<std::string> sh_cmd{
"sh", "-c", cmStrCat("cd \"", prefix, "\" && cmd //c cd")
};
if (cmSystemTools::RunSingleCommand(sh_cmd, &out, &err, &ret, nullptr,
cmSystemTools::OUTPUT_NONE)) {
if (ret == 0) {
out = cmTrimWhitespace(out);
cmSystemTools::ConvertToUnixSlashes(out);
if (cmSystemTools::FileIsDirectory(out)) {
return out;
}
}
}
}
}
return {};
}
std::string FallbackMSYSTEM_PREFIX(cm::string_view msystem)
{
// These layouts are used by distributions such as
// * MSYS2: https://www.msys2.org/docs/environments/
// * MinGW/MSYS 1.0: http://mingw.osdn.io/
if (msystem == "MSYS"_s) {
static std::string const msystem_msys = FindMSYSTEM_PREFIX({ "/usr" });
return msystem_msys;
}
if (msystem == "MINGW32"_s) {
static std::string const msystem_mingw32 =
FindMSYSTEM_PREFIX({ "/mingw32", "/mingw" });
return msystem_mingw32;
}
if (msystem == "MINGW64"_s) {
static std::string const msystem_mingw64 =
FindMSYSTEM_PREFIX({ "/mingw64" });
return msystem_mingw64;
}
if (msystem == "UCRT64"_s) {
static std::string const msystem_ucrt64 =
FindMSYSTEM_PREFIX({ "/ucrt64" });
return msystem_ucrt64;
}
if (msystem == "CLANG32"_s) {
static std::string const msystem_clang32 =
FindMSYSTEM_PREFIX({ "/clang32" });
return msystem_clang32;
}
if (msystem == "CLANG64"_s) {
static std::string const msystem_clang64 =
FindMSYSTEM_PREFIX({ "/clang64" });
return msystem_clang64;
}
if (msystem == "CLANGARM64"_s) {
static std::string const msystem_clangarm64 =
FindMSYSTEM_PREFIX({ "/clangarm64" });
return msystem_clangarm64;
}
return {};
}
cm::optional<std::string> GetWindowsValue(cmExecutionStatus& status,
std::string const& key)
{
@ -446,6 +526,23 @@ cm::optional<std::string> GetWindowsValue(cmExecutionStatus& status,
return vs10gen->FindMSBuildCommandEarly(&status.GetMakefile());
}
if (key == "MSYSTEM_PREFIX") {
// MSYSTEM_PREFIX is meaningful only under a MSYSTEM environment.
cm::optional<std::string> ms = cmSystemTools::GetEnvVar("MSYSTEM");
if (!ms || ms->empty()) {
return std::string();
}
// Prefer the MSYSTEM_PREFIX environment variable.
if (cm::optional<std::string> msp =
cmSystemTools::GetEnvVar("MSYSTEM_PREFIX")) {
cmSystemTools::ConvertToUnixSlashes(*msp);
if (cmSystemTools::FileIsDirectory(*msp)) {
return msp;
}
}
// Fall back to known distribution layouts.
return FallbackMSYSTEM_PREFIX(*ms);
}
return {};
}
#endif

View File

@ -474,6 +474,9 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE)
endif()
add_RunCMake_test(execute_process)
add_RunCMake_test(export)
if(CMake_TEST_MSYSTEM_PREFIX)
list(APPEND cmake_host_system_information_ARGS -DCMake_TEST_MSYSTEM_PREFIX=${CMake_TEST_MSYSTEM_PREFIX})
endif()
add_RunCMake_test(cmake_host_system_information)
add_RunCMake_test(cmake_language)
add_RunCMake_test(cmake_minimum_required)

View File

@ -0,0 +1 @@
MSYSTEM_PREFIX=''

View File

@ -0,0 +1,3 @@
unset(ENV{MSYSTEM})
cmake_host_system_information(RESULT result QUERY MSYSTEM_PREFIX)
message(STATUS "MSYSTEM_PREFIX='${result}'")

View File

@ -0,0 +1,3 @@
^CMake Error at [^
]*/Tests/RunCMake/cmake_host_system_information/MSYSTEM_PREFIX-Missing.cmake:[0-9]+ \(cmake_host_system_information\):
cmake_host_system_information does not recognize <key> MSYSTEM_PREFIX$

View File

@ -0,0 +1,2 @@
unset(ENV{MSYSTEM})
cmake_host_system_information(RESULT result QUERY MSYSTEM_PREFIX)

View File

@ -0,0 +1,2 @@
-- MSYSTEM_PREFIX='[^
]+'

View File

@ -0,0 +1,7 @@
cmake_host_system_information(RESULT result QUERY MSYSTEM_PREFIX)
message(STATUS "MSYSTEM_PREFIX='${result}'")
if(CMake_TEST_MSYSTEM_PREFIX)
if(NOT "${result}" STREQUAL "${CMake_TEST_MSYSTEM_PREFIX}")
message(FATAL_ERROR "Actual result:\n ${result}\nis not expected result:\n ${CMake_TEST_MSYSTEM_PREFIX}")
endif()
endif()

View File

@ -22,6 +22,17 @@ else()
run_cmake(VsMSBuildMissing)
endif()
if(CMAKE_HOST_WIN32)
run_cmake_script(MSYSTEM_PREFIX-Empty)
if("$ENV{MSYSTEM}" MATCHES "(MSYS|MINGW32|MINGW64|UCRT64)")
set(RunCMake_TEST_VARIANT_DESCRIPTION "-$ENV{MSYSTEM}")
run_cmake_script(MSYSTEM_PREFIX -DCMake_TEST_MSYSTEM_PREFIX=${CMake_TEST_MSYSTEM_PREFIX})
unset(RunCMake_TEST_VARIANT_DESCRIPTION)
endif()
else()
run_cmake_script(MSYSTEM_PREFIX-Missing)
endif()
# WINDOWS_REGISTRY tests
run_cmake(Registry_NoArgs)
run_cmake(Registry_BadQuery1)