]> git.xonotic.org Git - xonotic/xonotic.git/blob - derivation.nix
mapserv: add /ls endpoint
[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                 cp libd0_blind_id.so $out/lib
174
175                 mkdir -p $out/include/d0_blind_id
176                 (cd $src; cp d0_blind_id.h d0.h $out/include/d0_blind_id)
177             '';
178         };
179
180         darkplaces = let
181             unwrapped = mkDerivation rec {
182                 name = "darkplaces-unwrapped-${version}";
183                 version = "xonotic-${VERSION}";
184
185                 src = srcs."darkplaces";
186
187                 nativeBuildInputs = [
188                     cmake
189                 ];
190
191                 buildInputs = with pkgs; [
192                     SDL2
193
194                     zlib
195                     libjpeg
196                 ];
197
198                 installPhase = ''
199                     mkdir -p $out/bin
200                     cp darkplaces-{dedicated,sdl} $out/bin
201                 '';
202             };
203             result = mkDerivation rec {
204                 name = "darkplaces-${version}";
205                 version = "xonotic-${VERSION}";
206
207                 buildInputs = unwrapped.buildInputs ++ runtimeInputs;
208                 runtimeInputs = with pkgs; [
209                     d0_blind_id
210
211                     freetype
212
213                     curl
214                     zlib
215
216                     libjpeg
217                     libpng
218
219                     libogg
220                     libtheora
221                     libvorbis
222                 ];
223
224                 phases = [ "installPhase" ];
225                 installPhase = ''
226                     mkdir -p $out/bin
227
228                     cp -r ${unwrapped}/bin .
229                     chmod +w bin/*
230                     cd bin
231
232                     for exe in dedicated sdl; do
233                         f=darkplaces-$exe
234                         rpath=$(patchelf --print-rpath $f)
235                         rpath=''${rpath:+$rpath:}${lib.makeLibraryPath runtimeInputs}
236                         patchelf --set-rpath $rpath $f
237                         cp $f $out/bin/xonotic-linux64-$exe
238                     done
239                 '';
240             };
241         in result;
242
243         gmqcc = mkDerivation rec {
244             name = "gmqcc-${version}";
245             version = "xonotic-${VERSION}";
246
247             src = srcs."gmqcc";
248
249             nativeBuildInputs = [
250                 cmake
251             ];
252
253             installPhase = ''
254                 mkdir -p $out/bin
255                 cp gmqcc $out/bin
256             '';
257         };
258
259         netradiant = mkDerivation rec {
260             name = "netradiant-${version}";
261             version = VERSION;
262
263             src = srcs."netradiant";
264
265             nativeBuildInputs = with pkgs; [
266                 cmake
267                 git
268             ];
269
270             buildInputs = with pkgs; [
271                 pkgconfig
272                 glib
273                 pcre
274                 libxml2
275                 ncurses
276                 libjpeg
277                 libpng
278                 minizip
279
280                 mesa
281
282                 xorg.libXt
283                 xorg.libXmu
284                 xorg.libSM
285                 xorg.libICE
286                 xorg.libpthreadstubs
287                 xorg.libXdmcp
288
289                 gnome2.gtk
290                 gnome2.gtkglext
291                 gnome3.gtk
292             ];
293         };
294
295         xonotic-data = mkDerivation rec {
296             name = "xonotic-data-${version}";
297             version = "xonotic-${VERSION}";
298
299             src = srcs."data/xonotic-data";
300
301             phases = [ "installPhase" ];
302             installPhase = ''
303                 mkdir $out
304                 cp -r $src/. $out
305                 chmod -R +w $out
306                 find $out -depth -type d -empty -exec rmdir {} \;
307             '';
308         };
309
310         xonotic-data-code = mkDerivation rec {
311             name = "xonotic-data-code-${version}";
312             version = "xonotic-${VERSION}";
313
314             src = srcs."data/xonotic-data/qcsrc";
315
316             env = {
317                 QCC = "${gmqcc}/bin/gmqcc";
318             };
319
320             nativeBuildInputs = with pkgs; [
321                 cmake
322                 git
323             ];
324
325             installPhase = ''
326                 mkdir $out
327                 cp -r $src/. $out
328                 chmod -R +w $out
329                 cp {menu,progs,csprogs}.{dat,lno} $out
330                 find $out -depth -type d -empty -exec rmdir {} \;
331             '';
332         };
333
334         # todo: build
335         xonotic-maps = mkDerivation rec {
336             name = "xonotic-maps-${version}";
337             version = "xonotic-${VERSION}";
338
339             src = srcs."data/xonotic-maps";
340
341             phases = [ "installPhase" ];
342             installPhase = ''
343                 mkdir $out
344                 cp -r $src/. $out
345             '';
346
347             passthru.dance = mkDerivation rec {
348                 name = "dance";
349                 version = "xonotic-${VERSION}";
350
351                 src = pkgs.fetchurl {
352                     url = http://beta.xonotic.org/autobuild-bsp/dance-full-88c416b8c11bdcecfdb889af2a2b97b4c0e2b8de-319ee7234504199da56f07ce25185f6d6cb889cd.pk3;
353                     sha256 = "1jgdg4mz56kbxcy3mwn4h5qlf3ahm1cmarp9l70fz9nfn6cnaknq";
354                 };
355
356                 phases = [ "installPhase" ];
357
358                 installPhase = ''
359                     mkdir -p $out
360                     cd $out
361                     ${pkgs.unzip}/bin/unzip $src
362                 '';
363             };
364         };
365
366         xonotic-music = mkDerivation rec {
367             name = "xonotic-music-${version}";
368             version = "xonotic-${VERSION}";
369
370             src = srcs."data/xonotic-music";
371
372             phases = [ "installPhase" ];
373             installPhase = ''
374                 mkdir $out
375                 cp -r $src/. $out
376             '';
377
378             passthru.pk3args = "-0";
379         };
380
381         xonotic-nexcompat = mkDerivation rec {
382             name = "xonotic-nexcompat-${version}";
383             version = "xonotic-${VERSION}";
384
385             src = srcs."data/xonotic-nexcompat";
386
387             phases = [ "installPhase" ];
388             installPhase = ''
389                 mkdir $out
390                 cp -r $src/. $out
391             '';
392         };
393
394         mapserv = mkDerivation rec {
395             name = "mapserv-${version}";
396             version = "xonotic-${VERSION}";
397
398             src = "${srcs."xonotic"}/server/mapserv";
399
400             buildInputs = with pkgs; [
401                 python3
402                 mypy
403             ];
404             phases = [ "installPhase" ];
405             installPhase = ''
406                 mkdir $out
407                 cp -r $src/. $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/ls -l /data
468                         exec ${darkplaces}/bin/xonotic-linux64-dedicated "\''${@}"
469                         EOF
470                         chmod +x $out/init
471                     '';
472                 };
473                 config.Entrypoint = "/init";
474             };
475             unpackImage = { name, from, to }: pkgs.dockerTools.buildImage {
476                 name = "xonotic_${name}";
477                 tag = VERSION;
478                 contents = mkDerivation {
479                     name = "xonotic-${name}-init";
480                     phases = [ "installPhase" ];
481                     installPhase = ''
482                         mkdir -p $out
483                         cat > $out/init <<EOF
484                         #!${stdenv.shell}
485                         ${pkgs.coreutils}/bin/cp -r ${from} /data/${to}
486                         EOF
487                         chmod +x $out/init
488                     '';
489                 };
490                 config.Entrypoint = "/init";
491             };
492         in { main = main; }
493             // (lib.mapAttrs (k: v: unpackImage { name = k; from = pk3 v; to = "${k}.pk3"; }) xonotic.paks)
494         ;
495     };
496
497     cleanSourceFilter = name: type: let
498         baseName = baseNameOf (toString name);
499         result = (lib.cleanSourceFilter name type)
500             && !(lib.hasSuffix ".nix" baseName)
501             && !(type == "directory" && baseName == ".git")
502             && !(type == "directory" && baseName == ".idea")
503             && !(type == "directory" && (lib.hasPrefix "cmake-build-" baseName))
504         ;
505     in result;
506
507     localFilesCustom = src: filter:
508         builtins.filterSource (name: type: (cleanSourceFilter name type) && (filter name type)) src
509     ;
510
511     localFiles = src: localFilesCustom src (name: type: true);
512
513     stdenv = if (cc == null) then pkgs.stdenv
514             else pkgs.overrideCC pkgs.stdenv pkgs."${cc}";
515
516     mkDerivation = {env ? {}, shellHook ? "", runtimeInputs ? [], ...}@args: stdenv.mkDerivation ({}
517         // { enableParallelBuilding = true; }
518         // (removeAttrs args ["env" "shellHook" "runtimeInputs"])
519         // env
520         // {
521             shellHook = ''
522                 ${shellHook}
523                 ${lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v: "export ${n}=${v}") env)}
524                 export LD_LIBRARY_PATH=''${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}${lib.makeLibraryPath runtimeInputs}
525             '';
526         }
527     );
528
529     shell = let inputs = (lib.mapAttrsToList (k: v: v) targets); in stdenv.mkDerivation (rec {
530         name = "xonotic-shell";
531         nativeBuildInputs = lib.unique (builtins.map (it: it.nativeBuildInputs) (builtins.filter (it: it?nativeBuildInputs) inputs));
532         buildInputs = lib.unique (builtins.map (it: it.buildInputs) (builtins.filter (it: it?buildInputs) inputs));
533         shellHook = builtins.map (it: it.shellHook) (builtins.filter (it: it?shellHook) inputs);
534     });
535 in { inherit shell; } // targets