Mercurial
diff gui_ze/gui_ze.bzl @ 60:d64a8c189a77
Merged
| author | June Park <me@mrjunejune.com> |
|---|---|
| date | Sat, 20 Dec 2025 13:56:01 -0500 |
| parents | ccb42d5bf8fd |
| children | a30944e5719e |
line wrap: on
line diff
--- a/gui_ze/gui_ze.bzl Tue Dec 16 21:01:45 2025 -0500 +++ b/gui_ze/gui_ze.bzl Sat Dec 20 13:56:01 2025 -0500 @@ -10,7 +10,6 @@ implementation = _foo_impl, ) - def _bundle_impl(ctx): """ bundle binary target into a folder which can later be used to make a post to github easily. @@ -183,3 +182,169 @@ "dest": attr.string(), }, ) + + +def _macos_app_impl(ctx): + """Implementation for creating a macOS .app bundle from a binary.""" + binary = ctx.file.binary + app_name = ctx.attr.app_name + bundle_id = ctx.attr.bundle_id + + # Declare the .app directory as output + app_dir = ctx.actions.declare_directory(app_name + ".app") + + ctx.actions.run_shell( + inputs = [binary], + outputs = [app_dir], + command = """ + set -e + + APPDIR="{app_dir}" + + rm -rf "$APPDIR" + mkdir -p "$APPDIR/Contents/MacOS" + mkdir -p "$APPDIR/Contents/Resources" + + cp {binary} "$APPDIR/Contents/MacOS/{app_name}" + chmod +x "$APPDIR/Contents/MacOS/{app_name}" + + cat > "$APPDIR/Contents/Info.plist" <<EOF +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" + "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleExecutable</key> + <string>{app_name}</string> + <key>CFBundleIdentifier</key> + <string>{bundle_id}</string> + <key>CFBundleName</key> + <string>{app_name}</string> + <key>CFBundleVersion</key> + <string>1.0</string> +</dict> +</plist> +EOF + """.format( + app_dir = app_dir.path, + binary = binary.path, + app_name = app_name, + bundle_id = bundle_id, + ), + progress_message = "Creating macOS app bundle for {}".format(app_name), + ) + + return [DefaultInfo(files = depset([app_dir]))] + +_macos_app = rule( + implementation = _macos_app_impl, + attrs = { + "binary": attr.label( + allow_single_file = True, + mandatory = True, + doc = "The binary to bundle into a .app", + ), + "app_name": attr.string( + mandatory = True, + doc = "Name of the application", + ), + "bundle_id": attr.string( + mandatory = True, + doc = "Bundle identifier (e.g., com.example.app)", + ), + }, +) + +def _macos_signed_app_impl(ctx): + """Implementation for signing a macOS .app bundle.""" + app_dir = ctx.file.app + app_name = ctx.attr.app_name + + # Declare the signed .app directory as output + signed_app_dir = ctx.actions.declare_directory(app_name + "_signed.app") + + ctx.actions.run_shell( + inputs = [app_dir], + outputs = [signed_app_dir], + command = """ + set -e + + APPDIR="{app_dir}" + SIGNEDDIR="{signed_dir}" + + rm -rf "$SIGNEDDIR" + # Use -L to dereference symlinks, as codesign doesn't work with symlinks + cp -RL "$APPDIR" "$SIGNEDDIR" + + codesign --deep --force --sign - "$SIGNEDDIR" + """.format( + app_dir = app_dir.path, + signed_dir = signed_app_dir.path, + ), + progress_message = "Signing macOS app bundle {}".format(app_name), + ) + + return [DefaultInfo(files = depset([signed_app_dir]))] + +_macos_signed_app = rule( + implementation = _macos_signed_app_impl, + attrs = { + "app": attr.label( + allow_single_file = True, + mandatory = True, + doc = "The .app directory to sign", + ), + "app_name": attr.string( + mandatory = True, + doc = "Name of the application", + ), + }, +) + +def macos_app_and_dmg(name, binary, bundle_id = "com.example.app"): + """ + Creates a macOS .app bundle, signs it, and packages it into a DMG. + + Args: + name: Base name for the generated targets + binary: Label of the binary target to bundle + bundle_id: Bundle identifier for the app (default: com.example.app) + + Generates: + {name}_app: The .app bundle + {name}_signed_app: The signed .app bundle + {name}_dmg: The final DMG file + """ + # 1. Build the .app bundle + _macos_app( + name = name + "_app", + binary = binary, + app_name = name, + bundle_id = bundle_id, + ) + + # 2. Sign the .app + _macos_signed_app( + name = name + "_signed_app", + app = ":" + name + "_app", + app_name = name, + ) + + # 3. Create the DMG + native.genrule( + name = name + "_dmg", + srcs = [":" + name + "_signed_app"], + outs = [name + ".dmg"], + cmd = """ + set -e + + SIGNEDDIR="$(location :{name}_signed_app)" + + hdiutil create \ + -volname {name} \ + -srcfolder "$$SIGNEDDIR" \ + -ov -format UDZO "$@" + """.format(name = name), + local = 1, # Disable sandboxing for hdiutil + tags = ["no-sandbox"], + )