forked from crytic/echidna
-
Notifications
You must be signed in to change notification settings - Fork 0
/
flake.nix
167 lines (154 loc) · 7.4 KB
/
flake.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
flake-utils.url = "github:numtide/flake-utils";
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
nix-bundle-exe = {
url = "github:3noch/nix-bundle-exe";
flake = false;
};
solc-pkgs = {
url = "github:hellwolf/solc.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, flake-utils, nix-bundle-exe, solc-pkgs, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [solc-pkgs.overlay];
};
# prefer musl on Linux, static glibc + threading does not work properly
# TODO: maybe only override it for echidna-redistributable?
pkgsStatic = if pkgs.stdenv.hostPlatform.isLinux then pkgs.pkgsStatic else pkgs;
# this is not perfect for development as it hardcodes solc to 0.5.7, test suite runs fine though
# 0.5.7 is not available on aarch64 darwin so alternatively pick 0.8.5
solc = solc-pkgs.mkDefault pkgs (pkgs.solc_0_5_7 or pkgs.solc_0_8_5);
secp256k1-static = pkgsStatic.secp256k1.overrideAttrs (attrs: {
configureFlags = attrs.configureFlags ++ [ "--enable-static" ];
});
ncurses-static = pkgsStatic.ncurses.override { enableStatic = true; };
hsPkgs = ps :
ps.haskellPackages.override {
overrides = hfinal: hprev: {
with-utf8 =
if (with ps.stdenv; hostPlatform.isDarwin && hostPlatform.isx86)
then ps.haskell.lib.compose.overrideCabal (_ : { extraLibraries = [ps.libiconv]; }) hprev.with-utf8
else hprev.with-utf8;
# TODO: temporary fix for static build which is still on 9.4
witch = ps.haskell.lib.doJailbreak hprev.witch;
};
};
hevm = pkgs: pkgs.lib.pipe ((hsPkgs pkgs).callCabal2nix "hevm" (pkgs.fetchFromGitHub {
owner = "ethereum";
repo = "hevm";
rev = "f1f45d3c0d9767a38df04f398d1eab8b66dbe7fc";
sha256 = "sha256-3zEUwcZm4uZZLecvFTgVTV5CAm4qMfKPbLdwO88LnrY=";
}) { secp256k1 = pkgs.secp256k1; })
([
pkgs.haskell.lib.compose.dontCheck
]);
echidna = pkgs: with pkgs; lib.pipe
((hsPkgs pkgs).callCabal2nix "echidna" ./. { hevm = hevm pkgs; })
([
# FIXME: figure out solc situation, it conflicts with the one from
# solc-select that is installed with slither, disable tests in the meantime
haskell.lib.compose.dontCheck
(haskell.lib.compose.addTestToolDepends [ haskellPackages.hpack slither-analyzer solc ])
(haskell.lib.compose.disableCabalFlag "static")
]);
echidna-static = with pkgsStatic; lib.pipe
(echidna pkgsStatic)
[
(haskell.lib.compose.appendConfigureFlags
[
"--extra-lib-dirs=${stripDylib (gmp.override { withStatic = true; })}/lib"
"--extra-lib-dirs=${stripDylib secp256k1-static}/lib"
"--extra-lib-dirs=${stripDylib (libff.override { enableStatic = true; })}/lib"
"--extra-lib-dirs=${zlib.override { static = true; shared = false; }}/lib"
"--extra-lib-dirs=${stripDylib (libffi.overrideAttrs (_: { dontDisableStatic = true; }))}/lib"
"--extra-lib-dirs=${stripDylib (ncurses-static)}/lib"
])
(haskell.lib.compose.enableCabalFlag "static")
];
# "static" binary for distribution
# on linux this is actually a real fully static binary
# on macos this has everything except libcxx and libsystem
# statically linked. we can be confident that these two will always
# be provided in a well known location by macos itself.
echidnaRedistributable = let
grep = "${pkgs.gnugrep}/bin/grep";
perl = "${pkgs.perl}/bin/perl";
otool = "${pkgs.darwin.binutils.bintools}/bin/otool";
install_name_tool = "${pkgs.darwin.binutils.bintools}/bin/install_name_tool";
codesign_allocate = "${pkgs.darwin.binutils.bintools}/bin/codesign_allocate";
codesign = "${pkgs.darwin.sigtool}/bin/codesign";
in if pkgs.stdenv.isLinux
then pkgs.runCommand "echidna-stripNixRefs" {} ''
mkdir -p $out/bin
cp ${pkgsStatic.haskell.lib.dontCheck echidna-static}/bin/echidna $out/bin/
# fix TERMINFO path in ncurses
${perl} -i -pe 's#(${ncurses-static}/share/terminfo)#"/etc/terminfo:/lib/terminfo:/usr/share/terminfo:/usr/lib/terminfo" . "\x0" x (length($1) - 65)#e' $out/bin/echidna
chmod 555 $out/bin/echidna
'' else pkgs.runCommand "echidna-stripNixRefs" {} ''
mkdir -p $out/bin
cp ${pkgsStatic.haskell.lib.dontCheck echidna-static}/bin/echidna $out/bin/
# get the list of dynamic libs from otool and tidy the output
libs=$(${otool} -L $out/bin/echidna | tail -n +2 | sed 's/^[[:space:]]*//' | cut -d' ' -f1)
# get the path for libcxx
cxx=$(echo "$libs" | ${grep} '^/nix/store/.*/libc++\.')
cxxabi=$(echo "$libs" | ${grep} '^/nix/store/.*/libc++abi\.')
iconv=$(echo "$libs" | ${grep} '^/nix/store/.*/libiconv\.')
# rewrite /nix/... library paths to point to /usr/lib
chmod 777 $out/bin/echidna
${install_name_tool} -change "$cxx" /usr/lib/libc++.1.dylib $out/bin/echidna
${install_name_tool} -change "$cxxabi" /usr/lib/libc++abi.dylib $out/bin/echidna
${install_name_tool} -change "$iconv" /usr/lib/libiconv.dylib $out/bin/echidna
# fix TERMINFO path in ncurses
${perl} -i -pe 's#(${ncurses-static}/share/terminfo)#"/usr/share/terminfo" . "\x0" x (length($1) - 19)#e' $out/bin/echidna
# check that no nix deps remain
nixdeps=$(${otool} -L $out/bin/echidna | tail -n +2 | { ${grep} /nix/store -c || test $? = 1; })
if [ ! "$nixdeps" = "0" ]; then
echo "Nix deps remain in redistributable binary!"
exit 255
fi
# re-sign binary
CODESIGN_ALLOCATE=${codesign_allocate} ${codesign} -f -s - $out/bin/echidna
chmod 555 $out/bin/echidna
'';
# if we pass a library folder to ghc via --extra-lib-dirs that contains
# only .a files, then ghc will link that library statically instead of
# dynamically (even if --enable-executable-static is not passed to cabal).
# we use this trick to force static linking of some libraries on macos.
stripDylib = drv : pkgs.runCommand "${drv.name}-strip-dylibs" {} ''
mkdir -p $out
mkdir -p $out/lib
cp -r ${drv}/* $out/
rm -rf $out/**/*.dylib
'';
in rec {
packages.echidna = echidna pkgs;
packages.default = echidna pkgs;
packages.echidna-redistributable = echidnaRedistributable;
devShell = with pkgs;
haskellPackages.shellFor {
packages = _: [ (echidna pkgs) ];
shellHook = ''
hpack
'';
buildInputs = [
solc
slither-analyzer
haskellPackages.hlint
haskellPackages.cabal-install
haskellPackages.haskell-language-server
];
withHoogle = true;
};
}
);
}