1{
2 stdenv,
3 lib,
4 fetchurl,
5 SDL,
6 SDL2,
7 SDL2_image,
8 SDL2_mixer,
9 fmodex,
10 dwarf-fortress-unfuck,
11 autoPatchelfHook,
12
13 # Our own "unfuck" libs for macOS
14 ncurses,
15 gcc,
16
17 dfVersion,
18 dfVersions,
19}:
20
21let
22 inherit (lib)
23 attrNames
24 elemAt
25 getAttr
26 getLib
27 hasAttr
28 licenses
29 maintainers
30 optional
31 optionals
32 optionalString
33 splitVersion
34 toInt
35 ;
36
37 # Map Dwarf Fortress platform names to Nixpkgs platform names.
38 platforms = {
39 x86_64-linux = "linux";
40 x86_64-darwin = "darwin";
41 };
42
43 dfVersionTuple = splitVersion dfVersion;
44 dfVersionBaseIndex =
45 let
46 x = (builtins.length dfVersionTuple) - 2;
47 in
48 if x >= 0 then x else 0;
49 baseVersion = toInt (elemAt dfVersionTuple dfVersionBaseIndex);
50 patchVersion = elemAt dfVersionTuple (dfVersionBaseIndex + 1);
51
52 isAtLeast50 = baseVersion >= 50;
53 enableUnfuck =
54 !isAtLeast50
55 && dwarf-fortress-unfuck != null
56 && (dwarf-fortress-unfuck.dfVersion or null) == dfVersion;
57
58 game =
59 if hasAttr dfVersion dfVersions.game.versions then
60 (getAttr dfVersion dfVersions.game.versions).df
61 else
62 throw "Unknown Dwarf Fortress version: ${dfVersion}";
63 dfPlatform =
64 if hasAttr stdenv.hostPlatform.system platforms then
65 getAttr stdenv.hostPlatform.system platforms
66 else
67 throw "Unsupported system: ${stdenv.hostPlatform.system}";
68 url =
69 if hasAttr dfPlatform game.urls then
70 getAttr dfPlatform game.urls
71 else
72 throw "Unsupported dfPlatform: ${dfPlatform}";
73 exe =
74 if stdenv.hostPlatform.isLinux then
75 if baseVersion >= 50 then "dwarfort" else "libs/Dwarf_Fortress"
76 else
77 "dwarfort.exe";
78in
79
80stdenv.mkDerivation {
81 pname = "dwarf-fortress";
82 version = dfVersion;
83
84 src = fetchurl {
85 inherit (url) url;
86 hash = url.outputHash;
87 };
88
89 sourceRoot = ".";
90
91 postUnpack = ''
92 directory=${
93 if stdenv.hostPlatform.isLinux then
94 "df_linux"
95 else if stdenv.hostPlatform.isDarwin then
96 "df_osx"
97 else
98 throw "Unsupported system"
99 }
100 if [ -d "$directory" ]; then
101 mv "$directory/"* .
102 fi
103 '';
104
105 nativeBuildInputs = optional stdenv.hostPlatform.isLinux autoPatchelfHook;
106 buildInputs =
107 optionals isAtLeast50 [
108 SDL2
109 SDL2_image
110 SDL2_mixer
111 ]
112 ++ optional (!isAtLeast50) SDL
113 ++ optional enableUnfuck dwarf-fortress-unfuck
114 ++ [ (lib.getLib stdenv.cc.cc) ];
115
116 installPhase = ''
117 runHook preInstall
118
119 exe=$out/${exe}
120 mkdir -p $out
121 cp -r * $out
122
123 # Clean up OS X detritus in the tarball.
124 find $out -type f -name '._*' -exec rm -rf {} \;
125
126 # Lots of files are +x in the newer releases...
127 find $out -type d -exec chmod 0755 {} \;
128 find $out -type f -exec chmod 0644 {} \;
129 chmod +x $exe
130 [ -f $out/df ] && chmod +x $out/df
131 [ -f $out/run_df ] && chmod +x $out/run_df
132
133 # We don't need any of these since they will just break autoPatchelf on <version 50.
134 [ -d $out/libs ] && rm -rf $out/libs/*.so $out/libs/*.so.* $out/libs/*.dylib
135
136 # Store the original hash
137 md5sum $exe | awk '{ print $1 }' > $out/hash.md5.orig
138 echo "Original MD5: $(<$out/hash.md5.orig)" >&2
139 ''
140 + optionalString stdenv.hostPlatform.isDarwin ''
141 # My custom unfucked dwarfort.exe for macOS. Can't use
142 # absolute paths because original doesn't have enough
143 # header space. Someone plz break into Tarn's house & put
144 # -headerpad_max_install_names into his LDFLAGS.
145
146 ln -s ${getLib ncurses}/lib/libncurses.dylib $out/libs
147 ln -s ${getLib gcc.cc}/lib/libstdc++.6.dylib $out/libs
148 ln -s ${getLib gcc.cc}/lib/libgcc_s.1.dylib $out/libs
149 ln -s ${getLib fmodex}/lib/libfmodex.dylib $out/libs
150
151 install_name_tool \
152 -change /usr/lib/libncurses.5.4.dylib \
153 @executable_path/libs/libncurses.dylib \
154 -change /usr/local/lib/x86_64/libstdc++.6.dylib \
155 @executable_path/libs/libstdc++.6.dylib \
156 $exe
157 ''
158 + ''
159 runHook postInstall
160 '';
161
162 preFixup = ''
163 recompute_hash() {
164 # Store the new hash as the very last step.
165 exe=$out/${exe}
166 md5sum $exe | awk '{ print $1 }' > $out/hash.md5
167 echo "Patched MD5: $(<$out/hash.md5)" >&2
168 }
169
170 # Ensure that this runs after autoPatchelfHook.
171 trap recompute_hash EXIT
172 '';
173
174 passthru = {
175 inherit
176 baseVersion
177 patchVersion
178 dfVersion
179 exe
180 ;
181 updateScript = {
182 command = [ ./update.rb ];
183 attrPath = "dwarf-fortress-packages";
184 supportedFeatures = [ "commit" ];
185 };
186 };
187
188 meta = {
189 description = "Single-player fantasy game with a randomly generated adventure world";
190 homepage = "https://www.bay12games.com/dwarves/";
191 license = licenses.unfreeRedistributable;
192 platforms = attrNames platforms;
193 maintainers = with maintainers; [
194 a1russell
195 robbinch
196 roconnor
197 abbradar
198 numinit
199 shazow
200 ncfavier
201 ];
202 sourceProvenance = [ lib.sourceTypes.binaryNativeCode ];
203 };
204}