1# https://nim-lang.github.io/Nim/packaging.html
2
3{ stdenv, lib, fetchgit, fetchurl, makeWrapper, gdb, openssl, pcre, readline
4, boehmgc, sqlite, nim-unwrapped, nim }:
5
6let
7 version = "1.2.6";
8 src = fetchurl {
9 url = "https://nim-lang.org/download/nim-${version}.tar.xz";
10 sha256 = "0zk5qzxayqjw7kq6p92j4008g9bbyilyymhdc5xq9sln5rqym26z";
11 };
12
13 meta = with lib; {
14 description = "Statically typed, imperative programming language";
15 homepage = "https://nim-lang.org/";
16 license = licenses.mit;
17 maintainers = with maintainers; [ ehmry ];
18 };
19
20 parseCpu = platform:
21 with platform;
22 # Derive a Nim CPU identifier
23 if isAarch32 then
24 "arm"
25 else if isAarch64 then
26 "arm64"
27 else if isAlpha then
28 "alpha"
29 else if isAvr then
30 "avr"
31 else if isMips && is32bit then
32 "mips"
33 else if isMips && is64bit then
34 "mips64"
35 else if isMsp430 then
36 "msp430"
37 else if isPowerPC && is32bit then
38 "powerpc"
39 else if isPowerPC && is64bit then
40 "powerpc64"
41 else if isRiscV && is64bit then
42 "riscv64"
43 else if isSparc then
44 "sparc"
45 else if isx86_32 then
46 "i386"
47 else if isx86_64 then
48 "amd64"
49 else
50 abort "no Nim CPU support known for ${config}";
51
52 parseOs = platform:
53 with platform;
54 # Derive a Nim OS identifier
55 if isAndroid then
56 "Android"
57 else if isDarwin then
58 "MacOSX"
59 else if isFreeBSD then
60 "FreeBSD"
61 else if isGenode then
62 "Genode"
63 else if isLinux then
64 "Linux"
65 else if isNetBSD then
66 "NetBSD"
67 else if isNone then
68 "Standalone"
69 else if isOpenBSD then
70 "OpenBSD"
71 else if isWindows then
72 "Windows"
73 else if isiOS then
74 "iOS"
75 else
76 abort "no Nim OS support known for ${config}";
77
78 parsePlatform = p: {
79 cpu = parseCpu p;
80 os = parseOs p;
81 };
82
83 nimHost = parsePlatform stdenv.hostPlatform;
84 nimTarget = parsePlatform stdenv.targetPlatform;
85
86 wrapperInputs = rec {
87
88 bootstrap = stdenv.mkDerivation rec {
89 pname = "nim-bootstrap";
90 version = "0.20.0";
91
92 src = fetchgit {
93 # A Git checkout is much smaller than a GitHub tarball.
94 url = "https://github.com/nim-lang/csources.git";
95 rev = "v" + version;
96 sha256 = "0i6vsfy1sgapx43n226q8m0pvn159sw2mhp50zm3hhb9zfijanis";
97 };
98
99 enableParallelBuilding = true;
100
101 installPhase = ''
102 runHook preInstall
103 install -Dt $out/bin bin/nim
104 runHook postInstall
105 '';
106 };
107
108 unwrapped = stdenv.mkDerivation {
109 pname = "nim-unwrapped";
110 inherit version src;
111
112 buildInputs = [ boehmgc openssl pcre readline sqlite ];
113
114 patches = [
115 ./NIM_CONFIG_DIR.patch
116 # Override compiler configuration via an environmental variable
117
118 ./nixbuild.patch
119 # Load libraries at runtime by absolute path
120 ];
121
122 configurePhase = ''
123 runHook preConfigure
124 cp ${bootstrap}/bin/nim bin/
125 echo 'define:nixbuild' >> config/nim.cfg
126 runHook postConfigure
127 '';
128
129 kochArgs = [
130 "--cpu:${nimHost.cpu}"
131 "--os:${nimHost.os}"
132 "-d:release"
133 "-d:useGnuReadline"
134 ] ++ lib.optional (stdenv.isDarwin || stdenv.isLinux)
135 "-d:nativeStacktrace";
136
137 buildPhase = ''
138 runHook preBuild
139 local HOME=$TMPDIR
140 ./bin/nim c koch
141 ./koch boot $kochArgs --parallelBuild:$NIX_BUILD_CORES
142 ./koch tools $kochArgs --parallelBuild:$NIX_BUILD_CORES
143 runHook postBuild
144 '';
145
146 installPhase = ''
147 runHook preInstall
148 install -Dt $out/bin bin/*
149 ln -sf $out/nim/bin/nim $out/bin/nim
150 ./install.sh $out
151 runHook postInstall
152 '';
153
154 inherit meta;
155 };
156 };
157
158 wrapped = let
159 nim = nim-unwrapped;
160 inherit (stdenv) targetPlatform;
161 in stdenv.mkDerivation {
162 name = "${targetPlatform.config}-nim-wrapper-${nim.version}";
163 inherit (nim) version;
164 preferLocalBuild = true;
165
166 nativeBuildInputs = [ makeWrapper ];
167
168 unpackPhase = ''
169 runHook preUnpack
170 tar xf ${nim.src} nim-$version/config/nim.cfg
171 cd nim-$version
172 runHook postUnpack
173 '';
174
175 dontConfigure = true;
176
177 wrapperArgs = [
178 "--prefix PATH : ${lib.makeBinPath [ stdenv.cc gdb ]}:${
179 placeholder "out"
180 }/bin"
181 "--prefix LD_LIBRARY_PATH : ${
182 lib.makeLibraryPath [ stdenv.cc.libc openssl ]
183 }"
184 "--set NIM_CONFIG_PATH ${placeholder "out"}/etc/nim"
185 ''--set NIX_HARDENING_ENABLE "''${NIX_HARDENING_ENABLE/fortify}"''
186 # Fortify hardening appends -O2 to gcc flags which is unwanted for unoptimized nim builds.
187 ];
188
189 buildPhase = with stdenv;
190 let
191 ccType = if cc.isGNU then
192 "gcc"
193 else if cc.isClang then
194 "clang"
195 else
196 abort "no Nim configuration available for ${cc.name}";
197 in ''
198 runHook preBuild
199 cat >> config/nim.cfg << EOF
200
201 define:nixbuild
202 os = ${nimTarget.os}
203 cpu = ${nimTarget.cpu}
204 cc = ${ccType}
205 EOF
206
207 mkdir -p $out/bin $out/etc/nim
208 export cc=$CC
209 export cxx=$CXX
210 substituteAll config/nim.cfg $out/etc/nim/nim.cfg \
211 --replace "cc = gcc" ""
212
213 for binpath in ${nim}/bin/nim?*; do
214 local binname=`basename $binpath`
215 makeWrapper \
216 $binpath $out/bin/${targetPlatform.config}-$binname \
217 $wrapperArgs
218 ln -s $out/bin/${targetPlatform.config}-$binname $out/bin/$binname
219 done
220
221 makeWrapper \
222 ${nim}/nim/bin/nim $out/bin/${targetPlatform.config}-nim \
223 $wrapperArgs
224 ln -s $out/bin/${targetPlatform.config}-nim $out/bin/nim
225
226 runHook postBuild
227 '';
228
229 dontInstall = true;
230
231 meta = meta // {
232 description = nim.meta.description
233 + " (${targetPlatform.config} wrapper)";
234 platforms = lib.platforms.unix;
235 };
236
237 };
238
239in wrapped // wrapperInputs