257 lines · plain
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 target6# 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 target22# 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 to32 # remove. So, we regex-match the string and set target_arch to a cleaner33 # value.34 if(target_arch MATCHES "^mips")35 set(target_arch "mips")36 elseif(target_arch MATCHES "^aarch64|^arm64")37 set(target_arch "aarch64")38 elseif(target_arch MATCHES "^arm")39 set(target_arch "arm")40 elseif(target_arch MATCHES "(x86_64)|(AMD64|amd64)")41 set(target_arch "x86_64")42 elseif(target_arch MATCHES "(^i.86$)")43 set(target_arch "i386")44 elseif(target_arch MATCHES "^(powerpc|ppc)")45 set(target_arch "power")46 elseif(target_arch MATCHES "^riscv32")47 set(target_arch "riscv32")48 elseif(target_arch MATCHES "^riscv64")49 set(target_arch "riscv64")50 elseif(target_arch MATCHES "^amdgcn")51 set(target_arch "amdgpu")52 elseif(target_arch MATCHES "^nvptx64")53 set(target_arch "nvptx")54 elseif(target_arch MATCHES "^spirv64")55 set(target_arch "spirv64")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 -v82 RESULT_VARIABLE libc_compiler_info_result83 OUTPUT_VARIABLE libc_compiler_info84 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)97 98# One should not set LLVM_RUNTIMES_TARGET and LIBC_TARGET_TRIPLE99if(LLVM_RUNTIMES_TARGET AND LIBC_TARGET_TRIPLE)100 message(FATAL_ERROR101 "libc build: Specify only LLVM_RUNTIMES_TARGET if you are doing a "102 "runtimes/bootstrap build. If you are doing a standalone build, "103 "specify only LIBC_TARGET_TRIPLE.")104endif()105 106set(explicit_target_triple)107if(LLVM_RUNTIMES_TARGET)108 set(explicit_target_triple ${LLVM_RUNTIMES_TARGET})109elseif(LIBC_TARGET_TRIPLE)110 set(explicit_target_triple ${LIBC_TARGET_TRIPLE})111endif()112 113# The libc's target architecture and OS are set to match the compiler's default114# target triple above. However, one can explicitly set LIBC_TARGET_TRIPLE or115# LLVM_RUNTIMES_TARGET (for runtimes/bootstrap build). If one of them is set,116# then we will use that target triple to deduce libc's target OS and117# architecture.118if(explicit_target_triple)119 get_arch_and_system_from_triple(${explicit_target_triple} libc_arch libc_sys)120 if(NOT libc_arch OR NOT libc_sys)121 message(FATAL_ERROR122 "libc build: Invalid or unknown triple: ${explicit_target_triple}")123 endif()124 set(LIBC_TARGET_ARCHITECTURE ${libc_arch})125 set(LIBC_TARGET_OS ${libc_sys})126 # If the compiler target triple is not the same as the triple specified by127 # LIBC_TARGET_TRIPLE or LLVM_RUNTIMES_TARGET, we will add a --target option128 # if the compiler is clang. If the compiler is GCC we just error out as there129 # is no equivalent of an option like --target.130 if(NOT libc_compiler_triple STREQUAL explicit_target_triple)131 set(LIBC_CROSSBUILD TRUE)132 if(CMAKE_COMPILER_IS_GNUCXX)133 message(FATAL_ERROR134 "GCC target triple (${libc_compiler_triple}) and the explicity "135 "specified target triple (${explicit_target_triple}) do not match.")136 else()137 list(APPEND138 LIBC_COMPILE_OPTIONS_DEFAULT "--target=${explicit_target_triple}")139 endif()140 else()141 set(LIBC_CROSSBUILD FALSE)142 endif()143else()144 get_arch_and_system_from_triple(${libc_compiler_triple}145 compiler_arch compiler_sys)146 if(NOT compiler_arch OR NOT compiler_sys)147 message(FATAL_ERROR148 "libc build: Unknown compiler default target triple: "149 "${libc_compiler_triple}")150 endif()151 set(LIBC_TARGET_ARCHITECTURE ${compiler_arch})152 set(LIBC_TARGET_OS ${compiler_sys})153 set(LIBC_CROSSBUILD FALSE)154endif()155 156if((LIBC_TARGET_OS STREQUAL "unknown") OR (LIBC_TARGET_OS STREQUAL "none"))157 # We treat "unknown" and "none" systems as baremetal targets.158 set(LIBC_TARGET_OS "baremetal")159endif()160 161# Set up some convenient vars to make conditionals easy to use in other parts of162# the libc CMake infrastructure. Also, this is where we also check if the target163# architecture is currently supported.164if(LIBC_TARGET_ARCHITECTURE STREQUAL "arm")165 set(LIBC_TARGET_ARCHITECTURE_IS_ARM TRUE)166elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "aarch64")167 set(LIBC_TARGET_ARCHITECTURE_IS_AARCH64 TRUE)168elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "x86_64")169 set(LIBC_TARGET_ARCHITECTURE_IS_X86_64 TRUE)170elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "i386")171 set(LIBC_TARGET_ARCHITECTURE_IS_X86 TRUE)172elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "riscv64")173 set(LIBC_TARGET_ARCHITECTURE_IS_ANY_RISCV TRUE)174 set(LIBC_TARGET_ARCHITECTURE_IS_RISCV64 TRUE)175 set(LIBC_TARGET_ARCHITECTURE "riscv")176elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "riscv32")177 set(LIBC_TARGET_ARCHITECTURE_IS_ANY_RISCV TRUE)178 set(LIBC_TARGET_ARCHITECTURE_IS_RISCV32 TRUE)179 set(LIBC_TARGET_ARCHITECTURE "riscv")180elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "amdgpu")181 set(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU TRUE)182elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "nvptx")183 set(LIBC_TARGET_ARCHITECTURE_IS_NVPTX TRUE)184elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "spirv64")185 set(LIBC_TARGET_ARCHITECTURE_IS_SPIRV TRUE)186else()187 message(FATAL_ERROR188 "Unsupported libc target architecture ${LIBC_TARGET_ARCHITECTURE}")189endif()190 191if(LIBC_TARGET_OS STREQUAL "baremetal")192 set(LIBC_TARGET_OS_IS_BAREMETAL TRUE)193elseif(LIBC_TARGET_OS STREQUAL "linux")194 set(LIBC_TARGET_OS_IS_LINUX TRUE)195elseif(LIBC_TARGET_OS STREQUAL "poky" OR LIBC_TARGET_OS STREQUAL "suse" OR196 LIBC_TARGET_OS STREQUAL "redhat")197 # poky are custom Linux-base systems created by yocto. Since these are Linux198 # images, we change the LIBC_TARGET_OS to linux. This define is used to199 # include the right directories during compilation.200 #201 # openSUSE and redhat use different triple format which causes LIBC_TARGET_OS202 # to be computed as "suse" or "redhat" instead of "linux".203 set(LIBC_TARGET_OS_IS_LINUX TRUE)204 set(LIBC_TARGET_OS "linux")205elseif(LIBC_TARGET_OS STREQUAL "darwin")206 set(LIBC_TARGET_OS_IS_DARWIN TRUE)207elseif(LIBC_TARGET_OS STREQUAL "windows")208 set(LIBC_TARGET_OS_IS_WINDOWS TRUE)209elseif(LIBC_TARGET_OS STREQUAL "gpu")210 set(LIBC_TARGET_OS_IS_GPU TRUE)211elseif(LIBC_TARGET_OS STREQUAL "uefi")212 set(LIBC_TARGET_OS_IS_UEFI TRUE)213else()214 message(FATAL_ERROR215 "Unsupported libc target operating system ${LIBC_TARGET_OS}")216endif()217 218# If the compiler target triple is not the same as the triple specified by219# LIBC_TARGET_TRIPLE or LLVM_RUNTIMES_TARGET, we will add a --target option220# if the compiler is clang. If the compiler is GCC we just error out as there221# is no equivalent of an option like --target.222if(explicit_target_triple AND223 (NOT (libc_compiler_triple STREQUAL explicit_target_triple)))224 set(LIBC_CROSSBUILD TRUE)225 if(CMAKE_COMPILER_IS_GNUCXX)226 message(FATAL_ERROR227 "GCC target triple (${libc_compiler_triple}) and the explicity "228 "specified target triple (${explicit_target_triple}) do not match.")229 else()230 list(APPEND231 LIBC_COMPILE_OPTIONS_DEFAULT "--target=${explicit_target_triple}")232 endif()233endif()234 235if(LIBC_TARGET_OS_IS_DARWIN)236 execute_process(237 COMMAND xcrun --sdk macosx --show-sdk-path238 OUTPUT_VARIABLE MACOSX_SDK_PATH239 RESULT_VARIABLE MACOSX_SDK_PATH_RESULT240 OUTPUT_STRIP_TRAILING_WHITESPACE241 )242 if(MACOSX_SDK_PATH_RESULT EQUAL 0)243 list(APPEND LIBC_COMPILE_OPTIONS_DEFAULT "-I" "${MACOSX_SDK_PATH}/usr/include")244 else()245 message(WARNING "Could not find macOS SDK path. `xcrun --sdk macosx --show-sdk-path` failed.")246 endif()247endif()248 249# Windows does not support full mode build.250if (LIBC_TARGET_OS_IS_WINDOWS AND LLVM_LIBC_FULL_BUILD)251 message(FATAL_ERROR "Windows does not support full mode build.")252endif ()253 254message(STATUS255 "Building libc for ${LIBC_TARGET_ARCHITECTURE} on ${LIBC_TARGET_OS} with "256 "LIBC_COMPILE_OPTIONS_DEFAULT: ${LIBC_COMPILE_OPTIONS_DEFAULT}")257