writeDarwinBundle: use binary wrapper

Previously `writeDarwinBundle` used a handcrafted shell wrapper, however
this causes issues on Apple Silicon Macs as script-only application
bundles are always run under Rosetta[0][1].

Replacing the handcrafted shell wrapper with a binary wrapper allows
apps to run natively instead of requiring Rosetta. However, this means
we can no longer use `$1` and `$@`.

After checking nearly every current usage of `desktopToDarwinBundle`,
there were no apps that used `%[fFuU]` before the last argument, meaning
removing them naively is good enough for the current apps.

[0]: https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary
[1]: https://stackoverflow.com/a/68208374

+21 -13
+19 -11
pkgs/build-support/make-darwin-bundle/write-darwin-bundle.nix
··· 1 - { writeScriptBin, lib, ... }: 1 + { writeScriptBin, lib, makeBinaryWrapper }: 2 2 3 3 let 4 4 pListText = lib.generators.toPlist { } { ··· 17 17 18 18 readonly prefix=$1 19 19 readonly name=$2 20 - readonly exec=$3 20 + # TODO: support executables with spaces in their names 21 + readonly execName=''${3%% *} # Before the first space 22 + [[ $3 =~ " " ]] && readonly execArgs=''${3#* } # Everything after the first space 21 23 readonly icon=$4.icns 22 24 readonly squircle=''${5:-1} 23 25 readonly plist=$prefix/Applications/$name.app/Contents/Info.plist 26 + readonly binary=$prefix/bin/$execName 27 + readonly bundleExecutable=$prefix/Applications/$name.app/Contents/MacOS/$name 24 28 25 29 cat > "$plist" <<EOF 26 30 ${pListText} 27 31 EOF 28 32 29 - if [[ $squircle == 0 || $squircle == "false" ]]; then 30 - sed '/CFBundleIconFiles/,\|</array>|d' -i "$plist" 31 - fi 32 - 33 - cat > "$prefix/Applications/$name.app/Contents/MacOS/$name" <<EOF 34 - #!/bin/bash 35 - exec $prefix/bin/$exec 36 - EOF 33 + if [[ $squircle == 0 || $squircle == "false" ]]; then 34 + sed '/CFBundleIconFiles/,\|</array>|d' -i "$plist" 35 + fi 37 36 38 - chmod +x "$prefix/Applications/$name.app/Contents/MacOS/$name" 37 + if [[ -n "$execArgs" ]]; then 38 + ( 39 + source ${makeBinaryWrapper}/nix-support/setup-hook 40 + # WORKAROUND: makeBinaryWrapper fails when -u is set 41 + set +u 42 + makeBinaryWrapper "$binary" "$bundleExecutable" --add-flags "$execArgs" 43 + ) 44 + else 45 + ln -s "$binary" "$bundleExecutable" 46 + fi 39 47 ''
+2 -2
pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh
··· 204 204 local -r execNoKC="${execNoK/\%c/$(getDesktopParam "${file}" "Name")}" 205 205 local -r icon=$(getDesktopParam "${file}" "Icon") 206 206 local -r execNoKCI="${execNoKC/\%i/${icon:+--icon }${icon}}" 207 - local -r execNoKCIfu="${execNoKCI/\%[fu]/\$1}" 208 - local -r exec="${execNoKCIfu/\%[FU]/\$@}" 207 + local -r execNoKCIfu="${execNoKCI/ \%[fu]/}" 208 + local -r exec="${execNoKCIfu/ \%[FU]/}" 209 209 if [[ "$exec" != "$execRaw" ]]; then 210 210 echo 1>&2 "desktopToDarwinBundle: Application bundles do not understand desktop entry field codes. Changed '$execRaw' to '$exec'." 211 211 fi