xref: /llvm-project/libc/cmake/modules/LLVMLibCArchitectures.cmake (revision e083a33478b2d570c89d7a9d9f05328b9232c072)
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