From dae4d1a8eccc99d2315fc41992a21624801c7be2 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Wed, 27 Mar 2024 18:55:58 +0100 Subject: [PATCH] Android: Switch to native ELF TLS & latest LTS NDK --- .github/actions/3-build-cross/action.yml | 18 ++++++++---------- driver/linker-gcc.cpp | 8 -------- driver/main.d | 15 --------------- driver/targetmachine.cpp | 8 +++++--- runtime/druntime/src/rt/sections.d | 2 +- runtime/druntime/src/rt/sections_android.d | 2 ++ runtime/druntime/src/rt/sections_elf_shared.d | 1 + 7 files changed, 17 insertions(+), 37 deletions(-) diff --git a/.github/actions/3-build-cross/action.yml b/.github/actions/3-build-cross/action.yml index 2116bc201df..4b8a01f5711 100644 --- a/.github/actions/3-build-cross/action.yml +++ b/.github/actions/3-build-cross/action.yml @@ -14,10 +14,10 @@ inputs: default: false android_ndk_version: required: false - default: r21e + default: r26c android_api_level: required: false - default: 21 + default: 29 runs: using: composite steps: @@ -92,16 +92,11 @@ runs: cd .. version='${{ inputs.android_ndk_version }}' curl -fL --retry 3 --max-time 300 -o android-ndk.zip \ - https://dl.google.com/android/repository/android-ndk-$version-linux-x86_64.zip + https://dl.google.com/android/repository/android-ndk-$version-linux.zip unzip android-ndk.zip >/dev/null mv "android-ndk-$version" android-ndk rm android-ndk.zip - # The NDK toolchain file enforces `-g` as base C[XX] flag - remove it to - # *significantly* reduce executable sizes - toolchainFile="$PWD/android-ndk/build/cmake/android.toolchain.cmake" - sed -i 's|^ -g$||' "$toolchainFile" - arch='${{ inputs.arch }}' apiLevel='${{ inputs.android_api_level }}' cmakeFlags="-DTARGET_SYSTEM='Android;Linux;UNIX'" @@ -109,13 +104,16 @@ runs: triple="$arch-linux-androideabi$apiLevel" cmakeFlags+=' -DANDROID_ABI=armeabi-v7a' elif [[ "$arch" == aarch64 ]]; then + # FIXME: as of NDK rc26c, libc.a has __tls_get_addr, but libc.so only since API level 30 (Android v11) + apiLevel=30 triple="$arch-linux-android$apiLevel" cmakeFlags+=' -DANDROID_ABI=arm64-v8a' fi cmakeFlags+=" -DANDROID_NATIVE_API_LEVEL=$apiLevel" cmakeFlags+=" -DANDROID_STL=c++_static" - cmakeFlags+=" -DCMAKE_TOOLCHAIN_FILE=$toolchainFile" - cmakeFlags+=" -DLDC_LINK_MANUALLY=ON -DD_LINKER_ARGS='-fuse-ld=bfd;-L$PWD/build-cross-libs/lib;-lphobos2-ldc;-ldruntime-ldc'" + cmakeFlags+=" -DCMAKE_TOOLCHAIN_FILE=$PWD/android-ndk/build/cmake/android.toolchain.cmake" + cmakeFlags+=" -DANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF" + cmakeFlags+=" -DLDC_LINK_MANUALLY=ON -DD_LINKER_ARGS='-L$PWD/build-cross-libs/lib;-lphobos2-ldc;-ldruntime-ldc'" echo "DFLAGS=-mtriple=$triple -fvisibility=hidden -L-L$PWD/build-cross-libs/lib -gcc=$PWD/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/$triple-clang" >> $GITHUB_ENV echo "CROSS_TRIPLE=$triple" >> $GITHUB_ENV diff --git a/driver/linker-gcc.cpp b/driver/linker-gcc.cpp index beb802a6bdf..42ecf0d94f9 100644 --- a/driver/linker-gcc.cpp +++ b/driver/linker-gcc.cpp @@ -621,14 +621,6 @@ void ArgsBuilder::build(llvm::StringRef outputPath, void ArgsBuilder::addLinker() { llvm::StringRef linker = opts::linker; - // Default to ld.bfd for Android (placing .tdata and .tbss sections adjacent - // to each other as required by druntime's rt.sections_android, contrary to - // gold and lld as of Android NDK r21d). - if (global.params.targetTriple->getEnvironment() == llvm::Triple::Android && - opts::linker.getNumOccurrences() == 0) { - linker = "bfd"; - } - if (!linker.empty()) args.push_back(("-fuse-ld=" + linker).str()); } diff --git a/driver/main.d b/driver/main.d index 1ad69e82c6f..6b2e0988ae7 100644 --- a/driver/main.d +++ b/driver/main.d @@ -59,18 +59,3 @@ version (Windows) SetConsoleOutputCP(originalOutputCP); } } - -// TLS bracketing symbols required for our custom TLS emulation on Android -// as we don't have a D main() function for LDC and LDMD. -version (Android) -{ - import ldc.attributes; - - extern(C) __gshared - { - @section(".tdata") - int _tlsstart = 0; - @section(".tcommon") - int _tlsend = 0; - } -} diff --git a/driver/targetmachine.cpp b/driver/targetmachine.cpp index 3378877351b..a8f1704291f 100644 --- a/driver/targetmachine.cpp +++ b/driver/targetmachine.cpp @@ -639,12 +639,14 @@ createTargetMachine(const std::string targetTriple, const std::string arch, targetOptions.DataSections = true; } - // On Android, we depend on a custom TLS emulation scheme implemented in our - // LLVM fork. LLVM 7+ enables regular emutls by default; prevent that. + // On Android, enforce native ELF TLS (supported since API level 29 = Android + // v10), as required by druntime. (Some older LLVM versions might default to + // EmuTLS). if (triple.getEnvironment() == llvm::Triple::Android) { targetOptions.EmulatedTLS = false; #if LDC_LLVM_VER < 1700 - // Removed in this commit: https://github.com/llvm/llvm-project/commit/0d333bf0e3aa37e2e6ae211e3aa80631c3e01b85 + // Removed in this commit: + // https://github.com/llvm/llvm-project/commit/0d333bf0e3aa37e2e6ae211e3aa80631c3e01b85 targetOptions.ExplicitEmulatedTLS = true; #endif } diff --git a/runtime/druntime/src/rt/sections.d b/runtime/druntime/src/rt/sections.d index 7db4842818f..e285cb08b0d 100644 --- a/runtime/druntime/src/rt/sections.d +++ b/runtime/druntime/src/rt/sections.d @@ -64,7 +64,7 @@ else version (CRuntime_Microsoft) public import rt.sections_win64; } else version (CRuntime_Bionic) - public import rt.sections_android; + public import rt.sections_elf_shared; else version (CRuntime_UClibc) public import rt.sections_elf_shared; else diff --git a/runtime/druntime/src/rt/sections_android.d b/runtime/druntime/src/rt/sections_android.d index eabbc090422..65019acd99e 100644 --- a/runtime/druntime/src/rt/sections_android.d +++ b/runtime/druntime/src/rt/sections_android.d @@ -10,6 +10,8 @@ module rt.sections_android; +version (LDC) { /* implemented in rt.sections_elf_shared */ } else: + version (CRuntime_Bionic): // debug = PRINTF; diff --git a/runtime/druntime/src/rt/sections_elf_shared.d b/runtime/druntime/src/rt/sections_elf_shared.d index a8b37eab2c2..2b987853251 100644 --- a/runtime/druntime/src/rt/sections_elf_shared.d +++ b/runtime/druntime/src/rt/sections_elf_shared.d @@ -24,6 +24,7 @@ else version (CRuntime_Musl) enum SharedELF = true; else version (FreeBSD) enum SharedELF = true; else version (NetBSD) enum SharedELF = true; else version (DragonFlyBSD) enum SharedELF = true; +else version (CRuntime_Bionic) enum SharedELF = true; else version (CRuntime_UClibc) enum SharedELF = true; else enum SharedELF = false;