Files
simplex-chat/flake.nix
T
Moritz Angermann 748becda3e 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.
2026-10-16 13:22:52 +09:00

680 lines
33 KiB
Nix

{
description = "nix flake for simplex-chat";
# hkm/stable-haskell: use the same compiler and boot libraries on every target.
inputs.haskellNix.url = "github:input-output-hk/haskell.nix/54c49b7badca29e8b746fe8681d9bd70086e308a";
inputs.nixpkgs.follows = "haskellNix/nixpkgs";
inputs.mac2ios.url = "github:zw3rk/mobile-core-tools";
inputs.hackage = {
# Match the compiler integration's package index to reuse its cached builds.
url = "github:input-output-hk/hackage.nix/dc08bb4627efd6ff85d421b6dde5f52ada218afa";
flake = false;
};
inputs.haskellNix.inputs.hackage.follows = "hackage";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, haskellNix, nixpkgs, flake-utils, mac2ios, ... }:
let systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; in
flake-utils.lib.eachSystem systems (system:
# Preserve Android 8 as the minimum native API for both architectures.
let android26 = final: prev: {
pkgsCross = prev.pkgsCross // {
aarch64-android-prebuilt = import prev.path {
inherit system;
overlays = prev.overlays ++ [ (import ./scripts/nix/android-iconv-overlay.nix) ];
# Permit the SDK/NDK's unfree packages only in these Android sets.
# Some SDK fetchers use unprefixed names such as platform-tools.
config = prev.config // { allowUnfree = true; };
crossSystem = prev.lib.systems.examples.aarch64-android-prebuilt // { androidSdkVersion = "26"; };
};
armv7a-android-prebuilt = import prev.path {
inherit system;
overlays = prev.overlays ++ [ (import ./scripts/nix/android-iconv-overlay.nix) ];
# Permit the SDK/NDK's unfree packages only in these Android sets.
# Some SDK fetchers use unprefixed names such as platform-tools.
config = prev.config // { allowUnfree = true; };
crossSystem = prev.lib.systems.examples.armv7a-android-prebuilt // { androidSdkVersion = "26"; };
};
};
}; in
# `appendOverlays` with a singleton is identical to `extend`.
let nativePackages = import ./scripts/nix/native-packages.nix { inherit haskellNix; }; in
let compilerCache = import ./scripts/nix/compiler-cache-overlay.nix { inherit haskellNix; }; in
let androidEmulator = import ./scripts/nix/android-emulator-overlay.nix { inherit haskellNix; }; in
let pkgs = (nativePackages system).appendOverlays [android26 compilerCache androidEmulator]; in
let compilerSelection = import ./scripts/nix/compiler-selection.nix { inherit haskellNix; }; in
let mobileRuntime = import ./scripts/nix/mobile-runtime.nix { inherit pkgs compilerSelection; }; in
let drv' = { extra-modules, pkgs', package-flags ? {}, package-ghc-options ? {}, mobile ? false, ... }:
let packageFlags = pkgs.lib.recursiveUpdate {
direct-sqlcipher = { openssl = true; commoncrypto = false; tomcrypt = false; };
} package-flags;
packageGhcOptions = pkgs.lib.recursiveUpdate
(pkgs.lib.optionalAttrs pkgs'.stdenv.hostPlatform.isAndroid {
simplex-chat = [ "-pie" ];
}) package-ghc-options;
# Cabal 3.17 drops repeated option names in hsc2hs arguments. The
# Darwin archives need both -framework Security and CoreFoundation.
projectPkgs = if mobile && pkgs'.stdenv.hostPlatform.isDarwin
then pkgs'.appendOverlays [ (import ./scripts/nix/cabal-tool-overlay.nix) ]
else pkgs';
in projectPkgs.haskell-nix.project ({ config, ... }: {
compiler-nix-name = "ghc914-sh";
inherit compilerSelection;
# We need this, to specify we want the cabal project.
# If the stack.yaml was dropped, this would not be necessary.
projectFileName = "cabal.project";
# The v2 builder follows planned flags for source-repository packages.
# Render the same flags before planning and into the package modules.
cabalProjectLocal = pkgs.lib.concatStringsSep "\n" (
pkgs.lib.mapAttrsToList (package: flags: ''
package ${package}
flags: ${pkgs.lib.concatStringsSep " " (
pkgs.lib.mapAttrsToList (flag: enabled: "${if enabled then "+" else "-"}${flag}") flags
)}
'') packageFlags
) + "\n" + pkgs.lib.concatStringsSep "\n" (
pkgs.lib.mapAttrsToList (package: options: ''
package ${package}
ghc-options: ${pkgs.lib.concatStringsSep " " options}
'') packageGhcOptions
) + pkgs.lib.optionalString pkgs'.stdenv.hostPlatform.isDarwin ''
-- The compiler's ghc-internal package omits iconv's library directory.
package *
extra-lib-dirs: ${pkgs'.libiconv}/lib
'' + pkgs.lib.optionalString (mobile && pkgs'.stdenv.hostPlatform.isDarwin && pkgs'.stdenv.hostPlatform.isAarch64) ''
-- Keep every app C/C++ stub compatible with the same iOS ARM baseline.
package *
ghc-options: -optc-mcpu=apple-a7 -optc-march=armv8-a+norcpc -optcxx-mcpu=apple-a7 -optcxx-march=armv8-a+norcpc
'';
src = pkgs.haskell-nix.haskellLib.cleanSourceWith {
name = "simplex-chat";
src = pkgs.haskell-nix.haskellLib.cleanGit {
name = "simplex-chat";
src = ./.;
};
# This generated website asset is deployed separately, not as Cabal
# data. Its checkout symlink is dangling until the website is built,
# while the v2 source packager dereferences every included symlink.
filter = path: type: !(type == "symlink" && pkgs.lib.hasSuffix
"/apps/simplex-directory-service/web/directory.js" (toString path));
};
sha256map = import ./scripts/nix/sha256map.nix;
# The v2 builder compiles source-repository packages from a separate
# minimal Git repository, which currently skips package.patches.
# Patch the input before planning so both source paths agree.
inputMap = import ./scripts/nix/source-repository-patches.nix {
pkgs = config.evalPackages;
cabalProject = builtins.readFile ./cabal.project;
sha256map = import ./scripts/nix/sha256map.nix;
patchesByUrl = {
"https://github.com/simplex-chat/direct-sqlcipher.git" =
if pkgs'.stdenv.hostPlatform.isWindows
then [ ./scripts/nix/direct-sqlcipher-2.3.27-win.patch ]
else [ ./scripts/nix/direct-sqlcipher-2.3.27.patch ]
++ pkgs.lib.optional pkgs'.stdenv.hostPlatform.isAndroid
./scripts/nix/direct-sqlcipher-android-log.patch;
} // pkgs.lib.optionalAttrs pkgs'.stdenv.hostPlatform.isDarwin {
"https://github.com/simplex-chat/simplexmq.git" =
[ ./scripts/nix/simplexmq-blst-darwin-extern.patch ];
};
};
modules = [
{ packages = pkgs.lib.recursiveUpdate
(pkgs.lib.mapAttrs (_: flags: { inherit flags; }) packageFlags)
(pkgs.lib.mapAttrs (_: ghcOptions: { inherit ghcOptions; }) packageGhcOptions);
}
({ pkgs, lib, config, ... }:
{
# Override ghcOptions for ALL packages
ghcOptions = lib.mkDefault [
"-j1"
];
}
)
] ++ pkgs.lib.optional pkgs'.stdenv.hostPlatform.isAndroid mobileRuntime.androidModule ++ extra-modules;
}); in
# by defualt we don't need to pass extra-modules.
let drv = pkgs': drv' { extra-modules = []; inherit pkgs'; }; in
let inherit (import ./scripts/nix/mobile-library.nix { inherit pkgs; })
withComponentPhases withMobileLibrary; in
let chatExports = [
"chat_close_store"
"chat_decrypt_file"
"chat_decrypt_media"
"chat_encrypt_file"
"chat_encrypt_media"
"chat_migrate_init"
"chat_migrate_init_key"
"chat_migrate_init_queue"
"chat_parse_markdown"
"chat_parse_server"
"chat_parse_uri"
"chat_password_hash"
"chat_read_file"
"chat_recv_msg"
"chat_recv_msg_wait"
"chat_reopen_store"
"chat_send_cmd"
"chat_send_cmd_retry"
"chat_send_remote_cmd"
"chat_send_remote_cmd_retry"
"chat_valid_name"
"chat_parse_badge_code"
"chat_json_length"
"chat_badge_keygen"
"chat_badge_issue"
"chat_write_file"
]; in
# This will package up all *.a in $out into a pkg.zip that can
# be downloaded from hydra.
let withHydraLibPkg = pkg: pkg.overrideAttrs (old: {
postInstall = ''
mkdir -p $out/_pkg
find $out/lib -name "*.a" -exec cp {} $out/_pkg \;
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/pkg.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
}); in
let darwinOpenSSL = mobileRuntime.darwinCLibrary (pkgs.openssl.override { static = true; }); in
let iosPostInstall = bundleName: ''
${pkgs.tree}/bin/tree $out
mkdir tmp
find ./dist -name "libHS*-ghc*.a" -exec cp {} tmp \;
(cd tmp; ${pkgs.tree}/bin/tree .; ar x libHS*.a; for o in *.o; do if /usr/bin/otool -xv $o|grep ldadd ; then echo $o; fi; done; cd ..; rm -fR tmp)
mkdir -p $out/_pkg
# copy over includes, we might want those, but maybe not.
# cp -r $out/lib/*/*/include $out/_pkg/
# find the libHS...ghc-X.Y.Z.a static library; this is the
# rolled up one with all dependencies included.
find ./dist -name "libHS*.a" -exec cp {} $out/_pkg \;
find ${mobileRuntime.darwinCLibrary (pkgs.libffi.overrideAttrs (old: { dontDisableStatic = true; }))}/lib -name "*.a" -exec cp {} $out/_pkg \;
find ${mobileRuntime.darwinCLibrary (pkgs.gmp6.override { withStatic = true; })}/lib -name "*.a" -exec cp {} $out/_pkg \;
# There is no static libc
${pkgs.tree}/bin/tree $out/_pkg
for pkg in $out/_pkg/*.a; do
chmod +w $pkg
${mac2ios.packages.${system}.mac2ios}/bin/mac2ios $pkg
[[ "$pkg" == *simplex-chat* ]] && ${pkgs.stdenv.cc.targetPrefix}strip -x $pkg
chmod -w $pkg
done
mkdir tmp
find $out/_pkg -name "libHS*-ghc*.a" -exec cp {} tmp \;
(cd tmp; ${pkgs.tree}/bin/tree .; ar x libHS*.a; for o in *.o; do if /usr/bin/otool -xv $o|grep ldadd ; then echo $o; fi; done; cd ..; rm -fR tmp)
sha256sum $out/_pkg/*.a
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/${bundleName}.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
''; in
let iosOverrides = bundleName: {
kind = "ios";
packageDbs = mobileRuntime.darwinPackageDbs;
postInstall = iosPostInstall bundleName;
}; in
rec {
packages = {
"lib:simplex-chat" = (drv pkgs).simplex-chat.components.library;
"exe:simplex-chat" = (drv pkgs).simplex-chat.components.exes.simplex-chat;
} // ({
"x86_64-linux" =
let
androidPkgs = pkgs.pkgsCross.aarch64-android-prebuilt;
android32Pkgs = pkgs.pkgsCross.armv7a-android-prebuilt;
# Similarly to icovn, for reasons beyond my current knowledge, nixpkgs andorid
# toolchain makes configure believe we have MEMFD_CREATE, which we don't in
# sdk 23.
androidFFI = androidPkgs.libffi.overrideAttrs (old: {
dontDisableStatic = true;
hardeningDisable = [ "fortify" ];
});
android32FFI = android32Pkgs.libffi.overrideAttrs (old: {
dontDisableStatic = true;
hardeningDisable = [ "fortify" ];
}
);in {
# STATIC x86_64-linux
"${pkgs.pkgsCross.musl64.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.musl64).simplex-chat.components.exes.simplex-chat;
# STATIC i686-linux
"${pkgs.pkgsCross.musl32.hostPlatform.system}-static:exe:simplex-chat" = (drv' {
pkgs' = pkgs.pkgsCross.musl32;
extra-modules = [{
# 32 bit patches
packages.basement.patches = [
./scripts/nix/basement-pr-573.patch
];
packages.memory.patches = [
./scripts/nix/memory-pr-99.patch
];
}];
}).simplex-chat.components.exes.simplex-chat;
# WINDOWS x86_64-mingwW64
"${pkgs.pkgsCross.mingwW64.hostPlatform.system}:exe:simplex-chat" = withComponentPhases (drv' {
pkgs' = pkgs.pkgsCross.mingwW64;
package-flags = {
direct-sqlcipher.openssl = true;
bitvec.simd = false;
};
extra-modules = [{
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
(pkgs.pkgsCross.mingwW64.openssl) #.override) # { static = true; enableKTLS = false; })
];
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
(pkgs.pkgsCross.mingwW64.openssl) #.override) # { static = true; enableKTLS = false; })
];
packages.unix-time.postPatch = ''
sed -i 's/mingwex//g' unix-time.cabal
'';
}];
}).simplex-chat.components.exes.simplex-chat (old: {
installPhase = old.installPhase + ''
set -x
${pkgs.tree}/bin/tree $out
mkdir -p $out/_pkg
cp $out/bin/* $out/_pkg
${pkgs.tree}/bin/tree $out/_pkg
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/${pkgs.pkgsCross.mingwW64.hostPlatform.system}-simplex-chat.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
});
"${pkgs.pkgsCross.mingwW64.hostPlatform.system}:lib:simplex-chat" = withMobileLibrary (drv' rec {
pkgs' = pkgs.pkgsCross.mingwW64;
package-flags = {
direct-sqlcipher.openssl = true;
# simd will try to read __cpu_model, which we don't expose
# from the rts (yet!).
bitvec.simd = false;
simplex-chat.client_library = true;
simplexmq.client_library = true;
};
extra-modules = [{
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
pkgs.pkgsCross.mingwW64.openssl
];
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
pkgs.pkgsCross.mingwW64.openssl
];
packages.unix-time.postPatch = ''
sed -i 's/mingwex//g' unix-time.cabal
'';
}];
}).simplex-chat.components.library
{
kind = "windows";
linkOptions = [
"-optl-lffi"
"-optl-Wl,--out-implib,libsimplex.dll.a"
"${./libsimplex.dll.def}"
];
postInstall = ''
set -x
function deps() {
${pkgs.binutils}/bin/strings "$1" | grep '.\.dll'|grep -v -E 'Winsock|ADVAPI32|dbghelp|KERNEL32|msvcrt|ntdll|ole32|RPCRT4|SHELL32|USER32|WINMM|WS2_32|kernel32|GDI32'|grep -v "$1"
}
${pkgs.tree}/bin/tree $out
mkdir -p $out/_pkg
cp libsimplex.dll $out/_pkg
cp libsimplex.dll.a $out/_pkg
mkdir $out/libs
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.openssl} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.libffi} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.gmp} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.stdenv.cc.cc} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.windows.mcfgthreads} -name "*.dll" -exec cp {} $out/libs \;
pushd $out/_pkg
function copyDeps() {
for dep in $(deps "$1"); do
if [ ! -f "$dep" ]; then
if [ ! -f ../libs/"$dep" ]; then
echo "WARN: $1 -> $dep not found!"
else
cp ../libs/"$dep" .
copyDeps "$dep"
fi
fi
done
}
copyDeps libsimplex.dll
popd
${pkgs.tree}/bin/tree $out/_pkg
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/pkg-${pkgs.pkgsCross.mingwW64.hostPlatform.system}-libsimplex.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
# "${pkgs.pkgsCross.muslpi.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.muslpi).simplex-chat.components.exes.simplex-chat;
# STATIC aarch64-linux
"${pkgs.pkgsCross.aarch64-multiplatform-musl.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.aarch64-multiplatform-musl).simplex-chat.components.exes.simplex-chat;
"armv7a-android:lib:support" = withMobileLibrary (drv android32Pkgs).android-support.components.library {
kind = "android-support";
packageName = "android-support";
linkOptions = [
"-optl-Wl,-u,setLineBuffering"
"-optl-Wl,-u,pipe_std_to_socket"
];
postInstall = ''
mkdir -p $out/_pkg
cp libsupport.so $out/_pkg
${pkgs.patchelf}/bin/patchelf --remove-needed libunwind.so.1 $out/_pkg/libsupport.so
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/pkg-armv7a-android-libsupport.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
# The android-support package is at
# https://github.com/simplex-chat/android-support
"aarch64-android:lib:support" = withMobileLibrary (drv androidPkgs).android-support.components.library {
kind = "android-support";
packageName = "android-support";
linkOptions = [
"-optl-Wl,-u,setLineBuffering"
"-optl-Wl,-u,pipe_std_to_socket"
"-optl-Wl,-z,max-page-size=16384"
];
postInstall = ''
mkdir -p $out/_pkg
cp libsupport.so $out/_pkg
ls -lah $out/_pkg/*
${pkgs.patchelf}/bin/patchelf --remove-needed libunwind.so.1 $out/_pkg/libsupport.so
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/pkg-aarch64-android-libsupport.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
"armv7a-android:lib:simplex-chat" = withMobileLibrary (drv' {
pkgs' = android32Pkgs;
package-flags = {
text.simdutf = false;
direct-sqlcipher.openssl = true;
simplex-chat.client_library = true;
simplexmq.client_library = true;
};
extra-modules = [{
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
(android32Pkgs.openssl.override { static = true; enableKTLS = false; })
];
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
(android32Pkgs.openssl.override { static = true; enableKTLS = false; })
];
# 32 bit patches
packages.basement.patches = [
./scripts/nix/basement-pr-573.patch
];
packages.memory.patches = [
./scripts/nix/memory-pr-99.patch
];
}];
}).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 = map (sym: "-optl-Wl,-u,${sym}") chatExports;
postInstall = ''
set -x
${pkgs.tree}/bin/tree $out
mkdir -p $out/_pkg
# copy over includes, we might want those, but maybe not.
# cp -r $out/lib/*/*/include $out/_pkg/
# find the libHS...ghc-X.Y.Z.a static library; this is the
# rolled up one with all dependencies included.
cp libsimplex.so $out/_pkg
# find ./dist -name "lib*.so" -exec cp {} $out/_pkg \;
# find ./dist -name "libHS*-ghc*.a" -exec cp {} $out/_pkg \;
# find ${android32FFI}/lib -name "*.a" -exec cp {} $out/_pkg \;
# find ${android32Pkgs.gmp6.override { withStatic = true; }}/lib -name "*.a" -exec cp {} $out/_pkg \;
# find ${android32Pkgs.stdenv.cc.libc}/lib -name "*.a" -exec cp {} $out/_pkg \;
echo ${android32Pkgs.openssl.override { enableKTLS = false; }}
find ${(android32Pkgs.openssl.override { enableKTLS = false; }).out}/lib -name "*.so" -exec cp {} $out/_pkg \;
# remove the .1 and other version suffixes from .so's. Androids linker
# doesn't play nice with them.
for lib in $out/_pkg/*.so; do
for dep in $(${pkgs.patchelf}/bin/patchelf --print-needed "$lib"); do
if [[ "''${dep##*.so}" ]]; then
echo "$lib : $dep -> ''${dep%%.so*}.so"
chmod +w "$lib"
${pkgs.patchelf}/bin/patchelf --replace-needed "$dep" "''${dep%%.so*}.so" "$lib"
fi
done
done
for lib in $out/_pkg/*.so; do
chmod +w "$lib"
${pkgs.patchelf}/bin/patchelf --remove-needed libunwind.so "$lib"
[[ "$lib" != *libsimplex.so ]] && ${pkgs.patchelf}/bin/patchelf --set-soname "$(basename -a $lib)" "$lib"
done
${pkgs.tree}/bin/tree $out/_pkg
# Strip from debug symbols
find "$out/_pkg" -type f -name "*.so" -exec ${android32Pkgs.stdenv.cc.targetPrefix}strip --strip-unneeded {} +
# Normalize permissions + timestamps
find "$out/_pkg" -type f -exec chmod 644 {} +
find "$out/_pkg" -type d -exec chmod 755 {} +
find "$out/_pkg" -exec touch -h -d '@1764547200' {} +
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 -X $out/pkg-armv7a-android-libsimplex.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
"aarch64-android:lib:simplex-chat" = withMobileLibrary (drv' {
pkgs' = androidPkgs;
package-flags = {
text.simdutf = false;
direct-sqlcipher.openssl = true;
simplex-chat.client_library = true;
simplexmq.client_library = true;
};
extra-modules = [{
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
(androidPkgs.openssl.override { static = true; })
];
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
(androidPkgs.openssl.override { static = true; })
];
}];
}).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-Wl,-z,max-page-size=16384"
] ++ map (sym: "-optl-Wl,-u,${sym}") chatExports;
postInstall = ''
set -x
${pkgs.tree}/bin/tree $out
mkdir -p $out/_pkg
# copy over includes, we might want those, but maybe not.
# cp -r $out/lib/*/*/include $out/_pkg/
# find the libHS...ghc-X.Y.Z.a static library; this is the
# rolled up one with all dependencies included.
cp libsimplex.so $out/_pkg
# find ./dist -name "lib*.so" -exec cp {} $out/_pkg \;
# find ./dist -name "libHS*-ghc*.a" -exec cp {} $out/_pkg \;
# find ${androidFFI}/lib -name "*.a" -exec cp {} $out/_pkg \;
# find ${androidPkgs.gmp6.override { withStatic = true; }}/lib -name "*.a" -exec cp {} $out/_pkg \;
# find ${androidPkgs.stdenv.cc.libc}/lib -name "*.a" -exec cp {} $out/_pkg \;
echo ${androidPkgs.openssl}
find ${androidPkgs.openssl.out}/lib -name "*.so" -exec cp {} $out/_pkg \;
# remove the .1 and other version suffixes from .so's. Androids linker
# doesn't play nice with them.
for lib in $out/_pkg/*.so; do
for dep in $(${pkgs.patchelf}/bin/patchelf --print-needed "$lib"); do
if [[ "''${dep##*.so}" ]]; then
echo "$lib : $dep -> ''${dep%%.so*}.so"
chmod +w "$lib"
${pkgs.patchelf}/bin/patchelf --replace-needed "$dep" "''${dep%%.so*}.so" "$lib"
fi
done
done
for lib in $out/_pkg/*.so; do
chmod +w "$lib"
${pkgs.patchelf}/bin/patchelf --remove-needed libunwind.so "$lib"
[[ "$lib" != *libsimplex.so ]] && ${pkgs.patchelf}/bin/patchelf --set-soname "$(basename -a $lib)" "$lib"
done
${pkgs.tree}/bin/tree $out/_pkg
# Strip from debug symbols
find "$out/_pkg" -type f -name "*.so" -exec ${androidPkgs.stdenv.cc.targetPrefix}strip --strip-unneeded {} +
# Normalize permissions + timestamps
find "$out/_pkg" -type f -exec chmod 644 {} +
find "$out/_pkg" -type d -exec chmod 755 {} +
find "$out/_pkg" -exec touch -h -d '@1764547200' {} +
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 -X $out/pkg-aarch64-android-libsimplex.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
};
# builds for iOS and iOS simulator
"aarch64-darwin" = {
# aarch64-darwin iOS build (to be patched with mac2ios)
"aarch64-darwin-ios:lib:simplex-chat" = withMobileLibrary (drv' {
pkgs' = pkgs;
mobile = true;
package-ghc-options.simplex-chat = [ "-DIOS" ];
package-flags = {
simplex-chat.swift = true;
simplexmq.swift = true;
direct-sqlcipher.commoncrypto = true;
direct-sqlcipher.openssl = false;
simplexmq.commoncrypto = true;
entropy.DoNotGetEntropy = true;
simplex-chat.client_library = true;
simplexmq.client_library = true;
};
extra-modules = [{
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
# TODO: have a cross override for iOS, that sets this.
darwinOpenSSL
];
}];
}).simplex-chat.components.library (
iosOverrides "pkg-ios-aarch64-swift-json"
);
# aarch64-darwin build with tagged JSON format (for Mac & Flutter)
"aarch64-darwin:lib:simplex-chat" = withMobileLibrary (drv' {
pkgs' = pkgs;
mobile = true;
package-ghc-options.simplex-chat = [ "-DIOS" ];
package-flags = {
direct-sqlcipher.commoncrypto = true;
direct-sqlcipher.openssl = false;
simplexmq.commoncrypto = true;
entropy.DoNotGetEntropy = true;
simplex-chat.client_library = true;
simplexmq.client_library = true;
};
extra-modules = [{
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
darwinOpenSSL
];
}];
}).simplex-chat.components.library (
iosOverrides "pkg-ios-aarch64-tagged-json"
);
};
"x86_64-darwin" = {
# x86_64-darwin iOS simulator build (to be patched with mac2ios)
"x86_64-darwin-ios:lib:simplex-chat" = withMobileLibrary (drv' {
pkgs' = pkgs;
mobile = true;
package-ghc-options.simplex-chat = [ "-DIOS" ];
package-flags = {
simplex-chat.swift = true;
simplexmq.swift = true;
direct-sqlcipher.commoncrypto = true;
direct-sqlcipher.openssl = false;
simplexmq.commoncrypto = true;
entropy.DoNotGetEntropy = true;
simplex-chat.client_library = true;
simplexmq.client_library = true;
};
extra-modules = [{
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
darwinOpenSSL
];
}];
}).simplex-chat.components.library (
iosOverrides "pkg-ios-x86_64-swift-json"
);
# x86_64-darwin build with tagged JSON format (for Mac & Flutter iOS simulator)
"x86_64-darwin:lib:simplex-chat" = withMobileLibrary (drv' {
pkgs' = pkgs;
mobile = true;
package-ghc-options.simplex-chat = [ "-DIOS" ];
package-flags = {
direct-sqlcipher.commoncrypto = true;
direct-sqlcipher.openssl = false;
simplexmq.commoncrypto = true;
entropy.DoNotGetEntropy = true;
simplex-chat.client_library = true;
simplexmq.client_library = true;
};
extra-modules = [{
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
darwinOpenSSL
];
}];
}).simplex-chat.components.library (
iosOverrides "pkg-ios-x86_64-tagged-json"
);
};
}.${system} or {});
# build all packages in hydra.
hydraJobs = packages;
devShell = let
updateCmd = pkgs.writeShellApplication {
name = "update-sha256map";
runtimeInputs = [ pkgs.nix-prefetch-git pkgs.jq pkgs.gawk ];
text = ''
gawk -f ./scripts/nix/update-sha256.awk cabal.project > ./scripts/nix/sha256map.nix
'';
}; in
(drv pkgs).shellFor {
withHoogle = false;
buildInputs = pkgs.lib.optionals pkgs.stdenv.hostPlatform.isDarwin [ pkgs.libiconv ];
nativeBuildInputs = [
updateCmd
pkgs.haskell-nix.nix-tools-unchecked-sh.exes.cabal
];
};
}
);
}