forked from ethereum/hevm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathflake.nix
159 lines (141 loc) · 6.18 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
{
description = "hevm";
inputs = {
flake-utils.url = "github:numtide/flake-utils";
nixpkgs.url = "github:nixos/nixpkgs";
# nixpkgs with working solc
nixpkgs-solc.url = "github:nixos/nixpkgs/1b71def42b74811323de2df52f180b795ec506fc";
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
solidity = {
url = "github:ethereum/solidity/1c8745c54a239d20b6fb0f79a8bd2628d779b27e";
flake = false;
};
ethereum-tests = {
url = "github:ethereum/tests/v11.2";
flake = false;
};
};
outputs = { self, nixpkgs, nixpkgs-solc, flake-utils, solidity, ethereum-tests, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
solc' = nixpkgs-solc.legacyPackages.${system}.solc;
secp256k1-static = stripDylib (pkgs.secp256k1.overrideAttrs (attrs: {
configureFlags = attrs.configureFlags ++ [ "--enable-static" ];
}));
hevmUnwrapped = (with pkgs; lib.pipe (
haskellPackages.callCabal2nix "hevm" ./. {
# Haskell libs with the same names as C libs...
# Depend on the C libs, not the Haskell libs.
# These are system deps, not Cabal deps.
inherit secp256k1;
})
[
(haskell.lib.compose.overrideCabal (old: { testTarget = "test"; }))
(haskell.lib.compose.addTestToolDepends [ solc' z3 cvc5 go-ethereum ])
(haskell.lib.compose.appendConfigureFlags (
[ "-fci"
"-O2"
"--extra-lib-dirs=${stripDylib (pkgs.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.static}/lib"
"--extra-lib-dirs=${stripDylib (libffi.overrideAttrs (_: { dontDisableStatic = true; }))}/lib"
"--extra-lib-dirs=${stripDylib (ncurses.override { enableStatic = true; })}/lib"
]
++ lib.optionals stdenv.isLinux [
"--enable-executable-static"
# TODO: replace this with musl: https://stackoverflow.com/a/57478728
"--extra-lib-dirs=${glibc}/lib"
"--extra-lib-dirs=${glibc.static}/lib"
]))
haskell.lib.dontHaddock
]).overrideAttrs(final: prev: {
HEVM_SOLIDITY_REPO = solidity;
HEVM_ETHEREUM_TESTS_REPO = ethereum-tests;
});
# wrapped binary for use on systems with nix available. ensures all
# required runtime deps are available and on path
hevmWrapped = with pkgs; symlinkJoin {
name = "hevm";
paths = [ (haskell.lib.dontCheck hevmUnwrapped) ];
buildInputs = [ makeWrapper ];
postBuild = ''
wrapProgram $out/bin/hevm \
--prefix PATH : "${lib.makeBinPath ([ bash coreutils git solc' z3 cvc5 ])}"
'';
};
# "static" binary for distribution
# on linux this is actually a real fully static binary
# on macos this has everything except libcxx, libsystem and libiconv
# statically linked. we can be confident that these three will always
# be provided in a well known location by macos itself.
hevmRedistributable = let
grep = "${pkgs.gnugrep}/bin/grep";
otool = "${pkgs.darwin.binutils.bintools}/bin/otool";
install_name_tool = "${pkgs.darwin.binutils.bintools}/bin/install_name_tool";
in if pkgs.stdenv.isLinux
then pkgs.haskell.lib.dontCheck hevmUnwrapped
else pkgs.runCommand "stripNixRefs" {} ''
mkdir -p $out/bin
cp ${pkgs.haskell.lib.dontCheck hevmUnwrapped}/bin/hevm $out/bin/
# get the list of dynamic libs from otool and tidy the output
libs=$(${otool} -L $out/bin/hevm | tail -n +2 | sed 's/^[[:space:]]*//' | cut -d' ' -f1)
# get the paths for libcxx and libiconv
cxx=$(echo "$libs" | ${grep} '^/nix/store/.*-libcxx')
iconv=$(echo "$libs" | ${grep} '^/nix/store/.*-libiconv')
# rewrite /nix/... library paths to point to /usr/lib
chmod 777 $out/bin/hevm
${install_name_tool} -change "$cxx" /usr/lib/libc++.1.dylib $out/bin/hevm
${install_name_tool} -change "$iconv" /usr/lib/libiconv.dylib $out/bin/hevm
chmod 555 $out/bin/hevm
'';
# 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 ----
packages.withTests = hevmUnwrapped;
packages.hevm = hevmWrapped;
packages.redistributable = hevmRedistributable;
packages.default = packages.hevm;
# --- apps ----
apps.hevm = flake-utils.lib.mkApp { drv = packages.hevm; };
apps.default = apps.hevm;
# --- shell ---
devShell = with pkgs;
let libraryPath = "${lib.makeLibraryPath [ libff secp256k1 gmp ]}";
in haskellPackages.shellFor {
packages = _: [ hevmUnwrapped ];
buildInputs = [
z3
cvc5
solc'
mdbook
yarn
go-ethereum
haskellPackages.cabal-install
haskellPackages.haskell-language-server
];
withHoogle = true;
# NOTE: hacks for bugged cabal new-repl
LD_LIBRARY_PATH = libraryPath;
HEVM_SOLIDITY_REPO = solidity;
HEVM_ETHEREUM_TESTS_REPO = ethereum-tests;
shellHook = lib.optionalString stdenv.isDarwin ''
export DYLD_LIBRARY_PATH="${libraryPath}";
'';
};
}
);
}