1{
2 lib,
3 stdenv,
4 chromium,
5 nodejs,
6 fetchYarnDeps,
7 fetchNpmDeps,
8 fetchpatch,
9 fixup-yarn-lock,
10 npmHooks,
11 yarn,
12 libnotify,
13 unzip,
14 pkgsBuildHost,
15 pipewire,
16 libsecret,
17 libpulseaudio,
18 speechd-minimal,
19 info,
20 gclient2nix,
21}:
22
23let
24 gclientDeps = gclient2nix.importGclientDeps info.deps;
25in
26
27((chromium.override { upstream-info = info.chromium; }).mkDerivation (base: {
28 packageName = "electron";
29 inherit (info) version;
30 buildTargets = [
31 "electron:copy_node_headers"
32 "electron:electron_dist_zip"
33 ];
34
35 outputs = [
36 "out"
37 "headers"
38 ];
39
40 # don't automatically move the include directory from $headers back into $out
41 moveToDev = false;
42
43 nativeBuildInputs = base.nativeBuildInputs ++ [
44 nodejs
45 yarn
46 fixup-yarn-lock
47 unzip
48 npmHooks.npmConfigHook
49 gclient2nix.gclientUnpackHook
50 ];
51 buildInputs = base.buildInputs ++ [ libnotify ];
52
53 electronOfflineCache = fetchYarnDeps {
54 yarnLock = gclientDeps."src/electron".path + "/yarn.lock";
55 sha256 = info.electron_yarn_hash;
56 };
57 npmDeps = fetchNpmDeps rec {
58 src = gclientDeps."src".path;
59 # Assume that the fetcher always unpack the source,
60 # based on update.py
61 sourceRoot = "${src.name}/third_party/node";
62 hash = info.chromium_npm_hash;
63 };
64 inherit gclientDeps;
65 unpackPhase = null; # prevent chromium's unpackPhase from being used
66 sourceRoot = "src";
67
68 env =
69 base.env
70 // {
71 # Hydra can fail to build electron due to clang spamming deprecation
72 # warnings mid-build, causing the build log to grow beyond the limit
73 # of 64mb and then getting killed by Hydra.
74 # For some reason, the log size limit appears to only be enforced on
75 # aarch64-linux. x86_64-linux happily succeeds to build with ~180mb. To
76 # unbreak the build on h.n.o, we simply disable those warnings for now.
77 # https://hydra.nixos.org/build/283952243
78 NIX_CFLAGS_COMPILE = base.env.NIX_CFLAGS_COMPILE + " -Wno-deprecated";
79 }
80 // lib.optionalAttrs (lib.versionAtLeast info.version "35") {
81 # Needed for header generation in electron 35 and above
82 ELECTRON_OUT_DIR = "Release";
83 };
84
85 src = null;
86
87 patches =
88 base.patches
89 # Fix building with Rust 1.86+
90 # electron_33 and electron_34 use older chromium versions which expect rust
91 # to provide the older `adler` library instead of the newer `adler2` library
92 # This patch makes those older versions also use the new adler2 library
93 ++ lib.optionals (lib.versionOlder info.version "35") [
94 ./use-rust-adler2.patch
95 ]
96 # Requirements for the next section
97 ++ lib.optionals (lib.versionOlder info.version "35") [
98 (fetchpatch {
99 name = "Avoid-build-rust-PartitionAlloc-dep-when-not-build_with_chromium.patch";
100 url = "https://github.com/chromium/chromium/commit/ee94f376a0dd642a93fbf4a5fa8e7aa8fb2a69b5.patch";
101 hash = "sha256-qGjy9VZ4d3T5AuqOrBKEajBswwBU/7j0n80rpvHZLmM=";
102 })
103 (fetchpatch {
104 name = "Suppress-unsafe_libc_call-warning-for-rust-remap_alloc-cc.patch";
105 url = "https://github.com/chromium/chromium/commit/d5d79d881e74c6c8630f7d2f3affd4f656fdeb4e.patch";
106 hash = "sha256-1oy5WRvNzKuUTJkt8kULUqE4JU+EKEV1PB9QN8HF4SE=";
107 })
108 ]
109 # Fix building with Rust 1.87+
110 # https://issues.chromium.org/issues/407024458
111 ++ lib.optionals (lib.versionOlder info.version "37") [
112 # https://chromium-review.googlesource.com/c/chromium/src/+/6432410
113 # Not using fetchpatch here because it ignores file renames: https://github.com/nixos/nixpkgs/issues/32084
114 ./Reland-Use-global_allocator-to-provide-Rust-allocator-implementation.patch
115
116 # https://chromium-review.googlesource.com/c/chromium/src/+/6434355
117 (fetchpatch {
118 name = "Call-Rust-default-allocator-directly-from-Rust.patch";
119 url = "https://github.com/chromium/chromium/commit/73eef8797a8138f5c26f52a1372644b20613f5ee.patch";
120 hash = "sha256-IcSjPv21xT+l9BwJuzeW2AfwBdKI0dQb3nskk6yeKHU=";
121 })
122
123 # https://chromium-review.googlesource.com/c/chromium/src/+/6439711
124 (fetchpatch {
125 name = "Roll-rust.patch";
126 url = "https://github.com/chromium/chromium/commit/a6c30520486be844735dc646cd5b9b434afa0c6b.patch";
127 includes = [ "build/rust/allocator/*" ];
128 hash = "sha256-MFdR75oSAdFW6telEZt/s0qdUvq/BiYFEHW0vk+RgDk=";
129 })
130
131 # https://chromium-review.googlesource.com/c/chromium/src/+/6456604
132 (fetchpatch {
133 name = "Drop-remap_alloc-dep.patch";
134 url = "https://github.com/chromium/chromium/commit/87d5ad2f621e0d5c81849dde24f3a5347efcb167.patch";
135 hash = "sha256-bEoR6jxEyw6Fzm4Zv4US54Cxa0li/0UTZTU2WUf0Rgo=";
136 })
137
138 # https://chromium-review.googlesource.com/c/chromium/src/+/6454872
139 (fetchpatch {
140 name = "rust-Clean-up-build-rust-allocator-after-a-Rust-tool.patch";
141 url = "https://github.com/chromium/chromium/commit/5c74fcf6fd14491f33dd820022a9ca045f492f68.patch";
142 hash = "sha256-vcD0Zfo4Io/FVpupWOdgurFEqwFCv+oDOtSmHbm+ons=";
143 })
144 ]
145 # Fix building with gperf 3.2+
146 # https://issues.chromium.org/issues/40209959
147 ++ lib.optionals (lib.versionOlder info.version "37") [
148 # https://chromium-review.googlesource.com/c/chromium/src/+/6445471
149 (fetchpatch {
150 name = "Dont-apply-FALLTHROUGH-edit-to-gperf-3-2-output.patch";
151 url = "https://github.com/chromium/chromium/commit/f8f21fb4aa01f75acbb12abf5ea8c263c6817141.patch";
152 hash = "sha256-z/aQ1oQjFZnkUeRnrD6P/WDZiYAI1ncGhOUM+HmjMZA=";
153 })
154 ];
155
156 npmRoot = "third_party/node";
157
158 postPatch = ''
159 mkdir -p third_party/jdk/current/bin
160
161 echo 'build_with_chromium = true' >> build/config/gclient_args.gni
162 echo 'checkout_google_benchmark = false' >> build/config/gclient_args.gni
163 echo 'checkout_android = false' >> build/config/gclient_args.gni
164 echo 'checkout_android_prebuilts_build_tools = false' >> build/config/gclient_args.gni
165 echo 'checkout_android_native_support = false' >> build/config/gclient_args.gni
166 echo 'checkout_ios_webkit = false' >> build/config/gclient_args.gni
167 echo 'checkout_nacl = false' >> build/config/gclient_args.gni
168 echo 'checkout_openxr = false' >> build/config/gclient_args.gni
169 echo 'checkout_rts_model = false' >> build/config/gclient_args.gni
170 echo 'checkout_src_internal = false' >> build/config/gclient_args.gni
171 echo 'cros_boards = ""' >> build/config/gclient_args.gni
172 echo 'cros_boards_with_qemu_images = ""' >> build/config/gclient_args.gni
173 echo 'generate_location_tags = true' >> build/config/gclient_args.gni
174
175 echo 'LASTCHANGE=${info.deps."src".args.tag}-refs/heads/master@{#0}' > build/util/LASTCHANGE
176 echo "$SOURCE_DATE_EPOCH" > build/util/LASTCHANGE.committime
177
178 cat << EOF > gpu/config/gpu_lists_version.h
179 /* Generated by lastchange.py, do not edit.*/
180 #ifndef GPU_CONFIG_GPU_LISTS_VERSION_H_
181 #define GPU_CONFIG_GPU_LISTS_VERSION_H_
182 #define GPU_LISTS_VERSION "${info.deps."src".args.tag}"
183 #endif // GPU_CONFIG_GPU_LISTS_VERSION_H_
184 EOF
185
186 cat << EOF > skia/ext/skia_commit_hash.h
187 /* Generated by lastchange.py, do not edit.*/
188 #ifndef SKIA_EXT_SKIA_COMMIT_HASH_H_
189 #define SKIA_EXT_SKIA_COMMIT_HASH_H_
190 #define SKIA_COMMIT_HASH "${info.deps."src/third_party/skia".args.rev}-"
191 #endif // SKIA_EXT_SKIA_COMMIT_HASH_H_
192 EOF
193
194 echo -n '${info.deps."src/third_party/dawn".args.rev}' > gpu/webgpu/DAWN_VERSION
195
196 (
197 cd electron
198 export HOME=$TMPDIR/fake_home
199 yarn config --offline set yarn-offline-mirror $electronOfflineCache
200 fixup-yarn-lock yarn.lock
201 yarn install --offline --frozen-lockfile --ignore-scripts --no-progress --non-interactive
202 )
203
204 (
205 cd ..
206 PATH=$PATH:${
207 lib.makeBinPath (
208 with pkgsBuildHost;
209 [
210 jq
211 git
212 ]
213 )
214 }
215 config=src/electron/patches/config.json
216 for entry in $(cat $config | jq -c ".[]")
217 do
218 patch_dir=$(echo $entry | jq -r ".patch_dir")
219 repo=$(echo $entry | jq -r ".repo")
220 for patch in $(cat $patch_dir/.patches)
221 do
222 echo applying in $repo: $patch
223 git apply -p1 --directory=$repo --exclude='src/third_party/blink/web_tests/*' --exclude='src/content/test/data/*' $patch_dir/$patch
224 done
225 done
226 )
227 ''
228 + lib.optionalString (lib.versionAtLeast info.version "36") ''
229 echo 'checkout_glic_e2e_tests = false' >> build/config/gclient_args.gni
230 echo 'checkout_mutter = false' >> build/config/gclient_args.gni
231 ''
232 + base.postPatch;
233
234 preConfigure = ''
235 (
236 cd third_party/node
237 grep patch update_npm_deps | sh
238 )
239 ''
240 + (base.preConfigure or "");
241
242 gnFlags = rec {
243 # build/args/release.gn
244 is_component_build = false;
245 is_official_build = true;
246 rtc_use_h264 = proprietary_codecs;
247 is_component_ffmpeg = true;
248
249 # build/args/all.gn
250 is_electron_build = true;
251 root_extra_deps = [ "//electron" ];
252 node_module_version = lib.toInt info.modules;
253 v8_promise_internal_field_count = 1;
254 v8_embedder_string = "-electron.0";
255 v8_enable_snapshot_native_code_counters = false;
256 v8_enable_javascript_promise_hooks = true;
257 enable_cdm_host_verification = false;
258 proprietary_codecs = true;
259 ffmpeg_branding = "Chrome";
260 enable_printing = true;
261 angle_enable_vulkan_validation_layers = false;
262 dawn_enable_vulkan_validation_layers = false;
263 enable_pseudolocales = false;
264 allow_runtime_configurable_key_storage = true;
265 enable_cet_shadow_stack = false;
266 is_cfi = false;
267 v8_builtins_profiling_log_file = "";
268 enable_dangling_raw_ptr_checks = false;
269 dawn_use_built_dxc = false;
270 v8_enable_private_mapping_fork_optimization = true;
271 v8_expose_public_symbols = true;
272 enable_dangling_raw_ptr_feature_flag = false;
273 clang_unsafe_buffers_paths = "";
274 enterprise_cloud_content_analysis = false;
275 content_enable_legacy_ipc = true;
276
277 # other
278 enable_widevine = false;
279 override_electron_version = info.version;
280 };
281
282 installPhase = ''
283 runHook preInstall
284
285 mkdir -p $libExecPath
286 unzip -d $libExecPath out/Release/dist.zip
287
288 mkdir -p $headers
289 cp -r out/Release/gen/node_headers/* $headers/
290
291 runHook postInstall
292 '';
293
294 postFixup =
295 let
296 libPath = lib.makeLibraryPath [
297 libnotify
298 pipewire
299 stdenv.cc.cc
300 libsecret
301 libpulseaudio
302 speechd-minimal
303 ];
304 in
305 base.postFixup
306 + ''
307 patchelf \
308 --add-rpath "${libPath}" \
309 $out/libexec/electron/electron
310 '';
311
312 requiredSystemFeatures = [ "big-parallel" ];
313
314 passthru = {
315 inherit info;
316 };
317
318 meta = with lib; {
319 description = "Cross platform desktop application shell";
320 homepage = "https://github.com/electron/electron";
321 platforms = lib.platforms.linux;
322 license = licenses.mit;
323 maintainers = with maintainers; [
324 yayayayaka
325 teutat3s
326 tomasajt
327 ];
328 mainProgram = "electron";
329 hydraPlatforms =
330 lib.optionals (!(hasInfix "alpha" info.version) && !(hasInfix "beta" info.version))
331 [
332 "aarch64-linux"
333 "x86_64-linux"
334 ];
335 timeout = 172800; # 48 hours (increased from the Hydra default of 10h)
336 };
337})).overrideAttrs
338 (
339 finalAttrs: prevAttrs: {
340 # this was the only way I could get the package to properly reference itself
341 passthru = prevAttrs.passthru // {
342 dist = finalAttrs.finalPackage + "/libexec/electron";
343 };
344 }
345 )