diff --git a/build-tools/xaprepare/xaprepare/ConfigAndData/BuildAndroidPlatforms.cs b/build-tools/xaprepare/xaprepare/ConfigAndData/BuildAndroidPlatforms.cs index f767821a506..8bc4193eb15 100644 --- a/build-tools/xaprepare/xaprepare/ConfigAndData/BuildAndroidPlatforms.cs +++ b/build-tools/xaprepare/xaprepare/ConfigAndData/BuildAndroidPlatforms.cs @@ -5,8 +5,8 @@ namespace Xamarin.Android.Prepare { class BuildAndroidPlatforms { - public const string AndroidNdkVersion = "28c"; - public const string AndroidNdkPkgRevision = "28.2.13676358"; + public const string AndroidNdkVersion = "29"; + public const string AndroidNdkPkgRevision = "29.0.14206865"; public const int NdkMinimumAPI = 21; public const int NdkMinimumAPILegacy32 = 21; diff --git a/src-ThirdParty/llvm/libcxx/src/verbose_abort.cpp b/src-ThirdParty/llvm/libcxx/src/verbose_abort.cpp new file mode 100644 index 00000000000..fd6bc4943d6 --- /dev/null +++ b/src-ThirdParty/llvm/libcxx/src/verbose_abort.cpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <__config> +#include <__verbose_abort> +#include +#include +#include + +#ifdef __BIONIC__ +# include +extern "C" void android_set_abort_message(const char* msg); +#endif // __BIONIC__ + +#if defined(__APPLE__) && __has_include() +# include +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_WEAK void __libcpp_verbose_abort(char const* format, ...) _LIBCPP_VERBOSE_ABORT_NOEXCEPT { + // Write message to stderr. We do this before formatting into a + // buffer so that we still get some information out if that fails. + { + va_list list; + va_start(list, format); + std::vfprintf(stderr, format, list); + va_end(list); + } + + // Format the arguments into an allocated buffer for CrashReport & friends. + // We leak the buffer on purpose, since we're about to abort() anyway. + char* buffer; + (void)buffer; + va_list list; + va_start(list, format); + +#if defined(__APPLE__) && __has_include() + // Note that we should technically synchronize accesses here (by e.g. taking a lock), + // however concretely we're only setting a pointer, so the likelihood of a race here + // is low. + vasprintf(&buffer, format, list); + CRSetCrashLogMessage(buffer); +#elif defined(__BIONIC__) + vasprintf(&buffer, format, list); + + // Show error in tombstone. + android_set_abort_message(buffer); + + // Show error in logcat. + openlog("libc++", 0, 0); + syslog(LOG_CRIT, "%s", buffer); + closelog(); +#endif + va_end(list); + + std::abort(); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets index ba0ae385391..f10deb35148 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets @@ -121,8 +121,8 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. <_NdkLibs Include="@(RuntimePackAsset->WithMetadataValue('Filename', 'libnaot-android.$(Configuration.ToLower())-static-$(Configuration.ToLower())'))" /> - <_NdkLibs Include="$(_NdkSysrootDir)libc++_static.a" /> - <_NdkLibs Include="$(_NdkSysrootDir)libc++abi.a" /> + + diff --git a/src/native/CMakeLists.txt b/src/native/CMakeLists.txt index 3b65133c34a..e0e587ce728 100644 --- a/src/native/CMakeLists.txt +++ b/src/native/CMakeLists.txt @@ -155,7 +155,15 @@ include(CheckLinkerFlag) # # General config # +file(REAL_PATH "../../" REPO_ROOT_DIR) +set(EXTERNAL_DIR "${REPO_ROOT_DIR}/external") +set(JAVA_INTEROP_SRC_PATH "${EXTERNAL_DIR}/Java.Interop/src/java-interop") +set(LIBUNWIND_SOURCE_DIR "${EXTERNAL_DIR}/libunwind") +set(ROBIN_MAP_DIR "${EXTERNAL_DIR}/robin-map") + set(XA_BUILD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Build${XA_BUILD_CONFIGURATION}") +set(THIRD_PARTY_SOURCE_DIR "${REPO_ROOT_DIR}/src-ThirdParty") + include("${XA_BUILD_DIR}/xa_build_configuration.cmake") # @@ -221,13 +229,6 @@ else() message(FATAL "${ANDROID_ABI} is not supported for .NET 6+ builds") endif() - -file(REAL_PATH "../../" REPO_ROOT_DIR) -set(EXTERNAL_DIR "${REPO_ROOT_DIR}/external") -set(JAVA_INTEROP_SRC_PATH "${EXTERNAL_DIR}/Java.Interop/src/java-interop") -set(LIBUNWIND_SOURCE_DIR "${EXTERNAL_DIR}/libunwind") -set(ROBIN_MAP_DIR "${EXTERNAL_DIR}/robin-map") - # # Include directories # @@ -243,7 +244,7 @@ else() set(CLR_REPO_ROOT_PATH "${LOCAL_CORECLR_PATH}/../..") set(RUNTIME_INCLUDE_DIR "${CLR_REPO_ROOT_PATH}/src/native/corehost;${CLR_REPO_ROOT_PATH}/src/coreclr/hosts/inc") else() - set(RUNTIME_INCLUDE_DIR ${REPO_ROOT_DIR}/src-ThirdParty/dotnet/runtime) + set(RUNTIME_INCLUDE_DIR ${THIRD_PARTY_SOURCE_DIR}/dotnet/runtime) endif() endif() diff --git a/src/native/CMakePresets.json.in b/src/native/CMakePresets.json.in index 79a3ac46282..9a163e9e286 100644 --- a/src/native/CMakePresets.json.in +++ b/src/native/CMakePresets.json.in @@ -54,25 +54,23 @@ }, { - "name": "analyzers-common", + "name": "nativeaot-default-common", "hidden": true, "inherits": "common", "cacheVariables": { - "ANDROID_STL": "c++_static", - "ANDROID_CPP_FEATURES": "rtti exceptions" + "ANDROID_STL": "none", + "ANDROID_CPP_FEATURES": "no-rtti no-exceptions" } }, { - "name": "default-debug", - "hidden": true, - "inherits": ["default-common", "common-debug"] - }, - - { - "name": "default-release", + "name": "analyzers-common", "hidden": true, - "inherits": ["default-common", "common-release"] + "inherits": "common", + "cacheVariables": { + "ANDROID_STL": "c++_static", + "ANDROID_CPP_FEATURES": "rtti exceptions" + } }, { @@ -196,11 +194,21 @@ "inherits": ["default-common", "common-debug", "common-arm64-v8a"] }, + { + "name": "nativeaot-default-debug-arm64-v8a", + "inherits": ["nativeaot-default-common", "common-debug", "common-arm64-v8a"] + }, + { "name": "default-release-arm64-v8a", "inherits": ["default-common", "common-release", "common-arm64-v8a"] }, + { + "name": "nativeaot-default-release-arm64-v8a", + "inherits": ["nativeaot-default-common", "common-release", "common-arm64-v8a"] + }, + { "name": "analyzers-debug-arm64-v8a", "hidden": true, @@ -284,11 +292,21 @@ "inherits": ["default-common", "common-debug", "common-x86_64"] }, + { + "name": "nativeaot-default-debug-x86_64", + "inherits": ["nativeaot-default-common", "common-debug", "common-x86_64"] + }, + { "name": "default-release-x86_64", "inherits": ["default-common", "common-release", "common-x86_64"] }, + { + "name": "nativeaot-default-release-x86_64", + "inherits": ["nativeaot-default-common", "common-release", "common-x86_64"] + }, + { "name": "analyzers-debug-x86_64", "hidden": true, diff --git a/src/native/native.targets b/src/native/native.targets index 9cd05f59b3a..90797d35cee 100644 --- a/src/native/native.targets +++ b/src/native/native.targets @@ -118,6 +118,7 @@ Inputs="@(_ConfigureRuntimesInputs)" Outputs="@(_ConfigureRuntimesOutputs)"> + <_PresetPrefix Condition=" '$(CMakeRuntimeFlavor)' == 'NativeAOT' ">nativeaot- <_NoInline Condition=" '$(DoNotInlineMonodroid)' == 'true' ">-DDONT_INLINE=ON <_NoStrip Condition=" '$(DoNotStripMonodroid)' == 'true' ">-DSTRIP_DEBUG=OFF <_LocalDotNetRuntimePath Condition=" '$(CLRLocalRuntimePath)' != '' And '$(CMakeRuntimeFlavor)' == 'CoreCLR' ">-DLOCAL_CORECLR_PATH="$(CLRLocalRuntimePath)" @@ -128,13 +129,13 @@ <_ConfigureRuntimeCommands Include="@(AndroidSupportedTargetJitAbi)"> $(CmakePath) - --preset default-debug-%(AndroidSupportedTargetJitAbi.Identity) $(_CmakeAndroidFlags) + --preset $(_PresetPrefix)default-debug-%(AndroidSupportedTargetJitAbi.Identity) $(_CmakeAndroidFlags) $(FlavorIntermediateOutputPath)%(AndroidSupportedTargetJitAbi.AndroidRID)-Debug <_ConfigureRuntimeCommands Include="@(AndroidSupportedTargetJitAbi)"> $(CmakePath) - --preset default-release-%(AndroidSupportedTargetJitAbi.Identity) $(_CmakeAndroidFlags) + --preset $(_PresetPrefix)default-release-%(AndroidSupportedTargetJitAbi.Identity) $(_CmakeAndroidFlags) $(FlavorIntermediateOutputPath)%(AndroidSupportedTargetJitAbi.AndroidRID)-Release @@ -142,25 +143,25 @@ <_ConfigureRuntimeCommands Include="@(AndroidSupportedTargetJitAbi)"> $(CmakePath) - --preset asan-debug-%(AndroidSupportedTargetJitAbi.Identity) $(_CmakeAndroidFlags) + --preset $(_PresetPrefix)asan-debug-%(AndroidSupportedTargetJitAbi.Identity) $(_CmakeAndroidFlags) $(FlavorIntermediateOutputPath)%(AndroidSupportedTargetJitAbi.AndroidRID)-asan-Debug <_ConfigureRuntimeCommands Include="@(AndroidSupportedTargetJitAbi)"> $(CmakePath) - --preset asan-release-%(AndroidSupportedTargetJitAbi.Identity) $(_CmakeAndroidFlags) + --preset $(_PresetPrefix)asan-release-%(AndroidSupportedTargetJitAbi.Identity) $(_CmakeAndroidFlags) $(FlavorIntermediateOutputPath)%(AndroidSupportedTargetJitAbi.AndroidRID)-asan-Release <_ConfigureRuntimeCommands Include="@(AndroidSupportedTargetJitAbi)"> $(CmakePath) - --preset ubsan-debug-%(AndroidSupportedTargetJitAbi.Identity) $(_CmakeAndroidFlags) + --preset $(_PresetPrefix)ubsan-debug-%(AndroidSupportedTargetJitAbi.Identity) $(_CmakeAndroidFlags) $(FlavorIntermediateOutputPath)%(AndroidSupportedTargetJitAbi.AndroidRID)-ubsan-Debug <_ConfigureRuntimeCommands Include="@(AndroidSupportedTargetJitAbi)"> $(CmakePath) - --preset ubsan-release-%(AndroidSupportedTargetJitAbi.Identity) $(_CmakeAndroidFlags) + --preset $(_PresetPrefix)ubsan-release-%(AndroidSupportedTargetJitAbi.Identity) $(_CmakeAndroidFlags) $(FlavorIntermediateOutputPath)%(AndroidSupportedTargetJitAbi.AndroidRID)-ubsan-Release diff --git a/src/native/nativeaot/cxx-abi/new.cc b/src/native/nativeaot/cxx-abi/new.cc new file mode 100644 index 00000000000..5aa1298aff0 --- /dev/null +++ b/src/native/nativeaot/cxx-abi/new.cc @@ -0,0 +1,181 @@ +// +// Code based on the original libc++ `libcxx/src/new.cpp` source, modified +// heavily for our use +// + +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <__assert> +#include <__memory/aligned_alloc.h> +#include +#include +#include + +#include + +#define _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE [[gnu::section ("__TEXT,__lcxx_override,regular,pure_instructions")]] + +namespace { + void* operator_new_impl(std::size_t size) + { + if (size == 0) { + size = 1; + } + + return std::malloc (size); + } +} + +_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE +[[gnu::weak]] +void* operator new (std::size_t size) +{ + void *p = operator_new_impl (size); + if (p == nullptr) { + xamarin::android::Helpers::abort_application ("Out of memory in the `new` operator"); + } + + return p; +} + +[[gnu::weak]] +void* operator new (size_t size, const std::nothrow_t&) noexcept +{ + return operator_new_impl (size); +} + +_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE +[[gnu::weak]] +void* operator new[] (size_t size) +{ + return ::operator new (size); +} + +[[gnu::weak]] +void* operator new[] (size_t size, const std::nothrow_t&) noexcept +{ + return operator_new_impl (size); +} + +[[gnu::weak]] +void operator delete(void* ptr) noexcept +{ + std::free (ptr); +} + +[[gnu::weak]] +void operator delete (void* ptr, const std::nothrow_t&) noexcept +{ + ::operator delete(ptr); +} + +[[gnu::weak]] +void operator delete (void* ptr, size_t) noexcept +{ + ::operator delete(ptr); +} + +[[gnu::weak]] +void operator delete[] (void* ptr) noexcept +{ + ::operator delete(ptr); +} + +[[gnu::weak]] +void operator delete[] (void* ptr, const std::nothrow_t&) noexcept +{ + ::operator delete[](ptr); +} + +[[gnu::weak]] +void operator delete[] (void* ptr, size_t) noexcept +{ + ::operator delete[](ptr); +} + +namespace { + void* operator_new_aligned_impl (std::size_t size, std::align_val_t alignment) + { + if (size == 0) { + size = 1; + } + + if (static_cast(alignment) < sizeof(void*)) { + alignment = std::align_val_t(sizeof(void*)); + } + + return std::__libcpp_aligned_alloc (static_cast(alignment), size); + } +} + +_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE +[[gnu::weak]] +void* operator new (std::size_t size, std::align_val_t alignment) +{ + void* p = operator_new_aligned_impl (size, alignment); + if (p == nullptr) { + xamarin::android::Helpers::abort_application ("Out of memory in the aligned `new` operator"); + } + + return p; +} + +[[gnu::weak]] +void* operator new (size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept +{ + return operator_new_aligned_impl (size, alignment); +} + +_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE +[[gnu::weak]] +void* operator new[] (size_t size, std::align_val_t alignment) +{ + return ::operator new (size, alignment); +} + +[[gnu::weak]] +void* operator new[] (size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept +{ + return operator_new_aligned_impl (size, alignment); +} + +[[gnu::weak]] +void operator delete (void* ptr, std::align_val_t) noexcept +{ + std::__libcpp_aligned_free(ptr); +} + +[[gnu::weak]] +void operator delete (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept +{ + ::operator delete(ptr, alignment); +} + +[[gnu::weak]] +void operator delete (void* ptr, size_t, std::align_val_t alignment) noexcept +{ + ::operator delete(ptr, alignment); +} + +[[gnu::weak]] +void operator delete[] (void* ptr, std::align_val_t alignment) noexcept +{ + ::operator delete(ptr, alignment); +} + +[[gnu::weak]] +void operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept +{ + ::operator delete[](ptr, alignment); +} + +[[gnu::weak]] void operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept +{ + ::operator delete[](ptr, alignment); +} diff --git a/src/native/nativeaot/cxx-abi/string.cc b/src/native/nativeaot/cxx-abi/string.cc new file mode 100644 index 00000000000..30d528e14ac --- /dev/null +++ b/src/native/nativeaot/cxx-abi/string.cc @@ -0,0 +1,12 @@ +// +// Defining the macro will make the the explicit instantations below truely hidden +// +#define _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS + +#include + +_LIBCPP_BEGIN_NAMESPACE_STD + +template class __attribute__ ((__visibility__("hidden"))) basic_string; + +_LIBCPP_END_NAMESPACE_STD diff --git a/src/native/nativeaot/cxx-abi/terminate.cc b/src/native/nativeaot/cxx-abi/terminate.cc new file mode 100644 index 00000000000..772eb2e5b5b --- /dev/null +++ b/src/native/nativeaot/cxx-abi/terminate.cc @@ -0,0 +1,17 @@ +// +// Simple implementation of std::terminate() for Xamarin.Android +// +// Does NOT support terminate handlers, since we don't use them. +// +#include +#include + +#include + +namespace std { + [[noreturn]] void + terminate () noexcept + { + xamarin::android::Helpers::abort_application ("std::terminate() called. Aborting."); + } +} diff --git a/src/native/nativeaot/host/CMakeLists.txt b/src/native/nativeaot/host/CMakeLists.txt index 9f4ce16fb25..5a542111ace 100644 --- a/src/native/nativeaot/host/CMakeLists.txt +++ b/src/native/nativeaot/host/CMakeLists.txt @@ -14,6 +14,11 @@ if(DEBUG_BUILD) set(CMAKE_CXX_FLAGS_DEBUG ${XA_COMPILER_FLAGS_DEBUG}) endif() +# Extra source directories +set(LIBCXX_SOURCE_DIR "${THIRD_PARTY_SOURCE_DIR}/llvm/libcxx/src") +set(BIONIC_SOURCE_DIR "${THIRD_PARTY_SOURCE_DIR}/bionic") +set(CXXABI_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../cxx-abi) + # Library directories set(XA_LIBRARY_OUTPUT_DIRECTORY "${XA_LIB_TOP_DIR}/lib/${ANDROID_RID}") @@ -35,6 +40,17 @@ set(XAMARIN_MONODROID_SOURCES ../runtime-base/android-system.cc + # Bionic sources + ${BIONIC_SOURCE_DIR}//cxa_guard.cc + + # libc++ sources + ${LIBCXX_SOURCE_DIR}/verbose_abort.cpp + + # C++ ABI sources + ${CXXABI_SOURCE_DIR}/new.cc + ${CXXABI_SOURCE_DIR}/string.cc + ${CXXABI_SOURCE_DIR}/terminate.cc + # Sources from CoreCLR host ${CLR_SOURCES_PATH}/host/bridge-processing.cc ${CLR_SOURCES_PATH}/host/gc-bridge.cc