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