[libc-commits] [libc] 4f9c10e - [libc] Add support for standalone cross compilation of libc.
Siva Chandra Reddy via libc-commits
libc-commits at lists.llvm.org
Mon Dec 19 16:33:45 PST 2022
Author: Siva Chandra Reddy
Date: 2022-12-20T00:33:35Z
New Revision: 4f9c10eb48a3725ecfd844d44ccf3068fbadbb85
URL: https://github.com/llvm/llvm-project/commit/4f9c10eb48a3725ecfd844d44ccf3068fbadbb85
DIFF: https://github.com/llvm/llvm-project/commit/4f9c10eb48a3725ecfd844d44ccf3068fbadbb85.diff
LOG: [libc] Add support for standalone cross compilation of libc.
One should be able to do a cross build of the libc now. For example, using
clang on a x86_64 linux host, one can build for an aarch64 linux target by
specifying -DLIBC_TARGET_TRIPLE=aarch64-linux-gnu.
Follow up changes will add a baremetal config and also appropriate
documentation about cross compiling the libc for CPU targets.
Reviewed By: jhuber6
Differential Revision: https://reviews.llvm.org/D140351
Added:
Modified:
libc/CMakeLists.txt
libc/cmake/modules/LLVMLibCArchitectures.cmake
libc/cmake/modules/prepare_libc_gpu_build.cmake
libc/docs/gpu_mode.rst
Removed:
################################################################################
diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index fa0ce829a168a..8eb45838f954a 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -55,17 +55,18 @@ option(LLVM_LIBC_FULL_BUILD "Build and test LLVM libc as if it is the full libc"
option(LLVM_LIBC_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR "Build LLVM libc tests assuming our implementation-defined behavior" ON)
option(LLVM_LIBC_ENABLE_LINTING "Enables linting of libc source files" OFF)
-set(LLVM_LIBC_TARGET_OS ${CMAKE_SYSTEM_NAME} CACHE STRING "Target operating system for LLVM libc")
-string(TOLOWER ${LLVM_LIBC_TARGET_OS} LIBC_TARGET_OS)
+option(LIBC_GPU_BUILD "Build libc for the GPU. All CPU build options will be ignored." OFF)
+set(LIBC_TARGET_TRIPLE "" CACHE STRING "The target triple for the libc build.")
# Defines LIBC_TARGET_ARCHITECTURE and associated macros.
include(LLVMLibCArchitectures)
-include(LLVMLibCCheckMPFR)
if(LIBC_TARGET_ARCHITECTURE_IS_GPU)
include(prepare_libc_gpu_build)
endif()
+include(LLVMLibCCheckMPFR)
+
if(LLVM_LIBC_CLANG_TIDY)
set(LLVM_LIBC_ENABLE_LINTING ON)
endif()
diff --git a/libc/cmake/modules/LLVMLibCArchitectures.cmake b/libc/cmake/modules/LLVMLibCArchitectures.cmake
index 9da74c4410d84..3c99f645e4867 100644
--- a/libc/cmake/modules/LLVMLibCArchitectures.cmake
+++ b/libc/cmake/modules/LLVMLibCArchitectures.cmake
@@ -1,25 +1,139 @@
# ------------------------------------------------------------------------------
-# Architecture definitions
+# 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(LIBC_TARGET_OS MATCHES "gpu")
+if(LIBC_GPU_BUILD)
+ # We set the generic target and OS to "gpu" here. More specific defintions
+ # for the exact target GPU are set up in prepare_libc_gpu_build.cmake.
+ set(LIBC_TARGET_OS "gpu")
set(LIBC_TARGET_ARCHITECTURE_IS_GPU TRUE)
set(LIBC_TARGET_ARCHITECTURE "gpu")
-elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips")
- set(LIBC_TARGET_ARCHITECTURE_IS_MIPS TRUE)
- set(LIBC_TARGET_ARCHITECTURE "mips")
-elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
- set(LIBC_TARGET_ARCHITECTURE_IS_ARM TRUE)
- set(LIBC_TARGET_ARCHITECTURE "arm")
-elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64")
- set(LIBC_TARGET_ARCHITECTURE_IS_AARCH64 TRUE)
- set(LIBC_TARGET_ARCHITECTURE "aarch64")
-elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(AMD64|amd64)|(^i.86$)")
- set(LIBC_TARGET_ARCHITECTURE_IS_X86 TRUE)
- set(LIBC_TARGET_ARCHITECTURE "x86_64")
-elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
- set(LIBC_TARGET_ARCHITECTURE_IS_POWER TRUE)
- set(LIBC_TARGET_ARCHITECTURE "power")
+ if(LIBC_TARGET_TRIPLE)
+ message(WARNING "LIBC_TARGET_TRIPLE is ignored as LIBC_GPU_BUILD is on. ")
+ endif()
+ return()
+endif()
+
+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 "^arm")
+ set(target_arch "arm")
+ elseif(target_arch MATCHES "^aarch64")
+ set(target_arch "aarch64")
+ elseif(target_arch MATCHES "(x86_64)|(AMD64|amd64)|(^i.86$)")
+ set(target_arch "x86_64")
+ elseif(target_arch MATCHES "^(powerpc|ppc)")
+ set(target_arch "power")
+ else()
+ return()
+ endif()
+
+ set(${arch_var} ${target_arch} PARENT_SCOPE)
+ list(GET triple_comps ${system_index} target_sys)
+ set(${sys_var} ${target_sys} PARENT_SCOPE)
+endfunction(get_arch_and_system_from_triple)
+
+# Query the default target triple of the compiler.
+set(target_triple_option "-print-target-triple")
+if(CMAKE_COMPILER_IS_GNUCXX)
+ # GCC does not support the "-print-target-triple" option but supports
+ # "-print-multiarch" which clang does not support for all targets.
+ set(target_triple_option "-print-multiarch")
+endif()
+execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${target_triple_option}
+ RESULT_VARIABLE libc_compiler_triple_check
+ OUTPUT_VARIABLE libc_compiler_triple)
+if(NOT (libc_compiler_triple_check EQUAL "0"))
+ message(FATAL_ERROR "libc build: error querying target triple from the "
+ "compiler: ${libc_compiler_triple}")
+endif()
+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})
+
+# 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. If it
+# is and does not match the compiler's target triple, then we will use it set up
+# libc's target architecture and OS.
+if(LIBC_TARGET_TRIPLE)
+ get_arch_and_system_from_triple(${LIBC_TARGET_TRIPLE} libc_arch libc_sys)
+ if(NOT libc_arch)
+ message(FATAL_ERROR
+ "libc build: Invalid or unknown triple in LIBC_TARGET_TRIPLE: "
+ "${LIBC_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_LIBC_TARGET_ARCHITECTUREITECTURE_IS_ARM TRUE)
+elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "aarch64")
+ set(LIBC_LIBC_TARGET_ARCHITECTUREITECTURE_IS_AARCH64 TRUE)
+elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "x86_64")
+ set(LIBC_LIBC_TARGET_ARCHITECTUREITECTURE_IS_X86 TRUE)
else()
- message(FATAL_ERROR "Unsupported processor ${CMAKE_SYSTEM_PROCESSOR}")
+ message(FATAL_ERROR
+ "Unsupported libc target architecture ${LIBC_TARGET_ARCHITECTURE}")
+endif()
+
+# If the compiler target triple is not the same as the triple specified by
+# LIBC_TARGET_TRIPLE, 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(LIBC_TARGET_TRIPLE AND
+ (NOT (libc_compiler_triple STREQUAL LIBC_TARGET_TRIPLE)))
+ if(CMAKE_COMPILER_IS_GNUCXX)
+ message(FATAL_ERROR
+ "GCC target triple and LIBC_TARGET_TRIPLE do not match.")
+ else()
+ list(APPEND LIBC_COMPILE_OPTIONS_DEFAULT "--target=${LIBC_TARGET_TRIPLE}")
+ endif()
endif()
+
+message(STATUS
+ "Building libc for ${LIBC_TARGET_ARCHITECTURE} on ${LIBC_TARGET_OS}")
diff --git a/libc/cmake/modules/prepare_libc_gpu_build.cmake b/libc/cmake/modules/prepare_libc_gpu_build.cmake
index 62090948f8d40..20fa57f26872f 100644
--- a/libc/cmake/modules/prepare_libc_gpu_build.cmake
+++ b/libc/cmake/modules/prepare_libc_gpu_build.cmake
@@ -1,3 +1,8 @@
+if(NOT LIBC_TARGET_ARCHITECTURE_IS_GPU)
+ message(FATAL_ERROR
+ "libc build: Invalid attempt to set up GPU architectures.")
+endif()
+
# Set up the target architectures to build the GPU libc for.
set(all_gpu_architectures "sm_35;sm_37;sm_50;sm_52;sm_53;sm_60;sm_61;sm_62;"
"sm_70;sm_72;sm_75;sm_80;sm_86;gfx700;gfx701;gfx801;"
@@ -13,9 +18,8 @@ endif()
# Ensure the compiler is a valid clang when building the GPU target.
set(req_ver "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}")
-if(LIBC_TARGET_ARCHITECTURE_IS_GPU AND
- NOT (CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang" AND
- ${CMAKE_CXX_COMPILER_VERSION} VERSION_EQUAL "${req_ver}"))
+if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang" AND
+ ${CMAKE_CXX_COMPILER_VERSION} VERSION_EQUAL "${req_ver}"))
message(FATAL_ERROR "Cannot build libc for GPU. CMake compiler "
"'${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}' "
" is not `Clang ${req_ver}.")
diff --git a/libc/docs/gpu_mode.rst b/libc/docs/gpu_mode.rst
index b95dba3184cfd..b71b6eec5daee 100644
--- a/libc/docs/gpu_mode.rst
+++ b/libc/docs/gpu_mode.rst
@@ -44,7 +44,7 @@ configuration will look like this:
-DLLVM_ENABLE_RUNTIMES="libc;openmp" \
-DCMAKE_BUILD_TYPE=<Debug|Release> \ # Select build type
-DLLVM_LIBC_FULL_BUILD=ON \ # We need the full libc
- -DLLVM_LIBC_TARGET_OS=gpu \ # Build in GPU mode
+ -DLIBC_GPU_BUILD=ON \ # Build in GPU mode
-DLLVM_LIBC_GPU_ARCHITECTURES=all \ # Build all supported architectures
-DCMAKE_INSTALL_PREFIX=<PATH> \ # Where 'libcgpu.a' will live
$> ninja install
More information about the libc-commits
mailing list