[llvm] TargetParser: Move triple to CMake system name mapping into CMake (PR #225379)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 22 05:04:48 PDT 2026
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/225379
Reimplement the triple -> CMAKE_SYSTEM_NAME derivation added in #208773
entirely in CMake, dropping the Python script it introduced.
The previous mechanism widened TRIPLE_OS/TRIPLE_ENV in TripleName.def with
a CMake system name column and parsed it from a Python helper invoked by
CMake at configure time. Two problems motivated this rework:
- The CMake system name is a property of CMake (and can vary by CMake
version), not of llvm::Triple, so it does not belong in the shared
triple name table. The C++ never consumed the added column.
- Invoking Python from CMake at configure time is an unwanted build
dependency, and the Python-driven lit test broke Windows bots where the
interpreter path contains a space.
Revert the TripleName.def/Triple.cpp column back to the two-argument
macros, delete the Python script and its unittest, and reimplement the
mapping as a self-contained pure-CMake module. The classification still
mirrors Triple::normalize's permissiveness for unnormalized and legacy
triples. A cmake -P driven unit test replaces the Python unittest and adds
a drift guard asserting every OS/environment name in TripleName.def has a
mapping entry.
Co-authored-by: Claude (Opus 4.8) <noreply at anthropic.com>
>From 922809a8a3c18f3375050983d15015dc2efdc561 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Sun, 2 Aug 2026 21:43:55 +0200
Subject: [PATCH] TargetParser: Move triple to CMake system name mapping into
CMake
Reimplement the triple -> CMAKE_SYSTEM_NAME derivation added in #208773
entirely in CMake, dropping the Python script it introduced.
The previous mechanism widened TRIPLE_OS/TRIPLE_ENV in TripleName.def with
a CMake system name column and parsed it from a Python helper invoked by
CMake at configure time. Two problems motivated this rework:
- The CMake system name is a property of CMake (and can vary by CMake
version), not of llvm::Triple, so it does not belong in the shared
triple name table. The C++ never consumed the added column.
- Invoking Python from CMake at configure time is an unwanted build
dependency, and the Python-driven lit test broke Windows bots where the
interpreter path contains a space.
Revert the TripleName.def/Triple.cpp column back to the two-argument
macros, delete the Python script and its unittest, and reimplement the
mapping as a self-contained pure-CMake module. The classification still
mirrors Triple::normalize's permissiveness for unnormalized and legacy
triples. A cmake -P driven unit test replaces the Python unittest and adds
a drift guard asserting every OS/environment name in TripleName.def has a
mapping entry.
Co-authored-by: Claude (Opus 4.8) <noreply at anthropic.com>
---
cmake/Modules/GetTripleCMakeSystemName.cmake | 162 +++++++++++--
llvm/include/llvm/TargetParser/TripleName.def | 228 +++++++++---------
llvm/lib/TargetParser/Triple.cpp | 8 +-
llvm/test/lit.cfg.py | 1 +
llvm/test/lit.site.cfg.py.in | 1 +
.../get-triple-cmake-system-name.cmake | 208 ++++++++++++++++
.../TargetParser/get-triple-system-name.test | 9 +-
.../get_triple_system_name_test.py | 206 ----------------
llvm/utils/get_triple_system_name.py | 148 ------------
9 files changed, 476 insertions(+), 495 deletions(-)
create mode 100644 llvm/test/tools/TargetParser/get-triple-cmake-system-name.cmake
delete mode 100644 llvm/test/tools/TargetParser/get_triple_system_name_test.py
delete mode 100755 llvm/utils/get_triple_system_name.py
diff --git a/cmake/Modules/GetTripleCMakeSystemName.cmake b/cmake/Modules/GetTripleCMakeSystemName.cmake
index 8ad725f34175c..d7b1d1388fcea 100644
--- a/cmake/Modules/GetTripleCMakeSystemName.cmake
+++ b/cmake/Modules/GetTripleCMakeSystemName.cmake
@@ -13,25 +13,157 @@
#
# Sets <out_var> to the CMake-style system name
# (e.g. "x86_64-pc-linux-gnu" -> Linux, "arm64-apple-macos" ->
-# "Darwin"). A triple with an OS cmake does not recognize maps to
-# "Generic".
+# "Darwin"). A triple whose OS CMake does not recognize maps to
+# "Generic"; a triple with no identifiable OS falls back to
+# CMAKE_HOST_SYSTEM_NAME.
#
-# The OS/environment -> system name data is derived from
-# llvm/include/llvm/TargetParser/TripleName.def
+# The recognized OS and environment names mirror the tables in
+# llvm/include/llvm/TargetParser/TripleName.def (and the classification
+# mirrors Triple::normalize), but the OS -> CMake system name mapping is
+# maintained here: the CMake system names are a property of CMake, not of
+# llvm::Triple, and can vary by CMake version.
+#
+# llvm/test/tools/TargetParser/get-triple-cmake-system-name.cmake unit
+# tests this module and guards against the .def OS/environment tables
+# drifting out of sync with the mapping below.
-get_filename_component(_gtcsn_llvm_dir "${CMAKE_CURRENT_LIST_DIR}/../../llvm"
- ABSOLUTE)
-set(_gtcsn_script "${_gtcsn_llvm_dir}/utils/get_triple_system_name.py")
+# Populate the OS/environment name tables in the caller's scope. Defined as
+# a macro so both the classifier and the unit test share one copy of the data.
+#
+# Order is significant: matching is by prefix, so a name that is a prefix of
+# another must come first (wasip1/2/3 before wasi). _GTCSN_OS_NAMES and
+# _GTCSN_OS_CMAKE are parallel lists. Only environments that force a system
+# name regardless of the OS appear in the environment tables.
+macro(_gtcsn_populate_tables)
+ set(_GTCSN_OS_NAMES
+ darwin dragonfly freebsd fuchsia ios kfreebsd linux lv2 macosx macos
+ managarm netbsd openbsd solaris uefi windows win32 zos haiku rtems aix
+ cuda nvcl amdhsa ps4 ps5 elfiamcu tvos watchos bridgeos driverkit xros
+ visionos mesa3d amdpal hermit hurd wasip1 wasip2 wasip3 wasi emscripten
+ shadermodel liteos serenity vulkan cheriotrtos opencl chipstar firmware
+ qurt h2)
+ set(_GTCSN_OS_CMAKE
+ Darwin DragonFly FreeBSD Fuchsia iOS FreeBSD Linux Generic Darwin Darwin
+ Generic NetBSD OpenBSD SunOS Generic Windows Windows OS390 Haiku RTEMS AIX
+ Generic Generic Generic Generic Generic Generic tvOS watchOS Darwin Darwin
+ visionOS visionOS Generic Generic Generic GNU WASI WASI WASI WASI
+ Emscripten Generic Generic SerenityOS Generic Generic Generic Generic
+ Generic Generic Generic)
-function(get_triple_cmake_system_name triple out_var)
- execute_process(
- COMMAND "${Python3_EXECUTABLE}" "${_gtcsn_script}" "--triple" "${triple}"
- OUTPUT_VARIABLE _name
- OUTPUT_STRIP_TRAILING_WHITESPACE
- RESULT_VARIABLE _result)
- if(NOT _result EQUAL 0)
- message(FATAL_ERROR "Failed to derive CMake system name for '${triple}'")
+ set(_GTCSN_ENV_NAMES android cygnus)
+ set(_GTCSN_ENV_OVERRIDE Android CYGWIN)
+endmacro()
+
+# Return TRUE in result_var if str starts with prefix.
+function(_gtcsn_starts_with str prefix result_var)
+ string(FIND "${str}" "${prefix}" _pos)
+ if(_pos EQUAL 0)
+ set(${result_var} TRUE PARENT_SCOPE)
+ else()
+ set(${result_var} FALSE PARENT_SCOPE)
+ endif()
+endfunction()
+
+# Classify a triple to a CMake system name, or the empty string if no OS
+# component can be identified (the caller then falls back to the host system
+# name). This mirrors the component classification of Triple::normalize: it
+# does not trust fixed positions, since a triple may omit the vendor
+# (aarch64-linux-android), put the OS in the vendor slot (wasm32-wasi,
+# i686-linux), or be a bare OS with no arch (clang accepts --target=darwin as
+# unknown-unknown-darwin). No arch name is a prefix of any OS/env name, so
+# scanning the first component too cannot misclassify a real arch.
+function(_get_triple_cmake_system_name_raw triple out_var)
+ _gtcsn_populate_tables()
+
+ string(REPLACE "-" ";" _parts "${triple}")
+ list(LENGTH _parts _nparts)
+
+ # An environment override takes precedence over the OS mapping (e.g. android
+ # wins over the linux in aarch64-linux-android), so scan for it first.
+ list(LENGTH _GTCSN_ENV_NAMES _nenv)
+ if(_nenv GREATER 0)
+ math(EXPR _last_env "${_nenv} - 1")
+ foreach(_comp IN LISTS _parts)
+ foreach(_i RANGE ${_last_env})
+ list(GET _GTCSN_ENV_NAMES ${_i} _name)
+ _gtcsn_starts_with("${_comp}" "${_name}" _match)
+ if(_match)
+ list(GET _GTCSN_ENV_OVERRIDE ${_i} _override)
+ set(${out_var} "${_override}" PARENT_SCOPE)
+ return()
+ endif()
+ endforeach()
+ endforeach()
+ endif()
+
+ # Find the first component that classifies as an OS. A specific (non-Generic)
+ # name wins immediately. A "Generic" match means the component is a recognized
+ # OS with no CMake equivalent; stop scanning once any OS is identified.
+ list(LENGTH _GTCSN_OS_NAMES _nos)
+ math(EXPR _last_os "${_nos} - 1")
+ set(_found_generic_os FALSE)
+ foreach(_comp IN LISTS _parts)
+ set(_matched FALSE)
+ foreach(_i RANGE ${_last_os})
+ list(GET _GTCSN_OS_NAMES ${_i} _name)
+ _gtcsn_starts_with("${_comp}" "${_name}" _match)
+ if(_match)
+ list(GET _GTCSN_OS_CMAKE ${_i} _cmake)
+ if(NOT _cmake STREQUAL "Generic")
+ set(${out_var} "${_cmake}" PARENT_SCOPE)
+ return()
+ endif()
+ set(_found_generic_os TRUE)
+ set(_matched TRUE)
+ break()
+ endif()
+ endforeach()
+ if(_matched)
+ break()
+ endif()
+ endforeach()
+
+ # Legacy OS spellings that normalize rewrites to windows.
+ foreach(_comp IN LISTS _parts)
+ _gtcsn_starts_with("${_comp}" "mingw" _match)
+ if(_match)
+ set(${out_var} "Windows" PARENT_SCOPE)
+ return()
+ endif()
+ _gtcsn_starts_with("${_comp}" "cygwin" _match_cygwin)
+ _gtcsn_starts_with("${_comp}" "msys" _match_msys)
+ if(_match_cygwin OR _match_msys)
+ set(${out_var} "CYGWIN" PARENT_SCOPE)
+ return()
+ endif()
+ endforeach()
+
+ # Apple vendor triples with no specific CMake OS name (e.g. firmware) map to
+ # Darwin.
+ if(_nparts GREATER 1)
+ list(GET _parts 1 _vendor)
+ if(_vendor STREQUAL "apple")
+ set(${out_var} "Darwin" PARENT_SCOPE)
+ return()
+ endif()
endif()
+
+ if(_found_generic_os)
+ set(${out_var} "Generic" PARENT_SCOPE)
+ return()
+ endif()
+
+ # No OS could be identified. Too few components to have one -> let the caller
+ # fall back to the host system name.
+ if(_nparts LESS 3)
+ set(${out_var} "" PARENT_SCOPE)
+ else()
+ set(${out_var} "Generic" PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(get_triple_cmake_system_name triple out_var)
+ _get_triple_cmake_system_name_raw("${triple}" _name)
if(_name)
set(${out_var} "${_name}" PARENT_SCOPE)
else()
diff --git a/llvm/include/llvm/TargetParser/TripleName.def b/llvm/include/llvm/TargetParser/TripleName.def
index 95026bd39db78..bbc03b3188019 100644
--- a/llvm/include/llvm/TargetParser/TripleName.def
+++ b/llvm/include/llvm/TargetParser/TripleName.def
@@ -5,21 +5,15 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-//
-// Also parsed by llvm/utils/get_triple_system_name.py, so keep the macro
-// invocations one per line with string literals.
-//
-//===----------------------------------------------------------------------===//
// NOTE: NO INCLUDE GUARD DESIRED!
//===----------------------------------------------------------------------===//
// OS names.
//
-// TRIPLE_OS(Enum, Name, CMakeName)
-// Enum - the Triple::OSType enumerator
-// Name - the canonical string
-// CMakeName - the CMake system name, or "Generic" if there is no equivalent
+// TRIPLE_OS(Enum, Name)
+// Enum - the Triple::OSType enumerator
+// Name - the canonical string
//
// TRIPLE_OS_ALIAS(Enum, AliasName)
// An additional prefix maps to an OSType.
@@ -29,64 +23,64 @@
// ===----------------------------------------------------------------------===//
#ifndef TRIPLE_OS
-#define TRIPLE_OS(Enum, Name, CMakeName)
+#define TRIPLE_OS(Enum, Name)
#endif
#ifndef TRIPLE_OS_ALIAS
#define TRIPLE_OS_ALIAS(Enum, AliasName)
#endif
-TRIPLE_OS(Darwin, "darwin", "Darwin")
-TRIPLE_OS(DragonFly, "dragonfly", "DragonFly")
-TRIPLE_OS(FreeBSD, "freebsd", "FreeBSD")
-TRIPLE_OS(Fuchsia, "fuchsia", "Fuchsia")
-TRIPLE_OS(IOS, "ios", "iOS")
-TRIPLE_OS(KFreeBSD, "kfreebsd", "FreeBSD")
-TRIPLE_OS(Linux, "linux", "Linux")
-TRIPLE_OS(Lv2, "lv2", "Generic")
-TRIPLE_OS(MacOSX, "macosx", "Darwin")
+TRIPLE_OS(Darwin, "darwin")
+TRIPLE_OS(DragonFly, "dragonfly")
+TRIPLE_OS(FreeBSD, "freebsd")
+TRIPLE_OS(Fuchsia, "fuchsia")
+TRIPLE_OS(IOS, "ios")
+TRIPLE_OS(KFreeBSD, "kfreebsd")
+TRIPLE_OS(Linux, "linux")
+TRIPLE_OS(Lv2, "lv2")
+TRIPLE_OS(MacOSX, "macosx")
TRIPLE_OS_ALIAS(MacOSX, "macos")
-TRIPLE_OS(Managarm, "managarm", "Generic")
-TRIPLE_OS(NetBSD, "netbsd", "NetBSD")
-TRIPLE_OS(OpenBSD, "openbsd", "OpenBSD")
-TRIPLE_OS(Solaris, "solaris", "SunOS")
-TRIPLE_OS(UEFI, "uefi", "Generic")
-TRIPLE_OS(Win32, "windows", "Windows")
+TRIPLE_OS(Managarm, "managarm")
+TRIPLE_OS(NetBSD, "netbsd")
+TRIPLE_OS(OpenBSD, "openbsd")
+TRIPLE_OS(Solaris, "solaris")
+TRIPLE_OS(UEFI, "uefi")
+TRIPLE_OS(Win32, "windows")
TRIPLE_OS_ALIAS(Win32, "win32")
-TRIPLE_OS(ZOS, "zos", "OS390")
-TRIPLE_OS(Haiku, "haiku", "Haiku")
-TRIPLE_OS(RTEMS, "rtems", "RTEMS")
-TRIPLE_OS(AIX, "aix", "AIX")
-TRIPLE_OS(CUDA, "cuda", "Generic")
-TRIPLE_OS(NVCL, "nvcl", "Generic")
-TRIPLE_OS(AMDHSA, "amdhsa", "Generic")
-TRIPLE_OS(PS4, "ps4", "Generic")
-TRIPLE_OS(PS5, "ps5", "Generic")
-TRIPLE_OS(ELFIAMCU, "elfiamcu", "Generic")
-TRIPLE_OS(TvOS, "tvos", "tvOS")
-TRIPLE_OS(WatchOS, "watchos", "watchOS")
-TRIPLE_OS(BridgeOS, "bridgeos", "Darwin")
-TRIPLE_OS(DriverKit, "driverkit", "Darwin")
-TRIPLE_OS(XROS, "xros", "visionOS")
+TRIPLE_OS(ZOS, "zos")
+TRIPLE_OS(Haiku, "haiku")
+TRIPLE_OS(RTEMS, "rtems")
+TRIPLE_OS(AIX, "aix")
+TRIPLE_OS(CUDA, "cuda")
+TRIPLE_OS(NVCL, "nvcl")
+TRIPLE_OS(AMDHSA, "amdhsa")
+TRIPLE_OS(PS4, "ps4")
+TRIPLE_OS(PS5, "ps5")
+TRIPLE_OS(ELFIAMCU, "elfiamcu")
+TRIPLE_OS(TvOS, "tvos")
+TRIPLE_OS(WatchOS, "watchos")
+TRIPLE_OS(BridgeOS, "bridgeos")
+TRIPLE_OS(DriverKit, "driverkit")
+TRIPLE_OS(XROS, "xros")
TRIPLE_OS_ALIAS(XROS, "visionos")
-TRIPLE_OS(Mesa3D, "mesa3d", "Generic")
-TRIPLE_OS(AMDPAL, "amdpal", "Generic")
-TRIPLE_OS(HermitCore, "hermit", "Generic")
-TRIPLE_OS(Hurd, "hurd", "GNU")
-TRIPLE_OS(WASIp1, "wasip1", "WASI")
-TRIPLE_OS(WASIp2, "wasip2", "WASI")
-TRIPLE_OS(WASIp3, "wasip3", "WASI")
-TRIPLE_OS(WASI, "wasi", "WASI")
-TRIPLE_OS(Emscripten, "emscripten", "Emscripten")
-TRIPLE_OS(ShaderModel, "shadermodel", "Generic")
-TRIPLE_OS(LiteOS, "liteos", "Generic")
-TRIPLE_OS(Serenity, "serenity", "SerenityOS")
-TRIPLE_OS(Vulkan, "vulkan", "Generic")
-TRIPLE_OS(CheriotRTOS, "cheriotrtos", "Generic")
-TRIPLE_OS(OpenCL, "opencl", "Generic")
-TRIPLE_OS(ChipStar, "chipstar", "Generic")
-TRIPLE_OS(Firmware, "firmware", "Generic")
-TRIPLE_OS(QURT, "qurt", "Generic")
-TRIPLE_OS(H2, "h2", "Generic")
+TRIPLE_OS(Mesa3D, "mesa3d")
+TRIPLE_OS(AMDPAL, "amdpal")
+TRIPLE_OS(HermitCore, "hermit")
+TRIPLE_OS(Hurd, "hurd")
+TRIPLE_OS(WASIp1, "wasip1")
+TRIPLE_OS(WASIp2, "wasip2")
+TRIPLE_OS(WASIp3, "wasip3")
+TRIPLE_OS(WASI, "wasi")
+TRIPLE_OS(Emscripten, "emscripten")
+TRIPLE_OS(ShaderModel, "shadermodel")
+TRIPLE_OS(LiteOS, "liteos")
+TRIPLE_OS(Serenity, "serenity")
+TRIPLE_OS(Vulkan, "vulkan")
+TRIPLE_OS(CheriotRTOS, "cheriotrtos")
+TRIPLE_OS(OpenCL, "opencl")
+TRIPLE_OS(ChipStar, "chipstar")
+TRIPLE_OS(Firmware, "firmware")
+TRIPLE_OS(QURT, "qurt")
+TRIPLE_OS(H2, "h2")
#undef TRIPLE_OS
#undef TRIPLE_OS_ALIAS
@@ -94,73 +88,71 @@ TRIPLE_OS(H2, "h2", "Generic")
//===----------------------------------------------------------------------===//
// Environment names.
//
-// TRIPLE_ENV(Enum, Name, CMakeOverride)
-// Enum - the Triple::EnvironmentType enumerator.
-// Name - the canonical string
-// CMakeOverride - a CMake system name this environment forces regardless of
-// the OS, or "" for no override
+// TRIPLE_ENV(Enum, Name)
+// Enum - the Triple::EnvironmentType enumerator.
+// Name - the canonical string
//
// Order is significant for the same prefix-matching reason as OS (eabihf before
// eabi; the gnu*/musl* variants before gnu/musl).
//===----------------------------------------------------------------------===//
#ifndef TRIPLE_ENV
-#define TRIPLE_ENV(Enum, Name, CMakeOverride)
+#define TRIPLE_ENV(Enum, Name)
#endif
-TRIPLE_ENV(EABIHF, "eabihf", "")
-TRIPLE_ENV(EABI, "eabi", "")
-TRIPLE_ENV(GNUABIN32, "gnuabin32", "")
-TRIPLE_ENV(GNUABI64, "gnuabi64", "")
-TRIPLE_ENV(GNUEABIHFT64, "gnueabihft64", "")
-TRIPLE_ENV(GNUEABIHF, "gnueabihf", "")
-TRIPLE_ENV(GNUEABIT64, "gnueabit64", "")
-TRIPLE_ENV(GNUEABI, "gnueabi", "")
-TRIPLE_ENV(GNUF32, "gnuf32", "")
-TRIPLE_ENV(GNUF64, "gnuf64", "")
-TRIPLE_ENV(GNUSF, "gnusf", "")
-TRIPLE_ENV(GNUX32, "gnux32", "")
-TRIPLE_ENV(GNUILP32, "gnu_ilp32", "")
-TRIPLE_ENV(CODE16, "code16", "")
-TRIPLE_ENV(GNUT64, "gnut64", "")
-TRIPLE_ENV(GNU, "gnu", "")
-TRIPLE_ENV(Android, "android", "Android")
-TRIPLE_ENV(MuslABIN32, "muslabin32", "")
-TRIPLE_ENV(MuslABI64, "muslabi64", "")
-TRIPLE_ENV(MuslEABIHF, "musleabihf", "")
-TRIPLE_ENV(MuslEABI, "musleabi", "")
-TRIPLE_ENV(MuslF32, "muslf32", "")
-TRIPLE_ENV(MuslSF, "muslsf", "")
-TRIPLE_ENV(MuslX32, "muslx32", "")
-TRIPLE_ENV(MuslWALI, "muslwali", "")
-TRIPLE_ENV(Musl, "musl", "")
-TRIPLE_ENV(MSVC, "msvc", "")
-TRIPLE_ENV(Itanium, "itanium", "")
-TRIPLE_ENV(Cygnus, "cygnus", "CYGWIN")
-TRIPLE_ENV(CoreCLR, "coreclr", "")
-TRIPLE_ENV(Simulator, "simulator", "")
-TRIPLE_ENV(MacABI, "macabi", "")
-TRIPLE_ENV(Pixel, "pixel", "")
-TRIPLE_ENV(Vertex, "vertex", "")
-TRIPLE_ENV(Geometry, "geometry", "")
-TRIPLE_ENV(Hull, "hull", "")
-TRIPLE_ENV(Domain, "domain", "")
-TRIPLE_ENV(Compute, "compute", "")
-TRIPLE_ENV(Library, "library", "")
-TRIPLE_ENV(RayGeneration, "raygeneration", "")
-TRIPLE_ENV(Intersection, "intersection", "")
-TRIPLE_ENV(AnyHit, "anyhit", "")
-TRIPLE_ENV(ClosestHit, "closesthit", "")
-TRIPLE_ENV(Miss, "miss", "")
-TRIPLE_ENV(Callable, "callable", "")
-TRIPLE_ENV(Mesh, "mesh", "")
-TRIPLE_ENV(Amplification, "amplification", "")
-TRIPLE_ENV(RootSignature, "rootsignature", "")
-TRIPLE_ENV(OpenHOS, "ohos", "")
-TRIPLE_ENV(PAuthTest, "pauthtest", "")
-TRIPLE_ENV(LLVM, "llvm", "")
-TRIPLE_ENV(Mlibc, "mlibc", "")
-TRIPLE_ENV(MTIA, "mtia", "")
+TRIPLE_ENV(EABIHF, "eabihf")
+TRIPLE_ENV(EABI, "eabi")
+TRIPLE_ENV(GNUABIN32, "gnuabin32")
+TRIPLE_ENV(GNUABI64, "gnuabi64")
+TRIPLE_ENV(GNUEABIHFT64, "gnueabihft64")
+TRIPLE_ENV(GNUEABIHF, "gnueabihf")
+TRIPLE_ENV(GNUEABIT64, "gnueabit64")
+TRIPLE_ENV(GNUEABI, "gnueabi")
+TRIPLE_ENV(GNUF32, "gnuf32")
+TRIPLE_ENV(GNUF64, "gnuf64")
+TRIPLE_ENV(GNUSF, "gnusf")
+TRIPLE_ENV(GNUX32, "gnux32")
+TRIPLE_ENV(GNUILP32, "gnu_ilp32")
+TRIPLE_ENV(CODE16, "code16")
+TRIPLE_ENV(GNUT64, "gnut64")
+TRIPLE_ENV(GNU, "gnu")
+TRIPLE_ENV(Android, "android")
+TRIPLE_ENV(MuslABIN32, "muslabin32")
+TRIPLE_ENV(MuslABI64, "muslabi64")
+TRIPLE_ENV(MuslEABIHF, "musleabihf")
+TRIPLE_ENV(MuslEABI, "musleabi")
+TRIPLE_ENV(MuslF32, "muslf32")
+TRIPLE_ENV(MuslSF, "muslsf")
+TRIPLE_ENV(MuslX32, "muslx32")
+TRIPLE_ENV(MuslWALI, "muslwali")
+TRIPLE_ENV(Musl, "musl")
+TRIPLE_ENV(MSVC, "msvc")
+TRIPLE_ENV(Itanium, "itanium")
+TRIPLE_ENV(Cygnus, "cygnus")
+TRIPLE_ENV(CoreCLR, "coreclr")
+TRIPLE_ENV(Simulator, "simulator")
+TRIPLE_ENV(MacABI, "macabi")
+TRIPLE_ENV(Pixel, "pixel")
+TRIPLE_ENV(Vertex, "vertex")
+TRIPLE_ENV(Geometry, "geometry")
+TRIPLE_ENV(Hull, "hull")
+TRIPLE_ENV(Domain, "domain")
+TRIPLE_ENV(Compute, "compute")
+TRIPLE_ENV(Library, "library")
+TRIPLE_ENV(RayGeneration, "raygeneration")
+TRIPLE_ENV(Intersection, "intersection")
+TRIPLE_ENV(AnyHit, "anyhit")
+TRIPLE_ENV(ClosestHit, "closesthit")
+TRIPLE_ENV(Miss, "miss")
+TRIPLE_ENV(Callable, "callable")
+TRIPLE_ENV(Mesh, "mesh")
+TRIPLE_ENV(Amplification, "amplification")
+TRIPLE_ENV(RootSignature, "rootsignature")
+TRIPLE_ENV(OpenHOS, "ohos")
+TRIPLE_ENV(PAuthTest, "pauthtest")
+TRIPLE_ENV(LLVM, "llvm")
+TRIPLE_ENV(Mlibc, "mlibc")
+TRIPLE_ENV(MTIA, "mtia")
#undef TRIPLE_ENV
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index fb54408c0729f..b9b6a04f04137 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -393,7 +393,7 @@ StringRef Triple::getOSTypeName(OSType Kind) {
switch (Kind) {
case UnknownOS:
return "unknown";
-#define TRIPLE_OS(Enum, Name, CMakeName) \
+#define TRIPLE_OS(Enum, Name) \
case Enum: \
return Name;
#include "llvm/TargetParser/TripleName.def"
@@ -406,7 +406,7 @@ StringRef Triple::getEnvironmentTypeName(EnvironmentType Kind) {
switch (Kind) {
case UnknownEnvironment:
return "unknown";
-#define TRIPLE_ENV(Enum, Name, CMakeOverride) \
+#define TRIPLE_ENV(Enum, Name) \
case Enum: \
return Name;
#include "llvm/TargetParser/TripleName.def"
@@ -705,7 +705,7 @@ static Triple::VendorType parseVendor(StringRef VendorName) {
static Triple::OSType parseOS(StringRef OSName) {
return StringSwitch<Triple::OSType>(OSName)
-#define TRIPLE_OS(Enum, Name, CMakeName) .StartsWith(Name, Triple::Enum)
+#define TRIPLE_OS(Enum, Name) .StartsWith(Name, Triple::Enum)
#define TRIPLE_OS_ALIAS(Enum, AliasName) .StartsWith(AliasName, Triple::Enum)
#include "llvm/TargetParser/TripleName.def"
.Default(Triple::UnknownOS);
@@ -713,7 +713,7 @@ static Triple::OSType parseOS(StringRef OSName) {
static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) {
return StringSwitch<Triple::EnvironmentType>(EnvironmentName)
-#define TRIPLE_ENV(Enum, Name, CMakeOverride) .StartsWith(Name, Triple::Enum)
+#define TRIPLE_ENV(Enum, Name) .StartsWith(Name, Triple::Enum)
#include "llvm/TargetParser/TripleName.def"
.Default(Triple::UnknownEnvironment);
}
diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py
index d8913b1fbdc87..0adde7144b0d9 100644
--- a/llvm/test/lit.cfg.py
+++ b/llvm/test/lit.cfg.py
@@ -239,6 +239,7 @@ def get_asan_rtlib():
ToolSubst("%llvm-bitcode-strip", FindTool("llvm-bitcode-strip")),
ToolSubst("%llvm-extract-bundle-entry", FindTool("llvm-extract-bundle-entry")),
ToolSubst("%split-file", FindTool("split-file")),
+ ToolSubst("%cmake", config.cmake_command, unresolved="ignore"),
]
# FIXME: Why do we have both `lli` and `%lli` that do slightly different things?
diff --git a/llvm/test/lit.site.cfg.py.in b/llvm/test/lit.site.cfg.py.in
index 60b22ef5a7a85..d3fa24b243bd0 100644
--- a/llvm/test/lit.site.cfg.py.in
+++ b/llvm/test/lit.site.cfg.py.in
@@ -17,6 +17,7 @@ config.llvm_exe_ext = "@EXEEXT@"
config.lit_tools_dir = path(r"@LLVM_LIT_TOOLS_DIR@")
config.errc_messages = "@LLVM_LIT_ERRC_MESSAGES@"
config.python_executable = "@Python3_EXECUTABLE@"
+config.cmake_command = "@CMAKE_COMMAND@"
config.gold_executable = "@GOLD_EXECUTABLE@"
config.ld_bfd_executable = "@LD_BFD_EXECUTABLE@"
config.ld64_executable = "@LD64_EXECUTABLE@"
diff --git a/llvm/test/tools/TargetParser/get-triple-cmake-system-name.cmake b/llvm/test/tools/TargetParser/get-triple-cmake-system-name.cmake
new file mode 100644
index 0000000000000..ac75a38901f2b
--- /dev/null
+++ b/llvm/test/tools/TargetParser/get-triple-cmake-system-name.cmake
@@ -0,0 +1,208 @@
+#===--------------------------------------------------------------------===//
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+#===--------------------------------------------------------------------===//
+
+# Unit test for cmake/Modules/GetTripleCMakeSystemName.cmake. Run via:
+# cmake -P get-triple-cmake-system-name.cmake
+#
+# _get_triple_cmake_system_name_raw must classify the same OS that
+# Triple::normalize picks, including for the unnormalized/legacy triple
+# shapes the runtimes build may feed in. The final block guards against the
+# OS/environment tables drifting out of sync with TripleName.def.
+
+cmake_minimum_required(VERSION 3.20)
+
+# This script lives in llvm/test/tools/TargetParser/; the module is under the
+# top-level cmake/, and TripleName.def under llvm/include/.
+get_filename_component(_llvm_dir "${CMAKE_CURRENT_LIST_DIR}/../../.." ABSOLUTE)
+get_filename_component(_project_dir "${_llvm_dir}/.." ABSOLUTE)
+
+include("${_project_dir}/cmake/Modules/GetTripleCMakeSystemName.cmake")
+
+# Accumulate failures in a global property so it survives function scopes; the
+# final OK marker is only printed when it stays zero. This matters because the
+# lit test pipes into FileCheck, which would otherwise miss a non-zero exit.
+set_property(GLOBAL PROPERTY _gtcsn_failures 0)
+
+function(_fail msg)
+ message(SEND_ERROR "${msg}")
+ get_property(_n GLOBAL PROPERTY _gtcsn_failures)
+ math(EXPR _n "${_n} + 1")
+ set_property(GLOBAL PROPERTY _gtcsn_failures "${_n}")
+endfunction()
+
+# Assert the classifier maps triple to expected.
+function(expect triple expected)
+ _get_triple_cmake_system_name_raw("${triple}" got)
+ if(NOT got STREQUAL expected)
+ _fail("'${triple}': got '${got}', expected '${expected}'")
+ endif()
+endfunction()
+
+# Canonical triples, one per interesting mapping.
+expect("x86_64-unknown-linux-gnu" "Linux")
+expect("arm64-apple-darwin" "Darwin")
+expect("s390x-ibm-zos" "OS390")
+expect("aarch64-unknown-linux-android" "Android")
+expect("x86_64-pc-windows-cygnus" "CYGWIN")
+expect("wasm32-unknown-wasip1" "WASI")
+expect("arm64-apple-ios" "iOS")
+expect("riscv64-unknown-elf" "Generic")
+
+# TRIPLE_OS_ALIAS rows resolve to their target OS's CMake name.
+expect("x86_64-apple-macos" "Darwin") # -> MacOSX
+expect("x86_64-pc-win32" "Windows") # -> Win32
+expect("arm64-apple-visionos" "visionOS") # -> XROS
+
+# Vendor omitted / OS or env out of the fixed position, version suffixes, and
+# GCC-legacy spellings.
+expect("aarch64-linux-android21" "Android")
+expect("aarch64-unknown-linux-android21" "Android")
+expect("arm-linux-androideabi" "Android")
+expect("armv7a-linux-androideabi29" "Android")
+expect("x86_64-linux-gnu" "Linux")
+expect("riscv64-linux-gnu" "Linux")
+expect("x86_64-apple-macosx10.15" "Darwin")
+expect("armv7-apple-ios13.0" "iOS")
+expect("x86_64-pc-freebsd14" "FreeBSD")
+
+# The "real-world funky triples" from TripleTest.cpp's Normalization test.
+expect("i386-mingw32" "Windows") # -> i386-unknown-windows-gnu
+expect("i486-linux-gnu" "Linux") # -> i486-unknown-linux-gnu
+expect("i386-redhat-linux" "Linux")
+expect("i686-linux" "Linux")
+expect("arm-none-eabi" "Generic") # no OS
+expect("ve-linux" "Linux")
+expect("wasm32-wasi" "WASI")
+expect("wasm64-wasi" "WASI")
+expect("x86_64-pc-cygwin" "CYGWIN") # -> windows-cygnus
+expect("x86_64-pc-msys" "CYGWIN") # -> windows-cygnus
+expect("x86_64-w64-mingw32" "Windows")
+expect("i686-w64-mingw32" "Windows")
+
+# OS/environment special-cases that Triple::normalize applies.
+expect("x86_64-pc-windows" "Windows")
+expect("x86_64-pc-windows-msvc" "Windows")
+expect("x86_64-pc-windows-gnu" "Windows")
+expect("x86_64-apple-macosx" "Darwin")
+expect("arm-apple-darwin" "Darwin")
+expect("arm-apple-ios" "iOS")
+expect("arm-apple-tvos" "tvOS")
+expect("arm-apple-watchos" "watchOS")
+expect("arm-apple-xros" "visionOS")
+expect("arm-apple-driverkit" "Darwin")
+expect("arm-apple-bridgeos" "Darwin")
+expect("arm-apple-firmware" "Darwin")
+
+# firmware has no dedicated CMake name and only maps to Darwin for the apple
+# vendor; any other vendor is Generic.
+expect("arm-none-firmware" "Generic")
+expect("arm-unknown-firmware" "Generic")
+expect("arm-pc-firmware" "Generic")
+
+# driverkit and bridgeos are always Apple, so they map to Darwin regardless of
+# the vendor component.
+foreach(_os driverkit bridgeos)
+ foreach(_vendor apple none unknown pc)
+ expect("arm-${_vendor}-${_os}" "Darwin")
+ endforeach()
+endforeach()
+
+# A lone OS component with no arch is a valid clang target (e.g.
+# --target=darwin -> unknown-unknown-darwin), so it classifies by the first
+# (and only) component.
+expect("darwin" "Darwin")
+expect("linux" "Linux")
+expect("ios" "iOS")
+expect("freebsd" "FreeBSD")
+expect("wasi" "WASI")
+expect("zos" "OS390")
+expect("mingw32" "Windows")
+expect("cygwin" "CYGWIN")
+
+# Only when no component classifies as an OS does the classifier return empty
+# (the caller then falls back to the host system name).
+expect("x86_64" "")
+expect("arm-none" "")
+
+# Data-driven: a canonical arch-unknown-<os> triple maps to the CMake name the
+# module declares for every OS/alias row.
+_gtcsn_populate_tables()
+list(LENGTH _GTCSN_OS_NAMES _nos)
+math(EXPR _last_os "${_nos} - 1")
+foreach(_i RANGE ${_last_os})
+ list(GET _GTCSN_OS_NAMES ${_i} _name)
+ list(GET _GTCSN_OS_CMAKE ${_i} _cmake)
+ expect("arch-unknown-${_name}" "${_cmake}")
+endforeach()
+
+# A name that is a prefix of a LATER name would shadow it under prefix matching,
+# so within each table a name must never be a prefix of an earlier one.
+function(check_prefix_order)
+ foreach(_list _GTCSN_OS_NAMES _GTCSN_ENV_NAMES)
+ set(_names "${${_list}}")
+ list(LENGTH _names _n)
+ math(EXPR _last "${_n} - 1")
+ foreach(_i RANGE ${_last})
+ list(GET _names ${_i} _short)
+ math(EXPR _next "${_i} + 1")
+ if(_next GREATER _last)
+ continue()
+ endif()
+ foreach(_j RANGE ${_next} ${_last})
+ list(GET _names ${_j} _longer)
+ string(FIND "${_longer}" "${_short}" _pos)
+ if(_pos EQUAL 0 AND NOT _longer STREQUAL _short)
+ _fail("${_list}: '${_short}' precedes and shadows '${_longer}'")
+ endif()
+ endforeach()
+ endforeach()
+ endforeach()
+endfunction()
+check_prefix_order()
+
+# Drift guard: every OS/alias name in TripleName.def must have a mapping entry
+# in the module, and every environment override the module relies on must still
+# name a real environment in the .def. The CMake system names themselves live
+# only in the module (they are a CMake property, not part of llvm::Triple), so
+# the .def is only cross-checked for the set of recognized names.
+set(_def "${_llvm_dir}/include/llvm/TargetParser/TripleName.def")
+if(NOT EXISTS "${_def}")
+ message(FATAL_ERROR "TripleName.def not found at ${_def}")
+endif()
+
+file(STRINGS "${_def}" _os_lines REGEX "^[ \t]*TRIPLE_OS(_ALIAS)?\\(")
+foreach(_line IN LISTS _os_lines)
+ if(_line MATCHES "\"([^\"]+)\"")
+ set(_name "${CMAKE_MATCH_1}")
+ if(NOT _name IN_LIST _GTCSN_OS_NAMES)
+ _fail("TripleName.def OS '${_name}' has no CMake system-name mapping "
+ "in GetTripleCMakeSystemName.cmake")
+ endif()
+ endif()
+endforeach()
+
+file(STRINGS "${_def}" _env_lines REGEX "^[ \t]*TRIPLE_ENV\\(")
+set(_def_env_names "")
+foreach(_line IN LISTS _env_lines)
+ if(_line MATCHES "\"([^\"]+)\"")
+ list(APPEND _def_env_names "${CMAKE_MATCH_1}")
+ endif()
+endforeach()
+foreach(_name IN LISTS _GTCSN_ENV_NAMES)
+ if(NOT _name IN_LIST _def_env_names)
+ _fail("GetTripleCMakeSystemName.cmake environment override '${_name}' "
+ "is no longer an environment in TripleName.def")
+ endif()
+endforeach()
+
+get_property(_failures GLOBAL PROPERTY _gtcsn_failures)
+if(_failures GREATER 0)
+ message(FATAL_ERROR "${_failures} case(s) failed")
+endif()
+
+message(STATUS "get-triple-cmake-system-name: OK")
diff --git a/llvm/test/tools/TargetParser/get-triple-system-name.test b/llvm/test/tools/TargetParser/get-triple-system-name.test
index db1d0cb3aa92e..001c073dcfc23 100644
--- a/llvm/test/tools/TargetParser/get-triple-system-name.test
+++ b/llvm/test/tools/TargetParser/get-triple-system-name.test
@@ -1,6 +1,7 @@
-# Run the unit tests for get_triple_system_name.py, which parses
-# TripleName.def and must stay in sync with llvm::Triple.
+# Unit test for cmake/Modules/GetTripleCMakeSystemName.cmake, which maps a
+# target triple to a CMake system name and must stay in sync with the OS and
+# environment tables in TripleName.def.
-# RUN: %python %S/get_triple_system_name_test.py 2>&1 | FileCheck %s
+# RUN: %cmake -P %S/get-triple-cmake-system-name.cmake 2>&1 | FileCheck %s
-# CHECK: OK
+# CHECK: get-triple-cmake-system-name: OK
diff --git a/llvm/test/tools/TargetParser/get_triple_system_name_test.py b/llvm/test/tools/TargetParser/get_triple_system_name_test.py
deleted file mode 100644
index c6ffd1c7fbe6d..0000000000000
--- a/llvm/test/tools/TargetParser/get_triple_system_name_test.py
+++ /dev/null
@@ -1,206 +0,0 @@
-# ===----------------------------------------------------------------------===##
-#
-# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-# See https://llvm.org/LICENSE.txt for license information.
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-#
-# ===----------------------------------------------------------------------===##
-"""Tests for get_triple_system_name.
-
-The parser must stay in sync with TripleName.def, and system_name() must
-classify the same OS that Triple::normalize picks, including for the
-unnormalized/legacy triple shapes the runtimes build may feed in.
-"""
-
-import os
-import sys
-import unittest
-
-sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "..", "utils"))
-
-import get_triple_system_name as g
-
-
-class Test(unittest.TestCase):
- def setUp(self):
- self.names = g.parse(g.find_def_file())
-
- def test_all_def_rows_parsed(self):
- # Guard against the regex silently dropping a .def row the C++ accepts.
- with open(g.find_def_file()) as f:
- lines = [l for l in f if "#define" not in l]
-
- def count(macro):
- return sum(1 for l in lines if l.lstrip().startswith(macro + "("))
-
- self.assertEqual(
- len(self.names.os), count("TRIPLE_OS") + count("TRIPLE_OS_ALIAS")
- )
- self.assertEqual(len(self.names.env), count("TRIPLE_ENV"))
-
- def test_prefix_ordering(self):
- # A name that is a prefix of a LATER name would shadow it under the
- # StartsWith matching both the C++ and this script rely on.
- for table in (self.names.os, self.names.env):
- names = [n for n, _ in table]
- for i, short in enumerate(names):
- for longer in names[i + 1 :]:
- self.assertFalse(
- longer.startswith(short) and longer != short,
- f"'{short}' precedes and shadows '{longer}'",
- )
-
- def test_every_os_row(self):
- # Data-driven: a canonical arch-unknown-<os> triple must map to the
- # CMake name the .def declares for every OS (and alias) row. This is
- # the exhaustive counterpart to the hand-picked cases below; it fails
- # automatically when a new OS is added without a CMake mapping.
- for name, cmake_name in self.names.os:
- # firmware/driverkit/bridgeos also have vendor-specific behavior
- # exercised separately; here the plain arch-unknown form suffices.
- triple = f"arch-unknown-{name}"
- self.assertEqual(g.system_name(self.names, triple), cmake_name, triple)
-
- def test_known_triples(self):
- cases = {
- "x86_64-unknown-linux-gnu": "Linux",
- "arm64-apple-darwin": "Darwin",
- "s390x-ibm-zos": "OS390",
- "aarch64-unknown-linux-android": "Android",
- "x86_64-pc-windows-cygnus": "CYGWIN",
- "wasm32-unknown-wasip1": "WASI",
- "arm64-apple-ios": "iOS",
- "riscv64-unknown-elf": "Generic",
- }
- for triple, want in cases.items():
- self.assertEqual(g.system_name(self.names, triple), want, triple)
-
- def test_os_aliases(self):
- # The TRIPLE_OS_ALIAS rows resolve to their target OS's CMake name.
- cases = {
- "x86_64-apple-macos": "Darwin", # -> MacOSX
- "x86_64-pc-win32": "Windows", # -> Win32
- "arm64-apple-visionos": "visionOS", # -> XROS
- }
- for triple, want in cases.items():
- self.assertEqual(g.system_name(self.names, triple), want, triple)
-
- def test_non_canonical_triples(self):
- # Vendor omitted / non-standard, os or env not in the fixed position,
- # version suffixes, and GCC-legacy spellings.
- cases = {
- "aarch64-linux-android21": "Android",
- "aarch64-unknown-linux-android21": "Android",
- "arm-linux-androideabi": "Android",
- "armv7a-linux-androideabi29": "Android",
- # Vendor omitted, os in the vendor slot.
- "x86_64-linux-gnu": "Linux",
- "riscv64-linux-gnu": "Linux",
- # OS version suffix.
- "x86_64-apple-macosx10.15": "Darwin",
- "armv7-apple-ios13.0": "iOS",
- # Non-standard vendor, still resolvable by os component.
- "x86_64-pc-freebsd14": "FreeBSD",
- }
- for triple, want in cases.items():
- self.assertEqual(g.system_name(self.names, triple), want, triple)
-
- def test_matches_normalize_funky_triples(self):
- # The "real-world funky triples" from TripleTest.cpp's Normalization
- # test. system_name must classify the same OS that Triple::normalize
- # picks, including os-in-vendor-slot and GCC-legacy windows spellings
- # (mingw* -> windows-gnu, cygwin*/msys -> windows-cygnus).
- cases = {
- "i386-mingw32": "Windows", # -> i386-unknown-windows-gnu
- "x86_64-linux-gnu": "Linux", # -> x86_64-unknown-linux-gnu
- "i486-linux-gnu": "Linux", # -> i486-unknown-linux-gnu
- "i386-redhat-linux": "Linux", # -> i386-redhat-linux
- "i686-linux": "Linux", # -> i686-unknown-linux
- "arm-none-eabi": "Generic", # -> arm-unknown-none-eabi (no OS)
- "ve-linux": "Linux", # -> ve-unknown-linux
- "wasm32-wasi": "WASI", # -> wasm32-unknown-wasi
- "wasm64-wasi": "WASI", # -> wasm64-unknown-wasi
- "x86_64-pc-cygwin": "CYGWIN", # -> x86_64-pc-windows-cygnus
- "x86_64-pc-msys": "CYGWIN", # -> x86_64-pc-windows-cygnus
- "x86_64-w64-mingw32": "Windows", # -> x86_64-w64-windows-gnu
- "i686-w64-mingw32": "Windows",
- }
- for triple, want in cases.items():
- self.assertEqual(g.system_name(self.names, triple), want, triple)
-
- def test_normalize_special_cases(self):
- # The OS/environment special-cases that Triple::normalize applies, one
- # per category, to ensure the script tracks each rewrite it performs.
- cases = {
- # Win32 normalizes to "windows" regardless of the incoming spelling
- # or msvc/gnu environment.
- "x86_64-pc-windows": "Windows",
- "x86_64-pc-windows-msvc": "Windows",
- "x86_64-pc-windows-gnu": "Windows",
- # mingw* -> windows-gnu; cygwin*/msys -> windows-cygnus.
- "x86_64-w64-mingw32": "Windows",
- "x86_64-pc-cygwin": "CYGWIN",
- "x86_64-pc-msys": "CYGWIN",
- # androideabi keeps the Android environment override.
- "arm-linux-androideabi": "Android",
- # The full Apple OS family. driverkit/bridgeos map to Darwin
- # directly in the table (they are always Apple); firmware has no
- # dedicated CMake name and maps to Darwin via the apple-vendor
- # catch-all.
- "x86_64-apple-macosx": "Darwin",
- "arm-apple-darwin": "Darwin",
- "arm-apple-ios": "iOS",
- "arm-apple-tvos": "tvOS",
- "arm-apple-watchos": "watchOS",
- "arm-apple-xros": "visionOS",
- "arm64-apple-visionos": "visionOS",
- "arm-apple-driverkit": "Darwin",
- "arm-apple-bridgeos": "Darwin",
- "arm-apple-firmware": "Darwin",
- }
- for triple, want in cases.items():
- self.assertEqual(g.system_name(self.names, triple), want, triple)
-
- def test_firmware_requires_apple_vendor(self):
- # firmware has no dedicated CMake name and only maps to Darwin for the
- # apple vendor. With any other vendor it is Generic. (For a non-apple
- # vendor Triple::normalize actually fatal-errors; here we only need to
- # ensure we never claim Darwin.)
- for vendor in ("none", "unknown", "pc"):
- triple = f"arm-{vendor}-firmware"
- self.assertEqual(g.system_name(self.names, triple), "Generic", triple)
-
- def test_driverkit_bridgeos_always_darwin(self):
- # driverkit and bridgeos are always Apple, so they map to Darwin
- # directly in the table regardless of the vendor component.
- for os_name in ("driverkit", "bridgeos"):
- for vendor in ("apple", "none", "unknown", "pc"):
- triple = f"arm-{vendor}-{os_name}"
- self.assertEqual(g.system_name(self.names, triple), "Darwin", triple)
-
- def test_bare_os_no_arch(self):
- # A lone os component with no arch is a valid clang target (e.g.
- # --target=darwin -> unknown-unknown-darwin), so it must classify by
- # the first (and only) component rather than being skipped as the arch.
- cases = {
- "darwin": "Darwin",
- "linux": "Linux",
- "ios": "iOS",
- "freebsd": "FreeBSD",
- "wasi": "WASI",
- "zos": "OS390",
- "mingw32": "Windows",
- "cygwin": "CYGWIN",
- }
- for triple, want in cases.items():
- self.assertEqual(g.system_name(self.names, triple), want, triple)
-
- def test_no_classifiable_os_falls_back(self):
- # Only when no component classifies as an OS does the caller fall back
- # to the host system name.
- self.assertIsNone(g.system_name(self.names, "x86_64"))
- self.assertIsNone(g.system_name(self.names, "arm-none"))
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/llvm/utils/get_triple_system_name.py b/llvm/utils/get_triple_system_name.py
deleted file mode 100755
index 369c57ada4285..0000000000000
--- a/llvm/utils/get_triple_system_name.py
+++ /dev/null
@@ -1,148 +0,0 @@
-#!/usr/bin/env python3
-"""Derive a CMake system name from a target triple.
-
-The recognized OS and environment names are defined in
-llvm/include/llvm/TargetParser/TripleName.def. This script parses that
-file so the CMake runtimes build can map a (possibly unnormalized)
-triple to a CMake system name without running a compiled tool. CMake
-invokes it once per target with --triple and reads the printed name.
-
-Modes:
- --triple TRIPLE Print the CMake system name for TRIPLE (empty if unknown or
- the triple has too few components; the caller then falls back
- to the host system name).
-
-Options:
- --def-file PATH Path to TripleName.def to parse instead of the copy located
- relative to this script (in llvm/include/llvm/TargetParser).
-
-"""
-
-import argparse
-import os
-import re
-import sys
-
-_OS_RE = re.compile(r'^\s*TRIPLE_OS\(\s*(\w+)\s*,\s*"([^"]*)"\s*,\s*"([^"]*)"\s*\)')
-_OS_ALIAS_RE = re.compile(r'^\s*TRIPLE_OS_ALIAS\(\s*(\w+)\s*,\s*"([^"]*)"\s*\)')
-_ENV_RE = re.compile(r'^\s*TRIPLE_ENV\(\s*(\w+)\s*,\s*"([^"]*)"\s*,\s*"([^"]*)"\s*\)')
-
-
-class TripleNames:
- def __init__(self):
- # Ordered lists of (prefix, value) preserving .def order, which matters
- # for prefix matching (longer prefixes precede shorter ones).
- self.os = [] # (name, cmake_name)
- self.env = [] # (name, cmake_override)
-
-
-def find_def_file():
- # This script lives in llvm/utils/, the .def in llvm/include/...
- llvm_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
- return os.path.join(llvm_dir, "include", "llvm", "TargetParser", "TripleName.def")
-
-
-def parse(def_path):
- names = TripleNames()
- with open(def_path) as f:
- lines = f.readlines()
-
- # First pass: map each OS enum to its CMake name so aliases can reuse it.
- os_cmake = {}
- for line in lines:
- if m := _OS_RE.match(line):
- enum, _name, cmake_name = m.groups()
- os_cmake[enum] = cmake_name
-
- # Second pass: build the ordered lists (order matters for prefix matching).
- for line in lines:
- if m := _OS_RE.match(line):
- _enum, name, cmake_name = m.groups()
- names.os.append((name, cmake_name))
- elif m := _OS_ALIAS_RE.match(line):
- enum, alias = m.groups()
- names.os.append((alias, os_cmake.get(enum, "Generic")))
- elif m := _ENV_RE.match(line):
- _enum, name, override = m.groups()
- names.env.append((name, override))
- return names
-
-
-def system_name(names, triple):
- # Mirror the component classification of Triple::normalize: do not
- # trust fixed positions. A triple may omit the vendor
- # (aarch64-linux-android), put the os in the vendor slot
- # (wasm32-wasi, i686-linux), or even be a bare os with no arch at
- # all (clang accepts --target=darwin as unknown-unknown-darwin),
- # so scan every component and use the first that classifies. No
- # arch name is a prefix of any os/env name, so scanning the first
- # component too cannot misclassify a real arch. This makes the
- # result match what normalize would produce even for unnormalized
- # inputs.
- parts = triple.split("-")
-
- # Environment override takes precedence over the OS mapping
- # (e.g. android wins over the linux in aarch64-linux-android), so
- # scan for it first.
- for comp in parts:
- for name, override in names.env:
- if override and comp.startswith(name):
- return override
-
- # Find the first component that classifies as an OS. A specific
- # (non-Generic) name wins immediately. A "Generic" match means the
- # component is a recognized OS with no CMake equivalent.
- found_generic_os = False
- for comp in parts:
- matched = False
- for name, cmake_name in names.os:
- if comp.startswith(name):
- if cmake_name != "Generic":
- return cmake_name
- found_generic_os = True
- matched = True
- break
- if matched:
- break
-
- # Handle special case legacy os spellings that normalize rewrites
- # to windows.
- for comp in parts:
- if comp.startswith("mingw"):
- return "Windows"
- if comp.startswith("cygwin") or comp.startswith("msys"):
- return "CYGWIN"
-
- # Apple vendor triples with no specific CMake OS name (e.g.
- # firmware) map to Darwin.
- if len(parts) > 1 and parts[1] == "apple":
- return "Darwin"
-
- if found_generic_os:
- return "Generic"
-
- # No OS could be identified. Too few components to have one -> let
- # the caller fall back to the host system name.
- if len(parts) < 3:
- return None
- return "Generic"
-
-
-def main():
- ap = argparse.ArgumentParser(description=__doc__)
- ap.add_argument("--def-file", default=None, help="Path to TripleName.def")
- ap.add_argument(
- "--triple", required=True, help="Print the CMake system name for this triple"
- )
- args = ap.parse_args()
-
- def_path = args.def_file or find_def_file()
- names = parse(def_path)
-
- result = system_name(names, args.triple)
- print(result if result is not None else "")
- return 0
-
-
-if __name__ == "__main__":
- sys.exit(main())
More information about the llvm-commits
mailing list