1# ------------------------------------------------------------------------------ 2# Architecture and OS definitions. 3# 4# The correct target OS and architecture to build the libc for is deduced here. 5# When possible, we also setup appropriate compile options for the target 6# platform. 7# ------------------------------------------------------------------------------ 8 9if(MSVC) 10 # If the compiler is visual c++ or equivalent, we will assume a host build. 11 set(LIBC_TARGET_OS ${CMAKE_HOST_SYSTEM_NAME}) 12 string(TOLOWER ${LIBC_TARGET_OS} LIBC_TARGET_OS) 13 set(LIBC_TARGET_ARCHITECTURE ${CMAKE_HOST_SYSTEM_PROCESSOR}) 14 if(LIBC_TARGET_TRIPLE) 15 message(WARNING "libc build: Detected MSVC or equivalent compiler; " 16 "LIBC_TARGET_TRIPLE is ignored and a host build is assumed.") 17 endif() 18 return() 19endif() 20 21# A helper function to get the architecture and system components from a target 22# triple. 23function(get_arch_and_system_from_triple triple arch_var sys_var) 24 string(REPLACE "-" ";" triple_comps ${triple}) 25 list(LENGTH triple_comps triple_size) 26 if(triple_size LESS "3") 27 return() 28 endif() 29 math(EXPR system_index "${triple_size} - 2") 30 list(GET triple_comps 0 target_arch) 31 # The target_arch string can have sub-architecture suffixes which we want to 32 # remove. So, we regex-match the string and set target_arch to a cleaner 33 # value. 34 if(target_arch MATCHES "^mips") 35 set(target_arch "mips") 36 elseif(target_arch MATCHES "^arm") 37 # TODO(lntue): Shall we separate `arm64`? It is currently recognized as 38 # `arm` here. 39 set(target_arch "arm") 40 elseif(target_arch MATCHES "^aarch64") 41 set(target_arch "aarch64") 42 elseif(target_arch MATCHES "(x86_64)|(AMD64|amd64)") 43 set(target_arch "x86_64") 44 elseif(target_arch MATCHES "(^i.86$)") 45 set(target_arch "i386") 46 elseif(target_arch MATCHES "^(powerpc|ppc)") 47 set(target_arch "power") 48 elseif(target_arch MATCHES "^riscv32") 49 set(target_arch "riscv32") 50 elseif(target_arch MATCHES "^riscv64") 51 set(target_arch "riscv64") 52 elseif(target_arch MATCHES "^amdgcn") 53 set(target_arch "amdgpu") 54 elseif(target_arch MATCHES "^nvptx64") 55 set(target_arch "nvptx") 56 else() 57 return() 58 endif() 59 60 set(${arch_var} ${target_arch} PARENT_SCOPE) 61 list(GET triple_comps ${system_index} target_sys) 62 63 # Correcting OS name for Apple's systems. 64 if(target_sys STREQUAL "apple") 65 list(GET triple_comps 2 target_sys) 66 endif() 67 # Strip version from `darwin###` 68 if(target_sys MATCHES "^darwin") 69 set(target_sys "darwin") 70 endif() 71 72 # Setting OS name for GPU architectures. 73 list(GET triple_comps -1 gpu_target_sys) 74 if(gpu_target_sys MATCHES "^amdhsa" OR gpu_target_sys MATCHES "^cuda") 75 set(target_sys "gpu") 76 endif() 77 78 set(${sys_var} ${target_sys} PARENT_SCOPE) 79endfunction(get_arch_and_system_from_triple) 80 81execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version -v 82 RESULT_VARIABLE libc_compiler_info_result 83 OUTPUT_VARIABLE libc_compiler_info 84 ERROR_VARIABLE libc_compiler_info) 85if(NOT (libc_compiler_info_result EQUAL "0")) 86 message(FATAL_ERROR "libc build: error querying compiler info from the " 87 "compiler: ${libc_compiler_info}") 88endif() 89string(REGEX MATCH "Target: [-_a-zA-Z0-9.]+[ \r\n]+" 90 libc_compiler_target_info ${libc_compiler_info}) 91if(NOT libc_compiler_target_info) 92 message(FATAL_ERROR "libc build: could not read compiler target info from:\n" 93 "${libc_compiler_info}") 94endif() 95string(STRIP ${libc_compiler_target_info} libc_compiler_target_info) 96string(SUBSTRING ${libc_compiler_target_info} 8 -1 libc_compiler_triple) 97get_arch_and_system_from_triple(${libc_compiler_triple} 98 compiler_arch compiler_sys) 99if(NOT compiler_arch) 100 message(FATAL_ERROR 101 "libc build: Invalid or unknown libc compiler target triple: " 102 "${libc_compiler_triple}") 103endif() 104 105set(LIBC_TARGET_ARCHITECTURE ${compiler_arch}) 106set(LIBC_TARGET_OS ${compiler_sys}) 107set(LIBC_CROSSBUILD FALSE) 108 109# One should not set LLVM_RUNTIMES_TARGET and LIBC_TARGET_TRIPLE 110if(LLVM_RUNTIMES_TARGET AND LIBC_TARGET_TRIPLE) 111 message(FATAL_ERROR 112 "libc build: Specify only LLVM_RUNTIMES_TARGET if you are doing a " 113 "runtimes/bootstrap build. If you are doing a standalone build, " 114 "specify only LIBC_TARGET_TRIPLE.") 115endif() 116 117set(explicit_target_triple) 118if(LLVM_RUNTIMES_TARGET) 119 set(explicit_target_triple ${LLVM_RUNTIMES_TARGET}) 120elseif(LIBC_TARGET_TRIPLE) 121 set(explicit_target_triple ${LIBC_TARGET_TRIPLE}) 122endif() 123 124# The libc's target architecture and OS are set to match the compiler's default 125# target triple above. However, one can explicitly set LIBC_TARGET_TRIPLE or 126# LLVM_RUNTIMES_TARGET (for runtimes/bootstrap build). If one of them is set, 127# then we will use that target triple to deduce libc's target OS and 128# architecture. 129if(explicit_target_triple) 130 get_arch_and_system_from_triple(${explicit_target_triple} libc_arch libc_sys) 131 if(NOT libc_arch) 132 message(FATAL_ERROR 133 "libc build: Invalid or unknown triple: ${explicit_target_triple}") 134 endif() 135 set(LIBC_TARGET_ARCHITECTURE ${libc_arch}) 136 set(LIBC_TARGET_OS ${libc_sys}) 137endif() 138 139if((LIBC_TARGET_OS STREQUAL "unknown") OR (LIBC_TARGET_OS STREQUAL "none")) 140 # We treat "unknown" and "none" systems as baremetal targets. 141 set(LIBC_TARGET_OS "baremetal") 142endif() 143 144# Set up some convenient vars to make conditionals easy to use in other parts of 145# the libc CMake infrastructure. Also, this is where we also check if the target 146# architecture is currently supported. 147if(LIBC_TARGET_ARCHITECTURE STREQUAL "arm") 148 set(LIBC_TARGET_ARCHITECTURE_IS_ARM TRUE) 149elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "aarch64") 150 set(LIBC_TARGET_ARCHITECTURE_IS_AARCH64 TRUE) 151elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "x86_64") 152 set(LIBC_TARGET_ARCHITECTURE_IS_X86_64 TRUE) 153elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "i386") 154 set(LIBC_TARGET_ARCHITECTURE_IS_X86 TRUE) 155elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "riscv64") 156 set(LIBC_TARGET_ARCHITECTURE_IS_RISCV64 TRUE) 157 set(LIBC_TARGET_ARCHITECTURE "riscv") 158elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "riscv32") 159 set(LIBC_TARGET_ARCHITECTURE_IS_RISCV32 TRUE) 160 set(LIBC_TARGET_ARCHITECTURE "riscv") 161elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "amdgpu") 162 set(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU TRUE) 163elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "nvptx") 164 set(LIBC_TARGET_ARCHITECTURE_IS_NVPTX TRUE) 165else() 166 message(FATAL_ERROR 167 "Unsupported libc target architecture ${LIBC_TARGET_ARCHITECTURE}") 168endif() 169 170if(LIBC_TARGET_OS STREQUAL "baremetal") 171 set(LIBC_TARGET_OS_IS_BAREMETAL TRUE) 172elseif(LIBC_TARGET_OS STREQUAL "linux") 173 set(LIBC_TARGET_OS_IS_LINUX TRUE) 174elseif(LIBC_TARGET_OS STREQUAL "poky" OR LIBC_TARGET_OS STREQUAL "suse" OR 175 LIBC_TARGET_OS STREQUAL "redhat") 176 # poky are custom Linux-base systems created by yocto. Since these are Linux 177 # images, we change the LIBC_TARGET_OS to linux. This define is used to 178 # include the right directories during compilation. 179 # 180 # openSUSE and redhat use different triple format which causes LIBC_TARGET_OS 181 # to be computed as "suse" or "redhat" instead of "linux". 182 set(LIBC_TARGET_OS_IS_LINUX TRUE) 183 set(LIBC_TARGET_OS "linux") 184elseif(LIBC_TARGET_OS STREQUAL "darwin") 185 set(LIBC_TARGET_OS_IS_DARWIN TRUE) 186elseif(LIBC_TARGET_OS STREQUAL "windows") 187 set(LIBC_TARGET_OS_IS_WINDOWS TRUE) 188elseif(LIBC_TARGET_OS STREQUAL "gpu") 189 set(LIBC_TARGET_OS_IS_GPU TRUE) 190else() 191 message(FATAL_ERROR 192 "Unsupported libc target operating system ${LIBC_TARGET_OS}") 193endif() 194 195 196# If the compiler target triple is not the same as the triple specified by 197# LIBC_TARGET_TRIPLE or LLVM_RUNTIMES_TARGET, we will add a --target option 198# if the compiler is clang. If the compiler is GCC we just error out as there 199# is no equivalent of an option like --target. 200if(explicit_target_triple AND 201 (NOT (libc_compiler_triple STREQUAL explicit_target_triple))) 202 set(LIBC_CROSSBUILD TRUE) 203 if(CMAKE_COMPILER_IS_GNUCXX) 204 message(FATAL_ERROR 205 "GCC target triple (${libc_compiler_triple}) and the explicity " 206 "specified target triple (${explicit_target_triple}) do not match.") 207 else() 208 list(APPEND 209 LIBC_COMPILE_OPTIONS_DEFAULT "--target=${explicit_target_triple}") 210 endif() 211endif() 212 213 214# Windows does not support full mode build. 215if (LIBC_TARGET_OS_IS_WINDOWS AND LLVM_LIBC_FULL_BUILD) 216 message(FATAL_ERROR "Windows does not support full mode build.") 217endif () 218 219 220message(STATUS 221 "Building libc for ${LIBC_TARGET_ARCHITECTURE} on ${LIBC_TARGET_OS} with 222 LIBC_COMPILE_OPTIONS_DEFAULT: ${LIBC_COMPILE_OPTIONS_DEFAULT}") 223