cmake: Derive CMake system name from a triple via new mechanism (#208773)
This commit is contained in:
parent
c27bee245f
commit
6b98f82fe9
6 changed files with 522 additions and 114 deletions
40
cmake/Modules/GetTripleCMakeSystemName.cmake
Normal file
40
cmake/Modules/GetTripleCMakeSystemName.cmake
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#===--------------------------------------------------------------------===//
|
||||
#
|
||||
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
# See https://llvm.org/LICENSE.txt for details.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
#===--------------------------------------------------------------------===//
|
||||
|
||||
# Map a target triple to the corresponding CMake system name.
|
||||
#
|
||||
# Usage:
|
||||
# get_triple_cmake_system_name(<triple> <out_var>)
|
||||
#
|
||||
# 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".
|
||||
#
|
||||
# The OS/environment -> system name data is derived from
|
||||
# llvm/include/llvm/TargetParser/TripleName.def
|
||||
|
||||
get_filename_component(_gtcsn_llvm_dir "${CMAKE_CURRENT_LIST_DIR}/../../llvm"
|
||||
ABSOLUTE)
|
||||
set(_gtcsn_script "${_gtcsn_llvm_dir}/utils/get_triple_system_name.py")
|
||||
|
||||
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}'")
|
||||
endif()
|
||||
if(_name)
|
||||
set(${out_var} "${_name}" PARENT_SCOPE)
|
||||
else()
|
||||
set(${out_var} "${CMAKE_HOST_SYSTEM_NAME}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
|
@ -5,15 +5,21 @@
|
|||
// 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)
|
||||
// Enum - the Triple::OSType enumerator
|
||||
// Name - the canonical string
|
||||
// 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_ALIAS(Enum, AliasName)
|
||||
// An additional prefix maps to an OSType.
|
||||
|
|
@ -23,64 +29,64 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef TRIPLE_OS
|
||||
#define TRIPLE_OS(Enum, Name)
|
||||
#define TRIPLE_OS(Enum, Name, CMakeName)
|
||||
#endif
|
||||
#ifndef TRIPLE_OS_ALIAS
|
||||
#define TRIPLE_OS_ALIAS(Enum, AliasName)
|
||||
#endif
|
||||
|
||||
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(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_ALIAS(MacOSX, "macos")
|
||||
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(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_ALIAS(Win32, "win32")
|
||||
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(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_ALIAS(XROS, "visionos")
|
||||
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")
|
||||
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")
|
||||
|
||||
#undef TRIPLE_OS
|
||||
#undef TRIPLE_OS_ALIAS
|
||||
|
|
@ -88,71 +94,73 @@ TRIPLE_OS(H2, "h2")
|
|||
//===----------------------------------------------------------------------===//
|
||||
// Environment names.
|
||||
//
|
||||
// TRIPLE_ENV(Enum, Name)
|
||||
// Enum - the Triple::EnvironmentType enumerator.
|
||||
// Name - the canonical string
|
||||
// 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
|
||||
//
|
||||
// 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)
|
||||
#define TRIPLE_ENV(Enum, Name, CMakeOverride)
|
||||
#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")
|
||||
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")
|
||||
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", "")
|
||||
|
||||
#undef TRIPLE_ENV
|
||||
|
||||
|
|
|
|||
|
|
@ -392,7 +392,7 @@ StringRef Triple::getOSTypeName(OSType Kind) {
|
|||
switch (Kind) {
|
||||
case UnknownOS:
|
||||
return "unknown";
|
||||
#define TRIPLE_OS(Enum, Name) \
|
||||
#define TRIPLE_OS(Enum, Name, CMakeName) \
|
||||
case Enum: \
|
||||
return Name;
|
||||
#include "llvm/TargetParser/TripleName.def"
|
||||
|
|
@ -405,7 +405,7 @@ StringRef Triple::getEnvironmentTypeName(EnvironmentType Kind) {
|
|||
switch (Kind) {
|
||||
case UnknownEnvironment:
|
||||
return "unknown";
|
||||
#define TRIPLE_ENV(Enum, Name) \
|
||||
#define TRIPLE_ENV(Enum, Name, CMakeOverride) \
|
||||
case Enum: \
|
||||
return Name;
|
||||
#include "llvm/TargetParser/TripleName.def"
|
||||
|
|
@ -703,7 +703,7 @@ static Triple::VendorType parseVendor(StringRef VendorName) {
|
|||
|
||||
static Triple::OSType parseOS(StringRef OSName) {
|
||||
return StringSwitch<Triple::OSType>(OSName)
|
||||
#define TRIPLE_OS(Enum, Name) .StartsWith(Name, Triple::Enum)
|
||||
#define TRIPLE_OS(Enum, Name, CMakeName) .StartsWith(Name, Triple::Enum)
|
||||
#define TRIPLE_OS_ALIAS(Enum, AliasName) .StartsWith(AliasName, Triple::Enum)
|
||||
#include "llvm/TargetParser/TripleName.def"
|
||||
.Default(Triple::UnknownOS);
|
||||
|
|
@ -711,7 +711,7 @@ static Triple::OSType parseOS(StringRef OSName) {
|
|||
|
||||
static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) {
|
||||
return StringSwitch<Triple::EnvironmentType>(EnvironmentName)
|
||||
#define TRIPLE_ENV(Enum, Name) .StartsWith(Name, Triple::Enum)
|
||||
#define TRIPLE_ENV(Enum, Name, CMakeOverride) .StartsWith(Name, Triple::Enum)
|
||||
#include "llvm/TargetParser/TripleName.def"
|
||||
.Default(Triple::UnknownEnvironment);
|
||||
}
|
||||
|
|
|
|||
6
llvm/test/tools/TargetParser/get-triple-system-name.test
Normal file
6
llvm/test/tools/TargetParser/get-triple-system-name.test
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# Run the unit tests for get_triple_system_name.py, which parses
|
||||
# TripleName.def and must stay in sync with llvm::Triple.
|
||||
|
||||
# RUN: "%python" %S/get_triple_system_name_test.py 2>&1 | FileCheck %s
|
||||
|
||||
# CHECK: OK
|
||||
206
llvm/test/tools/TargetParser/get_triple_system_name_test.py
Normal file
206
llvm/test/tools/TargetParser/get_triple_system_name_test.py
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
# ===----------------------------------------------------------------------===##
|
||||
#
|
||||
# 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()
|
||||
148
llvm/utils/get_triple_system_name.py
Executable file
148
llvm/utils/get_triple_system_name.py
Executable file
|
|
@ -0,0 +1,148 @@
|
|||
#!/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())
|
||||
Loading…
Reference in a new issue