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