Improved the tool kit for making DMG packages for macOS.

This commit is contained in:
Kazunari Sekigawa 2020-05-23 11:49:19 +09:00 committed by Matthias Koefferlein
parent 004eb09b7c
commit 106a5c879d
5 changed files with 116 additions and 37 deletions

Binary file not shown.

Binary file not shown.

View File

@ -3,19 +3,20 @@
* Template File: * Template File:
* macbuild/Resources/template-KLayoutDMG.applescript * macbuild/Resources/template-KLayoutDMG.applescript
* *
* On the runtime, "makeDMG4mac.py" will generate the actual AppleScrip File: * On the runtime, "makeDMG4mac.py" will generate the actual AppleScrip File
* "macbuild/Resources/KLayoutDMG.applescript" * "macbuild/Resources/KLayoutDMG.applescript"
* from this template. Hence, the generated actual scrip file does not need * from this template. Hence, the generated actual scrip file does not need
* to be version controlled by Git. * to be version controlled by Git.
* *
* Description: * Description:
* A template AppleScript to make a fancy DMG installer of KLayout * This is a template AppleScript to make a fancy DMG installer of KLayout
* (http://www.klayout.de/index.php) bundles. * (http://www.klayout.de/index.php) application bundles.
* "makeDMG4mac.py" will read this template and generate the actual AppleScript to execute. * "makeDMG4mac.py" will read this template and generate the actual AppleScript to execute.
* Values to be found and replaced by "makeDMG4mac.py" are marked by ${KEYWORD}. * Those values to be found and replaced by "makeDMG4mac.py" are marked by ${KEYWORD} in this
* template file.
* *
* The background image was designed using Logoist3 (http://www.syniumsoftware.com/en/logoist) * The background PNG image file (1000 x 500 pix size) was designed by using Logoist3
* and exported to a PNG file of 1000 x 500 pix size. * (http://www.syniumsoftware.com/en/logoist).
*----------------------------------------------------------------------------------------------- *-----------------------------------------------------------------------------------------------
* This is a derivative work of Ref. 2) below. Refer to "macbuild/LICENSE" file. * This is a derivative work of Ref. 2) below. Refer to "macbuild/LICENSE" file.
* Ref. * Ref.
@ -65,14 +66,16 @@ on run (volumeName) -- most likely, the volume name is "KLayout"
set arrangement to not arranged set arrangement to not arranged
end tell end tell
-- [6] Set the background PNG image (1000 x 700 pix) file name stored -- [6] Set the background PNG image file name stored
set background picture of opts to file ".background:${BACKGROUND_PNG_FILE}" set background picture of opts to file ".background:${BACKGROUND_PNG_FILE}"
-- [7] Set positions of each icon -- [7] Set positions of each icon
-- ITEM_1 = klayout.app {860, 165} -- ITEM_1 = klayout.app {860, 165}
-- ITEM_2 = Applications {860, 345} -- ITEM_2 = Applications {860, 345}
-- ITEM_3 = AUX. holder {700, 450}
set position of item "${ITEM_1}" to {${X1}, ${Y1}} set position of item "${ITEM_1}" to {${X1}, ${Y1}}
set position of item "${ITEM_2}" to {${X2}, ${Y2}} set position of item "${ITEM_2}" to {${X2}, ${Y2}}
${ITEM_3}
-- [8] Update the contents of container -- [8] Update the contents of container
close close

View File

@ -17,6 +17,7 @@ import sys
import os import os
import re import re
import shutil import shutil
import zipfile
import glob import glob
import platform import platform
import optparse import optparse
@ -47,7 +48,7 @@ def SetGlobals():
global PackagePrefix # the package prefix: 'ST-', 'LW-', 'HW-', or 'EX-' global PackagePrefix # the package prefix: 'ST-', 'LW-', 'HW-', or 'EX-'
global QtIdentification # Qt identification global QtIdentification # Qt identification
global RubyPythonID # Ruby- and Python-identification global RubyPythonID # Ruby- and Python-identification
global Version # KLayout's version global KLVersion # KLayout's version
global OccupiedDS # approx. occupied disc space global OccupiedDS # approx. occupied disc space
global BackgroundPNG # the background PNG image file global BackgroundPNG # the background PNG image file
global VolumeIcons # the volume icon file global VolumeIcons # the volume icon file
@ -56,6 +57,10 @@ def SetGlobals():
global VolumeDMG # the volume name of DMG global VolumeDMG # the volume name of DMG
global TargetDMG # the name of target DMG file global TargetDMG # the name of target DMG file
global RootApplications # reserved directory name for applications global RootApplications # reserved directory name for applications
global CatalinaAnaconda3 # True if 'Catalina with Anaconda3'
global CatalinaHomebrew # True if 'Catalina with Homebrew'
global DicLightWeight # dictionary for LW-* packages
global Item3AppleScript # ITEM_3 in the Apple script
# auxiliary variables on platform # auxiliary variables on platform
global System # 6-tuple from platform.uname() global System # 6-tuple from platform.uname()
global Node # - do - global Node # - do -
@ -130,7 +135,7 @@ def SetGlobals():
PackagePrefix = "" PackagePrefix = ""
QtIdentification = "" QtIdentification = ""
RubyPythonID = "" RubyPythonID = ""
Version = GetKLayoutVersionFrom( "./version.sh" ) KLVersion = GetKLayoutVersionFrom( "./version.sh" )
OccupiedDS = -1 OccupiedDS = -1
BackgroundPNG = "KLayoutDMG-Back.png" BackgroundPNG = "KLayoutDMG-Back.png"
VolumeIcons = "KLayoutHDD.icns" VolumeIcons = "KLayoutHDD.icns"
@ -139,6 +144,21 @@ def SetGlobals():
VolumeDMG = "KLayout" VolumeDMG = "KLayout"
TargetDMG = "" TargetDMG = ""
RootApplications = "/Applications" RootApplications = "/Applications"
CatalinaAnaconda3 = False
CatalinaHomebrew = False
DicLightWeight = dict()
Item3AppleScript = ""
# Populate DicLightWeight
DicLightWeight[ "ana3" ] = dict()
DicLightWeight[ "brew" ] = dict()
DicLightWeight[ "ana3" ]["zip"] = "macbuild/Resources/script-bundle-A.zip"
DicLightWeight[ "ana3" ]["src"] = "script-bundle-A"
DicLightWeight[ "ana3" ]["des"] = "Anaconda3User-ReadMeFirst"
DicLightWeight[ "ana3" ]["item3"] = 'set position of item "Anaconda3User-ReadMeFirst" to {700, 400}'
DicLightWeight[ "brew" ]["zip"] = "macbuild/Resources/script-bundle-B.zip"
DicLightWeight[ "brew" ]["src"] = "script-bundle-B"
DicLightWeight[ "brew" ]["des"] = "HomebrewUser-ReadMeFirst"
DicLightWeight[ "brew" ]["item3"] = 'set position of item "HomebrewUser-ReadMeFirst" to {700, 400}'
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
## To check the contents of the package directory ## To check the contents of the package directory
@ -156,11 +176,18 @@ def SetGlobals():
# on failure, -1 # on failure, -1
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
def CheckPkgDirectory(): def CheckPkgDirectory():
global Platform
global OpClean
global OpMake
global DefaultBundleName global DefaultBundleName
global BundleName global BundleName
global PackagePrefix global PackagePrefix
global QtIdentification global QtIdentification
global RubyPythonID global RubyPythonID
global CatalinaAnaconda3
global CatalinaHomebrew
global DicLightWeight
global Item3AppleScript
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# [1] Check the contents of the package directory # [1] Check the contents of the package directory
@ -175,30 +202,12 @@ def CheckPkgDirectory():
print( "" ) print( "" )
return -1 return -1
os.chdir(PkgDir)
if not os.path.isdir( DefaultBundleName ):
print( "! The package directory <%s> does not hold <%s> bundle" % (PkgDir, DefaultBundleName), file=sys.stderr )
print( "" )
os.chdir(ProjectDir)
return -1
command = "\du -sm %s" % DefaultBundleName
sizeApp = int( os.popen(command).read().strip("\n").split("\t")[0] )
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# [2] Change the application bundle name on demand # [2] Identify (Qt, Ruby, Python) from PkgDir
#-----------------------------------------------------------------------------
if BundleName == "":
BundleName = DefaultBundleName
else:
os.rename( DefaultBundleName, BundleName )
os.chdir(ProjectDir)
#-----------------------------------------------------------------------------
# [3] Identify (Qt, Ruby, Python)
# #
# * ST-qt5MP.pkg.macos-Catalina-release-RsysPsys # * ST-qt5MP.pkg.macos-Catalina-release-RsysPsys
# * LW-qt5Ana3.pkg.macos-Catalina-release-Rana3Pana3 # * LW-qt5Ana3.pkg.macos-Catalina-release-Rana3Pana3
# * LW-qt5Brew.pkg.macos-Catalina-release-Rhb27Phb37
# * HW-qt5Brew.pkg.macos-Catalina-release-RsysPhb37 # * HW-qt5Brew.pkg.macos-Catalina-release-RsysPhb37
# * EX-qt5MP.pkg.macos-Catalina-release-Rmp26Pmp37 # * EX-qt5MP.pkg.macos-Catalina-release-Rmp26Pmp37
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
@ -213,7 +222,73 @@ def CheckPkgDirectory():
PackagePrefix = pkgdirComponents[0] PackagePrefix = pkgdirComponents[0]
QtIdentification = pkgdirComponents[2] QtIdentification = pkgdirComponents[2]
RubyPythonID = pkgdirComponents[5] RubyPythonID = pkgdirComponents[5]
return sizeApp
#-----------------------------------------------------------------------------
# [3] Check if Catalina with Anaconda3 / Homebrew
#-----------------------------------------------------------------------------
CatalinaAnaconda3 = Platform == "Catalina"
CatalinaAnaconda3 &= PackagePrefix == "LW"
CatalinaAnaconda3 &= QtIdentification == "qt5Ana3"
CatalinaAnaconda3 &= RubyPythonID == "Rana3Pana3"
CatalinaHomebrew = Platform == "Catalina"
CatalinaHomebrew &= PackagePrefix == "LW"
CatalinaHomebrew &= QtIdentification == "qt5Brew"
CatalinaHomebrew &= RubyPythonID == "Rhb27Phb37"
if CatalinaAnaconda3:
mydic = DicLightWeight["ana3"]
srcDir = PkgDir + "/" + mydic["src"]
desDir = PkgDir + "/" + mydic["des"]
if OpMake:
with zipfile.ZipFile( mydic["zip"], 'r' ) as zip_ref:
zip_ref.extractall(PkgDir)
os.rename( srcDir, desDir )
if OpClean:
if os.path.isdir(srcDir):
shutil.rmtree(srcDir)
if os.path.isdir(desDir):
shutil.rmtree(desDir)
Item3AppleScript = mydic["item3"]
if CatalinaHomebrew:
mydic = DicLightWeight["brew"]
srcDir = PkgDir + "/" + mydic["src"]
desDir = PkgDir + "/" + mydic["des"]
if OpMake:
with zipfile.ZipFile( mydic["zip"], 'r' ) as zip_ref:
zip_ref.extractall(PkgDir)
os.rename( srcDir, desDir )
if OpClean:
if os.path.isdir(srcDir):
shutil.rmtree(srcDir)
if os.path.isdir(desDir):
shutil.rmtree(desDir)
Item3AppleScript = mydic["item3"]
#------------------------------------------------------
# [4] Check the presence of the default bundle
#------------------------------------------------------
os.chdir(PkgDir)
if not os.path.isdir( DefaultBundleName ):
print( "! The package directory <%s> does not hold <%s> bundle" % (PkgDir, DefaultBundleName), file=sys.stderr )
print( "" )
os.chdir(ProjectDir)
return -1
#------------------------------------------------------
# [5] Check the occupied disk space
#------------------------------------------------------
command = "\du -sm %s" % DefaultBundleName
sizeApp = int( os.popen(command).read().strip("\n").split("\t")[0] )
#------------------------------------------------------
# [6] Change the application bundle name if required
#------------------------------------------------------
if OpMake and BundleName != "" and BundleName != DefaultBundleName:
os.rename( DefaultBundleName, BundleName )
os.chdir(ProjectDir)
return sizeApp
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
## To get command line parameters ## To get command line parameters
@ -231,7 +306,7 @@ def ParseCommandLineArguments():
global PackagePrefix global PackagePrefix
global QtIdentification global QtIdentification
global RubyPythonID global RubyPythonID
global Version global KLVersion
global OccupiedDS global OccupiedDS
global TargetDMG global TargetDMG
@ -290,7 +365,7 @@ def ParseCommandLineArguments():
base, ext = os.path.splitext( os.path.basename(opt.bundle_name) ) base, ext = os.path.splitext( os.path.basename(opt.bundle_name) )
BundleName = base + ".app" BundleName = base + ".app"
else: else:
BundleName = "" BundleName = DefaultBundleName
if (OpClean and OpMake) or (not OpClean and not OpMake): if (OpClean and OpMake) or (not OpClean and not OpMake):
print( "! Specify <-c|--clean> OR <-m|--make>", file=sys.stderr ) print( "! Specify <-c|--clean> OR <-m|--make>", file=sys.stderr )
@ -307,7 +382,7 @@ def ParseCommandLineArguments():
quit() quit()
else: else:
TargetDMG = "%s-klayout-%s-%s-%s-%d-%s-%s.dmg" \ TargetDMG = "%s-klayout-%s-%s-%s-%d-%s-%s.dmg" \
% (PackagePrefix, Version, GenOSName, Platform, DMGSerialNum, QtIdentification, RubyPythonID) % (PackagePrefix, KLVersion, GenOSName, Platform, DMGSerialNum, QtIdentification, RubyPythonID)
return return
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
@ -364,6 +439,7 @@ def MakeTargetDMGFile(msg=""):
BACKGROUND_PNG_FILE=BackgroundPNG, BACKGROUND_PNG_FILE=BackgroundPNG,
ITEM_1='%s' % BundleName, X1='860', Y1='165', ITEM_1='%s' % BundleName, X1='860', Y1='165',
ITEM_2='Applications', X2='860', Y2='345', ITEM_2='Applications', X2='860', Y2='345',
ITEM_3=Item3AppleScript,
CHECK_BASH='[ -f " & dotDSStore & " ]; echo $?' CHECK_BASH='[ -f " & dotDSStore & " ]; echo $?'
) )
try: try:
@ -523,10 +599,10 @@ def MakeTargetDMGFile(msg=""):
print( " generated MD5 checksum file <%s>" % md5TargetDMG ) print( " generated MD5 checksum file <%s>" % md5TargetDMG )
print( "" ) print( "" )
#------------------------------------------------------------- #-------------------------------------------------------------------------
# [3] Rename the application bundle if required # [3] Rename back the application bundle to the default name if required
#------------------------------------------------------------- #-------------------------------------------------------------------------
if not BundleName == DefaultBundleName: if BundleName != "" and BundleName != DefaultBundleName:
dirPresent = "%s/%s" % (PkgDir, BundleName) dirPresent = "%s/%s" % (PkgDir, BundleName)
dirDefault = "%s/%s" % (PkgDir, DefaultBundleName) dirDefault = "%s/%s" % (PkgDir, DefaultBundleName)
os.rename( dirPresent, dirDefault ) os.rename( dirPresent, dirDefault )