WIP: Parametrizing macbuild to make custom installations easier (#680)

* Changing indentation to 4 spaces

* squash

* removing more global variables (squash)

* | tee always exits with 0

* parameter is a dictionary now

* Changing default Makefile to HB38 and adding -rbinc2 option for Catalina

* Catalina building...

* macQAT fixed

* run_build_command depends on parameteres dict alone

* Adding options to macbuild/makeDMG4mac.py

In particular, we can now specify a -u (unsafe) option, and
specify the target dmg file with -t target.dmg
This commit is contained in:
Thomas Ferreira de Lima 2020-11-21 16:07:11 -05:00 committed by Matthias Koefferlein
parent beae26ec2e
commit b37ce4e130
10 changed files with 1508 additions and 1327 deletions

11
.gitignore vendored
View File

@ -37,6 +37,8 @@ build-*
bin-* bin-*
mkqtdecl.tmp mkqtdecl.tmp
testtmp testtmp
*build.macos*
*bin.macos*
# private data # private data
private private
@ -54,3 +56,12 @@ src/klayout.pro.user
*.egg-info/ *.egg-info/
build/ build/
dist/ dist/
# IDEs
.vscode
# Macos artifacts
*.dmg
*.dmg.md5

View File

@ -3,10 +3,10 @@
GITCOMMIT := $(shell git rev-parse --short HEAD) GITCOMMIT := $(shell git rev-parse --short HEAD)
KLAYOUT_VERSION := $(shell source version.sh && echo $$KLAYOUT_VERSION) KLAYOUT_VERSION := $(shell source version.sh && echo $$KLAYOUT_VERSION)
ifndef PYTHON_VERSION ifndef PYTHON_VERSION
PYTHON_VERSION := B37 PYTHON_VERSION := HB38
endif endif
ifndef MACOS_VERSION ifndef MACOS_VERSION
MACOS_VERSION := HighSierra MACOS_VERSION := Catalina
endif endif
.ONESHELL: .ONESHELL:
@ -15,11 +15,11 @@ default: help
help: help:
@echo "For Mac OS only" @echo "For Mac OS only"
@echo "make build PYTHON_VERSION=B37" @echo "make build PYTHON_VERSION=HB38"
@echo "make deploy PYTHON_VERSION=B37" @echo "make deploy PYTHON_VERSION=HB38"
@echo "make test MACOS_VERSION=HighSierra" @echo "make test MACOS_VERSION=HighSierra"
@echo "Valid Mac OS Versions: [Yosemite, ElCapitan, Sierra, HighSierra]" @echo "Valid Mac OS Versions: [Yosemite, ElCapitan, Sierra, HighSierra, Mojave, Catalina]"
@echo "Valid Python Version: [nil, Sys, B37]" @echo "Valid Python Version: [nil, Sys, HB38]"
build: build:
@echo "Building for Mac $(GITCOMMIT)" @echo "Building for Mac $(GITCOMMIT)"
@ -29,11 +29,11 @@ build:
deploy: deploy:
@echo "Deploying 4 Mac $(GITCOMMIT)" @echo "Deploying 4 Mac $(GITCOMMIT)"
./build4mac.py -p $(PYTHON_VERSION) -q Qt5Brew -y ./build4mac.py -p $(PYTHON_VERSION) -q Qt5Brew -y
test: test:
@echo "Testing 4 Mac $(GITCOMMIT)" @echo "Testing 4 Mac $(GITCOMMIT)"
qt5.pkg.macos-$(MACOS_VERSION)-release/klayout.app/Contents/MacOS/klayout -b -r test-pylib-script.py; \ PIP_REQUIRE_VIRTUALENV="false" HW-qt5Brew.pkg.macos-$(MACOS_VERSION)-release-RsysPhb38/klayout.app/Contents/MacOS/klayout -b -r test-pylib-script.py; \
cd qt5.build.macos-$(MACOS_VERSION)-release; \ cd qt5Brew.build.macos-$(MACOS_VERSION)-release-RsysPhb38; \
ln -s klayout.app/Contents/MacOS/klayout klayout; \ ln -s klayout.app/Contents/MacOS/klayout klayout; \
export TESTTMP=testtmp; \ export TESTTMP=testtmp; \
export TESTSRC=..; \ export TESTSRC=..; \
@ -41,18 +41,24 @@ test:
./ut_runner -h || true; \ ./ut_runner -h || true; \
cd .. cd ..
dmg-template:
mkdir -p testtemplate/klayout.app
./makeDMG4mac.py -p testtemplate -m -z -t klayoutDMGTemplate.dmg
cp -a klayoutDMGTemplate.dmg* macbuild/Resources/
rm -Rf testtemplate
dropbox-deploy: dropbox-deploy:
@echo "Preparing for dropbox deployment $(MACOS_VERSION) $(GITCOMMIT)" @echo "Preparing for dropbox deployment $(MACOS_VERSION) $(GITCOMMIT)"
mkdir -p deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION); \ mkdir -p deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION)
pwd; \ pwd
ls -lah; \ ls -lah
touch build.txt; \ touch build.txt
cp build.txt deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION)/qt5.pkg.macos-$(MACOS_VERSION)-$(PYTHON_VERSION)-release-$(KLAYOUT_VERSION)-$(GITCOMMIT).log.txt; \ cp build.txt deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION)/qt5.pkg.macos-$(MACOS_VERSION)-$(PYTHON_VERSION)-release-$(KLAYOUT_VERSION)-$(GITCOMMIT).log.txt
hdiutil convert macbuild/Resources/klayoutDMGTemplate.dmg -format UDRW -o work-KLayout.dmg; \ hdiutil convert macbuild/Resources/klayoutDMGTemplate.dmg -ov -format UDRW -o work-KLayout.dmg
hdiutil resize -size 500m work-KLayout.dmg; \ hdiutil resize -size 500m work-KLayout.dmg
hdiutil attach work-KLayout.dmg -readwrite -noverify -quiet -mountpoint tempKLayout -noautoopen; \ hdiutil attach -readwrite -noverify -quiet -mountpoint tempKLayout -noautoopen work-KLayout.dmg
cp -a qt5.pkg.macos-$(MACOS_VERSION)-release/ tempKLayout/; \ cp -a HW-qt5Brew.pkg.macos-$(MACOS_VERSION)-release-RsysPhb38/ tempKLayout/
hdiutil detach tempKLayout; \ hdiutil detach tempKLayout
hdiutil convert work-KLayout.dmg -format UDZO -imagekey zlib-level=9 -o deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION)/qt5.pkg.macos-$(MACOS_VERSION)-$(PYTHON_VERSION)-release-$(KLAYOUT_VERSION)-$(GITCOMMIT).dmg; \ hdiutil convert work-KLayout.dmg -ov -format UDZO -imagekey zlib-level=9 -o deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION)/qt5.pkg.macos-$(MACOS_VERSION)-$(PYTHON_VERSION)-release-$(KLAYOUT_VERSION)-$(GITCOMMIT).dmg
md5 -q deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION)/qt5.pkg.macos-$(MACOS_VERSION)-$(PYTHON_VERSION)-release-$(KLAYOUT_VERSION)-$(GITCOMMIT).dmg > deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION)/qt5.pkg.macos-$(MACOS_VERSION)-$(PYTHON_VERSION)-release-$(KLAYOUT_VERSION)-$(GITCOMMIT).dmg.md5; \ md5 -q deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION)/qt5.pkg.macos-$(MACOS_VERSION)-$(PYTHON_VERSION)-release-$(KLAYOUT_VERSION)-$(GITCOMMIT).dmg > deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION)/qt5.pkg.macos-$(MACOS_VERSION)-$(PYTHON_VERSION)-release-$(KLAYOUT_VERSION)-$(GITCOMMIT).dmg.md5
rm work-KLayout.dmg rm work-KLayout.dmg

View File

@ -532,6 +532,11 @@ if [ "$BIN" = "" ]; then
BIN=$CURR_DIR/bin-$CONFIG BIN=$CURR_DIR/bin-$CONFIG
fi fi
if [ "$QMAKE_CCACHE" = 1 ]; then
echo " Compilation caching is activated."
else
echo " Compilation caching is deactivated!"
fi
echo " Installation target: $BIN" echo " Installation target: $BIN"
echo " Build directory: $BUILD" echo " Build directory: $BUILD"

1
macbuild/.gitignore vendored
View File

@ -1 +1,2 @@
*.pyc *.pyc
KLayoutDMG.applescript

View File

@ -26,6 +26,12 @@
------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------
on run (volumeName) -- most likely, the volume name is "KLayout" on run (volumeName) -- most likely, the volume name is "KLayout"
tell application "Finder" tell application "Finder"
repeat 20 times
if (exists (disk (volumeName as string))) then
exit repeat
end if
delay 1
end repeat
tell disk (volumeName as string) tell disk (volumeName as string)
-- [1] Open the volume -- [1] Open the volume
open open

File diff suppressed because it is too large Load Diff

View File

@ -104,9 +104,10 @@ RubyMojave = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2
# !!! Catalina does not allow to hack the "/System" directory; it's READ ONLY even for the super user! # !!! Catalina does not allow to hack the "/System" directory; it's READ ONLY even for the super user!
# Hence, we need to refer to the Ruby header file in "Xcode.app" directly. # Hence, we need to refer to the Ruby header file in "Xcode.app" directly.
# [Key Type Name] = 'Sys' # [Key Type Name] = 'Sys'
CatalinaSDK = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk" CatalinaSDK = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk"
RubyCatalina = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby', RubyCatalina = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby',
'inc': '%s/System/Library/Frameworks/Ruby.framework/Headers' % CatalinaSDK, 'inc': '%s/System/Library/Frameworks/Ruby.framework/Headers' % CatalinaSDK,
'inc2': '%s/System/Library/Frameworks/Ruby.framework/Headers/ruby' % CatalinaSDK,
'lib': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.dylib' 'lib': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.dylib'
} }
@ -221,6 +222,21 @@ Python38Brew = { 'exe': '%s/Versions/3.8/bin/python3.8' % HBPython38Framework
'lib': '%s/Versions/3.8/lib/libpython3.8.dylib' % HBPython38FrameworkPath 'lib': '%s/Versions/3.8/lib/libpython3.8.dylib' % HBPython38FrameworkPath
} }
# # Latest Python from Homebrew *+*+*+ EXPERIMENTAL *+*+*+
# # install with 'brew install python'
# # [Key Type Name] = 'HBAuto'
# import glob
# # In my system, there are four candidates: (python, python3, python@3, python@3.8)
# # Hard to tell which is going to be available to the user. Picking the last one
# HBAutoFrameworkPath = glob.glob("/usr/local/opt/python*/Frameworks/Python.framework/")[-1]
# # expand 3* into _py_version, there should be only one, but I am taking no chances.
# HBAutoFrameworkVersionPath, _py_version = os.path.split(glob.glob("%s/Versions/3*" % HBAutoFrameworkPath)[0])
# PythonAutoBrew = { 'exe': '%s/bin/python%s' % (HBAutoFrameworkVersionPath, _py_version),
# 'inc': '%s/include/python%s' % (HBAutoFrameworkVersionPath, _py_version),
# 'lib': glob.glob("%s/lib/*.dylib" % HBAutoFrameworkVersionPath)[0]
# }
# Python 3.8 bundled with anaconda3 installed under /Applications/anaconda3/ *+*+*+ EXPERIMENTAL *+*+*+ # Python 3.8 bundled with anaconda3 installed under /Applications/anaconda3/ *+*+*+ EXPERIMENTAL *+*+*+
# The standard installation deploys the tool under $HOME/opt/anaconda3/. # The standard installation deploys the tool under $HOME/opt/anaconda3/.
# If so, you need to make a symbolic link: /Applications/anaconda3 ---> $HOME/opt/anaconda3/ # If so, you need to make a symbolic link: /Applications/anaconda3 ---> $HOME/opt/anaconda3/

View File

@ -43,15 +43,15 @@ from build4mac_env import *
# @return a dictionary # @return a dictionary
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
def DecomposeLibraryDependency( depstr ): def DecomposeLibraryDependency( depstr ):
alllines = depstr.split('\n') alllines = depstr.split('\n')
numlines = len(alllines) numlines = len(alllines)
dependent = alllines[0].split(':')[0].strip() dependent = alllines[0].split(':')[0].strip()
supporters = [] supporters = []
for line in alllines[1:]: for line in alllines[1:]:
supporter = line.strip().split(' ')[0].strip() supporter = line.strip().split(' ')[0].strip()
if not supporter == '': if not supporter == '':
supporters.append(supporter) supporters.append(supporter)
return { dependent: supporters } return { dependent: supporters }
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
## To print the contents of a library dependency dictionary ## To print the contents of a library dependency dictionary
@ -61,17 +61,17 @@ def DecomposeLibraryDependency( depstr ):
# @param[in] namedic dictionary name # @param[in] namedic dictionary name
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
def PrintLibraryDependencyDictionary( depdic, pathdic, namedic ): def PrintLibraryDependencyDictionary( depdic, pathdic, namedic ):
keys = depdic.keys() keys = depdic.keys()
print("") print("")
print("##### Contents of <%s> #####:" % namedic ) print("##### Contents of <%s> #####:" % namedic )
for key in keys: for key in keys:
supporters = depdic[key] supporters = depdic[key]
keyName = os.path.basename(key) keyName = os.path.basename(key)
print( " %s: (%s)" % (key, pathdic[keyName]) ) print( " %s: (%s)" % (key, pathdic[keyName]) )
for item in supporters: for item in supporters:
itemName = os.path.basename(item) itemName = os.path.basename(item)
if itemName != keyName and (itemName in pathdic): if itemName != keyName and (itemName in pathdic):
print( " %s (%s)" % (item, pathdic[itemName]) ) print( " %s (%s)" % (item, pathdic[itemName]) )
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
## To set and change identification name of KLayout's dylib ## To set and change identification name of KLayout's dylib
@ -81,39 +81,39 @@ def PrintLibraryDependencyDictionary( depdic, pathdic, namedic ):
# @return 0 on success; non-zero on failure # @return 0 on success; non-zero on failure
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
def SetChangeIdentificationNameOfDyLib( libdic, pathDic ): def SetChangeIdentificationNameOfDyLib( libdic, pathDic ):
cmdNameId = XcodeToolChain['nameID'] cmdNameId = XcodeToolChain['nameID']
cmdNameChg = XcodeToolChain['nameCH'] cmdNameChg = XcodeToolChain['nameCH']
dependentLibs = libdic.keys() dependentLibs = libdic.keys()
for lib in dependentLibs: for lib in dependentLibs:
#----------------------------------------------------------- #-----------------------------------------------------------
# [1] Set the identification name of each dependent library # [1] Set the identification name of each dependent library
#----------------------------------------------------------- #-----------------------------------------------------------
nameOld = "%s" % lib nameOld = "%s" % lib
libName = os.path.basename(lib) libName = os.path.basename(lib)
nameNew = pathDic[libName] nameNew = pathDic[libName]
command = "%s %s %s" % ( cmdNameId, nameNew, nameOld ) command = "%s %s %s" % ( cmdNameId, nameNew, nameOld )
if subprocess.call( command, shell=True ) != 0:
msg = "!!! Failed to set the new identification name to <%s> !!!"
print( msg % lib, file=sys.stderr )
return 1
#-------------------------------------------------------------------------
# [2] Make the library aware of the new identifications of all supporters
#-------------------------------------------------------------------------
supporters = libdic[lib]
for sup in supporters:
supName = os.path.basename(sup)
if libName != supName and (supName in pathDic):
nameOld = "%s" % sup
nameNew = pathDic[supName]
command = "%s %s %s %s" % ( cmdNameChg, nameOld, nameNew, lib )
if subprocess.call( command, shell=True ) != 0: if subprocess.call( command, shell=True ) != 0:
msg = "!!! Failed to make the library aware of the new identification name <%s> of supporter <%s> !!!" msg = "!!! Failed to set the new identification name to <%s> !!!"
print( msg % (nameNew, sup), file=sys.stderr ) print( msg % lib, file=sys.stderr )
return 1 return 1
# for-lib
return 0 #-------------------------------------------------------------------------
# [2] Make the library aware of the new identifications of all supporters
#-------------------------------------------------------------------------
supporters = libdic[lib]
for sup in supporters:
supName = os.path.basename(sup)
if libName != supName and (supName in pathDic):
nameOld = "%s" % sup
nameNew = pathDic[supName]
command = "%s %s %s %s" % ( cmdNameChg, nameOld, nameNew, lib )
if subprocess.call( command, shell=True ) != 0:
msg = "!!! Failed to make the library aware of the new identification name <%s> of supporter <%s> !!!"
print( msg % (nameNew, sup), file=sys.stderr )
return 1
# for-lib
return 0
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
## To set the identification names of KLayout's libraries to an executable ## To set the identification names of KLayout's libraries to an executable
@ -148,38 +148,38 @@ def SetChangeIdentificationNameOfDyLib( libdic, pathDic ):
# @return 0 on success; non-zero on failure # @return 0 on success; non-zero on failure
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
def SetChangeLibIdentificationName( executable, relativedir ): def SetChangeLibIdentificationName( executable, relativedir ):
cmdNameId = XcodeToolChain['nameID'] cmdNameId = XcodeToolChain['nameID']
cmdNameChg = XcodeToolChain['nameCH'] cmdNameChg = XcodeToolChain['nameCH']
otoolCm = "otool -L %s | grep libklayout" % executable otoolCm = "otool -L %s | grep libklayout" % executable
otoolOut = os.popen( otoolCm ).read() otoolOut = os.popen( otoolCm ).read()
exedepdic = DecomposeLibraryDependency( executable + ":\n" + otoolOut ) exedepdic = DecomposeLibraryDependency( executable + ":\n" + otoolOut )
keys = exedepdic.keys() keys = exedepdic.keys()
deplibs = exedepdic[ list(keys)[0] ] deplibs = exedepdic[ list(keys)[0] ]
for lib in deplibs: for lib in deplibs:
#----------------------------------------------------------- #-----------------------------------------------------------
# [1] Set the identification names for the library # [1] Set the identification names for the library
#----------------------------------------------------------- #-----------------------------------------------------------
nameOld = "klayout.app/Contents/Frameworks/%s" % lib nameOld = "klayout.app/Contents/Frameworks/%s" % lib
nameNew = "@executable_path/%s/%s" % ( relativedir, lib ) nameNew = "@executable_path/%s/%s" % ( relativedir, lib )
command = "%s %s %s" % ( cmdNameId, nameNew, nameOld ) command = "%s %s %s" % ( cmdNameId, nameNew, nameOld )
if subprocess.call( command, shell=True ) != 0: if subprocess.call( command, shell=True ) != 0:
msg = "!!! Failed to set the new identification name to <%s> !!!" msg = "!!! Failed to set the new identification name to <%s> !!!"
print( msg % lib, file=sys.stderr ) print( msg % lib, file=sys.stderr )
return 1 return 1
#----------------------------------------------------------- #-----------------------------------------------------------
# [2] Make the application aware of the new identification # [2] Make the application aware of the new identification
#----------------------------------------------------------- #-----------------------------------------------------------
nameOld = "%s" % lib nameOld = "%s" % lib
nameNew = "@executable_path/%s/%s" % ( relativedir, lib ) nameNew = "@executable_path/%s/%s" % ( relativedir, lib )
command = "%s %s %s %s" % ( cmdNameChg, nameOld, nameNew, executable ) command = "%s %s %s %s" % ( cmdNameChg, nameOld, nameNew, executable )
if subprocess.call( command, shell=True ) != 0: if subprocess.call( command, shell=True ) != 0:
msg = "!!! Failed to make the application aware of the new identification name <%s> !!!" msg = "!!! Failed to make the application aware of the new identification name <%s> !!!"
print( msg % nameNew, file=sys.stderr ) print( msg % nameNew, file=sys.stderr )
return 1 return 1
# for-lib # for-lib
return 0 return 0
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
## To make a library dependency dictionary by recursively walk down the lib hierarchy ## To make a library dependency dictionary by recursively walk down the lib hierarchy
@ -191,23 +191,23 @@ def SetChangeLibIdentificationName( executable, relativedir ):
# @return a dictionary # @return a dictionary
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
def WalkLibDependencyTree( dylibPath, depth=0, filter_regex=r'\t+/usr/local/opt' ): def WalkLibDependencyTree( dylibPath, depth=0, filter_regex=r'\t+/usr/local/opt' ):
otoolCm = 'otool -L %s | grep -E "%s"' % (dylibPath, filter_regex) otoolCm = 'otool -L %s | grep -E "%s"' % (dylibPath, filter_regex)
otoolOut = os.popen( otoolCm ).read() otoolOut = os.popen( otoolCm ).read()
exedepdic = DecomposeLibraryDependency( dylibPath + ":\n" + otoolOut ) exedepdic = DecomposeLibraryDependency( dylibPath + ":\n" + otoolOut )
keys = exedepdic.keys() keys = exedepdic.keys()
deplibs = exedepdic[ list(keys)[0] ] deplibs = exedepdic[ list(keys)[0] ]
if depth < 5: if depth < 5:
if len(deplibs) > 0: if len(deplibs) > 0:
for idx, lib in enumerate(deplibs): for idx, lib in enumerate(deplibs):
lib = str(lib) lib = str(lib)
if lib != list(keys)[0]: if lib != list(keys)[0]:
deplibs[idx] = WalkLibDependencyTree(lib, depth+1, filter_regex) deplibs[idx] = WalkLibDependencyTree(lib, depth+1, filter_regex)
if depth == 0: if depth == 0:
return deplibs return deplibs
return exedepdic return exedepdic
else: else:
raise RuntimeError( "Exceeded maximum recursion depth." ) raise RuntimeError( "Exceeded maximum recursion depth." )
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
## To make a library dependency dictionary by recursively walk down the Framework ## To make a library dependency dictionary by recursively walk down the Framework
@ -219,27 +219,27 @@ def WalkLibDependencyTree( dylibPath, depth=0, filter_regex=r'\t+/usr/local/opt'
# @return a dictionary # @return a dictionary
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
def WalkFrameworkPaths( frameworkPaths, filter_regex=r'\.(so|dylib)$', def WalkFrameworkPaths( frameworkPaths, filter_regex=r'\.(so|dylib)$',
search_path_filter=r'\t+/usr/local/opt' ): search_path_filter=r'\t+/usr/local/opt' ):
if isinstance(frameworkPaths, str): if isinstance(frameworkPaths, str):
frameworkPathsIter = [frameworkPaths] frameworkPathsIter = [frameworkPaths]
else: else:
frameworkPathsIter = frameworkPaths frameworkPathsIter = frameworkPaths
dependency_dict = dict() dependency_dict = dict()
for frameworkPath in frameworkPathsIter: for frameworkPath in frameworkPathsIter:
# print("Calling:", 'find %s -type f | grep -E "%s"' % (frameworkPath, filter_regex)) # print("Calling:", 'find %s -type f | grep -E "%s"' % (frameworkPath, filter_regex))
find_grep_results = os.popen('find %s -type f | grep -E "%s"' % (frameworkPath, filter_regex)).read().split('\n') find_grep_results = os.popen('find %s -type f | grep -E "%s"' % (frameworkPath, filter_regex)).read().split('\n')
framework_files = filter(lambda x: x != '', framework_files = filter(lambda x: x != '',
map(lambda x: x.strip(), map(lambda x: x.strip(),
find_grep_results)) find_grep_results))
dependency_dict[frameworkPath] = list() dependency_dict[frameworkPath] = list()
for idx, file in enumerate(framework_files): for idx, file in enumerate(framework_files):
dict_file = {file: WalkLibDependencyTree(file, filter_regex=search_path_filter)} dict_file = {file: WalkLibDependencyTree(file, filter_regex=search_path_filter)}
dependency_dict[frameworkPath].append(dict_file) dependency_dict[frameworkPath].append(dict_file)
return dependency_dict return dependency_dict
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
## To make a list of changed libraries ## To make a list of changed libraries
@ -250,32 +250,32 @@ def WalkFrameworkPaths( frameworkPaths, filter_regex=r'\.(so|dylib)$',
# @return a list # @return a list
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
def WalkDictTree( dependencyDict, visited_files ): def WalkDictTree( dependencyDict, visited_files ):
libNameChanges = list() libNameChanges = list()
for lib, dependencies in dependencyDict.items(): for lib, dependencies in dependencyDict.items():
if lib in visited_files: if lib in visited_files:
continue continue
dependency_list = list() dependency_list = list()
if isinstance(dependencies, list): if isinstance(dependencies, list):
for deplib in dependencies: for deplib in dependencies:
if isinstance(deplib, str): if isinstance(deplib, str):
dependency_list.append(deplib) dependency_list.append(deplib)
if deplib not in visited_files: if deplib not in visited_files:
visited_files.append(deplib) visited_files.append(deplib)
elif isinstance(deplib, dict): elif isinstance(deplib, dict):
dependency_list.append(next(iter(deplib))) dependency_list.append(next(iter(deplib)))
libNameChanges.extend(WalkDictTree(deplib, visited_files)) libNameChanges.extend(WalkDictTree(deplib, visited_files))
else:
#raise RuntimeError("Unexpected value: %s" % deplib)
pass
else: else:
#raise RuntimeError("Unexpected value: %s" % deplib) raise RuntimeError("Unexpected value: %s" % dependencies)
pass if len(dependency_list) > 0:
else: libNameChanges.append((lib, dependency_list))
raise RuntimeError("Unexpected value: %s" % dependencies) else:
if len(dependency_list) > 0: libNameChanges.append((lib, ))
libNameChanges.append((lib, dependency_list)) visited_files.append(lib)
else: return libNameChanges
libNameChanges.append((lib, ))
visited_files.append(lib)
return libNameChanges
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
## To find the Framework name from a library name ## To find the Framework name from a library name
@ -286,10 +286,10 @@ def WalkDictTree( dependencyDict, visited_files ):
# @return the path to a Framework # @return the path to a Framework
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
def FindFramework( path, root_path ): def FindFramework( path, root_path ):
relPath = os.path.relpath(path, root_path) relPath = os.path.relpath(path, root_path)
frmPath = os.path.join(root_path, relPath.split(os.sep)[0]) frmPath = os.path.join(root_path, relPath.split(os.sep)[0])
#print( "###", frmPath, path, root_path ) #print( "###", frmPath, path, root_path )
return frmPath return frmPath
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
## To resolve an executable path ## To resolve an executable path
@ -300,9 +300,9 @@ def FindFramework( path, root_path ):
# @return the resolved path # @return the resolved path
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
def ResolveExecutablePath( path, executable_path ): def ResolveExecutablePath( path, executable_path ):
""" Transforms @executable_path into executable_path""" """ Transforms @executable_path into executable_path"""
p = path.replace("@executable_path", "/%s/" % executable_path) p = path.replace("@executable_path", "/%s/" % executable_path)
return p return p
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
## To detect the changed library names ## To detect the changed library names
@ -315,12 +315,12 @@ def ResolveExecutablePath( path, executable_path ):
# * ('lib.dylib',) # * ('lib.dylib',)
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
def DetectChanges(frameworkDependencyDict): def DetectChanges(frameworkDependencyDict):
visited_files = list() visited_files = list()
libNameChanges = list() libNameChanges = list()
for framework, libraries in frameworkDependencyDict.items(): for framework, libraries in frameworkDependencyDict.items():
for libraryDict in libraries: for libraryDict in libraries:
libNameChanges.extend(WalkDictTree(libraryDict, visited_files)) libNameChanges.extend(WalkDictTree(libraryDict, visited_files))
return libNameChanges return libNameChanges
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
## To perform the required changes ## To perform the required changes
@ -332,79 +332,79 @@ def DetectChanges(frameworkDependencyDict):
# @return 0 on success; > 0 on failure # @return 0 on success; > 0 on failure
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
def PerformChanges( frameworkDependencyDict, replaceFromToPairs=None, executable_path="/tmp/klayout" ): def PerformChanges( frameworkDependencyDict, replaceFromToPairs=None, executable_path="/tmp/klayout" ):
libNameChanges = DetectChanges(frameworkDependencyDict) libNameChanges = DetectChanges(frameworkDependencyDict)
#print(libNameChanges) #print(libNameChanges)
cmdNameId = XcodeToolChain['nameID'] cmdNameId = XcodeToolChain['nameID']
cmdNameChg = XcodeToolChain['nameCH'] cmdNameChg = XcodeToolChain['nameCH']
if replaceFromToPairs is None: if replaceFromToPairs is None:
return 0 return 0
else: else:
for libNameChange in libNameChanges: for libNameChange in libNameChanges:
libNameChangeIterator = iter(libNameChange) libNameChangeIterator = iter(libNameChange)
lib = next(libNameChangeIterator) lib = next(libNameChangeIterator)
try: try:
dependencies = next(libNameChangeIterator) dependencies = next(libNameChangeIterator)
except StopIteration: except StopIteration:
dependencies = list() dependencies = list()
for replaceFrom, replaceTo, libdir in replaceFromToPairs: for replaceFrom, replaceTo, libdir in replaceFromToPairs:
fileName = ResolveExecutablePath(lib.replace(replaceFrom, replaceTo), executable_path) fileName = ResolveExecutablePath(lib.replace(replaceFrom, replaceTo), executable_path)
if fileName.startswith('/usr'): if fileName.startswith('/usr'):
# print(f'skipping fileName: {fileName}') # print(f'skipping fileName: {fileName}')
continue continue
if lib.find(replaceFrom) >= 0: if lib.find(replaceFrom) >= 0:
if libdir: if libdir:
frameworkPath = FindFramework(lib, replaceFrom) frameworkPath = FindFramework(lib, replaceFrom)
else: else:
frameworkPath = lib frameworkPath = lib
destFrameworkPath = frameworkPath.replace(replaceFrom, replaceTo) destFrameworkPath = frameworkPath.replace(replaceFrom, replaceTo)
destFrameworkPath = ResolveExecutablePath(destFrameworkPath, executable_path) destFrameworkPath = ResolveExecutablePath(destFrameworkPath, executable_path)
if not os.path.exists(fileName): if not os.path.exists(fileName):
print( " NOT FOUND:", lib.replace(replaceFrom, replaceTo) ) print( " NOT FOUND:", lib.replace(replaceFrom, replaceTo) )
print( " COPYING:", frameworkPath, " -> ", destFrameworkPath ) print( " COPYING:", frameworkPath, " -> ", destFrameworkPath )
shutil.copytree(frameworkPath, destFrameworkPath) shutil.copytree(frameworkPath, destFrameworkPath)
nameId = lib.replace(replaceFrom, replaceTo) nameId = lib.replace(replaceFrom, replaceTo)
command = "%s %s %s" % ( cmdNameId, nameId, fileName ) command = "%s %s %s" % ( cmdNameId, nameId, fileName )
if not os.access(fileName, os.W_OK): if not os.access(fileName, os.W_OK):
command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName) command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName)
# print("\t%s" % command) # print("\t%s" % command)
if subprocess.call( command, shell=True ) != 0: if subprocess.call( command, shell=True ) != 0:
msg = "!!! Failed to set the new identification name to <%s> !!!" msg = "!!! Failed to set the new identification name to <%s> !!!"
print( msg % fileName, file=sys.stderr ) print( msg % fileName, file=sys.stderr )
return 1 return 1
for dependency in dependencies: for dependency in dependencies:
if dependency.find(replaceFrom) >= 0: if dependency.find(replaceFrom) >= 0:
print( " IN:", fileName ) print( " IN:", fileName )
print( " RENAMING:", dependency, " -> ", dependency.replace(replaceFrom, replaceTo) ) print( " RENAMING:", dependency, " -> ", dependency.replace(replaceFrom, replaceTo) )
# Try changing id first # Try changing id first
nameId = dependency.replace(replaceFrom, replaceTo) nameId = dependency.replace(replaceFrom, replaceTo)
command = "%s %s %s" % ( cmdNameId, nameId, fileName) command = "%s %s %s" % ( cmdNameId, nameId, fileName)
if not os.access(str(fileName), os.W_OK): if not os.access(str(fileName), os.W_OK):
command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName) command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName)
# print("\t%s" % command) # print("\t%s" % command)
if subprocess.call( command, shell=True ) != 0: if subprocess.call( command, shell=True ) != 0:
msg = "!!! Failed to set the new identification name to <%s> !!!" msg = "!!! Failed to set the new identification name to <%s> !!!"
print( msg % fileName, file=sys.stderr ) print( msg % fileName, file=sys.stderr )
return 1 return 1
# Rename dependencies # Rename dependencies
nameOld = dependency nameOld = dependency
nameNew = dependency.replace(replaceFrom, replaceTo) nameNew = dependency.replace(replaceFrom, replaceTo)
command = "%s %s %s %s" % ( cmdNameChg, nameOld, nameNew, str(fileName) ) command = "%s %s %s %s" % ( cmdNameChg, nameOld, nameNew, str(fileName) )
if not os.access(str(fileName), os.W_OK): if not os.access(str(fileName), os.W_OK):
command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName) command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName)
# print("\t%s" % command) # print("\t%s" % command)
if subprocess.call( command, shell=True ) != 0: if subprocess.call( command, shell=True ) != 0:
msg = "!!! Failed to set the new identification name to <%s> !!!" msg = "!!! Failed to set the new identification name to <%s> !!!"
print( msg % fileName, file=sys.stderr ) print( msg % fileName, file=sys.stderr )
return 1 return 1
return 0 return 0
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
## To get KLayout's version from a file; most likely from 'version.sh' ## To get KLayout's version from a file; most likely from 'version.sh'
@ -414,25 +414,25 @@ def PerformChanges( frameworkDependencyDict, replaceFromToPairs=None, executable
# @return version string # @return version string
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
def GetKLayoutVersionFrom( verfile='version.h' ): def GetKLayoutVersionFrom( verfile='version.h' ):
version = "?.?.?" version = "?.?.?"
try: try:
fd = open( verfile, "r" ) fd = open( verfile, "r" )
contents = fd.readlines() contents = fd.readlines()
fd.close() fd.close()
except Exception as e: except Exception as e:
return version return version
verReg = re.compile( u'(KLAYOUT_VERSION=\")([0-9A-Z_a-z\.]+)(\")' ) verReg = re.compile( u'(KLAYOUT_VERSION=\")([0-9A-Z_a-z\.]+)(\")' )
for line in contents: for line in contents:
m = verReg.match(line) m = verReg.match(line)
if m: if m:
# print(m.group(0)) # KLAYOUT_VERSION="0.26.1" # print(m.group(0)) # KLAYOUT_VERSION="0.26.1"
# print(m.group(1)) # KLAYOUT_VERSION=" # print(m.group(1)) # KLAYOUT_VERSION="
# print(m.group(2)) # 0.26.1 # print(m.group(2)) # 0.26.1
# print(m.group(3)) # " # print(m.group(3)) # "
version = m.group(2) version = m.group(2)
return version return version
return version return version
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
## To generate the contents of "Info.plist" file from a template ## To generate the contents of "Info.plist" file from a template
@ -443,24 +443,24 @@ def GetKLayoutVersionFrom( verfile='version.h' ):
# @return generated strings # @return generated strings
#---------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------
def GenerateInfoPlist( keydic, templfile ): def GenerateInfoPlist( keydic, templfile ):
val_exe = keydic['exe'] val_exe = keydic['exe']
val_icon = keydic['icon'] val_icon = keydic['icon']
val_bname = keydic['bname'] val_bname = keydic['bname']
val_ver = keydic['ver'] val_ver = keydic['ver']
try: try:
fd = open( templfile, "r" ) fd = open( templfile, "r" )
template = fd.read() template = fd.read()
fd.close() fd.close()
except Exception as e: except Exception as e:
return "???" return "???"
t = string.Template(template) t = string.Template(template)
s = t.substitute( EXECUTABLE = val_exe, s = t.substitute( EXECUTABLE = val_exe,
ICONFILE = val_icon, ICONFILE = val_icon,
BUNDLENAME = val_bname, BUNDLENAME = val_bname,
VERSION = val_ver) VERSION = val_ver)
return s return s
#---------------- #----------------
# End of File # End of File

View File

@ -23,6 +23,7 @@ import platform
import optparse import optparse
import subprocess import subprocess
import hashlib import hashlib
import string
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
## To import global dictionaries of different modules and utility functions ## To import global dictionaries of different modules and utility functions
@ -41,6 +42,7 @@ def SetGlobals():
global GenOSName # generic OS name global GenOSName # generic OS name
global Platform # platform global Platform # platform
global PkgDir # the package directory where "klayout.app" exists global PkgDir # the package directory where "klayout.app" exists
global UnsafePkg # flags whether to proceed to making "invalid" dmg
global OpClean # 'clean' operation global OpClean # 'clean' operation
global OpMake # 'make' operation global OpMake # 'make' operation
global DefaultBundleName # the default bundle name 'klayout.app' global DefaultBundleName # the default bundle name 'klayout.app'
@ -87,6 +89,8 @@ def SetGlobals():
Usage += " : <-c|--clean> and <-m|--make> are mutually exclusive | \n" Usage += " : <-c|--clean> and <-m|--make> are mutually exclusive | \n"
Usage += " [-b|--bundle <name>] : forcibly use this bundle name in the DMG | '' \n" Usage += " [-b|--bundle <name>] : forcibly use this bundle name in the DMG | '' \n"
Usage += " [-s|--serial <num>] : DMG serial number | 1 \n" Usage += " [-s|--serial <num>] : DMG serial number | 1 \n"
Usage += " <-u|--unsafe> : Ignores a few checks (use with caution) | disabled \n"
Usage += " <-t|--targetdmg> : Specify output .dmg filename | chosen by script \n"
Usage += " [-?|--?] : print this usage and exit | disabled \n" Usage += " [-?|--?] : print this usage and exit | disabled \n"
Usage += "-------------------------------------------------------------------------------------+------------------\n" Usage += "-------------------------------------------------------------------------------------+------------------\n"
@ -131,6 +135,7 @@ def SetGlobals():
sys.exit(1) sys.exit(1)
PkgDir = "" PkgDir = ""
UnsafePkg = False
OpClean = False OpClean = False
OpMake = False OpMake = False
DefaultBundleName = "klayout.app" DefaultBundleName = "klayout.app"
@ -189,6 +194,8 @@ def SetGlobals():
# on failure, -1 # on failure, -1
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
def CheckPkgDirectory(): def CheckPkgDirectory():
global PkgDir
global UnsafePkg
global Platform global Platform
global OpClean global OpClean
global OpMake global OpMake
@ -229,76 +236,79 @@ def CheckPkgDirectory():
regQRP = re.compile(patQRP) regQRP = re.compile(patQRP)
if not regQRP.match(PkgDir): if not regQRP.match(PkgDir):
print( "! Cannot identify (Qt, Ruby, Python) from the package directory name" ) print( "! Cannot identify (Qt, Ruby, Python) from the package directory name" )
print( "" ) if UnsafePkg:
return -1 print( "! Ignoring..." )
else:
print( "" )
return -1
else: else:
pkgdirComponents = regQRP.match(PkgDir).groups() pkgdirComponents = regQRP.match(PkgDir).groups()
PackagePrefix = pkgdirComponents[0] PackagePrefix = pkgdirComponents[0]
QtIdentification = pkgdirComponents[2] QtIdentification = pkgdirComponents[2]
RubyPythonID = pkgdirComponents[5] RubyPythonID = pkgdirComponents[5]
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# [3] Check if the "LatestOS" with MacPorts / Homebrew / Anaconda3 # [3] Check if the "LatestOS" with MacPorts / Homebrew / Anaconda3
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
LatestOSMacPorts = Platform == LatestOS LatestOSMacPorts = Platform == LatestOS
LatestOSMacPorts &= PackagePrefix == "LW" LatestOSMacPorts &= PackagePrefix == "LW"
LatestOSMacPorts &= QtIdentification == "qt5MP" LatestOSMacPorts &= QtIdentification == "qt5MP"
LatestOSMacPorts &= RubyPythonID == "Rmp26Pmp38" LatestOSMacPorts &= RubyPythonID == "Rmp26Pmp38"
LatestOSHomebrew = Platform == LatestOS LatestOSHomebrew = Platform == LatestOS
LatestOSHomebrew &= PackagePrefix == "LW" LatestOSHomebrew &= PackagePrefix == "LW"
LatestOSHomebrew &= QtIdentification == "qt5Brew" LatestOSHomebrew &= QtIdentification == "qt5Brew"
LatestOSHomebrew &= RubyPythonID == "Rhb27Phb38" LatestOSHomebrew &= RubyPythonID == "Rhb27Phb38"
LatestOSAnaconda3 = Platform == LatestOS LatestOSAnaconda3 = Platform == LatestOS
LatestOSAnaconda3 &= PackagePrefix == "LW" LatestOSAnaconda3 &= PackagePrefix == "LW"
LatestOSAnaconda3 &= QtIdentification == "qt5Ana3" LatestOSAnaconda3 &= QtIdentification == "qt5Ana3"
LatestOSAnaconda3 &= RubyPythonID == "Rana3Pana3" LatestOSAnaconda3 &= RubyPythonID == "Rana3Pana3"
if LatestOSMacPorts: if LatestOSMacPorts:
mydic = DicLightWeight["ports"] mydic = DicLightWeight["ports"]
srcDir = PkgDir + "/" + mydic["src"] srcDir = PkgDir + "/" + mydic["src"]
desDir = PkgDir + "/" + mydic["des"] desDir = PkgDir + "/" + mydic["des"]
if OpMake: if OpMake:
with zipfile.ZipFile( mydic["zip"], 'r' ) as zip_ref: with zipfile.ZipFile( mydic["zip"], 'r' ) as zip_ref:
zip_ref.extractall(PkgDir) zip_ref.extractall(PkgDir)
os.rename( srcDir, desDir ) os.rename( srcDir, desDir )
if OpClean: if OpClean:
if os.path.isdir(srcDir): if os.path.isdir(srcDir):
shutil.rmtree(srcDir) shutil.rmtree(srcDir)
if os.path.isdir(desDir): if os.path.isdir(desDir):
shutil.rmtree(desDir) shutil.rmtree(desDir)
Item3AppleScript = mydic["item3"] Item3AppleScript = mydic["item3"]
if LatestOSHomebrew: if LatestOSHomebrew:
mydic = DicLightWeight["brew"] mydic = DicLightWeight["brew"]
srcDir = PkgDir + "/" + mydic["src"] srcDir = PkgDir + "/" + mydic["src"]
desDir = PkgDir + "/" + mydic["des"] desDir = PkgDir + "/" + mydic["des"]
if OpMake: if OpMake:
with zipfile.ZipFile( mydic["zip"], 'r' ) as zip_ref: with zipfile.ZipFile( mydic["zip"], 'r' ) as zip_ref:
zip_ref.extractall(PkgDir) zip_ref.extractall(PkgDir)
os.rename( srcDir, desDir ) os.rename( srcDir, desDir )
if OpClean: if OpClean:
if os.path.isdir(srcDir): if os.path.isdir(srcDir):
shutil.rmtree(srcDir) shutil.rmtree(srcDir)
if os.path.isdir(desDir): if os.path.isdir(desDir):
shutil.rmtree(desDir) shutil.rmtree(desDir)
Item3AppleScript = mydic["item3"] Item3AppleScript = mydic["item3"]
if LatestOSAnaconda3: if LatestOSAnaconda3:
mydic = DicLightWeight["ana3"] mydic = DicLightWeight["ana3"]
srcDir = PkgDir + "/" + mydic["src"] srcDir = PkgDir + "/" + mydic["src"]
desDir = PkgDir + "/" + mydic["des"] desDir = PkgDir + "/" + mydic["des"]
if OpMake: if OpMake:
with zipfile.ZipFile( mydic["zip"], 'r' ) as zip_ref: with zipfile.ZipFile( mydic["zip"], 'r' ) as zip_ref:
zip_ref.extractall(PkgDir) zip_ref.extractall(PkgDir)
os.rename( srcDir, desDir ) os.rename( srcDir, desDir )
if OpClean: if OpClean:
if os.path.isdir(srcDir): if os.path.isdir(srcDir):
shutil.rmtree(srcDir) shutil.rmtree(srcDir)
if os.path.isdir(desDir): if os.path.isdir(desDir):
shutil.rmtree(desDir) shutil.rmtree(desDir)
Item3AppleScript = mydic["item3"] Item3AppleScript = mydic["item3"]
#------------------------------------------------------ #------------------------------------------------------
# [4] Check the presence of the default bundle # [4] Check the presence of the default bundle
@ -337,6 +347,7 @@ def ParseCommandLineArguments():
global OpMake global OpMake
global BundleName global BundleName
global DMGSerialNum global DMGSerialNum
global UnsafePkg
global PackagePrefix global PackagePrefix
global QtIdentification global QtIdentification
global RubyPythonID global RubyPythonID
@ -369,6 +380,16 @@ def ParseCommandLineArguments():
dest='dmg_serial', dest='dmg_serial',
help="DMG serial number" ) help="DMG serial number" )
p.add_option( '-t', '--targetdmg',
dest='target_dmg',
help="output DMG filename" )
p.add_option( '-z', '--unsafe',
action='store_true',
dest='unsafe',
default=False,
help="If set, do not check whether pkg folder is empty" )
p.add_option( '-?', '--??', p.add_option( '-?', '--??',
action='store_true', action='store_true',
dest='checkusage', dest='checkusage',
@ -379,7 +400,9 @@ def ParseCommandLineArguments():
operation_clean = False, operation_clean = False,
operation_make = False, operation_make = False,
bundle_name = "", bundle_name = "",
target_dmg = "",
dmg_serial = "1", dmg_serial = "1",
unsafe = False,
checkusage = False ) checkusage = False )
#----------------------------------------------------------- #-----------------------------------------------------------
@ -394,6 +417,7 @@ def ParseCommandLineArguments():
OpClean = opt.operation_clean OpClean = opt.operation_clean
OpMake = opt.operation_make OpMake = opt.operation_make
DMGSerialNum = int(opt.dmg_serial) DMGSerialNum = int(opt.dmg_serial)
UnsafePkg = opt.unsafe
if not opt.bundle_name == "": if not opt.bundle_name == "":
base, ext = os.path.splitext( os.path.basename(opt.bundle_name) ) base, ext = os.path.splitext( os.path.basename(opt.bundle_name) )
@ -410,10 +434,13 @@ def ParseCommandLineArguments():
# [2] Check the PKG directory to set QtIdentification, RubyPythonID, and BundleName # [2] Check the PKG directory to set QtIdentification, RubyPythonID, and BundleName
#------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------
OccupiedDS = CheckPkgDirectory() OccupiedDS = CheckPkgDirectory()
if not 0 < OccupiedDS: if not 0 < OccupiedDS and not UnsafePkg:
print( "! Failed to check the PKG directory" ) print( "! Failed to check the PKG directory" )
print( "" ) print( "" )
quit() quit()
if opt.target_dmg != "":
TargetDMG = opt.target_dmg
else: else:
TargetDMG = "%s-klayout-%s-%s-%s-%d-%s-%s.dmg" \ TargetDMG = "%s-klayout-%s-%s-%s-%d-%s-%s.dmg" \
% (PackagePrefix, KLVersion, GenOSName, Platform, DMGSerialNum, QtIdentification, RubyPythonID) % (PackagePrefix, KLVersion, GenOSName, Platform, DMGSerialNum, QtIdentification, RubyPythonID)
@ -663,7 +690,8 @@ def CleanUp(msg=""):
os.chdir(ProjectDir) os.chdir(ProjectDir)
dmgs = glob.glob( "*.dmg*" ) dmgs = glob.glob( "*.dmg*" )
for item in dmgs: for item in dmgs:
os.system( "rm -Rf %s" % item ) print("Removing %s" % item)
os.system( "rm -Rf -- \"%s\"" % item )
#---------------------------------------------------- #----------------------------------------------------
# [3] Clean up AppleScript if any # [3] Clean up AppleScript if any