<pre style='margin:0'>
Christopher Nielsen (mascguy) pushed a commit to branch master
in repository macports-ports.

</pre>
<p><a href="https://github.com/macports/macports-ports/commit/723048be8dd46a8f0a15ad5261445b06fb45deb3">https://github.com/macports/macports-ports/commit/723048be8dd46a8f0a15ad5261445b06fb45deb3</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 723048be8dd46a8f0a15ad5261445b06fb45deb3
</span>Author: Christopher Nielsen <mascguy@github.com>
AuthorDate: Fri Sep 16 08:59:23 2022 -0400

<span style='display:block; white-space:pre;color:#404040;'>    pg app 1.1: new version, utilizing callback mechanism
</span><span style='display:block; white-space:pre;color:#404040;'>    Fixes: https://trac.macports.org/ticket/65721
</span>---
 _resources/port1.0/group/app-1.1.tcl | 531 +++++++++++++++++++++++++++++++++++
 1 file changed, 531 insertions(+)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/_resources/port1.0/group/app-1.1.tcl b/_resources/port1.0/group/app-1.1.tcl
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 00000000000..8eb0677216b
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/_resources/port1.0/group/app-1.1.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,531 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#===============================================================================
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app 1.1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# This PortGroup helps create an application bundle the user can open from the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Finder or the Dock. This is useful for ports that install a program built
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# with an SDK like SDL or Qt that, when launched, causes an icon to appear in
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# the Dock and opens a proper macOS GUI, but that do not build their own
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app bundle to easily launch it.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# NOTE: This new version is essentially identical to the original, except that
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# it utilizes the pg callback mechanism. This solves some issues when multiple
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# pgs are involved, with few if any downsides.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#===============================================================================
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+namespace eval app {}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.create: whether to create the app bundle at all
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default is yes.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.create
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.create yes
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.name: the name of the app that users will see in the Finder
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default is based on ${name}: if ${name} contains any uppercase letters,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# ${name} is used, otherwise the first character of ${name} is uppercased.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Info.plist key CFBundleName.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.name
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.name {[app::get_default_name]}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc app::get_default_name {} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    global name
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[regexp {[A-Z]} ${name}]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return ${name}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return [string totitle ${name}]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.executable: the program the app will run
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default is ${name}; relative paths are relative to ${prefix}/bin. If you
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# specify a relative or absolute path to a program that exists in ${destroot},
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# the app will contain a symlink to that program. If you specify an absolute
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# path in ${workpath} or ${filespath} it will be copied into the app. This is
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# useful if you need to write a wrapper script, for example to set environment
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# variables. If your wrapper script can be used as-is, leave it in ${filespath}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# and let it be copied from there. If the wrapper needs placeholders to be
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# reinplaced first, copy it into ${workpath}, do your reinplacing, then let it
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# be copied from there.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Relates to Info.plist key CFBundleExecutable.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.executable
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.executable {${name}}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.icon: the icon the app will have
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default is empty; if no icon graphic is available for this software, this
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# is fine. You can supply the path to an existing .icns file, or the path to a
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# .png or other graphic file that the makeicns program can convert. A build
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# dependency on makeicns will be added automatically if needed. You can also
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# supply the path to a .svg file and it will be rasterized to the different icon
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# formats. A build dependency on librsvg will be added automatically if needed.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Paths may be absolute or relative to ${worksrcpath}.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Relates to Info.plist key CFBundleIconFile.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.icon
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.icon ""
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.short_version_string: the version number
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default is ${version}. This is fine for most ports, but ports that list
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# both version and build number in ${version} may wish to separate these here.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Info.plist key CFBundleShortVersionString.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.short_version_string
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.short_version_string {${version}}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.version: the build number
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default is ${version}. This is fine for most ports, but ports that list
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# both version and build number in ${version} may wish to separate these here.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Info.plist key CFBundleVersion.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.version
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.version {${version}}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.identifier: the app's unique bundle identifier
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default is computed based on ${homepage} and ${app.name}. For most ports
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# this does not need to be overridden, but for software that already has an
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# established bundle identifier outside of MacPorts, you can set it here.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Info.plist key CFBundleIdentifier.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.identifier
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.identifier {[app::get_default_identifier]}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc app::get_default_identifier {} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    global homepage
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_name [option app.name]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set identifier [split [lindex [split ${homepage} "/"] 2] .]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[lindex ${identifier} 0] eq "www"} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set identifier [lrange ${identifier} 1 end]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set identifier [lreverse ${identifier}]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set identifier [concat ${identifier} [lrange [split ${homepage} "/"] 3 end]]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[lindex ${identifier} end] eq ""} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set identifier [lrange ${identifier} 0 end-1]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    lappend identifier [string map {"." ""} ${app_name}]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return [regsub -all -nocase {[^a-z0-9.-]} [join ${identifier} .] ""]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.retina: whether the app supports Retina display resolutions
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default is no.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Info.plist key NSHighResolutionCapable.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.retina
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.retina no
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.dark_mode: whether the app supports dark mode
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default is yes.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Info.plist key NSRequiresAquaSystemAppearance.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.dark_mode
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.dark_mode yes
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.privacy_microphone: whether the app needs microphone access
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default is empty and therefore disabled. To enable write a
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# message that tells the user why the app is requesting access to the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# device's microphone.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Info.plist key NSMicrophoneUsageDescription.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.privacy_microphone
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.privacy_microphone ""
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.privacy_camera: whether the app needs camera access
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default is empty and therefore disabled. To enable write a
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# message that tells the user why the app is requesting access to the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# device's camera.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Info.plist key NSCameraUsageDescription.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.privacy_camera
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.privacy_camera ""
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.privacy_contacts: whether the app needs contacts access
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default is empty and therefore disabled. To enable write a
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# message that tells the user why the app is requesting access to the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# user's contacts.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Info.plist key NSContactsUsageDescription.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.privacy_contacts
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.privacy_contacts ""
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.privacy_calendars: whether the app needs calendars access
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default is empty and therefore disabled. To enable write a
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# message that tells the user why the app is requesting access to the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# user's calendar data.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Info.plist key NSCalendarsUsageDescription.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.privacy_calendars
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.privacy_calendars ""
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.privacy_photo: whether the app needs photo access
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default is empty and therefore disabled. To enable write a
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# message that tells the user why the app is requesting access to the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# user's photo library.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Info.plist key NSPhotoLibraryUsageDescription.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.privacy_photo
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.privacy_photo ""
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.hide_dock_icon: hide the Dock icon
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# SDKs like SDL and Qt use the necessary macOS APIs to implement proper Dock
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# icon functionality, including stopping the icon from bounding when the app
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# has finished launching and bringing the app to the front when the icon is
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# clicked. Other SDKs like X11 don't use those macOS APIs, so Dock icons for
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# apps using those SDKs would not function correctly and should be hidden. The
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# default is based on whether the port has an x11 variant and the user has
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# enabled it.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Info.plist key LSUIElement.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.hide_dock_icon
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.hide_dock_icon  {[app::get_default_hide_dock_icon]}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc app::get_default_hide_dock_icon {} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return [variant_exists x11] && [variant_isset x11]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# app.use_launch_script: use shell launch script instead of symlink to executable
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# The default behaviour is to symlink the executable into the bundle. However,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# this has two issues: OS X 10.8 and earlier pass a `-psn` argument (the process
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# serial number) to the executable, which some programs can't handle. Also, it
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# doesn't modify the PATH, e.g. to add ${prefix}/bin to it. Using a launch
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# script solves both of these issues.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#-------------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+options app.use_launch_script
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+default app.use_launch_script  no
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc app::pre_destroot {} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    global destroot applications_dir
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_name   [option app.name]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_create [option app.create]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[tbool app_create]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # Ensure app.name is valid.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[regexp {[/]} ${app_name}]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            return -code error "app.name ${app_name} contains illegal characters"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # Make the app bundle directories.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set app_dir ${destroot}${applications_dir}/${app_name}.app
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        xinstall -d ${app_dir}/Contents/MacOS \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    ${app_dir}/Contents/Resources
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc app::post_destroot {} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    global prefix destroot worksrcpath applications_dir
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_create               [option app.create]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_dark_mode            [option app.dark_mode]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_executable           [option app.executable]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_hide_dock_icon       [option app.hide_dock_icon]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_icon                 [option app.icon]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_identifier           [option app.identifier]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_name                 [option app.name]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_privacy_calendars    [option app.privacy_calendars]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_privacy_camera       [option app.privacy_camera]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_privacy_contacts     [option app.privacy_contacts]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_privacy_microphone   [option app.privacy_microphone]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_privacy_photo        [option app.privacy_photo]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_retina               [option app.retina]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_short_version_string [option app.short_version_string]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_use_launch_script    [option app.use_launch_script]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_version              [option app.version]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_dir_base      ${destroot}${applications_dir}/${app_name}.app
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_dir_contents  ${app_dir_base}/Contents
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_dir_macos     ${app_dir_contents}/MacOS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_dir_res       ${app_dir_contents}/Resources
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[tbool app_create]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # Ensure app.identifier is valid.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[regexp -nocase {[^a-z0-9.-]} ${app_identifier}]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            return -code error "app.identifier ${app_identifier} contains illegal characters"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[llength [split ${app_identifier} "."]] < 3} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            return -code error "app.identifier ${app_identifier} does not look like a valid CFBundleIdentifier"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {${app_icon} ne ""} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # Turn relative app.icon paths into absolute ones.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set icon [join ${app_icon}]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[string index ${icon} 0] ne "/"} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                set icon ${worksrcpath}/${icon}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # Ensure app.icon exists.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {![file exists ${icon}]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                return -code error "app.icon '[join ${app_icon}]' does not exist"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # If app.icon is an .icns file, copy it.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[file extension ${icon}] eq ".icns"} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                xinstall -m 0644 ${icon} ${app_dir_res}/${app_name}.icns
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # If app.icon is svg, rasterize and convert it.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            } elseif {[file extension ${icon}] eq ".svg"} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                set makeicnsargs {}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                foreach w {16 32 128 256 512} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    lappend makeicnsargs -$w ${worksrcpath}/${w}.png
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    if {[catch {system -W ${worksrcpath} "${prefix}/bin/rsvg-convert -w $w -h $w [shellescape ${icon}] > ${worksrcpath}/$w.png" }]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        return -code error "app.icon '[join ${app_icon}]' could not be converted to png: $::errorInfo"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {[catch {system -W ${worksrcpath} "${prefix}/bin/makeicns $makeicnsargs -out [shellescape ${app_dir_res}/${app_name}.icns] 2>&1"}]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    return -code error "app.icns could not be created: $::errorInfo"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # If app.icon is another type of image file, convert it.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {[catch {system -W ${worksrcpath} "${prefix}/bin/makeicns -in [shellescape ${icon}] -out [shellescape ${app_dir_res}/${app_name}.icns] 2>&1"}]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    return -code error "app.icon '[join ${app_icon}]' could not be converted to ${app_name}.icns: $::errorInfo"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # Turn relative app.executable paths into absolute ones.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set executable ${app_executable}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[string index ${executable} 0] ne "/"} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set executable ${prefix}/bin/${executable}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # Check for a possible maintainer error.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[string first ${destroot} ${executable}] == 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            return -code error "app.executable ${app_executable} should not start with \${destroot}"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # If app.executable is in the destroot, use it as the target.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[file exists ${destroot}[app::resolve_symlink ${executable} ${destroot}]]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[tbool app_use_launch_script]} then {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                app::write_launch_script ${executable} ${app_dir_macos}/${app_name}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                ln -s ${executable} ${app_dir_macos}/${app_name}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        } elseif {[file exists ${executable}]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # If app.executable starts with ${workpath} or ${filespath}, copy it.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[string first ${workpath} ${executable}] == 0 || [string first ${filespath} ${executable}] == 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                xinstall ${executable} ${app_dir_macos}/${app_name}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # app.executable refers to a file that exists but does not belong to this port.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # Assume it belongs to a dependency and use it as the target.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {[tbool app_use_launch_script]} then {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    app::write_launch_script ${executable} ${app_dir_macos}/${app_name}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    ln -s ${executable} ${app_dir_macos}/${app_name}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            return -code error "app.executable ${app_executable} does not exist"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # Build the Info.plist.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set fp [open ${app_dir_contents}/Info.plist w]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        puts ${fp} "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+<plist version=\"1.0\">
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+<dict>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <key>CFBundleDevelopmentRegion</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>English</string>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <key>CFBundleExecutable</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>${app_name}</string>"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {${app_icon} ne ""} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                puts ${fp} "    <key>CFBundleIconFile</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>${app_name}.icns</string>"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[tbool app_retina]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                puts ${fp} "    <key>NSHighResolutionCapable</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <true/>"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {![tbool app_dark_mode]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                puts ${fp} "    <key>NSRequiresAquaSystemAppearance</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <true/>"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {${app_privacy_microphone} ne ""} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                puts ${fp} "    <key>NSMicrophoneUsageDescription</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>${app_privacy_microphone}</string>"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {${app_privacy_camera} ne ""} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                puts ${fp} "    <key>NSCameraUsageDescription</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>${app_privacy_camera}</string>"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {${app_privacy_contacts} ne ""} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                puts ${fp} "    <key>NSContactsUsageDescription</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>${app_privacy_contacts}</string>"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {${app_privacy_calendars} ne ""} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                puts ${fp} "    <key>NSCalendarsUsageDescription</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>${app_privacy_calendars}</string>"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {${app_privacy_photo} ne ""} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                puts ${fp} "    <key>NSPhotoLibraryUsageDescription</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>${app_privacy_photo}</string>"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[tbool app_hide_dock_icon]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                puts ${fp} "    <key>LSUIElement</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <true/>"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            puts ${fp} "    <key>CFBundleIdentifier</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>${app_identifier}</string>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <key>CFBundleInfoDictionaryVersion</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>6.0</string>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <key>CFBundleName</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>${app_name}</string>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <key>CFBundlePackageType</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>APPL</string>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <key>CFBundleShortVersionString</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>${app_short_version_string}</string>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <key>CFBundleSignature</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>????</string>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <key>CFBundleVersion</key>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <string>${app_version}</string>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+</dict>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+</plist>"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        close ${fp}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # Build the PkgInfo file.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set fp [open ${app_dir_contents}/PkgInfo w]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        puts -nonewline ${fp} "APPL????"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        close ${fp}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc app::check_app_icon {} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    global depends_build
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set app_icon [option app.icon]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set needs_dep [expr {[file extension [join ${app_icon}]] ne ".icns"}]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {${needs_dep}} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        depends_build-delete port:makeicns
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        depends_build-append port:makeicns
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set needs_dep [expr {[file extension [join ${app_icon}]] eq ".svg"}]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {${needs_dep}} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        depends_build-delete port:librsvg
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        depends_build-append port:librsvg
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Recursively resolve a symlink in a destroot.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc app::resolve_symlink {path destroot} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[catch {set resolved_path [file join [file dirname ${path}] [file readlink ${destroot}${path}]]}]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#        ui_debug "In ${destroot}, ${path} is not a symlink"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return ${path}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#    ui_debug "In ${destroot}, ${path} is a symlink to ${resolved_path}"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return [app::resolve_symlink ${resolved_path} ${destroot}]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Write a launch script for the executable into the bundle, modifying PATH to
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# allow the executable to find other executables installed with MacPorts.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc app::write_launch_script {executable app_destination} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    global prefix
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set launch_script [open ${app_destination} w]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    puts ${launch_script} "#!/bin/bash
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+export PATH=\"${prefix}/bin:${prefix}/sbin:\$PATH\"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+exec [shellescape ${executable}]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    close ${launch_script}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    file attributes ${app_destination} -permissions 0755
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc app::pg_callback {} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    app::check_app_icon
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    pre-destroot {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        app::pre_destroot
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    post-destroot {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        app::post_destroot
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# callback after port is parsed
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+port::register_callback app::pg_callback
</span></pre><pre style='margin:0'>

</pre>