Skip to content

Commit

Permalink
Merge pull request #4618 from kinke/android_tls
Browse files Browse the repository at this point in the history
Android: Switch to native ELF TLS & latest LTS NDK, and enable shared druntime/Phobos
  • Loading branch information
kinke authored Apr 19, 2024
2 parents dad00ad + 75130c5 commit 11908ed
Show file tree
Hide file tree
Showing 13 changed files with 56 additions and 60 deletions.
20 changes: 9 additions & 11 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: r26d
android_api_level:
required: false
default: 21
default: 29
runs:
using: composite
steps:
Expand Down Expand Up @@ -92,32 +92,30 @@ 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 rc26d, 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 "DFLAGS=-mtriple=$triple -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
echo "CROSS_CMAKE_FLAGS=$cmakeFlags" >> $GITHUB_ENV
Expand Down
18 changes: 9 additions & 9 deletions .github/actions/3-build-cross/android-llvm-config.in
Original file line number Diff line number Diff line change
Expand Up @@ -53,25 +53,25 @@ LIBFILE="${prefix}/lib/libLLVM-$version.so"
components="aarch64 aarch64asmparser aarch64codegen aarch64desc aarch64disassembler aarch64info aarch64utils \
aggressiveinstcombine all all-targets analysis arm armasmparser armcodegen armdesc armdisassembler arminfo armutils \
asmparser asmprinter binaryformat bitreader bitstreamreader bitwriter cfguard codegen codegentypes core coroutines coverage \
debuginfobtf debuginfocodeview debuginfodwarf debuginfogsym debuginfologicalview debuginfomsf debuginfopdb demangle dlltooldriver dwarflinker dwarflinkerparallel dwp \
engine executionengine extensions filecheck frontendhlsl frontendopenacc frontendopenmp fuzzercli fuzzmutate globalisel instcombine \
debuginfobtf debuginfocodeview debuginfodwarf debuginfogsym debuginfologicalview debuginfomsf debuginfopdb demangle dlltooldriver dwarflinker dwarflinkerclassic dwarflinkerparallel dwp \
engine executionengine extensions filecheck frontenddriver frontendhlsl frontendoffloading frontendopenacc frontendopenmp fuzzercli fuzzmutate globalisel hipstdpar instcombine \
instrumentation interfacestub interpreter ipo irprinter irreader jitlink libdriver lineeditor linker lto mc mca mcdisassembler \
mcjit mcparser mirparser native nativecodegen objcarcopts objcopy object objectyaml option orcjit orcshared orctargetprocess \
mcjit mcparser mirparser native nativecodegen objcarcopts objcopy object objectyaml option orcdebugging orcjit orcshared orctargetprocess \
passes profiledata remarks runtimedyld scalaropts selectiondag spirv spirvcodegen spirvdesc spirvinfo support symbolize tablegen target targetparser textapi \
transformutils vectorize webassembly webassemblyasmparser webassemblycodegen webassemblydesc webassemblydisassembler \
textapibinaryreader transformutils vectorize webassembly webassemblyasmparser webassemblycodegen webassemblydesc webassemblydisassembler \
webassemblyinfo webassemblyutils windowsdriver windowsmanifest x86 x86asmparser x86codegen x86desc x86disassembler x86info \
x86targetmca xray"
static_libs="-lLLVMWindowsManifest -lLLVMXRay -lLLVMLibDriver -lLLVMDlltoolDriver -lLLVMCoverage -lLLVMLineEditor \
static_libs="-lLLVMWindowsManifest -lLLVMXRay -lLLVMLibDriver -lLLVMDlltoolDriver -lLLVMTextAPIBinaryReader -lLLVMCoverage -lLLVMLineEditor \
-lLLVMSPIRVCodeGen -lLLVMSPIRVDesc -lLLVMSPIRVInfo \
-lLLVMX86TargetMCA -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMX86Desc -lLLVMX86Info -lLLVMWebAssemblyDisassembler \
-lLLVMWebAssemblyAsmParser -lLLVMWebAssemblyCodeGen -lLLVMWebAssemblyUtils -lLLVMWebAssemblyDesc -lLLVMWebAssemblyInfo -lLLVMARMDisassembler \
-lLLVMARMAsmParser -lLLVMARMCodeGen -lLLVMARMDesc -lLLVMARMUtils -lLLVMARMInfo -lLLVMAArch64Disassembler \
-lLLVMAArch64AsmParser -lLLVMAArch64CodeGen -lLLVMAArch64Desc -lLLVMAArch64Utils -lLLVMAArch64Info -lLLVMOrcJIT \
-lLLVMAArch64AsmParser -lLLVMAArch64CodeGen -lLLVMAArch64Desc -lLLVMAArch64Utils -lLLVMAArch64Info -lLLVMOrcDebugging -lLLVMOrcJIT \
-lLLVMWindowsDriver -lLLVMMCJIT -lLLVMJITLink -lLLVMInterpreter -lLLVMExecutionEngine -lLLVMRuntimeDyld -lLLVMOrcTargetProcess -lLLVMOrcShared \
-lLLVMDWP -lLLVMDebugInfoLogicalView -lLLVMDebugInfoGSYM -lLLVMOption -lLLVMObjectYAML -lLLVMObjCopy -lLLVMMCA \
-lLLVMMCDisassembler -lLLVMLTO -lLLVMPasses -lLLVMCFGuard -lLLVMCoroutines -lLLVMipo \
-lLLVMVectorize -lLLVMLinker -lLLVMInstrumentation -lLLVMFrontendOpenMP -lLLVMFrontendOpenACC -lLLVMFrontendHLSL -lLLVMExtensions \
-lLLVMDWARFLinkerParallel -lLLVMDWARFLinker -lLLVMGlobalISel -lLLVMMIRParser -lLLVMAsmPrinter -lLLVMSelectionDAG \
-lLLVMMCDisassembler -lLLVMLTO -lLLVMPasses -lLLVMHipStdPar -lLLVMCFGuard -lLLVMCoroutines -lLLVMipo \
-lLLVMVectorize -lLLVMLinker -lLLVMInstrumentation -lLLVMFrontendOpenMP -lLLVMFrontendOffloading -lLLVMFrontendOpenACC -lLLVMFrontendHLSL -lLLVMFrontendDriver -lLLVMExtensions \
-lLLVMDWARFLinkerParallel -lLLVMDWARFLinkerClassic -lLLVMDWARFLinker -lLLVMGlobalISel -lLLVMMIRParser -lLLVMAsmPrinter -lLLVMSelectionDAG \
-lLLVMCodeGen -lLLVMTarget -lLLVMObjCARCOpts -lLLVMCodeGenTypes -lLLVMIRPrinter -lLLVMInterfaceStub -lLLVMFileCheck -lLLVMFuzzMutate \
-lLLVMScalarOpts -lLLVMInstCombine -lLLVMAggressiveInstCombine -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis \
-lLLVMProfileData -lLLVMSymbolize -lLLVMDebugInfoBTF -lLLVMDebugInfoPDB -lLLVMDebugInfoMSF -lLLVMDebugInfoDWARF -lLLVMObject -lLLVMTextAPI -lLLVMMCParser -lLLVMIRReader -lLLVMAsmParser -lLLVMMC -lLLVMDebugInfoCodeView \
Expand Down
4 changes: 2 additions & 2 deletions .github/actions/5a-android-x86/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ runs:
# use bootstrap-ldc, which is guaranteed to be native
bootstrap-ldc/bin/ldc-build-runtime --ninja \
--buildDir="build-libs-$arch" \
--dFlags="-mtriple=$triple;-fvisibility=hidden" \
--dFlags="-mtriple=$triple" \
--ldcSrcDir="$PWD/ldc" \
"${flags[@]}" \
ANDROID_ABI="$abi" # override the one in CROSS_CMAKE_FLAGS
mkdir "installed/lib-$arch"
cp "build-libs-$arch"/lib/*.a "installed/lib-$arch/"
cp "build-libs-$arch"/lib/* "installed/lib-$arch/"
6 changes: 3 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ jobs:
-DD_COMPILER_FLAGS="-O -flto=full -defaultlib=phobos2-ldc-lto,druntime-ldc-lto -L-exported_symbol '-L__*' -L-w"
-DEXTRA_CXXFLAGS=-flto=full
with_pgo: true
llvm_version: 17.0.6 # TODO

- job_name: Android armv7a
host_os: ubuntu-20.04
Expand All @@ -192,7 +193,6 @@ jobs:
timeout-minutes: 60
env:
MACOSX_DEPLOYMENT_TARGET: 11.0
LLVM_VERSION: 17.0.6 # TODO
steps:
- uses: actions/checkout@v4
with:
Expand All @@ -202,7 +202,7 @@ jobs:
uses: ./.github/actions/1-setup
with:
clang_version: ${{ env.CLANG_VERSION }}
llvm_version: ${{ env.LLVM_VERSION }}
llvm_version: ${{ matrix.llvm_version || env.LLVM_VERSION }}
arch: x86_64
- name: Build bootstrap LDC
uses: ./.github/actions/2-build-bootstrap
Expand All @@ -218,7 +218,7 @@ jobs:
with:
arch: ${{ matrix.arch }}
os: ${{ matrix.os }}
llvm_version: ${{ env.LLVM_VERSION }}
llvm_version: ${{ matrix.llvm_version || env.LLVM_VERSION }}
cmake_flags: ${{ matrix.extra_cmake_flags }}
with_pgo: ${{ matrix.with_pgo }}

Expand Down
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

#### Big news
- Frontend, druntime and Phobos are at version [2.108.0+](https://dlang.org/changelog/2.108.0.html). (#4591, #4615, #4619)
- Support for [LLVM 18](https://releases.llvm.org/18.1.0/docs/ReleaseNotes.html). The prebuilt packages use v18.1.3 (except for Android and macOS arm64). (#4599, #4605, #4607, #4604, #4622)
- Support for [LLVM 18](https://releases.llvm.org/18.1.0/docs/ReleaseNotes.html). The prebuilt packages use v18.1.3 (except for macOS arm64). (#4599, #4605, #4607, #4604, #4622)
- Android: Switch to native ELF TLS, supported since API level 29 (Android v10), dropping our former custom TLS emulation (requiring a modified LLVM and a legacy ld.bfd linker). The prebuilt packages themselves require Android v10+ (armv7a) / v11+ (aarch64) too, and are built with NDK r26d. Shared druntime and Phobos libraries are now available (`-link-defaultlib-shared`), as on regular Linux. (#4618)

#### Platform support
- Supports LLVM 11 - 18.

#### Bug fixes
- Android: Support the lld linker. (#3918)

# LDC 1.37.0 (2024-03-03)

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
3 changes: 1 addition & 2 deletions runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@ else()
endif()

set(SHARED_LIBS_SUPPORTED OFF)
if("${TARGET_SYSTEM}" MATCHES "Windows|Linux|FreeBSD|DragonFly|APPLE"
AND (NOT "${TARGET_SYSTEM}" MATCHES "Android"))
if("${TARGET_SYSTEM}" MATCHES "Windows|Linux|FreeBSD|DragonFly|APPLE")
set(SHARED_LIBS_SUPPORTED ON)
endif()

Expand Down
18 changes: 13 additions & 5 deletions runtime/druntime/src/core/sys/posix/dlfcn.d
Original file line number Diff line number Diff line change
Expand Up @@ -372,12 +372,20 @@ else version (Solaris)
}
else version (CRuntime_Bionic)
{
enum
enum RTLD_LOCAL = 0;
enum RTLD_LAZY = 0x00001;
enum RTLD_NOLOAD = 0x00004;
enum RTLD_NODELETE = 0x01000;

version (D_LP64)
{
enum RTLD_NOW = 0x00002;
enum RTLD_GLOBAL = 0x00100;
}
else // NDK: 'LP32 is broken for historical reasons'
{
RTLD_NOW = 0,
RTLD_LAZY = 1,
RTLD_LOCAL = 0,
RTLD_GLOBAL = 2
enum RTLD_NOW = 0;
enum RTLD_GLOBAL = 0x00002;
}

int dladdr(const scope void*, Dl_info*);
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
8 changes: 8 additions & 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 Expand Up @@ -1171,6 +1172,8 @@ else

version (LDC)
{
version (Android) version (X86) version = Android_X86;

version (PPC)
{
extern(C) void* __tls_get_addr_opt(tls_index* ti) nothrow @nogc;
Expand All @@ -1181,6 +1184,11 @@ version (LDC)
extern(C) void* __tls_get_addr_opt(tls_index* ti) nothrow @nogc;
alias __tls_get_addr = __tls_get_addr_opt;
}
else version (Android_X86) // extra underscore
{
extern(C) void* ___tls_get_addr(tls_index* ti) nothrow @nogc;
alias __tls_get_addr = ___tls_get_addr;
}
else
extern(C) void* __tls_get_addr(tls_index* ti) nothrow @nogc;
}
Expand Down

0 comments on commit 11908ed

Please sign in to comment.