| # ------------------------------------------------------------------------------ | 
 | # Architecture and OS definitions. | 
 | # | 
 | # The correct target OS and architecture to build the libc for is deduced here. | 
 | # When possible, we also setup appropriate compile options for the target | 
 | # platform. | 
 | # ------------------------------------------------------------------------------ | 
 |  | 
 | if(MSVC) | 
 |   # If the compiler is visual c++ or equivalent, we will assume a host build. | 
 |   set(LIBC_TARGET_OS ${CMAKE_HOST_SYSTEM_NAME}) | 
 |   string(TOLOWER ${LIBC_TARGET_OS} LIBC_TARGET_OS) | 
 |   set(LIBC_TARGET_ARCHITECTURE ${CMAKE_HOST_SYSTEM_PROCESSOR}) | 
 |   if(LIBC_TARGET_TRIPLE) | 
 |     message(WARNING "libc build: Detected MSVC or equivalent compiler; " | 
 |                     "LIBC_TARGET_TRIPLE is ignored and a host build is assumed.") | 
 |   endif() | 
 |   return() | 
 | endif() | 
 |  | 
 | # A helper function to get the architecture and system components from a target | 
 | # triple. | 
 | function(get_arch_and_system_from_triple triple arch_var sys_var) | 
 |   string(REPLACE "-" ";" triple_comps ${triple}) | 
 |   list(LENGTH triple_comps triple_size) | 
 |   if(triple_size LESS "3") | 
 |     return() | 
 |   endif() | 
 |   math(EXPR system_index "${triple_size} - 2") | 
 |   list(GET triple_comps 0 target_arch) | 
 |   # The target_arch string can have sub-architecture suffixes which we want to | 
 |   # remove. So, we regex-match the string and set target_arch to a cleaner | 
 |   # value. | 
 |   if(target_arch MATCHES "^mips") | 
 |     set(target_arch "mips") | 
 |   elseif(target_arch MATCHES "^aarch64|^arm64") | 
 |     set(target_arch "aarch64") | 
 |   elseif(target_arch MATCHES "^arm") | 
 |     set(target_arch "arm") | 
 |   elseif(target_arch MATCHES "(x86_64)|(AMD64|amd64)") | 
 |     set(target_arch "x86_64") | 
 |   elseif(target_arch MATCHES "(^i.86$)") | 
 |     set(target_arch "i386") | 
 |   elseif(target_arch MATCHES "^(powerpc|ppc)") | 
 |     set(target_arch "power") | 
 |   elseif(target_arch MATCHES "^riscv32") | 
 |     set(target_arch "riscv32") | 
 |   elseif(target_arch MATCHES "^riscv64") | 
 |     set(target_arch "riscv64") | 
 |   elseif(target_arch MATCHES "^amdgcn") | 
 |     set(target_arch "amdgpu") | 
 |   elseif(target_arch MATCHES "^nvptx64") | 
 |     set(target_arch "nvptx") | 
 |   elseif(target_arch MATCHES "^spirv64") | 
 |     set(target_arch "spirv64") | 
 |   else() | 
 |     return() | 
 |   endif() | 
 |  | 
 |   set(${arch_var} ${target_arch} PARENT_SCOPE) | 
 |   list(GET triple_comps ${system_index} target_sys) | 
 |  | 
 |   # Correcting OS name for Apple's systems. | 
 |   if(target_sys STREQUAL "apple") | 
 |     list(GET triple_comps 2 target_sys) | 
 |   endif() | 
 |   # Strip version from `darwin###` | 
 |   if(target_sys MATCHES "^darwin") | 
 |     set(target_sys "darwin") | 
 |   endif() | 
 |  | 
 |   # Setting OS name for GPU architectures. | 
 |   list(GET triple_comps -1 gpu_target_sys) | 
 |   if(gpu_target_sys MATCHES "^amdhsa" OR gpu_target_sys MATCHES "^cuda") | 
 |     set(target_sys "gpu") | 
 |   endif() | 
 |  | 
 |   set(${sys_var} ${target_sys} PARENT_SCOPE) | 
 | endfunction(get_arch_and_system_from_triple) | 
 |  | 
 | execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version -v | 
 |                 RESULT_VARIABLE libc_compiler_info_result | 
 |                 OUTPUT_VARIABLE libc_compiler_info | 
 |                 ERROR_VARIABLE libc_compiler_info) | 
 | if(NOT (libc_compiler_info_result EQUAL "0")) | 
 |   message(FATAL_ERROR "libc build: error querying compiler info from the " | 
 |                       "compiler: ${libc_compiler_info}") | 
 | endif() | 
 | string(REGEX MATCH "Target: [-_a-zA-Z0-9.]+[ \r\n]+" | 
 |        libc_compiler_target_info ${libc_compiler_info}) | 
 | if(NOT libc_compiler_target_info) | 
 |   message(FATAL_ERROR "libc build: could not read compiler target info from:\n" | 
 |                       "${libc_compiler_info}") | 
 | endif() | 
 | string(STRIP ${libc_compiler_target_info} libc_compiler_target_info) | 
 | string(SUBSTRING ${libc_compiler_target_info} 8 -1 libc_compiler_triple) | 
 | get_arch_and_system_from_triple(${libc_compiler_triple} | 
 |                                 compiler_arch compiler_sys) | 
 | if(NOT compiler_arch) | 
 |   message(FATAL_ERROR | 
 |           "libc build: Invalid or unknown libc compiler target triple: " | 
 |           "${libc_compiler_triple}") | 
 | endif() | 
 |  | 
 | set(LIBC_TARGET_ARCHITECTURE ${compiler_arch}) | 
 | set(LIBC_TARGET_OS ${compiler_sys}) | 
 | set(LIBC_CROSSBUILD FALSE) | 
 |  | 
 | # One should not set LLVM_RUNTIMES_TARGET and LIBC_TARGET_TRIPLE | 
 | if(LLVM_RUNTIMES_TARGET AND LIBC_TARGET_TRIPLE) | 
 |   message(FATAL_ERROR | 
 |           "libc build: Specify only LLVM_RUNTIMES_TARGET if you are doing a " | 
 |           "runtimes/bootstrap build. If you are doing a standalone build, " | 
 |           "specify only LIBC_TARGET_TRIPLE.") | 
 | endif() | 
 |  | 
 | set(explicit_target_triple) | 
 | if(LLVM_RUNTIMES_TARGET) | 
 |   set(explicit_target_triple ${LLVM_RUNTIMES_TARGET}) | 
 | elseif(LIBC_TARGET_TRIPLE) | 
 |   set(explicit_target_triple ${LIBC_TARGET_TRIPLE}) | 
 | endif() | 
 |  | 
 | # The libc's target architecture and OS are set to match the compiler's default | 
 | # target triple above. However, one can explicitly set LIBC_TARGET_TRIPLE or | 
 | # LLVM_RUNTIMES_TARGET (for runtimes/bootstrap build). If one of them is set, | 
 | # then we will use that target triple to deduce libc's target OS and | 
 | # architecture. | 
 | if(explicit_target_triple) | 
 |   get_arch_and_system_from_triple(${explicit_target_triple} libc_arch libc_sys) | 
 |   if(NOT libc_arch) | 
 |     message(FATAL_ERROR | 
 |             "libc build: Invalid or unknown triple: ${explicit_target_triple}") | 
 |   endif() | 
 |   set(LIBC_TARGET_ARCHITECTURE ${libc_arch}) | 
 |   set(LIBC_TARGET_OS ${libc_sys}) | 
 | endif() | 
 |  | 
 | if((LIBC_TARGET_OS STREQUAL "unknown") OR (LIBC_TARGET_OS STREQUAL "none")) | 
 |   # We treat "unknown" and "none" systems as baremetal targets. | 
 |   set(LIBC_TARGET_OS "baremetal") | 
 | endif() | 
 |  | 
 | # Set up some convenient vars to make conditionals easy to use in other parts of | 
 | # the libc CMake infrastructure. Also, this is where we also check if the target | 
 | # architecture is currently supported. | 
 | if(LIBC_TARGET_ARCHITECTURE STREQUAL "arm") | 
 |   set(LIBC_TARGET_ARCHITECTURE_IS_ARM TRUE) | 
 | elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "aarch64") | 
 |   set(LIBC_TARGET_ARCHITECTURE_IS_AARCH64 TRUE) | 
 | elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "x86_64") | 
 |   set(LIBC_TARGET_ARCHITECTURE_IS_X86_64 TRUE) | 
 | elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "i386") | 
 |   set(LIBC_TARGET_ARCHITECTURE_IS_X86 TRUE) | 
 | elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "riscv64") | 
 |   set(LIBC_TARGET_ARCHITECTURE_IS_RISCV64 TRUE) | 
 |   set(LIBC_TARGET_ARCHITECTURE "riscv") | 
 | elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "riscv32") | 
 |   set(LIBC_TARGET_ARCHITECTURE_IS_RISCV32 TRUE) | 
 |   set(LIBC_TARGET_ARCHITECTURE "riscv") | 
 | elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "amdgpu") | 
 |   set(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU TRUE) | 
 | elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "nvptx") | 
 |   set(LIBC_TARGET_ARCHITECTURE_IS_NVPTX TRUE) | 
 | elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "spirv64") | 
 |   set(LIBC_TARGET_ARCHITECTURE_IS_SPIRV TRUE) | 
 | else() | 
 |   message(FATAL_ERROR | 
 |           "Unsupported libc target architecture ${LIBC_TARGET_ARCHITECTURE}") | 
 | endif() | 
 |  | 
 | if(LIBC_TARGET_OS STREQUAL "baremetal") | 
 |   set(LIBC_TARGET_OS_IS_BAREMETAL TRUE) | 
 | elseif(LIBC_TARGET_OS STREQUAL "linux") | 
 |   set(LIBC_TARGET_OS_IS_LINUX TRUE) | 
 | elseif(LIBC_TARGET_OS STREQUAL "poky" OR LIBC_TARGET_OS STREQUAL "suse" OR | 
 |        LIBC_TARGET_OS STREQUAL "redhat") | 
 |   # poky are custom Linux-base systems created by yocto. Since these are Linux | 
 |   # images, we change the LIBC_TARGET_OS to linux. This define is used to | 
 |   # include the right directories during compilation. | 
 |   # | 
 |   # openSUSE and redhat use different triple format which causes LIBC_TARGET_OS | 
 |   # to be computed as "suse" or "redhat" instead of "linux". | 
 |   set(LIBC_TARGET_OS_IS_LINUX TRUE) | 
 |   set(LIBC_TARGET_OS "linux") | 
 | elseif(LIBC_TARGET_OS STREQUAL "darwin") | 
 |   set(LIBC_TARGET_OS_IS_DARWIN TRUE) | 
 | elseif(LIBC_TARGET_OS STREQUAL "windows") | 
 |   set(LIBC_TARGET_OS_IS_WINDOWS TRUE) | 
 | elseif(LIBC_TARGET_OS STREQUAL "gpu") | 
 |   set(LIBC_TARGET_OS_IS_GPU TRUE) | 
 | elseif(LIBC_TARGET_OS STREQUAL "uefi") | 
 |   set(LIBC_TARGET_OS_IS_UEFI TRUE) | 
 | else() | 
 |   message(FATAL_ERROR | 
 |           "Unsupported libc target operating system ${LIBC_TARGET_OS}") | 
 | endif() | 
 |  | 
 |  | 
 | # If the compiler target triple is not the same as the triple specified by | 
 | # LIBC_TARGET_TRIPLE or LLVM_RUNTIMES_TARGET, we will add a --target option | 
 | # if the compiler is clang. If the compiler is GCC we just error out as there | 
 | # is no equivalent of an option like --target. | 
 | if(explicit_target_triple AND | 
 |    (NOT (libc_compiler_triple STREQUAL explicit_target_triple))) | 
 |   set(LIBC_CROSSBUILD TRUE) | 
 |   if(CMAKE_COMPILER_IS_GNUCXX) | 
 |     message(FATAL_ERROR | 
 |             "GCC target triple (${libc_compiler_triple}) and the explicity " | 
 |             "specified target triple (${explicit_target_triple}) do not match.") | 
 |   else() | 
 |     list(APPEND | 
 |          LIBC_COMPILE_OPTIONS_DEFAULT "--target=${explicit_target_triple}") | 
 |   endif() | 
 | endif() | 
 |  | 
 |  | 
 | # Windows does not support full mode build. | 
 | if (LIBC_TARGET_OS_IS_WINDOWS AND LLVM_LIBC_FULL_BUILD) | 
 |   message(FATAL_ERROR "Windows does not support full mode build.") | 
 | endif () | 
 |  | 
 |  | 
 | message(STATUS | 
 |         "Building libc for ${LIBC_TARGET_ARCHITECTURE} on ${LIBC_TARGET_OS} with | 
 |         LIBC_COMPILE_OPTIONS_DEFAULT: ${LIBC_COMPILE_OPTIONS_DEFAULT}") |