diff --git a/pkgs/applications/networking/instant-messengers/element/element-desktop.nix b/pkgs/applications/networking/instant-messengers/element/element-desktop.nix
index 5ba7a1f7b205..d9683740667c 100644
--- a/pkgs/applications/networking/instant-messengers/element/element-desktop.nix
+++ b/pkgs/applications/networking/instant-messengers/element/element-desktop.nix
@@ -12,6 +12,7 @@
, Security
, AppKit
, CoreServices
+, desktopToDarwinBundle
}:
let
@@ -36,7 +37,7 @@ mkYarnPackage rec {
sha256 = pinData.desktopYarnHash;
};
- nativeBuildInputs = [ makeWrapper ];
+ nativeBuildInputs = [ makeWrapper ] ++ lib.optionals stdenv.isDarwin [ desktopToDarwinBundle ];
seshat = callPackage ./seshat { inherit CoreServices; };
keytar = callPackage ./keytar { inherit Security AppKit; };
diff --git a/pkgs/build-support/make-darwin-bundle/default.nix b/pkgs/build-support/make-darwin-bundle/default.nix
new file mode 100644
index 000000000000..b8f58882fff3
--- /dev/null
+++ b/pkgs/build-support/make-darwin-bundle/default.nix
@@ -0,0 +1,26 @@
+# given a package with an executable and an icon, make a darwin bundle for
+# it. This package should be used when generating launchers for native Darwin
+# applications. If the package conatins a .desktop file use
+# `desktopToDarwinLauncher` instead.
+
+{ lib, writeShellScript, writeDarwinBundle }:
+
+{ name # The name of the Application file.
+, exec # Executable file.
+, icon ? "" # Optional icon file.
+}:
+
+writeShellScript "make-darwin-bundle-${name}" (''
+ function makeDarwinBundlePhase() {
+ mkdir -p "$out/Applications/${name}.app/Contents/MacOS"
+ mkdir -p "$out/Applications/${name}.app/Contents/Resources"
+
+ if [ -n "${icon}" ]; then
+ ln -s "${icon}" "$out/Applications/${name}.app/Contents/Resources"
+ fi
+
+ ${writeDarwinBundle}/bin/write-darwin-bundle "$out" "${name}" "${exec}"
+ }
+
+ preDistPhases+=" makeDarwinBundlePhase"
+'')
diff --git a/pkgs/build-support/make-darwin-bundle/write-darwin-bundle.nix b/pkgs/build-support/make-darwin-bundle/write-darwin-bundle.nix
new file mode 100644
index 000000000000..63ef7e655075
--- /dev/null
+++ b/pkgs/build-support/make-darwin-bundle/write-darwin-bundle.nix
@@ -0,0 +1,40 @@
+{ writeScriptBin, lib, ... }:
+
+let
+ pListText = lib.generators.toPlist { } {
+ CFBundleDevelopmentRegion = "English";
+ CFBundleExecutable = "$name";
+ CFBundleIconFiles = [ "$iconPlistArray" ];
+ CFBundleIdentifier = "org.nixos.$name";
+ CFBundleInfoDictionaryVersion = "6.0";
+ CFBundleName = "$name";
+ CFBundlePackageType = "APPL";
+ CFBundleSignature = "???";
+ };
+
+# The generation of the CFBundleIconFiles array is a bit of a hack, since we
+# will always end up with an empty first element () but macOS
+# appears to ignore this which allows us to use the nix PList generator.
+in writeScriptBin "write-darwin-bundle" ''
+ shopt -s nullglob
+
+ readonly prefix="$1"
+ readonly name="$2"
+ readonly exec="$3"
+ iconPlistArray=""
+
+ for icon in "$prefix/Applications/$name.app/Contents/Resources"/*; do
+ iconPlistArray="$iconPlistArray"$(basename "$icon")""
+ done
+
+ cat > "$prefix/Applications/$name.app/Contents/Info.plist" < "$prefix/Applications/$name.app/Contents/MacOS/$name" </dev/null);
+ local -r pixMaps=$(find "$out/share/pixmaps/" -name "${iconName}.xpm" 2>/dev/null);
+
+ mkdir -p "$out/Applications/${name}.app/Contents/MacOS"
+ mkdir -p "$out/Applications/${name}.app/Contents/Resources"
+
+ local i=0;
+ for icon in $iconFiles; do
+ ln -s "$icon" "$out/Applications/${name}.app/Contents/Resources/$i-$(basename "$icon")"
+ (( i +=1 ));
+ done
+
+ for pixmap in $pixMaps; do
+ local newIconName="$i-$(basename "$pixmap")";
+ convert "$pixmap" "$out/Applications/${name}.app/Contents/Resources/${newIconName%.xpm}.png"
+ (( i +=1 ));
+ done
+
+ write-darwin-bundle "$out" "$name" "$exec"
+}
+
+convertDesktopFiles() {
+ local dir="$1/share/applications/"
+
+ if [ -d "${dir}" ]; then
+ for desktopFile in $(find "$dir" -iname "*.desktop"); do
+ convertDesktopFile "$desktopFile";
+ done
+ fi
+}
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 0bb3cbe5ec3b..5a28adb25aae 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -713,6 +713,8 @@ with pkgs;
makeDesktopItem = callPackage ../build-support/make-desktopitem { };
+ makeDarwinBundle = callPackage ../build-support/make-darwin-bundle { };
+
makeAutostartItem = callPackage ../build-support/make-startupitem { };
makeInitrd = callPackage ../build-support/kernel/make-initrd.nix; # Args intentionally left out
@@ -815,6 +817,11 @@ with pkgs;
substitutions = { inherit (binutils) targetPrefix; };
} ../build-support/setup-hooks/fix-darwin-dylib-names.sh;
+ writeDarwinBundle = callPackage ../build-support/make-darwin-bundle/write-darwin-bundle.nix { };
+
+ desktopToDarwinBundle = makeSetupHook { deps = [ writeDarwinBundle imagemagick ]; }
+ ../build-support/setup-hooks/desktop-to-darwin-bundle.sh;
+
keepBuildTree = makeSetupHook { } ../build-support/setup-hooks/keep-build-tree.sh;
enableGCOVInstrumentation = makeSetupHook { } ../build-support/setup-hooks/enable-coverage-instrumentation.sh;