1{
2 channel,
3 pname,
4 version,
5 sha256Hash,
6}:
7
8{
9 alsa-lib,
10 runtimeShell,
11 buildFHSEnv,
12 cacert,
13 coreutils,
14 dbus,
15 e2fsprogs,
16 expat,
17 fetchurl,
18 findutils,
19 file,
20 fontsConf,
21 git,
22 gnugrep,
23 gnused,
24 gnutar,
25 gtk2,
26 glib,
27 gzip,
28 fontconfig,
29 freetype,
30 libbsd,
31 libpulseaudio,
32 libGL,
33 libdrm,
34 libpng,
35 libuuid,
36 libsecret,
37 libX11,
38 libxcb,
39 libxkbcommon,
40 mesa-demos,
41 xcbutilwm,
42 xcbutilrenderutil,
43 xcbutilkeysyms,
44 xcbutilimage,
45 xcbutilcursor,
46 libxkbfile,
47 libXcomposite,
48 libXcursor,
49 libXdamage,
50 libXext,
51 libXfixes,
52 libXi,
53 libXrandr,
54 libXrender,
55 libXtst,
56 makeWrapper,
57 ncurses5,
58 nspr,
59 nss_latest,
60 pciutils,
61 pkgsi686Linux,
62 ps,
63 setxkbmap,
64 lib,
65 stdenv,
66 systemd,
67 unzip,
68 usbutils,
69 which,
70 runCommand,
71 wayland,
72 xkeyboard_config,
73 xorg,
74 zlib,
75 makeDesktopItem,
76 tiling_wm, # if we are using a tiling wm, need to set _JAVA_AWT_WM_NONREPARENTING in wrapper
77 androidenv,
78
79 forceWayland ? false,
80}:
81
82let
83 drvName = "android-studio-${channel}-${version}";
84 filename = "android-studio-${version}-linux.tar.gz";
85
86 androidStudio = stdenv.mkDerivation {
87 name = "${drvName}-unwrapped";
88
89 src = fetchurl {
90 url = "https://dl.google.com/dl/android/studio/ide-zips/${version}/${filename}";
91 sha256 = sha256Hash;
92 };
93
94 nativeBuildInputs = [
95 unzip
96 makeWrapper
97 ];
98
99 # Causes the shebangs in interpreter scripts deployed to mobile devices to be patched, which Android does not understand
100 dontPatchShebangs = true;
101
102 installPhase = ''
103 cp -r . $out
104 wrapProgram $out/bin/studio \
105 --set-default JAVA_HOME "$out/jbr" \
106 --set ANDROID_EMULATOR_USE_SYSTEM_LIBS 1 \
107 --set QT_XKB_CONFIG_ROOT "${xkeyboard_config}/share/X11/xkb" \
108 ${lib.optionalString tiling_wm "--set _JAVA_AWT_WM_NONREPARENTING 1"} \
109 --set FONTCONFIG_FILE ${fontsConf} \
110 --prefix PATH : "${
111 lib.makeBinPath [
112
113 # Checked in studio.sh
114 coreutils
115 findutils
116 gnugrep
117 which
118 gnused
119
120 # For Android emulator
121 file
122 mesa-demos
123 pciutils
124 setxkbmap
125
126 # Used during setup wizard
127 gnutar
128 gzip
129
130 # Runtime stuff
131 git
132 ps
133 usbutils
134 libsecret
135 ]
136 }" \
137 --prefix LD_LIBRARY_PATH : "${
138 lib.makeLibraryPath [
139
140 # Crash at startup without these
141 fontconfig
142 freetype
143 libXext
144 libXi
145 libXrender
146 libXtst
147 libsecret
148
149 # No crash, but attempted to load at startup
150 e2fsprogs
151
152 # Gradle wants libstdc++.so.6
153 (lib.getLib stdenv.cc.cc)
154 # mksdcard wants 32 bit libstdc++.so.6
155 pkgsi686Linux.stdenv.cc.cc.lib
156
157 # aapt wants libz.so.1
158 zlib
159 pkgsi686Linux.zlib
160 # Support multiple monitors
161 libXrandr
162
163 # For Android emulator
164 alsa-lib
165 dbus
166 expat
167 libbsd
168 libpulseaudio
169 libuuid
170 libX11
171 libxcb
172 libxkbcommon
173 xcbutilwm
174 xcbutilrenderutil
175 xcbutilkeysyms
176 xcbutilimage
177 xcbutilcursor
178 xorg.libICE
179 xorg.libSM
180 libxkbfile
181 libXcomposite
182 libXcursor
183 libXdamage
184 libXfixes
185 libGL
186 libdrm
187 libpng
188 nspr
189 nss_latest
190 systemd
191
192 # For GTKLookAndFeel
193 gtk2
194 glib
195
196 # For wayland support
197 wayland
198 ]
199 }" \
200 ${lib.optionalString forceWayland "--add-flags -Dawt.toolkit.name=WLToolkit"}
201
202 # AS launches LLDBFrontend with a custom LD_LIBRARY_PATH
203 wrapProgram $(find $out -name LLDBFrontend) --prefix LD_LIBRARY_PATH : "${
204 lib.makeLibraryPath [
205 ncurses5
206 zlib
207 ]
208 }"
209 '';
210 meta.mainProgram = "studio";
211 };
212
213 desktopItem = makeDesktopItem {
214 name = pname;
215 exec = pname;
216 icon = pname;
217 desktopName = "Android Studio (${channel} channel)";
218 comment = "The official Android IDE";
219 categories = [
220 "Development"
221 "IDE"
222 ];
223 startupNotify = true;
224 startupWMClass = "jetbrains-studio";
225 };
226
227 # Android Studio downloads prebuilt binaries as part of the SDK. These tools
228 # (e.g. `mksdcard`) have `/lib/ld-linux.so.2` set as the interpreter. An FHS
229 # environment is used as a work around for that.
230 fhsEnv = buildFHSEnv {
231 pname = "${drvName}-fhs-env";
232 inherit version;
233 multiPkgs = pkgs: [
234 ncurses5
235
236 # Flutter can only search for certs Fedora-way.
237 (runCommand "fedoracert" { } ''
238 mkdir -p $out/etc/pki/tls/
239 ln -s ${cacert}/etc/ssl/certs $out/etc/pki/tls/certs
240 '')
241 ];
242 };
243 mkAndroidStudioWrapper =
244 {
245 androidStudio,
246 androidSdk ? null,
247 }:
248 runCommand drvName
249 {
250 startScript =
251 let
252 hasAndroidSdk = androidSdk != null;
253 androidSdkRoot = lib.optionalString hasAndroidSdk "${androidSdk}/libexec/android-sdk";
254 in
255 ''
256 #!${runtimeShell}
257 ${lib.optionalString hasAndroidSdk ''
258 echo "=== nixpkgs Android Studio wrapper" >&2
259
260 # Default ANDROID_SDK_ROOT to the packaged one, if not provided.
261 ANDROID_SDK_ROOT="''${ANDROID_SDK_ROOT-${androidSdkRoot}}"
262
263 if [ -d "$ANDROID_SDK_ROOT" ]; then
264 export ANDROID_SDK_ROOT
265 # Legacy compatibility.
266 export ANDROID_HOME="$ANDROID_SDK_ROOT"
267 echo " - ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT" >&2
268
269 # See if we can export ANDROID_NDK_ROOT too.
270 ANDROID_NDK_ROOT="$ANDROID_SDK_ROOT/ndk-bundle"
271 if [ ! -d "$ANDROID_NDK_ROOT" ]; then
272 ANDROID_NDK_ROOT="$(ls "$ANDROID_SDK_ROOT/ndk/"* 2>/dev/null | head -n1)"
273 fi
274
275 if [ -d "$ANDROID_NDK_ROOT" ]; then
276 export ANDROID_NDK_ROOT
277 echo " - ANDROID_NDK_ROOT=$ANDROID_NDK_ROOT" >&2
278 else
279 unset ANDROID_NDK_ROOT
280 fi
281 else
282 unset ANDROID_SDK_ROOT
283 unset ANDROID_HOME
284 fi
285 ''}
286 exec ${fhsEnv}/bin/${drvName}-fhs-env ${lib.getExe androidStudio} "$@"
287 '';
288 preferLocalBuild = true;
289 allowSubstitutes = false;
290 passthru =
291 let
292 withSdk = androidSdk: mkAndroidStudioWrapper { inherit androidStudio androidSdk; };
293 in
294 {
295 inherit version;
296 unwrapped = androidStudio;
297 full = withSdk androidenv.androidPkgs.androidsdk;
298 inherit withSdk;
299 sdk = androidSdk;
300 updateScript = [
301 ./update.sh
302 "${channel}"
303 ];
304 };
305 meta = {
306 description = "Official IDE for Android (${channel} channel)";
307 longDescription = ''
308 Android Studio is the official IDE for Android app development, based on
309 IntelliJ IDEA.
310 '';
311 homepage =
312 if channel == "stable" then
313 "https://developer.android.com/studio/index.html"
314 else
315 "https://developer.android.com/studio/preview/index.html";
316 license = with lib.licenses; [
317 asl20
318 unfree
319 ]; # The code is under Apache-2.0, but:
320 # If one selects Help -> Licenses in Android Studio, the dialog shows the following:
321 # "Android Studio includes proprietary code subject to separate license,
322 # including JetBrains CLion(R) (www.jetbrains.com/clion) and IntelliJ(R)
323 # IDEA Community Edition (www.jetbrains.com/idea)."
324 # Also: For actual development the Android SDK is required and the Google
325 # binaries are also distributed as proprietary software (unlike the
326 # source-code itself).
327 platforms = [ "x86_64-linux" ];
328 maintainers =
329 rec {
330 stable = with lib.maintainers; [
331 alapshin
332 ];
333 beta = stable;
334 canary = stable;
335 dev = stable;
336 }
337 ."${channel}";
338 teams =
339 rec {
340 stable = with lib.teams; [
341 android
342 ];
343 beta = stable;
344 canary = stable;
345 dev = stable;
346 }
347 ."${channel}";
348 mainProgram = pname;
349 sourceProvenance = [ lib.sourceTypes.binaryNativeCode ];
350 };
351 }
352 ''
353 mkdir -p $out/{bin,share/pixmaps}
354
355 echo -n "$startScript" > $out/bin/${pname}
356 chmod +x $out/bin/${pname}
357
358 ln -s ${androidStudio}/bin/studio.png $out/share/pixmaps/${pname}.png
359 ln -s ${desktopItem}/share/applications $out/share/applications
360 '';
361in
362mkAndroidStudioWrapper { inherit androidStudio; }