nix: invert isCode condition
[xonotic/xonotic.git] / derivation.nix
1 # nix-shell -A shell
2 # nix-build -A xonotic
3 # --argstr cc clang
4 {
5     pkgs, lib,
6     cc ? null,
7     cmake ? pkgs.cmake_2_8,
8 }:
9 let
10     VERSION = "0.8.2";
11
12     srcs = {
13         # https://gitlab.com/xonotic/xonotic
14         "xonotic" = localFilesMain ./.;
15         "data/font-dejavu" = localFiles ./data/font-dejavu.pk3dir;
16         "data/font-nimbussansl" = localFiles ./data/font-nimbussansl.pk3dir;
17         "data/font-unifont" = localFiles ./data/font-unifont.pk3dir;
18         "data/font-xolonium" = localFiles ./data/font-xolonium.pk3dir;
19
20         # https://gitlab.com/xonotic/d0_blind_id
21         "d0_blind_id" = localFiles ./d0_blind_id;
22
23         # https://gitlab.com/xonotic/darkplaces
24         "darkplaces" = localFiles ./darkplaces;
25
26         # https://gitlab.com/xonotic/gmqcc
27         "gmqcc" = localFiles ./gmqcc;
28
29         # https://gitlab.com/xonotic/netradiant
30         "netradiant" = localFiles ./netradiant;
31
32         # https://gitlab.com/xonotic/xonotic-data.pk3dir
33         "data/xonotic-data" = localFilesCustom ./data/xonotic-data.pk3dir (name: type: type == "directory" || !(isCode name));
34         "data/xonotic-data/qcsrc" = localFilesCustom ./data/xonotic-data.pk3dir (name: type: type == "directory" || (isCode name));
35
36         # https://gitlab.com/xonotic/xonotic-maps.pk3dir
37         "data/xonotic-maps" = localFiles ./data/xonotic-maps.pk3dir;
38
39         # https://gitlab.com/xonotic/xonotic-music.pk3dir
40         "data/xonotic-music" = localFiles ./data/xonotic-music.pk3dir;
41
42         # https://gitlab.com/xonotic/xonotic-nexcompat.pk3dir
43         "data/xonotic-nexcompat" = localFiles ./data/xonotic-nexcompat.pk3dir;
44     };
45
46     localFilesMain = src: let
47         project = toString ./.;
48         cleanSourceFilterMain = name: type: let
49             baseName = baseNameOf (toString name);
50             result = (cleanSourceFilter name type)
51                 && !(name == "${project}/release")
52                 && !(name == "${project}/d0_blind_id")
53                 && !(name == "${project}/daemon")
54                 && !(name == "${project}/darkplaces")
55                 && !(name == "${project}/data")
56                 && !(name == "${project}/gmqcc")
57                 && !(name == "${project}/netradiant")
58                 && !(name == "${project}/wiki" || name == "${project}/wiki.yes")
59                 && !(name == "${project}/xonstat" || name == "${project}/xonstat.yes")
60             ;
61         in result;
62     in builtins.filterSource cleanSourceFilterMain src;
63
64     isCode = name: let
65         baseName = baseNameOf (toString name);
66         result = !(false
67             || (lib.hasSuffix ".ase" baseName)
68             || (lib.hasSuffix ".dem" baseName)
69             || (lib.hasSuffix ".dpm" baseName)
70             || (lib.hasSuffix ".framegroups" baseName)
71             || (lib.hasSuffix ".iqm" baseName)
72             || (lib.hasSuffix ".jpg" baseName)
73             || (lib.hasSuffix ".lmp" baseName)
74             || (lib.hasSuffix ".md3" baseName)
75             || (lib.hasSuffix ".mdl" baseName)
76             || (lib.hasSuffix ".obj" baseName)
77             || (lib.hasSuffix ".ogg" baseName)
78             || (lib.hasSuffix ".png" baseName)
79             || (lib.hasSuffix ".shader" baseName)
80             || (lib.hasSuffix ".skin" baseName)
81             || (lib.hasSuffix ".sounds" baseName)
82             || (lib.hasSuffix ".sp2" baseName)
83             || (lib.hasSuffix ".spr" baseName)
84             || (lib.hasSuffix ".spr32" baseName)
85             || (lib.hasSuffix ".svg" baseName)
86             || (lib.hasSuffix ".tga" baseName)
87             || (lib.hasSuffix ".wav" baseName)
88             || (lib.hasSuffix ".width" baseName)
89             || (lib.hasSuffix ".zym" baseName)
90         );
91     in result;
92
93     targets = rec {
94         font-dejavu = mkDerivation rec {
95             name = "font-dejavu-${version}";
96             version = VERSION;
97
98             src = srcs."data/font-dejavu";
99
100             phases = [ "installPhase" ];
101             installPhase = ''
102                 cp -r $src $out
103             '';
104         };
105
106         font-nimbussansl = mkDerivation rec {
107             name = "font-nimbussansl-${version}";
108             version = VERSION;
109
110             src = srcs."data/font-nimbussansl";
111
112             phases = [ "installPhase" ];
113             installPhase = ''
114                 cp -r $src $out
115             '';
116         };
117
118         font-unifont = mkDerivation rec {
119             name = "font-unifont-${version}";
120             version = VERSION;
121
122             src = srcs."data/font-unifont";
123
124             phases = [ "installPhase" ];
125             installPhase = ''
126                 cp -r $src $out
127             '';
128         };
129
130         font-xolonium = mkDerivation rec {
131             name = "font-xolonium-${version}";
132             version = VERSION;
133
134             src = srcs."data/font-xolonium";
135
136             phases = [ "installPhase" ];
137             installPhase = ''
138                 cp -r $src $out
139             '';
140         };
141
142         d0_blind_id = mkDerivation rec {
143             name = "d0_blind_id-${version}";
144             version = "xonotic-${VERSION}";
145
146             src = srcs."d0_blind_id";
147
148             nativeBuildInputs = [
149                 cmake
150             ];
151
152             buildInputs = with pkgs; [
153                 openssl
154             ];
155
156             installPhase = ''
157                 mkdir -p $out/lib
158                 cp libd0_blind_id.so $out/lib
159
160                 mkdir -p $out/include/d0_blind_id
161                 (cd $src; cp d0_blind_id.h d0.h $out/include/d0_blind_id)
162             '';
163         };
164
165         darkplaces = let
166             unwrapped = mkDerivation rec {
167                 name = "darkplaces-unwrapped-${version}";
168                 version = "xonotic-${VERSION}";
169
170                 src = srcs."darkplaces";
171
172                 nativeBuildInputs = [
173                     cmake
174                 ];
175
176                 buildInputs = with pkgs; [
177                     SDL2
178
179                     zlib
180                     libjpeg
181                 ];
182
183                 installPhase = ''
184                     mkdir -p $out/bin
185                     cp darkplaces-{dedicated,sdl} $out/bin
186                 '';
187             };
188             result = mkDerivation rec {
189                 name = "darkplaces-${version}";
190                 version = "xonotic-${VERSION}";
191
192                 buildInputs = unwrapped.buildInputs ++ runtimeInputs;
193                 runtimeInputs = with pkgs; [
194                     d0_blind_id
195
196                     freetype
197
198                     curl
199                     zlib
200
201                     libjpeg
202                     libpng
203
204                     libogg
205                     libtheora
206                     libvorbis
207                 ];
208
209                 phases = [ "installPhase" ];
210                 installPhase = ''
211                     mkdir -p $out/bin
212
213                     cp -r ${unwrapped}/bin .
214                     chmod +w bin/*
215                     cd bin
216
217                     for exe in darkplaces-sdl; do
218                         rpath=$(patchelf --print-rpath $exe)
219                         rpath=''${rpath:+$rpath:}${lib.makeLibraryPath runtimeInputs}
220                         patchelf --set-rpath $rpath $exe
221                     done
222
223                     for exe in dedicated sdl; do
224                         cp darkplaces-$exe $out/bin/xonotic-linux64-$exe
225                     done
226                 '';
227             };
228         in result;
229
230         gmqcc = mkDerivation rec {
231             name = "gmqcc-${version}";
232             version = "xonotic-${VERSION}";
233
234             src = srcs."gmqcc";
235
236             nativeBuildInputs = [
237                 cmake
238             ];
239
240             installPhase = ''
241                 mkdir -p $out/bin
242                 cp gmqcc $out/bin
243             '';
244         };
245
246         netradiant = mkDerivation rec {
247             name = "netradiant-${version}";
248             version = VERSION;
249
250             src = srcs."netradiant";
251
252             nativeBuildInputs = with pkgs; [
253                 cmake
254                 git
255             ];
256
257             buildInputs = with pkgs; [
258                 pkgconfig
259                 glib
260                 pcre
261                 libxml2
262                 ncurses
263                 libjpeg
264                 libpng
265                 minizip
266
267                 mesa
268
269                 xorg.libXt
270                 xorg.libXmu
271                 xorg.libSM
272                 xorg.libICE
273                 xorg.libpthreadstubs
274                 xorg.libXdmcp
275
276                 gnome2.gtk
277                 gnome2.gtkglext
278                 gnome3.gtk
279             ];
280         };
281
282         xonotic-data = mkDerivation rec {
283             name = "xonotic-data-${version}";
284             version = "xonotic-${VERSION}";
285
286             src = srcs."data/xonotic-data";
287
288             phases = [ "installPhase" ];
289             installPhase = ''
290                 mkdir $out
291                 cp -r $src/. $out
292                 chmod -R +w $out
293                 find $out -depth -type d -empty -exec rmdir {} \;
294             '';
295         };
296
297         xonotic-data-code = mkDerivation rec {
298             name = "xonotic-data-code-${version}";
299             version = "xonotic-${VERSION}";
300
301             src = srcs."data/xonotic-data/qcsrc";
302
303             env = {
304                 QCC = "${gmqcc}/bin/gmqcc";
305             };
306
307             nativeBuildInputs = with pkgs; [
308                 cmake
309                 git
310             ];
311
312             installPhase = ''
313                 mkdir $out
314                 cp -r $src/. $out
315                 chmod -R +w $out
316                 cp {menu,progs,csprogs}.{dat,lno} $out
317                 find $out -depth -type d -empty -exec rmdir {} \;
318             '';
319         };
320
321         xonotic = mkDerivation rec {
322             name = "xonotic-${version}";
323             version = VERSION;
324
325             src = srcs."xonotic";
326
327             env = {
328                 XON_NO_DAEMON = "1";
329             };
330
331             phases = [ "installPhase" ];
332
333             # test: `ln -s`
334             # release: `cp -r`
335             installPhase = ''
336                 mkdir $out
337                 cp -r $src/. $out
338                 cp ${darkplaces}/bin/* $out
339
340                 mkdir -p $out/data
341                 ln -s ${font-dejavu} $out/data/font-dejavu.pk3dir
342                 ln -s ${font-nimbussansl} $out/data/font-nimbussansl.pk3dir
343                 ln -s ${font-unifont} $out/data/font-unifont.pk3dir
344                 ln -s ${font-xolonium} $out/data/font-xolonium.pk3dir
345
346                 ln -s ${xonotic-data} $out/data/xonotic-data.pk3dir
347                 ln -s ${xonotic-data-code} $out/data/xonotic-data-code.pk3dir
348                 ln -s ${srcs."data/xonotic-maps"} $out/data/xonotic-maps.pk3dir # todo: build
349                 ln -s ${srcs."data/xonotic-music"} $out/data/xonotic-music.pk3dir
350                 ln -s ${srcs."data/xonotic-nexcompat"} $out/data/xonotic-nexcompat.pk3dir
351
352                 mkdir -p $out/mapping
353                 ln -s ${netradiant} $out/mapping/${netradiant.name}
354             '';
355         };
356     };
357
358     cleanSourceFilter = name: type: let
359         baseName = baseNameOf (toString name);
360         result = (lib.cleanSourceFilter name type)
361             && !(lib.hasSuffix ".nix" baseName)
362             && !(type == "directory" && baseName == ".git")
363             && !(type == "directory" && baseName == ".idea")
364             && !(type == "directory" && (lib.hasPrefix "cmake-build-" baseName))
365         ;
366     in result;
367
368     localFilesCustom = src: filter:
369         builtins.filterSource (name: type: (cleanSourceFilter name type) && (filter name type)) src
370     ;
371
372     localFiles = src: localFilesCustom src (name: type: true);
373
374     stdenv = if (cc == null) then pkgs.stdenv
375             else pkgs.overrideCC pkgs.stdenv pkgs."${cc}";
376
377     mkDerivation = {env ? {}, shellHook ? "", runtimeInputs ? [], ...}@args: stdenv.mkDerivation ({}
378         // { enableParallelBuilding = true; }
379         // (removeAttrs args ["env" "shellHook" "runtimeInputs"])
380         // env
381         // {
382             shellHook = ''
383                 ${shellHook}
384                 ${lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v: "export ${n}=${v}") env)}
385                 export LD_LIBRARY_PATH=''${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}${lib.makeLibraryPath runtimeInputs}
386             '';
387         }
388     );
389
390     shell = let inputs = (lib.mapAttrsToList (n: v: v) targets); in stdenv.mkDerivation (rec {
391         name = "xonotic-shell";
392         nativeBuildInputs = builtins.map (it: it.nativeBuildInputs) inputs;
393         buildInputs = builtins.map (it: it.buildInputs) inputs;
394         shellHook = builtins.map (it: it.shellHook) (builtins.filter (it: it?shellHook) inputs);
395     });
396 in { inherit shell; } // targets