diff --git a/pkgs/by-name/si/signal-desktop/package.nix b/pkgs/by-name/si/signal-desktop/package.nix index e2f1426fdf9c..1b7554e31d49 100644 --- a/pkgs/by-name/si/signal-desktop/package.nix +++ b/pkgs/by-name/si/signal-desktop/package.nix @@ -13,6 +13,7 @@ jq, makeDesktopItem, copyDesktopItems, + xcodebuild, replaceVars, noto-fonts-color-emoji, nixosTests, @@ -105,9 +106,14 @@ stdenv.mkDerivation (finalAttrs: { pnpmConfigHook pnpm makeWrapper - copyDesktopItems python3 jq + ] + ++ lib.optionals stdenv.hostPlatform.isDarwin [ + xcodebuild + ] + ++ lib.optionals stdenv.hostPlatform.isLinux [ + copyDesktopItems ]; buildInputs = (lib.optional (!withAppleEmojis) noto-fonts-color-emoji-png); @@ -134,6 +140,16 @@ stdenv.mkDerivation (finalAttrs: { # https://github.com/signalapp/Signal-Desktop/issues/7667 substituteInPlace ts/util/version.std.ts \ --replace-fail 'isAdhoc(version)' 'true' + + # Nix builds do not need upstream release hooks (notarization and + # language-pack postprocessing), and they expect a different macOS + # app layout than nixpkgs' Electron provides. + substituteInPlace package.json \ + --replace-fail '"artifactBuildCompleted": "ts/scripts/artifact-build-completed.node.js",' "" \ + --replace-fail '"afterSign": "ts/scripts/after-sign.node.js",' "" \ + --replace-fail '"afterPack": "ts/scripts/after-pack.node.js",' "" \ + --replace-fail '"sign": "./ts/scripts/sign-macos.node.js",' "" \ + --replace-fail '"afterAllArtifactBuild": "ts/scripts/after-all-artifact-build.node.js",' "" ''; pnpmDeps = fetchPnpmDeps { @@ -156,6 +172,10 @@ stdenv.mkDerivation (finalAttrs: { ELECTRON_SKIP_BINARY_DOWNLOAD = "1"; SIGNAL_ENV = "production"; SOURCE_DATE_EPOCH = 1771441806; + } + // lib.optionalAttrs stdenv.hostPlatform.isDarwin { + # Disable code signing during local macOS builds. + CSC_IDENTITY_AUTO_DISCOVERY = "false"; }; preBuild = '' @@ -200,6 +220,15 @@ stdenv.mkDerivation (finalAttrs: { rm -r node_modules/@signalapp/sqlcipher cp -r ${signal-sqlcipher} node_modules/@signalapp/sqlcipher + + # fs-xattr is required at runtime by preload.wrapper.js, + # but with npmRebuild disabled its native binding is missing. + # Build it explicitly against Electron headers ahead of packaging. + export npm_config_nodedir=${electron.headers} + pushd node_modules/fs-xattr + pnpm exec node-gyp rebuild + popd + test -f node_modules/fs-xattr/build/Release/xattr.node ''; buildPhase = '' @@ -212,18 +241,29 @@ stdenv.mkDerivation (finalAttrs: { pnpm run generate pnpm exec electron-builder \ - --linux "dir:${stdenv.hostPlatform.node.arch}" \ + ${ + if stdenv.hostPlatform.isDarwin then "--mac" else "--linux" + } "dir:${stdenv.hostPlatform.node.arch}" \ --config.extraMetadata.environment=$SIGNAL_ENV \ -c.electronDist=electron-dist \ - -c.electronVersion=${electron.version} + -c.electronVersion=${electron.version} \ + -c.npmRebuild=false \ + ${lib.optionalString stdenv.hostPlatform.isDarwin "-c.mac.identity=null"} runHook postBuild ''; installPhase = '' runHook preInstall - - mkdir -p $out/share/ + '' + + lib.optionalString stdenv.hostPlatform.isDarwin '' + mkdir -p $out/{Applications,bin} + cp -r dist/mac*/Signal.app $out/Applications + makeWrapper "$out/Applications/Signal.app/Contents/MacOS/Signal" "$out/bin/signal-desktop" \ + --add-flags ${lib.escapeShellArg commandLineArgs} + '' + + lib.optionalString (!stdenv.hostPlatform.isDarwin) '' + mkdir -p $out/share cp -r dist/*-unpacked/resources $out/share/signal-desktop for icon in build/icons/png/* @@ -236,7 +276,8 @@ stdenv.mkDerivation (finalAttrs: { --set-default ELECTRON_FORCE_IS_PACKAGED 1 \ --add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--enable-features=WaylandWindowDecorations --enable-wayland-ime=true}}" \ --add-flags ${lib.escapeShellArg commandLineArgs} - + '' + + '' runHook postInstall ''; @@ -293,6 +334,7 @@ stdenv.mkDerivation (finalAttrs: { ++ lib.optional withAppleEmojis unfree; maintainers = with lib.maintainers; [ eclairevoyant + iamanaws marcin-serwin teutat3s ]; @@ -300,6 +342,8 @@ stdenv.mkDerivation (finalAttrs: { platforms = [ "x86_64-linux" "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" ]; }; }) diff --git a/pkgs/by-name/si/signal-desktop/signal-sqlcipher.nix b/pkgs/by-name/si/signal-desktop/signal-sqlcipher.nix index 30baac157cb5..d753e1d9d938 100644 --- a/pkgs/by-name/si/signal-desktop/signal-sqlcipher.nix +++ b/pkgs/by-name/si/signal-desktop/signal-sqlcipher.nix @@ -10,6 +10,8 @@ cargo, dump_syms, python3, + xcodebuild, + cctools, }: stdenv.mkDerivation (finalAttrs: { pname = "node-sqlcipher"; @@ -45,6 +47,10 @@ stdenv.mkDerivation (finalAttrs: { cargo dump_syms python3 + ] + ++ lib.optionals stdenv.hostPlatform.isDarwin [ + xcodebuild + cctools.libtool ]; buildPhase = '' @@ -75,6 +81,6 @@ stdenv.mkDerivation (finalAttrs: { # deps/sqlcipher bsd3 ]; - platforms = lib.platforms.linux; + platforms = lib.platforms.linux ++ lib.platforms.darwin; }; }) diff --git a/pkgs/by-name/si/signal-desktop/webrtc.nix b/pkgs/by-name/si/signal-desktop/webrtc.nix index b4c02a195b94..8a33b1575517 100644 --- a/pkgs/by-name/si/signal-desktop/webrtc.nix +++ b/pkgs/by-name/si/signal-desktop/webrtc.nix @@ -4,6 +4,7 @@ buildPackages, ninja, gn, + symlinkJoin, python3, pkg-config, glib, @@ -12,9 +13,20 @@ writeShellScriptBin, gclient2nix, rustc, + apple-sdk, + xcodebuild, + llvmPackages, }: let + llvmCcAndBintools = symlinkJoin { + name = "signal-webrtc-llvm-cc-and-bintools"; + paths = [ + llvmPackages.llvm + llvmPackages.stdenv.cc + ]; + }; + chromiumRosettaStone = { cpu = platform: @@ -39,6 +51,13 @@ stdenv.mkDerivation (finalAttrs: { gclientDeps = gclient2nix.importGclientDeps ./webrtc-sources.json; sourceRoot = "src"; + # Chromium's Darwin toolchain defines _LIBCPP_HARDENING_MODE itself; keep + # cc-wrapper from injecting a conflicting default. + hardeningDisable = lib.optionals stdenv.isDarwin [ + "libcxxhardeningfast" + "libcxxhardeningextensive" + ]; + nativeBuildInputs = [ gn ninja @@ -49,21 +68,44 @@ stdenv.mkDerivation (finalAttrs: { rustc pkg-config gclient2nix.gclientUnpackHook + ] + ++ lib.optionals stdenv.isDarwin [ + apple-sdk + xcodebuild ]; buildInputs = [ glib - alsa-lib pulseaudio + ] + ++ lib.optionals stdenv.isDarwin [ + llvmPackages.compiler-rt + ] + ++ lib.optionals stdenv.isLinux [ + alsa-lib ]; postPatch = '' substituteInPlace build/toolchain/linux/BUILD.gn \ --replace-fail 'toolprefix = "aarch64-linux-gnu-"' 'toolprefix = ""' - patchShebangs build/mac/should_use_hermetic_xcode.py substituteInPlace modules/audio_device/linux/pulseaudiosymboltable_linux.cc \ --replace-fail "libpulse.so.0" "${pulseaudio}/lib/libpulse.so.0" + '' + + lib.optionalString stdenv.isDarwin '' + # Fix Darwin Python script shebangs for sandbox builds + patchShebangs build/mac/should_use_hermetic_xcode.py build/toolchain/apple/linker_driver.py + + substituteInPlace build/config/clang/BUILD.gn \ + --replace-fail '_clang_lib_dir = "$clang_base_path/lib/clang/$clang_version/lib"' \ + '_clang_lib_dir = "${llvmPackages.compiler-rt}/lib"' + + # Keep target triple aligned with nix cc-wrapper expectations to avoid + # arm64-apple-macos vs arm64-apple-darwin warning spam. + substituteInPlace build/config/mac/BUILD.gn \ + --replace-fail "apple-macos" "apple-darwin" + '' + + lib.optionalString stdenv.isLinux '' substituteInPlace modules/audio_device/linux/alsasymboltable_linux.cc \ --replace-fail "libasound.so.2" "${alsa-lib}/lib/libasound.so.2" ''; @@ -73,46 +115,59 @@ stdenv.mkDerivation (finalAttrs: { echo "generate_location_tags = true" >> build/config/gclient_args.gni ''; - gnFlags = [ - # webrtc uses chromium's `src/build/BUILDCONFIG.gn`. many of these flags - # are copied from pkgs/applications/networking/browsers/chromium/common.nix. - ''target_os="linux"'' - ''target_cpu="${chromiumRosettaStone.cpu stdenv.hostPlatform}"'' - ''pkg_config="${stdenv.cc.targetPrefix}pkg-config"'' - "use_sysroot=false" - "is_clang=false" - "treat_warnings_as_errors=false" - "use_llvm_libatomic=false" - "use_custom_libcxx=false" + gnFlags = + lib.optionals stdenv.isLinux [ + # webrtc uses chromium's `src/build/BUILDCONFIG.gn`. many of these flags + # are copied from pkgs/applications/networking/browsers/chromium/common.nix. + ''target_os="linux"'' + ''pkg_config="${stdenv.cc.targetPrefix}pkg-config"'' + "use_sysroot=false" + "is_clang=false" - # https://github.com/signalapp/ringrtc/blob/main/bin/build-desktop - "rtc_build_examples=false" - "rtc_build_tools=false" - "rtc_use_x11=false" - "rtc_enable_sctp=false" - "rtc_libvpx_build_vp9=true" - "rtc_disable_metrics=true" - "rtc_disable_trace_events=true" - "is_debug=false" - "symbol_level=1" - "rtc_include_tests=false" - "rtc_enable_protobuf=false" - - ''rust_sysroot_absolute="${buildPackages.rustc}"'' - - # Build using the system toolchain (for Linux distributions): - # - # What you would expect to be called "target_toolchain" is - # actually called either "default_toolchain" or "custom_toolchain", - # depending on which part of the codebase you are in; see: - # https://chromium.googlesource.com/chromium/src/build/+/3c4595444cc6d514600414e468db432e0f05b40f/config/BUILDCONFIG.gn#17 - ''custom_toolchain="//build/toolchain/linux/unbundle:default"'' - ''host_toolchain="//build/toolchain/linux/unbundle:default"'' - ] - ++ lib.optionals (stdenv.buildPlatform != stdenv.hostPlatform) [ - ''host_toolchain="//build/toolchain/linux/unbundle:host"'' - ''v8_snapshot_toolchain="//build/toolchain/linux/unbundle:host"'' - ]; + # Build using the system toolchain (for Linux distributions): + # + # What you would expect to be called "target_toolchain" is + # actually called either "default_toolchain" or "custom_toolchain", + # depending on which part of the codebase you are in; see: + # https://chromium.googlesource.com/chromium/src/build/+/3c4595444cc6d514600414e468db432e0f05b40f/config/BUILDCONFIG.gn#17 + ''custom_toolchain="//build/toolchain/linux/unbundle:default"'' + ''host_toolchain="//build/toolchain/linux/unbundle:default"'' + ] + ++ lib.optionals stdenv.isDarwin [ + ''target_os="mac"'' + ''mac_deployment_target="${stdenv.hostPlatform.darwinMinVersion}"'' + "use_sysroot=true" + "is_clang=true" + "use_lld=false" + "clang_use_chrome_plugins=false" + "clang_use_raw_ptr_plugin=false" + "use_clang_modules=false" + ''clang_base_path="${llvmCcAndBintools}"'' + ''custom_toolchain="//build/toolchain/mac:clang_${chromiumRosettaStone.cpu stdenv.hostPlatform}"'' + ] + ++ [ + ''target_cpu="${chromiumRosettaStone.cpu stdenv.hostPlatform}"'' + # https://github.com/signalapp/ringrtc/blob/main/bin/build-desktop + "rtc_build_examples=false" + "rtc_build_tools=false" + "rtc_use_x11=false" + "rtc_enable_sctp=false" + "rtc_libvpx_build_vp9=true" + "rtc_disable_metrics=true" + "rtc_disable_trace_events=true" + "is_debug=false" + "symbol_level=1" + "rtc_include_tests=false" + "rtc_enable_protobuf=false" + "treat_warnings_as_errors=false" + "use_llvm_libatomic=false" + "use_custom_libcxx=false" + ''rust_sysroot_absolute="${buildPackages.rustc}"'' + ] + ++ lib.optionals (stdenv.isLinux && stdenv.buildPlatform != stdenv.hostPlatform) [ + ''host_toolchain="//build/toolchain/linux/unbundle:host"'' + ''v8_snapshot_toolchain="//build/toolchain/linux/unbundle:host"'' + ]; ninjaFlags = [ "webrtc" ]; installPhase = '' @@ -128,6 +183,6 @@ stdenv.mkDerivation (finalAttrs: { homepage = "https://github.com/SignalApp/webrtc"; license = lib.licenses.bsd3; maintainers = [ ]; - platforms = lib.platforms.linux; + platforms = lib.platforms.linux ++ lib.platforms.darwin; }; })