Skip to content

Commit

Permalink
Android: Switch to native ELF TLS & latest LTS NDK
Browse files Browse the repository at this point in the history
  • Loading branch information
kinke committed Mar 28, 2024
1 parent 76c564b commit b29b6bb
Show file tree
Hide file tree
Showing 7 changed files with 17 additions and 37 deletions.
18 changes: 8 additions & 10 deletions .github/actions/3-build-cross/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -92,30 +92,28 @@ 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'"
if [[ "$arch" == armv7a ]]; then
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
Expand Down
8 changes: 0 additions & 8 deletions driver/linker-gcc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down
15 changes: 0 additions & 15 deletions driver/main.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
8 changes: 5 additions & 3 deletions driver/targetmachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/druntime/src/rt/sections.d
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions runtime/druntime/src/rt/sections_android.d
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

module rt.sections_android;

version (LDC) { /* implemented in rt.sections_elf_shared */ } else:

version (CRuntime_Bionic):

// debug = PRINTF;
Expand Down
1 change: 1 addition & 0 deletions runtime/druntime/src/rt/sections_elf_shared.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit b29b6bb

Please sign in to comment.