nim2: 2.0.2 -> 2.0.4
[NixPkgs.git] / pkgs / development / compilers / nim / default.nix
blob089043dc6deea7937e99e6954f6a12cbe6bc096c
1 # https://nim-lang.github.io/Nim/packaging.html
2 # https://nim-lang.org/docs/nimc.html
4 { lib, callPackage, buildPackages, stdenv, fetchurl, fetchgit, fetchFromGitHub
5 , makeWrapper, openssl, pcre, readline, boehmgc, sqlite, Security
6 , nim-unwrapped-2, nim-unwrapped-1, nim }:
8 let
9   parseCpu = platform:
10     with platform;
11     # Derive a Nim CPU identifier
12     if isAarch32 then
13       "arm"
14     else if isAarch64 then
15       "arm64"
16     else if isAlpha then
17       "alpha"
18     else if isAvr then
19       "avr"
20     else if isMips && is32bit then
21       "mips"
22     else if isMips && is64bit then
23       "mips64"
24     else if isMsp430 then
25       "msp430"
26     else if isPower && is32bit then
27       "powerpc"
28     else if isPower && is64bit then
29       "powerpc64"
30     else if isRiscV && is64bit then
31       "riscv64"
32     else if isSparc then
33       "sparc"
34     else if isx86_32 then
35       "i386"
36     else if isx86_64 then
37       "amd64"
38     else
39       abort "no Nim CPU support known for ${config}";
41   parseOs = platform:
42     with platform;
43     # Derive a Nim OS identifier
44     if isAndroid then
45       "Android"
46     else if isDarwin then
47       "MacOSX"
48     else if isFreeBSD then
49       "FreeBSD"
50     else if isGenode then
51       "Genode"
52     else if isLinux then
53       "Linux"
54     else if isNetBSD then
55       "NetBSD"
56     else if isNone then
57       "Standalone"
58     else if isOpenBSD then
59       "OpenBSD"
60     else if isWindows then
61       "Windows"
62     else if isiOS then
63       "iOS"
64     else
65       abort "no Nim OS support known for ${config}";
67   parsePlatform = p: {
68     cpu = parseCpu p;
69     os = parseOs p;
70   };
72   nimHost = parsePlatform stdenv.hostPlatform;
73   nimTarget = parsePlatform stdenv.targetPlatform;
75 in {
77   nim-unwrapped-2 = stdenv.mkDerivation (finalAttrs: {
78     pname = "nim-unwrapped";
79     version = "2.0.4";
80     strictDeps = true;
82     src = fetchurl {
83       url = "https://nim-lang.org/download/nim-${finalAttrs.version}.tar.xz";
84       hash = "sha256-cVJr0HQ53I43j6Gm60B+2hKY8fPU30R23KDjyjy+Pwk=";
85     };
87     buildInputs = [ boehmgc openssl pcre readline sqlite ]
88       ++ lib.optional stdenv.isDarwin Security;
90     patches = [
91       ./NIM_CONFIG_DIR.patch
92       # Override compiler configuration via an environmental variable
94       ./nixbuild.patch
95       # Load libraries at runtime by absolute path
97       ./extra-mangling.patch
98       # Mangle store paths of modules to prevent runtime dependence.
100       ./openssl.patch
101       # dlopen is widely used by Python, Ruby, Perl, ... what you're really telling me here is that your OS is fundamentally broken. That might be news for you, but it isn't for me.
102     ];
104     configurePhase = let
105       bootstrapCompiler = stdenv.mkDerivation {
106         pname = "nim-bootstrap";
107         inherit (finalAttrs) version src preBuild;
108         enableParallelBuilding = true;
109         installPhase = ''
110           runHook preInstall
111           install -Dt $out/bin bin/nim
112           runHook postInstall
113         '';
114       };
115     in ''
116       runHook preConfigure
117       cp ${bootstrapCompiler}/bin/nim bin/
118       echo 'define:nixbuild' >> config/nim.cfg
119       runHook postConfigure
120     '';
122     kochArgs = [
123       "--cpu:${nimHost.cpu}"
124       "--os:${nimHost.os}"
125       "-d:release"
126       "-d:useGnuReadline"
127     ] ++ lib.optional (stdenv.isDarwin || stdenv.isLinux) "-d:nativeStacktrace";
129     preBuild = lib.optionalString (stdenv.isDarwin && stdenv.isAarch64) ''
130       substituteInPlace makefile \
131         --replace "aarch64" "arm64"
132     '';
134     buildPhase = ''
135       runHook preBuild
136       local HOME=$TMPDIR
137       ./bin/nim c --parallelBuild:$NIX_BUILD_CORES koch
138       ./koch boot $kochArgs --parallelBuild:$NIX_BUILD_CORES
139       ./koch toolsNoExternal $kochArgs --parallelBuild:$NIX_BUILD_CORES
140       ./bin/nim js -d:release tools/dochack/dochack.nim
141       runHook postBuild
142     '';
144     installPhase = ''
145       runHook preInstall
146       install -Dt $out/bin bin/*
147       ln -sf $out/nim/bin/nim $out/bin/nim
148       ln -sf $out/nim/lib $out/lib
149       ./install.sh $out
150       cp -a tools dist $out/nim/
151       runHook postInstall
152     '';
154     meta = with lib; {
155       description = "Statically typed, imperative programming language";
156       homepage = "https://nim-lang.org/";
157       license = licenses.mit;
158       mainProgram = "nim";
159       maintainers = with maintainers; [ ehmry ];
160     };
161   });
163   nim-unwrapped-1 = nim-unwrapped-2.overrideAttrs (finalAttrs: prevAttrs: {
164     version = "1.6.20";
165     src = fetchurl {
166       url = "https://nim-lang.org/download/nim-${finalAttrs.version}.tar.xz";
167       hash = "sha256-/+0EdQTR/K9hDw3Xzz4Ce+kaKSsMnFEWFQTC87mE/7k=";
168     };
170     patches = [
171       ./NIM_CONFIG_DIR.patch
172       # Override compiler configuration via an environmental variable
174       ./nixbuild.patch
175       # Load libraries at runtime by absolute path
177       ./extra-mangling.patch
178       # Mangle store paths of modules to prevent runtime dependence.
179     ] ++ lib.optional (!stdenv.hostPlatform.isWindows) ./toLocation.patch;
180   });
182 } // (let
183   wrapNim = { nim', patches }:
184     let targetPlatformConfig = stdenv.targetPlatform.config;
185     in stdenv.mkDerivation (finalAttrs: {
186         name = "${targetPlatformConfig}-nim-wrapper-${nim'.version}";
187         inherit (nim') version;
188         preferLocalBuild = true;
189         strictDeps = true;
191         nativeBuildInputs = [ makeWrapper ];
193         # Needed for any nim package that uses the standard library's
194         # 'std/sysrand' module.
195         depsTargetTargetPropagated = lib.optional stdenv.isDarwin Security;
197         inherit patches;
199         unpackPhase = ''
200           runHook preUnpack
201           tar xf ${nim'.src} nim-$version/config
202           cd nim-$version
203           runHook postUnpack
204         '';
206         dontConfigure = true;
208         buildPhase =
209           # Configure the Nim compiler to use $CC and $CXX as backends
210           # The compiler is configured by two configuration files, each with
211           # a different DSL. The order of evaluation matters and that order
212           # is not documented, so duplicate the configuration across both files.
213           ''
214             runHook preBuild
215             cat >> config/config.nims << WTF
217             switch("os", "${nimTarget.os}")
218             switch("cpu", "${nimTarget.cpu}")
219             switch("define", "nixbuild")
221             # Configure the compiler using the $CC set by Nix at build time
222             import strutils
223             let cc = getEnv"CC"
224             if cc.contains("gcc"):
225               switch("cc", "gcc")
226             elif cc.contains("clang"):
227               switch("cc", "clang")
228             WTF
230             mv config/nim.cfg config/nim.cfg.old
231             cat > config/nim.cfg << WTF
232             os = "${nimTarget.os}"
233             cpu =  "${nimTarget.cpu}"
234             define:"nixbuild"
235             WTF
237             cat >> config/nim.cfg < config/nim.cfg.old
238             rm config/nim.cfg.old
240             cat >> config/nim.cfg << WTF
242             clang.cpp.exe %= "\$CXX"
243             clang.cpp.linkerexe %= "\$CXX"
244             clang.exe %= "\$CC"
245             clang.linkerexe %= "\$CC"
246             gcc.cpp.exe %= "\$CXX"
247             gcc.cpp.linkerexe %= "\$CXX"
248             gcc.exe %= "\$CC"
249             gcc.linkerexe %= "\$CC"
250             WTF
252             runHook postBuild
253           '';
255         wrapperArgs = lib.optionals (!(stdenv.isDarwin && stdenv.isAarch64)) [
256           "--prefix PATH : ${lib.makeBinPath [ buildPackages.gdb ]}:${
257             placeholder "out"
258           }/bin"
259           # Used by nim-gdb
261           "--prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [ openssl pcre ]}"
262           # These libraries may be referred to by the standard library.
263           # This is broken for cross-compilation because the package
264           # set will be shifted back by nativeBuildInputs.
266           "--set NIM_CONFIG_PATH ${placeholder "out"}/etc/nim"
267           # Use the custom configuration
268         ];
270         installPhase = ''
271           runHook preInstall
273           mkdir -p $out/bin $out/etc
275           cp -r config $out/etc/nim
277           for binpath in ${nim'}/bin/nim?*; do
278             local binname=`basename $binpath`
279             makeWrapper \
280               $binpath $out/bin/${targetPlatformConfig}-$binname \
281               $wrapperArgs
282             ln -s $out/bin/${targetPlatformConfig}-$binname $out/bin/$binname
283           done
285           makeWrapper \
286             ${nim'}/nim/bin/nim $out/bin/${targetPlatformConfig}-nim \
287             --set-default CC $(command -v $CC) \
288             --set-default CXX $(command -v $CXX) \
289             $wrapperArgs
290           ln -s $out/bin/${targetPlatformConfig}-nim $out/bin/nim
292           makeWrapper \
293             ${nim'}/bin/testament $out/bin/${targetPlatformConfig}-testament \
294             $wrapperArgs
295           ln -s $out/bin/${targetPlatformConfig}-testament $out/bin/testament
297         '' + ''
298           runHook postInstall
299         '';
301         passthru = { nim = nim'; };
303         meta = nim'.meta // {
304           description = nim'.meta.description
305             + " (${targetPlatformConfig} wrapper)";
306           platforms = with lib.platforms; unix ++ genode;
307         };
308       });
309 in {
311   nim2 = wrapNim {
312     nim' = buildPackages.nim-unwrapped-2;
313     patches = [ ./nim2.cfg.patch ];
314   };
316   nim1 = wrapNim {
317     nim' = buildPackages.nim-unwrapped-1;
318     patches = [ ./nim.cfg.patch ];
319   };