nix: fix crypto
[xonotic/xonotic.git] / derivation.nix
1 # nix-shell -A shell
2 # nix-build -A xonotic
3 # --argstr cc clang
4 # for it in $(nix-build -A dockerImage --no-out-link); do docker load -i $it; done
5 {
6     pkgs, lib,
7     cc ? null,
8     cmake ? pkgs.cmake_2_8,
9 }:
10 let
11     VERSION = "0.8.2";
12
13     srcs = {
14         # https://gitlab.com/xonotic/xonotic
15         "xonotic" = localFilesMain ./.;
16         "data/font-dejavu" = localFiles ./data/font-dejavu.pk3dir;
17         "data/font-nimbussansl" = localFiles ./data/font-nimbussansl.pk3dir;
18         "data/font-unifont" = localFiles ./data/font-unifont.pk3dir;
19         "data/font-xolonium" = localFiles ./data/font-xolonium.pk3dir;
20
21         # https://gitlab.com/xonotic/d0_blind_id
22         "d0_blind_id" = localFiles ./d0_blind_id;
23
24         # https://gitlab.com/xonotic/darkplaces
25         "darkplaces" = localFiles ./darkplaces;
26
27         # https://gitlab.com/xonotic/gmqcc
28         "gmqcc" = localFiles ./gmqcc;
29
30         # https://gitlab.com/xonotic/netradiant
31         "netradiant" = localFiles ./netradiant;
32
33         # https://gitlab.com/xonotic/xonotic-data.pk3dir
34         "data/xonotic-data" = localFilesCustom ./data/xonotic-data.pk3dir (name: type: type == "directory" || !(isCode name));
35         "data/xonotic-data/qcsrc" = localFilesCustom ./data/xonotic-data.pk3dir (name: type: type == "directory" || (isCode name));
36
37         # https://gitlab.com/xonotic/xonotic-maps.pk3dir
38         "data/xonotic-maps" = localFiles ./data/xonotic-maps.pk3dir;
39
40         # https://gitlab.com/xonotic/xonotic-music.pk3dir
41         "data/xonotic-music" = localFiles ./data/xonotic-music.pk3dir;
42
43         # https://gitlab.com/xonotic/xonotic-nexcompat.pk3dir
44         "data/xonotic-nexcompat" = localFiles ./data/xonotic-nexcompat.pk3dir;
45     };
46
47     localFilesMain = src: let
48         project = toString ./.;
49         cleanSourceFilterMain = name: type: let
50             baseName = baseNameOf (toString name);
51             result = (cleanSourceFilter name type)
52                 && !(name == "${project}/release")
53                 && !(name == "${project}/d0_blind_id")
54                 && !(name == "${project}/daemon")
55                 && !(name == "${project}/darkplaces")
56                 && !(name == "${project}/data")
57                 && !(name == "${project}/gmqcc")
58                 && !(name == "${project}/netradiant")
59                 && !(name == "${project}/wiki" || name == "${project}/wiki.yes")
60                 && !(name == "${project}/xonstat" || name == "${project}/xonstat.yes")
61             ;
62         in result;
63     in builtins.filterSource cleanSourceFilterMain src;
64
65     isCode = name: let
66         baseName = baseNameOf (toString name);
67         result = !(false
68             || (lib.hasSuffix ".ase" baseName)
69             || (lib.hasSuffix ".dem" baseName)
70             || (lib.hasSuffix ".dpm" baseName)
71             || (lib.hasSuffix ".framegroups" baseName)
72             || (lib.hasSuffix ".iqm" baseName)
73             || (lib.hasSuffix ".jpg" baseName)
74             || (lib.hasSuffix ".lmp" baseName)
75             || (lib.hasSuffix ".md3" baseName)
76             || (lib.hasSuffix ".mdl" baseName)
77             || (lib.hasSuffix ".obj" baseName)
78             || (lib.hasSuffix ".ogg" baseName)
79             || (lib.hasSuffix ".png" baseName)
80             || (lib.hasSuffix ".shader" baseName)
81             || (lib.hasSuffix ".skin" baseName)
82             || (lib.hasSuffix ".sounds" baseName)
83             || (lib.hasSuffix ".sp2" baseName)
84             || (lib.hasSuffix ".spr" baseName)
85             || (lib.hasSuffix ".spr32" baseName)
86             || (lib.hasSuffix ".svg" baseName)
87             || (lib.hasSuffix ".tga" baseName)
88             || (lib.hasSuffix ".wav" baseName)
89             || (lib.hasSuffix ".width" baseName)
90             || (lib.hasSuffix ".zym" baseName)
91         );
92     in result;
93
94     pk3 = drv: mkDerivation {
95         name = "${drv.name}.pk3";
96         version = drv.version;
97
98         nativeBuildInputs = with pkgs; [
99             zip
100         ];
101
102         phases = [ "installPhase" ];
103         installPhase = ''
104             (cd ${drv} && zip -r ${drv.pk3args or ""} $out .)
105         '';
106     };
107
108     targets = rec {
109         font-dejavu = mkDerivation rec {
110             name = "font-dejavu-${version}";
111             version = VERSION;
112
113             src = srcs."data/font-dejavu";
114
115             phases = [ "installPhase" ];
116             installPhase = ''
117                 cp -r $src $out
118             '';
119         };
120
121         font-nimbussansl = mkDerivation rec {
122             name = "font-nimbussansl-${version}";
123             version = VERSION;
124
125             src = srcs."data/font-nimbussansl";
126
127             phases = [ "installPhase" ];
128             installPhase = ''
129                 cp -r $src $out
130             '';
131         };
132
133         font-unifont = mkDerivation rec {
134             name = "font-unifont-${version}";
135             version = VERSION;
136
137             src = srcs."data/font-unifont";
138
139             phases = [ "installPhase" ];
140             installPhase = ''
141                 cp -r $src $out
142             '';
143         };
144
145         font-xolonium = mkDerivation rec {
146             name = "font-xolonium-${version}";
147             version = VERSION;
148
149             src = srcs."data/font-xolonium";
150
151             phases = [ "installPhase" ];
152             installPhase = ''
153                 cp -r $src $out
154             '';
155         };
156
157         d0_blind_id = mkDerivation rec {
158             name = "d0_blind_id-${version}";
159             version = "xonotic-${VERSION}";
160
161             src = srcs."d0_blind_id";
162
163             nativeBuildInputs = [
164                 cmake
165             ];
166
167             buildInputs = with pkgs; [
168                 openssl
169             ];
170
171             installPhase = ''
172                 mkdir -p $out/lib
173                 mkdir -p $out/include/d0_blind_id
174
175                 cp libd0_blind_id.so $out/lib
176                 (cd $src; cp d0.h d0_blind_id.h $out/include/d0_blind_id)
177
178                 cp libd0_rijndael.so $out/lib
179                 (cd $src; cp d0_rijndael.h $out/include/d0_blind_id)
180             '';
181         };
182
183         darkplaces = let
184             unwrapped = mkDerivation rec {
185                 name = "darkplaces-unwrapped-${version}";
186                 version = "xonotic-${VERSION}";
187
188                 src = srcs."darkplaces";
189
190                 nativeBuildInputs = [
191                     cmake
192                 ];
193
194                 buildInputs = with pkgs; [
195                     SDL2
196
197                     zlib
198                     libjpeg
199                 ];
200
201                 installPhase = ''
202                     mkdir -p $out/bin
203                     cp darkplaces-{dedicated,sdl} $out/bin
204                 '';
205             };
206             result = mkDerivation rec {
207                 name = "darkplaces-${version}";
208                 version = "xonotic-${VERSION}";
209
210                 buildInputs = unwrapped.buildInputs ++ runtimeInputs;
211                 runtimeInputs = with pkgs; [
212                     d0_blind_id
213
214                     freetype
215
216                     curl
217                     zlib
218
219                     libjpeg
220                     libpng
221
222                     libogg
223                     libtheora
224                     libvorbis
225                 ];
226
227                 phases = [ "installPhase" ];
228                 installPhase = ''
229                     mkdir -p $out/bin
230
231                     cp -r ${unwrapped}/bin .
232                     chmod +w bin/*
233                     cd bin
234
235                     for exe in dedicated sdl; do
236                         f=darkplaces-$exe
237                         rpath=$(patchelf --print-rpath $f)
238                         rpath=''${rpath:+$rpath:}${lib.makeLibraryPath runtimeInputs}
239                         patchelf --set-rpath $rpath $f
240                         cp $f $out/bin/xonotic-linux64-$exe
241                     done
242                 '';
243             };
244         in result;
245
246         gmqcc = mkDerivation rec {
247             name = "gmqcc-${version}";
248             version = "xonotic-${VERSION}";
249
250             src = srcs."gmqcc";
251
252             nativeBuildInputs = [
253                 cmake
254             ];
255
256             installPhase = ''
257                 mkdir -p $out/bin
258                 cp gmqcc $out/bin
259             '';
260         };
261
262         netradiant = mkDerivation rec {
263             name = "netradiant-${version}";
264             version = VERSION;
265
266             src = srcs."netradiant";
267
268             nativeBuildInputs = with pkgs; [
269                 cmake
270                 git
271             ];
272
273             buildInputs = with pkgs; [
274                 pkgconfig
275                 glib
276                 pcre
277                 libxml2
278                 ncurses
279                 libjpeg
280                 libpng
281                 minizip
282
283                 mesa
284
285                 xorg.libXt
286                 xorg.libXmu
287                 xorg.libSM
288                 xorg.libICE
289                 xorg.libpthreadstubs
290                 xorg.libXdmcp
291
292                 gnome2.gtk
293                 gnome2.gtkglext
294                 gnome3.gtk
295             ];
296         };
297
298         xonotic-data = mkDerivation rec {
299             name = "xonotic-data-${version}";
300             version = "xonotic-${VERSION}";
301
302             src = srcs."data/xonotic-data";
303
304             phases = [ "installPhase" ];
305             installPhase = ''
306                 mkdir $out
307                 cp -r $src/. $out
308                 chmod -R +w $out
309                 find $out -depth -type d -empty -exec rmdir {} \;
310             '';
311         };
312
313         xonotic-data-code = mkDerivation rec {
314             name = "xonotic-data-code-${version}";
315             version = "xonotic-${VERSION}";
316
317             src = srcs."data/xonotic-data/qcsrc";
318
319             env = {
320                 QCC = "${gmqcc}/bin/gmqcc";
321             };
322
323             nativeBuildInputs = with pkgs; [
324                 cmake
325                 git
326             ];
327
328             installPhase = ''
329                 mkdir $out
330                 cp -r $src/. $out
331                 chmod -R +w $out
332                 cp {menu,progs,csprogs}.{dat,lno} $out
333                 find $out -depth -type d -empty -exec rmdir {} \;
334             '';
335         };
336
337         # todo: build
338         xonotic-maps = mkDerivation rec {
339             name = "xonotic-maps-${version}";
340             version = "xonotic-${VERSION}";
341
342             src = srcs."data/xonotic-maps";
343
344             phases = [ "installPhase" ];
345             installPhase = ''
346                 mkdir $out
347                 cp -r $src/. $out
348             '';
349
350             passthru.dance = mkDerivation rec {
351                 name = "dance";
352                 version = "xonotic-${VERSION}";
353
354                 src = pkgs.fetchurl {
355                     url = http://beta.xonotic.org/autobuild-bsp/dance-full-88c416b8c11bdcecfdb889af2a2b97b4c0e2b8de-319ee7234504199da56f07ce25185f6d6cb889cd.pk3;
356                     sha256 = "1jgdg4mz56kbxcy3mwn4h5qlf3ahm1cmarp9l70fz9nfn6cnaknq";
357                 };
358
359                 phases = [ "installPhase" ];
360
361                 installPhase = ''
362                     mkdir -p $out
363                     cd $out
364                     ${pkgs.unzip}/bin/unzip $src
365                 '';
366             };
367         };
368
369         xonotic-music = mkDerivation rec {
370             name = "xonotic-music-${version}";
371             version = "xonotic-${VERSION}";
372
373             src = srcs."data/xonotic-music";
374
375             phases = [ "installPhase" ];
376             installPhase = ''
377                 mkdir $out
378                 cp -r $src/. $out
379             '';
380
381             passthru.pk3args = "-0";
382         };
383
384         xonotic-nexcompat = mkDerivation rec {
385             name = "xonotic-nexcompat-${version}";
386             version = "xonotic-${VERSION}";
387
388             src = srcs."data/xonotic-nexcompat";
389
390             phases = [ "installPhase" ];
391             installPhase = ''
392                 mkdir $out
393                 cp -r $src/. $out
394             '';
395         };
396
397         xonotic-keys = mkDerivation rec {
398             name = "xonotic-keys-${version}";
399             version = VERSION;
400
401             src = srcs."xonotic";
402
403             phases = [ "installPhase" ];
404
405             installPhase = ''
406                 mkdir $out
407                 cp $src/*.d0pk $out
408             '';
409         };
410
411         xonotic = mkDerivation rec {
412             name = "xonotic-${version}";
413             version = VERSION;
414
415             src = srcs."xonotic";
416
417             env = {
418                 XON_NO_DAEMON = "1";
419             };
420
421             passthru.paks = {
422                 inherit
423                     font-dejavu
424                     font-nimbussansl
425                     font-unifont
426                     font-xolonium
427                     xonotic-data
428                     xonotic-data-code
429                     xonotic-maps
430                     xonotic-music
431                     xonotic-nexcompat
432                 ;
433                 inherit (xonotic-maps)
434                     dance
435                 ;
436             };
437
438             phases = [ "installPhase" ];
439
440             installPhase = ''
441                 mkdir $out
442                 cp -r $src/. $out
443                 cp ${darkplaces}/bin/* $out
444
445                 mkdir -p $out/data
446                 ${lib.concatStringsSep "\n" (lib.mapAttrsToList (k: v:
447                     # "cp ${pk3 v} $out/data/${k}.pk3"
448                     "ln -s ${v} $out/data/${k}.pk3dir"
449                 ) passthru.paks)}
450
451                 mkdir -p $out/mapping
452                 ln -s ${netradiant} $out/mapping/${netradiant.name}
453             '';
454         };
455
456         dockerImage = let
457             main = pkgs.dockerTools.buildImage {
458                 name = "xonotic";
459                 tag = VERSION;
460                 contents = mkDerivation {
461                     name = "xonotic-init";
462                     phases = [ "installPhase" ];
463                     installPhase = ''
464                         mkdir -p $out
465                         cat > $out/init <<EOF
466                         #!${stdenv.shell}
467                         ${pkgs.coreutils}/bin/ln -s ${xonotic-keys}/* /
468
469                         ${pkgs.coreutils}/bin/ls -l /
470                         ${pkgs.coreutils}/bin/ls -l /data
471
472                         exec ${darkplaces}/bin/xonotic-linux64-dedicated "\''${@}"
473                         EOF
474                         chmod +x $out/init
475                     '';
476                 };
477                 config.Entrypoint = "/init";
478             };
479             unpackImage = { name, from, to }: pkgs.dockerTools.buildImage {
480                 name = "xonotic_${name}";
481                 tag = VERSION;
482                 contents = mkDerivation {
483                     name = "xonotic-${name}-init";
484                     phases = [ "installPhase" ];
485                     installPhase = ''
486                         mkdir -p $out
487                         cat > $out/init <<EOF
488                         #!${stdenv.shell}
489                         ${pkgs.coreutils}/bin/cp -r ${from} /data/${to}
490                         EOF
491                         chmod +x $out/init
492                     '';
493                 };
494                 config.Entrypoint = "/init";
495             };
496         in { main = main; }
497             // (lib.mapAttrs (k: v: unpackImage { name = k; from = pk3 v; to = "${k}.pk3"; }) xonotic.paks)
498         ;
499     };
500
501     cleanSourceFilter = name: type: let
502         baseName = baseNameOf (toString name);
503         result = (lib.cleanSourceFilter name type)
504             && !(lib.hasSuffix ".nix" baseName)
505             && !(type == "directory" && baseName == ".git")
506             && !(type == "directory" && baseName == ".idea")
507             && !(type == "directory" && (lib.hasPrefix "cmake-build-" baseName))
508         ;
509     in result;
510
511     localFilesCustom = src: filter:
512         builtins.filterSource (name: type: (cleanSourceFilter name type) && (filter name type)) src
513     ;
514
515     localFiles = src: localFilesCustom src (name: type: true);
516
517     stdenv = if (cc == null) then pkgs.stdenv
518             else pkgs.overrideCC pkgs.stdenv pkgs."${cc}";
519
520     mkDerivation = {env ? {}, shellHook ? "", runtimeInputs ? [], ...}@args: stdenv.mkDerivation ({}
521         // { enableParallelBuilding = true; }
522         // (removeAttrs args ["env" "shellHook" "runtimeInputs"])
523         // env
524         // {
525             shellHook = ''
526                 ${shellHook}
527                 ${lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v: "export ${n}=${v}") env)}
528                 export LD_LIBRARY_PATH=''${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}${lib.makeLibraryPath runtimeInputs}
529             '';
530         }
531     );
532
533     shell = let inputs = (lib.mapAttrsToList (k: v: v) targets); in stdenv.mkDerivation (rec {
534         name = "xonotic-shell";
535         nativeBuildInputs = builtins.map (it: it.nativeBuildInputs) (builtins.filter (it: it?nativeBuildInputs) inputs);
536         buildInputs = builtins.map (it: it.buildInputs) (builtins.filter (it: it?buildInputs) inputs);
537         shellHook = builtins.map (it: it.shellHook) (builtins.filter (it: it?shellHook) inputs);
538     });
539 in { inherit shell; } // targets