mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-11-04 19:27:55 +00:00
Enable ARM32 Android Template Haskell on emulated Linux builders
Scope the scheduling opt-out to the patched QEMU versions, patch the interpreter source before planning, and expose the real static Bionic and GNU iconv symbols. Use the RTS package dependency for Android libffi. The production interpreter reaches Haskell main on Rosetta and native ARM64 QEMU. Normal target TH, the ARM32 shared export, a C caller returning 42, and upstream annotations pass. Profiling execution is not yet validated.
This commit is contained in:
1 parent
6c5cc972ac
commit
748becda3e
5 files changed
+112
-9
No files matched your search
@@ -429,9 +429,8 @@
|
||||
}).simplex-chat.components.library {
|
||||
kind = "android";
|
||||
# Link the threaded RTS only at final link, outside TH/iserv.
|
||||
linkOptions = [
|
||||
"-optl-lffi"
|
||||
] ++ map (sym: "-optl-Wl,-u,${sym}") chatExports;
|
||||
# GHC 9.14's RTS package declares its bundled libffi archive.
|
||||
linkOptions = map (sym: "-optl-Wl,-u,${sym}") chatExports;
|
||||
postInstall = ''
|
||||
set -x
|
||||
${pkgs.tree}/bin/tree $out
|
||||
@@ -503,8 +502,8 @@
|
||||
}).simplex-chat.components.library {
|
||||
kind = "android";
|
||||
# Link the threaded RTS only at final link, outside TH/iserv.
|
||||
# GHC 9.14's RTS package declares its bundled libffi archive.
|
||||
linkOptions = [
|
||||
"-optl-lffi"
|
||||
"-optl-Wl,-z,max-page-size=16384"
|
||||
] ++ map (sym: "-optl-Wl,-u,${sym}") chatExports;
|
||||
postInstall = ''
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
final: prev:
|
||||
let
|
||||
lib = prev.lib;
|
||||
active = prev.stdenv.hostPlatform.isAndroid
|
||||
&& prev.stdenv.hostPlatform.isAarch32
|
||||
&& prev.stdenv.buildPlatform.isLinux;
|
||||
androidArm32 = prev.stdenv.hostPlatform.isAndroid
|
||||
&& prev.stdenv.hostPlatform.isAarch32;
|
||||
supportedEmulator = androidArm32
|
||||
&& prev.stdenv.buildPlatform.isLinux
|
||||
&& lib.versionAtLeast prev.pkgsBuildBuild.qemu.version "9.1"
|
||||
&& lib.versionOlder prev.pkgsBuildBuild.qemu.version "12";
|
||||
# Keep this outside the native compiler package sets. Only Android ARM32
|
||||
# Template Haskell and test wrappers need the guest personality fallback.
|
||||
emulator = import ./android-arm32-qemu.nix {
|
||||
@@ -13,7 +16,7 @@ let
|
||||
};
|
||||
exes = prev.haskell-nix.iserv-proxy-exes.ghc914-sh;
|
||||
mkTemplateHaskell = interpreterExes:
|
||||
{ inherit (prev.haskell-nix)
|
||||
{ inherit (final.haskell-nix)
|
||||
emulatorSystemFeatures emulatorNativeBuilderPackages; }
|
||||
// import (haskellNix + "/overlays/linux-cross.nix") {
|
||||
inherit (prev.stdenv) hostPlatform buildPlatform;
|
||||
@@ -25,8 +28,18 @@ let
|
||||
inherit (interpreterExes)
|
||||
iserv-proxy iserv-proxy-interpreter iserv-proxy-interpreter-prof;
|
||||
};
|
||||
in lib.optionalAttrs active {
|
||||
in lib.optionalAttrs androidArm32 {
|
||||
haskell-nix = prev.haskell-nix // {
|
||||
# Static-library symbol corrections do not depend on the emulator version.
|
||||
cabalProject' = projectModule: prev.haskell-nix.cabalProject' (
|
||||
[ ./android-iserv-project.nix ]
|
||||
++ (if builtins.isList projectModule then projectModule else [ projectModule ])
|
||||
);
|
||||
} // lib.optionalAttrs supportedEmulator {
|
||||
# Use the patched ARM32 emulator on local Linux builders too. This is the
|
||||
# supported haskell.nix opt-out from its native-builder scheduling marker;
|
||||
# other target package sets keep their existing restrictions.
|
||||
emulatorSystemFeatures = [];
|
||||
templateHaskell = prev.haskell-nix.templateHaskell // {
|
||||
ghc914-sh = mkTemplateHaskell exes // {
|
||||
evalWith = builtins.mapAttrs (_: mkTemplateHaskell) exes.evalWith;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
--- a/cbits/symbols.armv7a-android.c
|
||||
+++ b/cbits/symbols.armv7a-android.c
|
||||
@@ -5,6 +5,14 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
+
|
||||
+// Match GNU libiconv public prototypes without importing system headers
|
||||
+// that conflict with the legacy untyped declarations below. iconv_t is void*.
|
||||
+extern void *libiconv_open(const char *tocode, const char *fromcode);
|
||||
+extern size_t libiconv(void *cd, char **inbuf, size_t *inbytesleft,
|
||||
+ char **outbuf, size_t *outbytesleft);
|
||||
+extern int libiconv_close(void *cd);
|
||||
+extern const char *locale_charset(void);
|
||||
|
||||
extern void __aeabi_idiv(void);
|
||||
extern void __aeabi_idivmod(void);
|
||||
@@ -394,6 +402,12 @@
|
||||
|
||||
RtsSymbolVal my_iserv_syms[] = {
|
||||
// { "__sync_val_compare_and_swap_1", (void*)(&___sync_val_compare_and_swap_1), STRENGTH_NORMAL, 1 },
|
||||
+ // API 26 uses GNU libiconv. Static Bionic dlsym cannot expose these
|
||||
+ // definitions to loaded Haskell objects; register their real addresses.
|
||||
+ SYM(libiconv_open),
|
||||
+ SYM(libiconv),
|
||||
+ SYM(libiconv_close),
|
||||
+ SYM(locale_charset),
|
||||
SYM(strlen),
|
||||
SYM(__aeabi_idiv),
|
||||
SYM(__aeabi_idivmod),
|
||||
@@ -0,0 +1,20 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
lib.mkIf (
|
||||
pkgs.stdenv.hostPlatform.isAndroid
|
||||
&& pkgs.stdenv.hostPlatform.isAarch32
|
||||
&& config.compiler-nix-name == "ghc914-sh"
|
||||
&& config.name == "iserv-proxy"
|
||||
) {
|
||||
# Patch before Cabal planning: v2 hashes must describe the same source it
|
||||
# later packages. Bionic's real static libc routines must win at startup.
|
||||
src = lib.mkForce (pkgs.pkgsBuildBuild.applyPatches {
|
||||
name = "android-arm32-iserv-proxy-source";
|
||||
src = pkgs.haskell-nix.sources.iserv-proxy;
|
||||
patches = [
|
||||
./android-iserv-static-libc.patch
|
||||
# The API26 project declares GNU libiconv for ghc-internal. Its real
|
||||
# definitions need explicit registration in the static interpreter.
|
||||
./android-iserv-gnu-iconv.patch
|
||||
];
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
--- a/cbits/symbols.armv7a-android.c
|
||||
+++ b/cbits/symbols.armv7a-android.c
|
||||
@@ -353,34 +353,10 @@
|
||||
MISSING_FUN(__loader_add_thread_local_dtor)
|
||||
MISSING_FUN(__loader_remove_thread_local_dtor)
|
||||
MISSING_FUN(__clang_call_terminate)
|
||||
-// Symbols absent from the armv7a Android NDK's bionic / libc++ as
|
||||
-// shipped with our current toolchain. The dynamic linker would
|
||||
-// otherwise fail to load this library when it sees the unresolved
|
||||
-// references via `SYM(...)` below. These stubs are never expected
|
||||
-// to be invoked at runtime; if a real call ever lands here we
|
||||
-// `exit(1)` with a diagnostic so the caller is visible instead of
|
||||
-// silently corrupting state.
|
||||
-MISSING_FUN(__arm_fadvise64_64)
|
||||
-MISSING_FUN(__cxa_guard_abort)
|
||||
-MISSING_FUN(__cxa_guard_acquire)
|
||||
-MISSING_FUN(__cxa_guard_release)
|
||||
-MISSING_FUN(__cxa_thread_finalize)
|
||||
-MISSING_FUN(__fsetxattr)
|
||||
-MISSING_FUN(__libc_stdio_cleanup)
|
||||
-MISSING_FUN(_Z21__libc_shared_globalsv)
|
||||
-MISSING_FUN(getentropy)
|
||||
-MISSING_FUN(posix_spawn_file_actions_addchdir_np)
|
||||
-MISSING_FUN(posix_spawn_file_actions_addclose)
|
||||
-MISSING_FUN(posix_spawn_file_actions_adddup2)
|
||||
-MISSING_FUN(posix_spawn_file_actions_addopen)
|
||||
-MISSING_FUN(posix_spawn_file_actions_destroy)
|
||||
-MISSING_FUN(posix_spawn_file_actions_init)
|
||||
-MISSING_FUN(posix_spawnattr_destroy)
|
||||
-MISSING_FUN(posix_spawnattr_init)
|
||||
-MISSING_FUN(posix_spawnattr_setflags)
|
||||
-MISSING_FUN(posix_spawnattr_setsigdefault)
|
||||
-MISSING_FUN(posix_spawnp)
|
||||
-MISSING_FUN(statx)
|
||||
+// Bionic defines these functions in its static libc.a, including private
|
||||
+// startup routines absent from the API-specific shared libc.so stubs. Keep
|
||||
+// the extern/SYM references below so GHCi uses the same real libc state;
|
||||
+// defining MISSING_FUN replacements here would shadow those implementations.
|
||||
|
||||
typedef void SymbolAddr;
|
||||
typedef char SymbolName;
|
||||
Reference in new issue
Block a user