justawriter

Make .app Compiler

Sep 5th, 2025
25
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.25 KB | Software | 0 0
  1. #!/bin/bash
  2. #
  3. # =====================================================================
  4. # make_app_compiler — Convert a .command / .sh / .bsh script into a macOS .app
  5. # =====================================================================
  6. #
  7. # PURPOSE:
  8. # Turn any shell script (e.g., doom_launcher.command, filename.sh, filename.bsh)
  9. # into a double-clickable macOS .app. Uses an AppleScript wrapper via osacompile.
  10. #
  11. # QUICK USAGE:
  12. # make_app_compiler -f /path/to/doom_launcher.command
  13. #
  14. # REQUIRED:
  15. # -f, --file FILE Path to the .command/.sh/.bsh script to wrap
  16. #
  17. # OPTIONAL:
  18. # -n, --name NAME App name (default: input filename without extension)
  19. # -m, --mode MODE Run mode: "silent" (no Terminal) or "terminal" (default: silent)
  20. # -d, --dest DIR Destination folder for the .app (default: script's folder)
  21. # -h, --help Show usage with examples and exit
  22. #
  23. # EXAMPLES:
  24. # make_app_compiler -f ./doom_launcher.command
  25. # make_app_compiler -f ./filename.sh -m terminal
  26. # make_app_compiler -f ./filename.bsh -n "My Launcher" -d "/Applications"
  27. #
  28. # NOTES:
  29. # - The tool sets the source script executable (chmod +x).
  30. # - On first run, macOS Gatekeeper may block the app. Right‑click → Open (one time).
  31. # - Your original script is not modified.
  32. #
  33. # =====================================================================
  34.  
  35. set -euo pipefail
  36.  
  37. # ------------- helpers -------------
  38. usage() {
  39. cat <<'USAGE'
  40. make_app_compiler — Convert a .command / .sh / .bsh script into a macOS .app
  41.  
  42. REQUIRED:
  43. -f, --file FILE Path to the script to wrap (e.g., ./doom_launcher.command)
  44.  
  45. OPTIONAL:
  46. -n, --name NAME App name (default: source filename without extension)
  47. -m, --mode MODE Run mode: "silent" (no Terminal) or "terminal" (default: silent)
  48. -d, --dest DIR Output folder for the .app (default: same folder as the script)
  49. -h, --help Show this help and exit
  50.  
  51. EXAMPLES:
  52. make_app_compiler -f ./doom_launcher.command
  53. make_app_compiler -f ./filename.sh -m terminal
  54. make_app_compiler -f ./filename.bsh -n "My Launcher" -d "/Applications"
  55.  
  56. USAGE
  57. }
  58.  
  59. die() { echo "ERROR: $*" >&2; exit 1; }
  60. trim() { awk '{$1=$1;print}' <<<"$*"; }
  61.  
  62. # ------------- parse flags -------------
  63. SOURCE_SCRIPT=""
  64. APP_NAME=""
  65. RUN_MODE="silent"
  66. DEST_DIR=""
  67.  
  68. while (($#)); do
  69. case "$1" in
  70. -f|--file)
  71. shift
  72. SOURCE_SCRIPT="${1:-}"; [ -n "${SOURCE_SCRIPT}" ] || die "Missing value for -f|--file"
  73. ;;
  74. -n|--name)
  75. shift
  76. APP_NAME="${1:-}"; [ -n "${APP_NAME}" ] || die "Missing value for -n|--name"
  77. ;;
  78. -m|--mode)
  79. shift
  80. RUN_MODE="$(echo "${1:-}" | tr '[:upper:]' '[:lower:]')"
  81. [ -n "${RUN_MODE}" ] || die "Missing value for -m|--mode"
  82. ;;
  83. -d|--dest)
  84. shift
  85. DEST_DIR="${1:-}"; [ -n "${DEST_DIR}" ] || die "Missing value for -d|--dest"
  86. ;;
  87. -h|--help)
  88. usage; exit 0 ;;
  89. --) shift; break ;;
  90. -*)
  91. echo "Unknown option: $1" >&2
  92. usage; exit 2 ;;
  93. *)
  94. echo "Unexpected positional argument: $1" >&2
  95. usage; exit 2 ;;
  96. esac
  97. shift
  98. done
  99.  
  100. # Require -f/--file
  101. if [ -z "${SOURCE_SCRIPT}" ]; then
  102. echo "No source script provided."
  103. echo ""
  104. usage
  105. exit 2
  106. fi
  107.  
  108. # ------------- validate inputs -------------
  109. [ -f "$SOURCE_SCRIPT" ] || die "Script not found: $SOURCE_SCRIPT"
  110.  
  111. SCRIPT_DIR="$(cd "$(dirname "$SOURCE_SCRIPT")" && pwd)"
  112. SCRIPT_FILE="$(basename "$SOURCE_SCRIPT")"
  113. SCRIPT_ABS="$SCRIPT_DIR/$SCRIPT_FILE"
  114. BASENAME_NOEXT="${SCRIPT_FILE%.*}"
  115.  
  116. # Defaults for name and dest
  117. APP_NAME="${APP_NAME:-$BASENAME_NOEXT}"
  118. [ -n "${DEST_DIR}" ] || DEST_DIR="$SCRIPT_DIR"
  119. DEST_DIR="$(cd "$DEST_DIR" && pwd)"
  120.  
  121. # Validate mode
  122. case "$RUN_MODE" in
  123. silent|terminal) ;;
  124. *)
  125. die "Invalid --mode. Use 'silent' or 'terminal'."
  126. ;;
  127. esac
  128.  
  129. APP_OUT="$DEST_DIR/$APP_NAME.app"
  130.  
  131. # ------------- ensure executable -------------
  132. echo "Making script executable: $SCRIPT_ABS"
  133. chmod +x "$SCRIPT_ABS"
  134.  
  135. # ------------- AppleScript wrappers -------------
  136. read -r -d '' AS_SILENT <<'EOF' || true
  137. on run
  138. set scriptPOSIX to "%SCRIPT_PATH%"
  139. do shell script quoted form of scriptPOSIX
  140. end run
  141. EOF
  142.  
  143. read -r -d '' AS_TERMINAL <<'EOF' || true
  144. on run
  145. set scriptPOSIX to "%SCRIPT_PATH%"
  146. tell application "Terminal"
  147. activate
  148. do script quoted form of scriptPOSIX
  149. end tell
  150. end run
  151. EOF
  152.  
  153. AS_WRAPPER="$AS_SILENT"
  154. [ "$RUN_MODE" = "terminal" ] && AS_WRAPPER="$AS_TERMINAL"
  155. AS_WRAPPER="${AS_WRAPPER//%SCRIPT_PATH%/$SCRIPT_ABS}"
  156.  
  157. # ------------- compile app -------------
  158. command -v osacompile >/dev/null 2>&1 || die "osacompile not found (required on macOS)."
  159.  
  160. TMPDIR="$(mktemp -d)"
  161. AS_FILE="$TMPDIR/wrapper.applescript"
  162. printf "%s\n" "$AS_WRAPPER" > "$AS_FILE"
  163.  
  164. rm -rf "$APP_OUT"
  165. echo "Creating app: $APP_OUT"
  166. osacompile -o "$APP_OUT" "$AS_FILE"
  167.  
  168. # ------------- cleanup + summary -------------
  169. rm -rf "$TMPDIR"
  170.  
  171. echo ""
  172. echo "App created successfully:"
  173. echo " $APP_OUT"
  174. echo ""
  175. echo "Details:"
  176. echo " Source script : $SCRIPT_ABS"
  177. echo " App name : $APP_NAME"
  178. echo " Destination : $DEST_DIR"
  179. echo " Run mode : $RUN_MODE"
  180. echo ""
  181. echo "Note: If macOS blocks the app on first run, right-click it and choose 'Open'."
  182. echo ""
  183.  
  184. exit 0
Advertisement
Add Comment
Please, Sign In to add comment