1{ stdenv, fetchFromGitHub, overrideCC, gcc5
2, makeWrapper, unzip, which
3, curl, tzdata, gdb, darwin
4, callPackage
5, bootstrapVersion ? false
6, version ? "2.079.0"
7, dmdSha256 ? "1k6cky71pqnss6h6391p1ich2mjs598f5fda018aygnxg87qgh4y"
8, druntimeSha256 ? "183pqygj5w4105czs5kswyjn9mrcybx3wmkynz3in0m3ylzzjmvl"
9, phobosSha256 ? "0y9i86ggmf41ww2xk2bsrlsv9b1blj5dbyan6q6r6xp8dmgrd79w"
10}:
11
12let
13
14 bootstrapDmd = if !bootstrapVersion then
15 # Versions 2.070.2 and up require a working dmd compiler to build so we just
16 # use the last dmd without any D code to bootstrap the actual build.
17 callPackage ./default.nix {
18 stdenv = if stdenv.hostPlatform.isDarwin then
19 stdenv
20 else
21 # Doesn't build with gcc6 on linux
22 overrideCC stdenv gcc5;
23 bootstrapVersion = true;
24 version = "2.067.1";
25 dmdSha256 = "0fm29lg8axfmzdaj0y6vg70lhwb5d9rv4aavnvdd15xjschinlcz";
26 druntimeSha256 = "1n2qfw9kmnql0fk2nxikispqs7vh85nhvyyr00fk227n9lgnqf02";
27 phobosSha256 = "0fywgds9xvjcgnqxmpwr67p3wi2m535619pvj159cgwv5y0nr3p1";
28 }
29 else
30 "";
31
32 dmdBuild = stdenv.mkDerivation rec {
33 name = "dmdBuild-${version}";
34 inherit version;
35
36 enableParallelBuilding = true;
37
38 srcs = [
39 (fetchFromGitHub {
40 owner = "dlang";
41 repo = "dmd";
42 rev = "v${version}";
43 sha256 = dmdSha256;
44 name = "dmd";
45 })
46 (fetchFromGitHub {
47 owner = "dlang";
48 repo = "druntime";
49 rev = "v${version}";
50 sha256 = druntimeSha256;
51 name = "druntime";
52 })
53 (fetchFromGitHub {
54 owner = "dlang";
55 repo = "phobos";
56 rev = "v${version}";
57 sha256 = phobosSha256;
58 name = "phobos";
59 })
60 ];
61
62 sourceRoot = ".";
63
64 postUnpack = ''
65 patchShebangs .
66
67 # Remove cppa test for now because it doesn't work.
68 rm dmd/test/runnable/cppa.d
69 rm dmd/test/runnable/extra-files/cppb.cpp
70 '';
71
72 # Compile with PIC to prevent colliding modules with binutils 2.28.
73 # https://issues.dlang.org/show_bug.cgi?id=17375
74 usePIC = "-fPIC";
75 ROOT_HOME_DIR = "$(echo ~root)";
76
77 datetimePath = if bootstrapVersion then
78 "phobos/std/datetime.d"
79 else
80 "phobos/std/datetime/timezone.d";
81
82 phobosPatches = ''
83 # Ugly hack so the dlopen call has a chance to succeed.
84 # https://issues.dlang.org/show_bug.cgi?id=15391
85 substituteInPlace phobos/std/net/curl.d \
86 --replace libcurl.so ${curl.out}/lib/libcurl.so
87
88 # phobos uses curl, so we need to patch the path to the lib.
89 substituteInPlace phobos/posix.mak \
90 --replace "-soname=libcurl.so.4" "-soname=${curl.out}/lib/libcurl.so.4"
91
92 ''
93
94 + stdenv.lib.optionalString (!bootstrapVersion) ''
95 # Can be removed when https://github.com/dlang/phobos/pull/6224 is included.
96 substituteInPlace ${datetimePath} \
97 --replace "foreach (DirEntry de; dirEntries(tzDatabaseDir, SpanMode.depth))" "import std.path : baseName; foreach (DirEntry de; dirEntries(tzDatabaseDir, SpanMode.depth))"
98
99 substituteInPlace ${datetimePath} \
100 --replace "tzName == \"leapseconds\"" "baseName(tzName) == \"leapseconds\""
101 ''
102
103 + stdenv.lib.optionalString (bootstrapVersion) ''
104 substituteInPlace ${datetimePath} \
105 --replace "import std.traits;" "import std.traits;import std.path;"
106
107 substituteInPlace ${datetimePath} \
108 --replace "tzName == \"+VERSION\"" "baseName(tzName) == \"leapseconds\" || tzName == \"+VERSION\""
109
110 # Ugly hack to fix the hardcoded path to zoneinfo in the source file.
111 # https://issues.dlang.org/show_bug.cgi?id=15391
112 substituteInPlace ${datetimePath} \
113 --replace /usr/share/zoneinfo/ ${tzdata}/share/zoneinfo/
114 ''
115
116 + stdenv.lib.optionalString (bootstrapVersion && stdenv.hostPlatform.isLinux) ''
117 # See https://github.com/dlang/phobos/pull/5960
118 substituteInPlace phobos/std/path.d \
119 --replace "\"/root" "\"${ROOT_HOME_DIR}"
120 '';
121
122 dmdPath = if bootstrapVersion then
123 "dmd/src"
124 else
125 "dmd";
126
127 postPatch = ''
128 ''
129
130 + stdenv.lib.optionalString (!bootstrapVersion) ''
131 substituteInPlace druntime/test/common.mak \
132 --replace "DFLAGS:=" "DFLAGS:=${usePIC} "
133 ''
134
135 + stdenv.lib.optionalString (bootstrapVersion) ''
136 # Use proper C++ compiler
137 substituteInPlace ${dmdPath}/posix.mak \
138 --replace g++ $CXX
139 ''
140
141 + phobosPatches
142
143 + stdenv.lib.optionalString (stdenv.hostPlatform.isLinux && bootstrapVersion) ''
144 substituteInPlace ${dmdPath}/root/port.c \
145 --replace "#include <bits/mathdef.h>" "#include <complex.h>"
146 ''
147
148 + stdenv.lib.optionalString stdenv.hostPlatform.isDarwin ''
149 substituteInPlace ${dmdPath}/posix.mak \
150 --replace MACOSX_DEPLOYMENT_TARGET MACOSX_DEPLOYMENT_TARGET_
151 ''
152
153 + stdenv.lib.optionalString (stdenv.hostPlatform.isDarwin && bootstrapVersion) ''
154 # Was not able to compile on darwin due to "__inline_isnanl"
155 # being undefined.
156 substituteInPlace ${dmdPath}/root/port.c --replace __inline_isnanl __inline_isnan
157 '';
158
159 nativeBuildInputs = [ bootstrapDmd makeWrapper unzip which gdb ]
160
161 ++ stdenv.lib.optional stdenv.hostPlatform.isDarwin (with darwin.apple_sdk.frameworks; [
162 Foundation
163 ]);
164
165 buildInputs = [ curl tzdata ];
166
167 bits = builtins.toString stdenv.hostPlatform.parsed.cpu.bits;
168 osname = if stdenv.hostPlatform.isDarwin then
169 "osx"
170 else
171 stdenv.hostPlatform.parsed.kernel.name;
172 top = "$(echo $NIX_BUILD_TOP)";
173 pathToDmd = if bootstrapVersion then
174 "${top}/dmd/src/dmd"
175 else
176 "${top}/dmd/generated/${osname}/release/${bits}/dmd";
177
178 # Buid and install are based on http://wiki.dlang.org/Building_DMD
179 buildPhase = ''
180 cd dmd
181 make -j$NIX_BUILD_CORES -f posix.mak INSTALL_DIR=$out
182 cd ../druntime
183 make -j$NIX_BUILD_CORES -f posix.mak PIC=1 INSTALL_DIR=$out DMD=${pathToDmd}
184 cd ../phobos
185 make -j$NIX_BUILD_CORES -f posix.mak PIC=1 INSTALL_DIR=$out DMD=${pathToDmd} TZ_DATABASE_DIR=${tzdata}/share/zoneinfo/
186 cd ..
187 '';
188
189 doCheck = !bootstrapVersion;
190
191 checkPhase = ''
192 cd dmd
193 make -j$NIX_BUILD_CORES -C test -f Makefile PIC=1 DMD=${pathToDmd} BUILD=release SHARED=0 SHELL=$SHELL
194 cd ../druntime
195 make -j$NIX_BUILD_CORES -f posix.mak unittest PIC=1 DMD=${pathToDmd} BUILD=release
196 cd ..
197 '';
198
199 extension = if stdenv.hostPlatform.isDarwin then "a" else "{a,so}";
200
201 installPhase = ''
202 cd dmd
203 mkdir $out
204 mkdir $out/bin
205 cp ${pathToDmd} $out/bin
206
207 mkdir -p $out/share/man/man1
208 mkdir -p $out/share/man/man5
209 cp -r docs/man/man1/* $out/share/man/man1/
210 cp -r docs/man/man5/* $out/share/man/man5/
211
212 cd ../druntime
213 mkdir $out/include
214 mkdir $out/include/d2
215 cp -r import/* $out/include/d2
216
217 cd ../phobos
218 mkdir $out/lib
219 cp generated/${osname}/release/${bits}/libphobos2.${extension} $out/lib
220
221 cp -r std $out/include/d2
222 cp -r etc $out/include/d2
223
224 wrapProgram $out/bin/dmd \
225 --prefix PATH ":" "${stdenv.cc}/bin" \
226 --set-default CC "$CC"
227
228 cd $out/bin
229 tee dmd.conf << EOF
230 [Environment]
231 DFLAGS=-I$out/include/d2 -L-L$out/lib ${stdenv.lib.optionalString (!stdenv.cc.isClang) "-L--export-dynamic"} -fPIC
232 EOF
233 '';
234
235 meta = with stdenv.lib; {
236 description = "Official reference compiler for the D language";
237 homepage = http://dlang.org/;
238 # Everything is now Boost licensed, even the backend.
239 # https://github.com/dlang/dmd/pull/6680
240 license = licenses.boost;
241 maintainers = with maintainers; [ ThomasMader ];
242 platforms = [ "x86_64-linux" "i686-linux" "x86_64-darwin" ];
243 };
244 };
245
246 # Need to test Phobos in a fixed-output derivation, otherwise the
247 # network stuff in Phobos would fail if sandbox mode is enabled.
248 phobosUnittests = stdenv.mkDerivation rec {
249 name = "phobosUnittests-${version}";
250 version = dmdBuild.version;
251
252 enableParallelBuilding = dmdBuild.enableParallelBuilding;
253 preferLocalBuild = true;
254 inputString = dmdBuild.outPath;
255 outputHashAlgo = "sha256";
256 outputHash = builtins.hashString "sha256" inputString;
257
258 srcs = dmdBuild.srcs;
259
260 sourceRoot = ".";
261
262 postPatch = dmdBuild.phobosPatches;
263
264 nativeBuildInputs = dmdBuild.nativeBuildInputs;
265 buildInputs = dmdBuild.buildInputs;
266
267 buildPhase = ''
268 cd phobos
269 make -j$NIX_BUILD_CORES -f posix.mak unittest PIC=1 DMD=${dmdBuild}/bin/dmd BUILD=release TZ_DATABASE_DIR=${tzdata}/share/zoneinfo/
270 '';
271
272 installPhase = ''
273 echo -n $inputString > $out
274 '';
275 };
276
277in
278
279stdenv.mkDerivation rec {
280 inherit phobosUnittests;
281 name = "dmd-${version}";
282 phases = "installPhase";
283 buildInputs = dmdBuild.buildInputs;
284
285 installPhase = ''
286 mkdir $out
287 cp -r --symbolic-link ${dmdBuild}/* $out/
288 '';
289 meta = dmdBuild.meta;
290}
291