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