diff --git a/clang/cmake/caches/Android-libcxx.cmake b/clang/cmake/caches/Android-libcxx.cmake new file mode 100644 --- /dev/null +++ b/clang/cmake/caches/Android-libcxx.cmake @@ -0,0 +1,15 @@ +# Most of this will be supplanted by https://reviews.llvm.org/D139147. +set(LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "") +set(LIBUNWIND_HIDE_SYMBOLS ON CACHE BOOL "") + +set(LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "") +set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") + +set(LIBCXX_ENABLE_ABI_LINKER_SCRIPT OFF CACHE BOOL "") +set(LIBCXX_ENABLE_STATIC OFF CACHE BOOL "") +set(LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY ON CACHE BOOL "") + +set(LIBCXX_SHARED_OUTPUT_NAME c++_shared CACHE STRING "") +set(LIBCXX_STATIC_OUTPUT_NAME c++_static CACHE STRING "") + +set(LIBCXX_ABI_NAMESPACE __ndk1 CACHE STRING "") diff --git a/clang/cmake/caches/Android-runtimes.cmake b/clang/cmake/caches/Android-runtimes.cmake new file mode 100644 --- /dev/null +++ b/clang/cmake/caches/Android-runtimes.cmake @@ -0,0 +1,58 @@ +if(NOT NDK_PATH) + message(FATAL_ERROR "NDK_PATH must point to NDK path") +endif() + +set(LLVM_ENABLE_PROJECTS + clang + lld + CACHE STRING "") + +set(LLVM_ENABLE_RUNTIMES + compiler-rt + libunwind + libcxxabi + libcxx + CACHE STRING "") + +function(android_runtime arch api_level target) + if(arch STREQUAL armv7) + set(abi armeabi-v7a) + elseif(arch STREQUAL aarch64) + set(abi arm64-v8a) + elseif(arch STREQUAL i686) + set(abi x86) + elseif(arch STREQUAL x86_64) + set(abi x86_64) + else() + message(FATAL_ERROR "Invalid arch ${arch}") + endif() + + set(toolchain_file "${CMAKE_SOURCE_DIR}/cmake/platforms/Android-runtimes.cmake") + foreach(prefix BUILTINS RUNTIMES) + set(${prefix}_${target}_ANDROID_ABI ${abi} CACHE STRING "") + set(${prefix}_${target}_ANDROID_PLATFORM "android-${api_level}" CACHE STRING "") + set(${prefix}_${target}_NDK_PATH "${NDK_PATH}" CACHE PATH "") + set(${prefix}_${target}_CMAKE_TOOLCHAIN_FILE "${toolchain_file}" CACHE FILEPATH "") + endforeach() + + # This matches the NDK. It's problematic if you have emulated atomics + # used across shared libraries, but that should be very rare. + set(BUILTINS_${target}_COMPILER_RT_EXCLUDE_ATOMIC_BUILTIN OFF CACHE BOOL "") + + set(RUNTIMES_${target}_CMAKE_CACHES + "${CMAKE_CURRENT_LIST_DIR}/Android-libcxx.cmake" + CACHE STRING "") +endfunction() + +set(targets) +foreach(arch armv7 aarch64 i686 x86_64) + # 21 is the minimum supported and 29 adds ELF TLS. + foreach(api_level 21 29) + set(target "${arch}-none-linux-android${api_level}") + android_runtime(${arch} ${api_level} ${target}) + list(APPEND targets ${target}) + endforeach() +endforeach() + +set(LLVM_BUILTIN_TARGETS ${targets} CACHE STRING "") +set(LLVM_RUNTIME_TARGETS ${targets} CACHE STRING "") diff --git a/llvm/cmake/platforms/Android-runtimes.cmake b/llvm/cmake/platforms/Android-runtimes.cmake new file mode 100644 --- /dev/null +++ b/llvm/cmake/platforms/Android-runtimes.cmake @@ -0,0 +1,48 @@ +# A wrapper around the NDK's CMake toolchain that uses the just-built +# compiler instead of the NDK's and tweaks flags to work with a +# partially built toolchain, for the runtimes build. + +if(NOT NDK_PATH) + message(FATAL_ERROR "NDK_PATH must point to NDK path") +endif() + +# These are passed down from the runtimes build. +set(ORIGINAL_C_COMPILER "${CMAKE_C_COMPILER}") +set(ORIGINAL_CXX_COMPILER "${CMAKE_CXX_COMPILER}") + +include("${NDK_PATH}/build/cmake/android.toolchain.cmake") + +set(CMAKE_C_COMPILER "${ORIGINAL_C_COMPILER}") +set(CMAKE_CXX_COMPILER "${ORIGINAL_CXX_COMPILER}") + +list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES NDK_PATH) + +# We won't have libunwind available since we're building it. CMake's ABI +# checks fail without this. +# FIXME: compiler-rt uses --unwindlib=none already; does that just need +# to be more comprehensive, or is the "Detecting compiler ABI info" +# check ingrained enough in CMake that only the toolchain file can +# influence it? +string(APPEND CMAKE_EXE_LINKER_FLAGS " --unwindlib=none") +string(APPEND CMAKE_MODULE_LINKER_FLAGS " --unwindlib=none") +string(APPEND CMAKE_SHARED_LINKER_FLAGS " --unwindlib=none") + +# libatomic is provided by compiler-rt and our just-built compiler +# doesn't have the NDK's dummy libatomic available. +string(REPLACE "-latomic" "" CMAKE_C_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}") +string(REPLACE "-latomic" "" CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_CXX_STANDARD_LIBRARIES_INIT}") + +# Fortify doesn't play well with -ffreestanding, which is used heavily +# by sanitizers, because e.g. it prevents Clang's built-in limits.h from +# reaching out to the NDK's and supplying SSIZE_MAX. +# FIXME: should this be in compiler-rt instead? +string(REPLACE "-D_FORTIFY_SOURCE=2" "" CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS}") +string(REPLACE "-D_FORTIFY_SOURCE=2" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +string(REPLACE "-D_FORTIFY_SOURCE=2" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + +# Clang canonicalizes androideabi as just android, so we need to mimic +# that to get the correct per-target installation directory. +# FIXME: remove this once https://reviews.llvm.org/D140925 lands +string(REPLACE "androideabi" "android" CMAKE_ASM_COMPILER_TARGET "${CMAKE_ASM_COMPILER_TARGET}") +string(REPLACE "androideabi" "android" CMAKE_C_COMPILER_TARGET "${CMAKE_C_COMPILER_TARGET}") +string(REPLACE "androideabi" "android" CMAKE_CXX_COMPILER_TARGET "${CMAKE_CXX_COMPILER_TARGET}")