<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>