summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--pkgs/applications/networking/instant-messengers/element/element-desktop.nix3
-rw-r--r--pkgs/build-support/make-darwin-bundle/default.nix26
-rw-r--r--pkgs/build-support/make-darwin-bundle/write-darwin-bundle.nix40
-rw-r--r--pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh48
-rw-r--r--pkgs/top-level/all-packages.nix7
5 files changed, 123 insertions, 1 deletions
diff --git a/pkgs/applications/networking/instant-messengers/element/element-desktop.nix b/pkgs/applications/networking/instant-messengers/element/element-desktop.nix
index 5ba7a1f7b20..d9683740667 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 00000000000..b8f58882fff
--- /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 00000000000..63ef7e65507
--- /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 (<string></string>) 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</string><string>"$(basename "$icon")""
+    done
+
+    cat > "$prefix/Applications/$name.app/Contents/Info.plist" <<EOF
+${pListText}
+EOF
+
+    cat > "$prefix/Applications/$name.app/Contents/MacOS/$name" <<EOF
+#!/bin/bash
+exec $prefix/bin/$exec
+EOF
+
+    chmod +x "$prefix/Applications/$name.app/Contents/MacOS/$name"
+''
diff --git a/pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh b/pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh
new file mode 100644
index 00000000000..d1175d3a5f9
--- /dev/null
+++ b/pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh
@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+fixupOutputHooks+=('convertDesktopFiles $prefix')
+
+# Get a param out of a desktop file. First parameter is the file and the second
+# is a pattern of the key who's value we should fetch.
+getDesktopParam() {
+    local file="$1";
+    local pattern="$2";
+
+    awk -F "=" "/${pattern}/ {print \$2}" "${file}"
+}
+
+# For a given .desktop file, generate a darwin '.app' bundle for it.
+convertDesktopFile() {
+    local -r file="$1"
+    local -r name=$(getDesktopParam "${file}" "^Name")
+    local -r exec=$(getDesktopParam "${file}" "Exec")
+    local -r iconName=$(getDesktopParam "${file}" "Icon")
+    local -r iconFiles=$(find "$out/share/icons/" -name "${iconName}.*" 2>/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 0bb3cbe5ec3..5a28adb25aa 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;