Files
simplex-chat/flake.nix
T
Moritz Angermann 89ffaea1be Allow musl cross interpreters to load C dependencies
Keep static Haskell libraries and fully static application outputs while planning ghc914-sh iserv projects with a dynamic musl C loader. Scope the policy to Linux-built musl Cabal v2 interpreters and check that scope in static Linux CI.

Normal and profiled target plans preserve all unit IDs, source records and Haskell ways; only the iserv executable-static flag changes. The shared V2 project skeleton changes auxiliary derivation hashes. A small i686 musl probe reproduces static dlopen failure and verifies the dynamic loader under QEMU; full interpreter TH validation remains for canonical CI.
2026-10-17 02:17:58 +09:00

684 lines
34 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 muslIserv = import ./scripts/nix/musl-iserv-overlay.nix; in
let pkgs = (nativePackages system).appendOverlays [android26 compilerCache androidEmulator muslIserv]; 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 (config.compiler-nix-name == "ghc914-sh"
&& pkgs'.stdenv.buildPlatform.config != pkgs'.stdenv.hostPlatform.config) ''
-- composition deliberately avoids base, but GHC 9.14's wired-in
-- function types still need ghc-internal in a cross slice's DB.
-- Patch before planning so the v2 slice declares the same dependency.
packages: ${import ./scripts/nix/composition-source.nix { pkgs = config.evalPackages; }}
'' + 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.optional pkgs'.stdenv.hostPlatform.isMusl
./scripts/nix/direct-sqlcipher-static-libraries.patch;
} // pkgs.lib.optionalAttrs pkgs'.stdenv.hostPlatform.isDarwin {
"https://github.com/simplex-chat/simplexmq.git" =
[ ./scripts/nix/simplexmq-blst-darwin-extern.patch ];
} // pkgs.lib.optionalAttrs pkgs'.stdenv.hostPlatform.isMusl {
# -fully-static uses each producer's registered static C libraries.
"https://github.com/simplex-chat/simplexmq.git" =
[ ./scripts/nix/simplexmq-static-libraries.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.isWindows ({ lib, ... }: {
# Remove when the pin includes https://github.com/input-output-hk/haskell.nix/pull/2586.
packages.crypton-x509-system.patches = lib.mkForce [
({ version }:
if builtins.compareVersions version "1.6.8" < 0
then "${haskellNix}/overlays/patches/crypton-x509-system-1.6.patch"
else "${haskellNix}/overlays/patches/crypton-x509-system.patch")
];
# HANDLE needs a signed pointer-width constant. Convert via Int:
# Basement's RebindableSyntax has no HasNegation IntPtr instance.
packages.basement.patches = lib.mkAfter [ ./scripts/nix/basement-windows-intptr.patch ];
}) ++ 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 = import ./scripts/nix/chat-exports.nix; 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;
checks = pkgs.lib.optionalAttrs (system == "x86_64-linux") {
ghc-elf-alignment = import ./scripts/nix/check-elf-alignment.nix {
inherit pkgs;
compiler = (compilerSelection pkgs).ghc914-sh;
};
};
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
];
};
}
);
}