mirror of https://github.com/KLayout/klayout.git
* Updated the build system for Mac (#645)
* Catalina env. uses Python 3.8 in MacPorts, Homebrew, and Anaconda3.
This commit is contained in:
parent
151fd81bd3
commit
2f0fa28e58
|
|
@ -1,4 +1,4 @@
|
|||
Relevant KLayout version: 0.26.5
|
||||
Relevant KLayout version: 0.26.7
|
||||
|
||||
# 1. Introduction
|
||||
This directory **`macbuild`** contains different files required for building KLayout (http://www.klayout.de/) version 0.26.1 or later for different 64-bit Mac OSXs including:
|
||||
|
|
@ -72,16 +72,16 @@ $ [python] ./build4mac.py
|
|||
: MP26: use Ruby 2.6 from MacPorts |
|
||||
: HB27: use Ruby 2.7 from Homebrew |
|
||||
: Ana3: use Ruby 2.5 from Anaconda3 |
|
||||
[-p|--python <type>] : case-insensitive type=['nil', 'Sys', 'MP37', 'HB37', 'Ana3'] | sys
|
||||
[-p|--python <type>] : case-insensitive type=['nil', 'Sys', 'MP38', 'HB38', 'Ana3'] | sys
|
||||
: nil: don't bind Python |
|
||||
: Sys: use OS-bundled Python 2.7 [ElCapitan -- Catalina] |
|
||||
: MP37: use Python 3.7 from MacPorts |
|
||||
: HB37: use Python 3.7 from Homebrew |
|
||||
: Ana3: use Python 3.7 from Anaconda3 |
|
||||
: MP38: use Python 3.8 from MacPorts |
|
||||
: HB38: use Python 3.8 from Homebrew |
|
||||
: Ana3: use Python 3.8 from Anaconda3 |
|
||||
[-n|--noqtbinding] : don't create Qt bindings for ruby scripts | disabled
|
||||
[-m|--make <option>] : option passed to 'make' | '-j4'
|
||||
[-d|--debug] : enable debug mode build | disabled
|
||||
[-c|--checkcom] : check command-line and exit without building | disabled
|
||||
[-c|--checkcom] : check command line and exit without building | disabled
|
||||
[-y|--deploy] : deploy executables and dylibs including Qt's Frameworks | disabled
|
||||
[-Y|--DEPLOY] : deploy executables and dylibs for those who built KLayout | disabled
|
||||
: from the source code and use the tools in the same machine |
|
||||
|
|
@ -126,64 +126,64 @@ Then the directory name will be **`LW-qt5MP.pkg.macos-Catalina-release-RsysPsys`
|
|||
|
||||
#### If you build KLayout from the source code AND use it on the same machine, "-Y" option is highly recommended. ####
|
||||
|
||||
### 6B. Fully MacPorts-flavored build with MacPorts Ruby 2.6 and MacPorts Python 3.7
|
||||
### 6B. Fully MacPorts-flavored build with MacPorts Ruby 2.6 and MacPorts Python 3.8
|
||||
```
|
||||
$ cd /where/'build.sh'/exists
|
||||
$ ./build4mac.py -q qt5macports -r mp26 -p mp37
|
||||
$ ./build4mac.py -q qt5macports -r mp26 -p mp38
|
||||
```
|
||||
2. Confirm successful build (it will take about one hour depending on your machine spec).
|
||||
3. Run **`build4mac.py`** again with the same options used in 1. PLUS "-Y" to deploy executables and libraries under **`klayout.app`** bundle.<br>
|
||||
The buddy command-line tools (strm*) will also be deployed in this step.
|
||||
```
|
||||
$ ./build4mac.py -q qt5macports -r mp26 -p mp37 -Y
|
||||
$ ./build4mac.py -q qt5macports -r mp26 -p mp38 -Y
|
||||
```
|
||||
The application bundle **`klayout.app`** is located under:<br>
|
||||
**`LW-qt5MP.pkg.macos-Catalina-release-Rmp26Pmp37`** directory, where
|
||||
**`LW-qt5MP.pkg.macos-Catalina-release-Rmp26Pmp38`** directory, where
|
||||
* "LW-" means that this is a lightweight package.
|
||||
* "qt5MP" means that Qt5 from MacPorts is used.
|
||||
* "Rmp26Pmp37" means that Ruby is 2.6 from MacPorts; Python is 3.7 from MacPorts.
|
||||
* "Rmp26Pmp38" means that Ruby is 2.6 from MacPorts; Python is 3.8 from MacPorts.
|
||||
4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation.
|
||||
|
||||
### 6C. Fully Homebrew-flavored build with Homebrew Ruby 2.7 and Homebrew Python 3.7
|
||||
### 6C. Fully Homebrew-flavored build with Homebrew Ruby 2.7 and Homebrew Python 3.8
|
||||
```
|
||||
$ cd /where/'build.sh'/exists
|
||||
$ ./build4mac.py -q qt5brew -r hb27 -p hb37
|
||||
$ ./build4mac.py -q qt5brew -r hb27 -p hb38
|
||||
```
|
||||
2. Confirm successful build (it will take about one hour depending on your machine spec).
|
||||
3. Run **`build4mac.py`** again with the same options used in 1. PLUS "-Y" to deploy executables and libraries under **`klayout.app`** bundle.<br>
|
||||
The buddy command-line tools (strm*) will also be deployed in this step.
|
||||
```
|
||||
$ ./build4mac.py -q qt5brew -r hb27 -p hb37 -Y
|
||||
$ ./build4mac.py -q qt5brew -r hb27 -p hb38 -Y
|
||||
```
|
||||
The application bundle **`klayout.app`** is located under:<br>
|
||||
**`LW-qt5Brew.pkg.macos-Catalina-release-Rhb27Phb37`** directory, where
|
||||
**`LW-qt5Brew.pkg.macos-Catalina-release-Rhb27Phb38`** directory, where
|
||||
* "LW-" means that this is a lightweight package.
|
||||
* "qt5Brew" means that Qt5 from Homebrew is used.
|
||||
* "Rhb27Phb37" means that Ruby is 2.7 from Homebrew; Python is 3.7 from Homebrew.
|
||||
* "Rhb27Phb38" means that Ruby is 2.7 from Homebrew; Python is 3.8 from Homebrew.
|
||||
4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation.
|
||||
|
||||
### 6D. Partially Homebrew-flavored build with System Ruby and Homebrew Python 3.7
|
||||
### 6D. Partially Homebrew-flavored build with System Ruby and Homebrew Python 3.8
|
||||
```
|
||||
$ cd /where/'build.sh'/exists
|
||||
$ ./build4mac.py -q qt5brew -r sys -p hb37
|
||||
$ ./build4mac.py -q qt5brew -r sys -p hb38
|
||||
```
|
||||
2. Confirm successful build (it will take about one hour depending on your machine spec).
|
||||
3. Run **`build4mac.py`** again with the same options used in 1. PLUS "-y" to deploy executables and libraries (including Qt's frameworks and Python frameworks) under **`klayout.app`** bundle.<br>
|
||||
The buddy command-line tools (strm*) will also be deployed in this step.
|
||||
```
|
||||
$ ./build4mac.py -q qt5brew -r sys -p hb37 -y
|
||||
$ ./build4mac.py -q qt5brew -r sys -p hb38 -y
|
||||
```
|
||||
The application bundle **`klayout.app`** is located under:<br>
|
||||
**`HW-qt5Brew.pkg.macos-Catalina-release-RsysPhb37`** directory, where
|
||||
**`HW-qt5Brew.pkg.macos-Catalina-release-RsysPhb38`** directory, where
|
||||
* "HW-" means that this is a heavyweight package because both Qt5 and Python are deployed.
|
||||
* "qt5Brew" means that Qt5 from Homebrew is used.
|
||||
* "RsysPhb37" means that Ruby is OS-bundled; Python is 3.7 from Homebrew.
|
||||
* "RsysPhb38" means that Ruby is OS-bundled; Python is 3.8 from Homebrew.
|
||||
4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation.
|
||||
### Important ###
|
||||
So far, deployment of Homebrew Ruby is not supported. <br>
|
||||
Therefore, if you intend to use "-y" option, you need to use "-r sys" for building.
|
||||
|
||||
### 6E. Fully Anaconda3-flavored build with Anaconda3 Ruby 2.5 and Anaconda3 Python 3.7
|
||||
### 6E. Fully Anaconda3-flavored build with Anaconda3 Ruby 2.5 and Anaconda3 Python 3.8
|
||||
```
|
||||
$ cd /where/'build.sh'/exists
|
||||
$ ./build4mac.py -q qt5ana3 -r ana3 -p ana3
|
||||
|
|
@ -198,7 +198,7 @@ $ ./build4mac.py -q qt5ana3 -r ana3 -p ana3 -Y
|
|||
**`LW-qt5Ana3.pkg.macos-Catalina-release-Rana3Pana3`** directory, where
|
||||
* "LW-" means that this is a lightweight package.
|
||||
* "qt5Ana3" means that Qt5 from Anaconda3 is used.
|
||||
* "Rana3Pana3" means that Ruby (2.5) is from Anaconda3; Python (3.7) is from Anaconda3.
|
||||
* "Rana3Pana3" means that Ruby (2.5) is from Anaconda3; Python (3.8) is from Anaconda3.
|
||||
4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation.
|
||||
5. You may have to set `PYTHONHOME` environment variable like:
|
||||
```
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -73,11 +73,11 @@ def SetGlobals():
|
|||
Usage += " : MP26: use Ruby 2.6 from MacPorts | \n"
|
||||
Usage += " : HB27: use Ruby 2.7 from Homebrew | \n"
|
||||
Usage += " : Ana3: use Ruby 2.5 from Anaconda3 | \n"
|
||||
Usage += " [-p|--python <type>] : case-insensitive type=['nil', 'Sys', 'MP37', 'HB37', 'Ana3'] | sys \n"
|
||||
Usage += " [-p|--python <type>] : case-insensitive type=['nil', 'Sys', 'MP38', 'HB38', 'Ana3'] | sys \n"
|
||||
Usage += " : nil: don't bind Python | \n"
|
||||
Usage += " : Sys: use OS-bundled Python 2.7 [ElCapitan -- Catalina] | \n"
|
||||
Usage += " : MP37: use Python 3.7 from MacPorts | \n"
|
||||
Usage += " : HB37: use Python 3.7 from Homebrew | \n"
|
||||
Usage += " : MP38: use Python 3.8 from MacPorts | \n"
|
||||
Usage += " : HB38: use Python 3.8 from Homebrew | \n"
|
||||
Usage += " : Ana3: use Python 3.7 from Anaconda3 | \n"
|
||||
Usage += " [-n|--noqtbinding] : don't create Qt bindings for ruby scripts | disabled \n"
|
||||
Usage += " [-m|--make <option>] : option passed to 'make' | '-j4' \n"
|
||||
|
|
@ -195,7 +195,7 @@ def ParseCommandLineArguments():
|
|||
|
||||
p.add_option( '-p', '--python',
|
||||
dest='type_python',
|
||||
help="Python type=['nil', 'Sys', 'MP37', 'HB37', 'Ana3']" )
|
||||
help="Python type=['nil', 'Sys', 'MP38', 'HB38', 'Ana3']" )
|
||||
|
||||
p.add_option( '-n', '--noqtbinding',
|
||||
action='store_true',
|
||||
|
|
@ -332,8 +332,8 @@ def ParseCommandLineArguments():
|
|||
candidates = dict()
|
||||
candidates['NIL'] = 'nil'
|
||||
candidates['SYS'] = 'Sys'
|
||||
candidates['MP37'] = 'MP37'
|
||||
candidates['HB37'] = 'HB37'
|
||||
candidates['MP38'] = 'MP38'
|
||||
candidates['HB38'] = 'HB38'
|
||||
candidates['ANA3'] = 'Ana3'
|
||||
try:
|
||||
choicePython = candidates[ opt.type_python.upper() ]
|
||||
|
|
@ -355,11 +355,11 @@ def ParseCommandLineArguments():
|
|||
ModulePython = 'PythonSierra'
|
||||
elif Platform == "ElCapitan":
|
||||
ModulePython = 'PythonElCapitan'
|
||||
elif choicePython == "MP37":
|
||||
ModulePython = 'Python37MacPorts'
|
||||
elif choicePython == "MP38":
|
||||
ModulePython = 'Python38MacPorts'
|
||||
NonOSStdLang = True
|
||||
elif choicePython == "HB37":
|
||||
ModulePython = 'Python37Brew'
|
||||
elif choicePython == "HB38":
|
||||
ModulePython = 'Python38Brew'
|
||||
NonOSStdLang = True
|
||||
elif choicePython == "Ana3":
|
||||
ModulePython = 'PythonAnaconda3'
|
||||
|
|
@ -374,12 +374,12 @@ def ParseCommandLineArguments():
|
|||
# Set of modules chosen
|
||||
ModuleSet = ( choiceQt5, choiceRuby, choicePython )
|
||||
|
||||
NoQtBindings = opt.no_qt_binding
|
||||
MakeOptions = opt.make_option
|
||||
DebugMode = opt.debug_build
|
||||
CheckComOnly = opt.check_command
|
||||
DeploymentF = opt.deploy_full
|
||||
DeploymentP = opt.deploy_partial
|
||||
NoQtBindings = opt.no_qt_binding
|
||||
MakeOptions = opt.make_option
|
||||
DebugMode = opt.debug_build
|
||||
CheckComOnly = opt.check_command
|
||||
DeploymentF = opt.deploy_full
|
||||
DeploymentP = opt.deploy_partial
|
||||
|
||||
if DeploymentF and DeploymentP:
|
||||
print("")
|
||||
|
|
@ -409,9 +409,9 @@ def ParseCommandLineArguments():
|
|||
if (ModuleRuby in RubySys) and (ModulePython in PythonSys):
|
||||
PackagePrefix = "ST-"
|
||||
message += "a standard (ST-) package including Qt5 and using OS-bundled Ruby and Python..."
|
||||
elif ModulePython == 'Python37Brew':
|
||||
elif ModulePython == 'Python38Brew':
|
||||
PackagePrefix = "HW-"
|
||||
message += "a heavyweight (HW-) package including Qt5 and Python3.7 from Homebrew..."
|
||||
message += "a heavyweight (HW-) package including Qt5 and Python3.8 from Homebrew..."
|
||||
else:
|
||||
PackagePrefix = "EX-"
|
||||
message += "a package with exceptional (EX-) combinations of different modules..."
|
||||
|
|
@ -593,6 +593,7 @@ def RunMainBuildBash():
|
|||
os.remove( tarFile )
|
||||
os.chdir( "../" )
|
||||
shutil.copy2( "macbuild/macQAT.sh", MacBuildDirQAT )
|
||||
shutil.copy2( "macbuild/macQAT.py", MacBuildDirQAT )
|
||||
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
|
||||
print( "### <%s>: prepared the initial *.macQAT/" % myscript, file=sys.stderr )
|
||||
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
|
||||
|
|
@ -905,10 +906,6 @@ def DeployBinariesForBundle():
|
|||
deploytool = Qt5MacPorts['deploy']
|
||||
app_bundle = "klayout.app"
|
||||
options = macdepQtOpt + verbose
|
||||
# To use Qt5 from Homebrew on Catalina...
|
||||
# in "/usr/local/opt/python/lib/"
|
||||
# Python.framework -> ../Frameworks/Python.framework/ <=== this symbolic was needed
|
||||
# pkgconfig/
|
||||
elif ModuleQt == 'Qt5Brew':
|
||||
deploytool = Qt5Brew['deploy']
|
||||
app_bundle = "klayout.app"
|
||||
|
|
@ -932,39 +929,52 @@ def DeployBinariesForBundle():
|
|||
os.chdir(ProjectDir)
|
||||
return 1
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# [9] Special deployment of Python3.7 from Homebrew
|
||||
#-------------------------------------------------------------
|
||||
deploymentPython37HB = (ModulePython == 'Python37Brew')
|
||||
if deploymentPython37HB and NonOSStdLang:
|
||||
#-----------------------------------------------------------------------------------------------
|
||||
# [9] Special deployment of Python3.8 from Homebrew
|
||||
# To use Python3.8 from Homebrew on Catalina...
|
||||
# in "/usr/local/opt/python/lib/"
|
||||
# Python.framework -> ../Frameworks/Python.framework/ <=== this symbolic was needed
|
||||
# pkgconfig/
|
||||
#-----------------------------------------------------------------------------------------------
|
||||
deploymentPython38HB = (ModulePython == 'Python38Brew')
|
||||
if deploymentPython38HB and NonOSStdLang:
|
||||
from build4mac_util import WalkFrameworkPaths, PerformChanges
|
||||
|
||||
bundlePath = AbsMacPkgDir + '/klayout.app'
|
||||
bundleExecPathAbs = '%s/Contents/MacOS/' % bundlePath
|
||||
pythonHBVer = "3.8" # 'pinned' to this version as of KLayout version 0.26.7 (2020-09-13)
|
||||
bundlePath = AbsMacPkgDir + '/klayout.app'
|
||||
bundleExecPathAbs = '%s/Contents/MacOS/' % bundlePath
|
||||
pythonFrameworkPath = '%s/Contents/Frameworks/Python.framework' % bundlePath
|
||||
testTarget = '%s/Versions/%s/lib/python%s/test' % (pythonFrameworkPath, pythonHBVer, pythonHBVer)
|
||||
resourceTarget1 = '%s/Versions/%s/Resources' % (pythonFrameworkPath, pythonHBVer)
|
||||
resourceTarget2 = '%s/Resources' % pythonFrameworkPath
|
||||
binTarget = '%s/Versions/%s/bin' % (pythonFrameworkPath, pythonHBVer)
|
||||
sitepackagesTarget = '%s/Versions/%s/lib/python%s/site-packages' % (pythonFrameworkPath, pythonHBVer, pythonHBVer)
|
||||
sitepackagesSource = '%s/Versions/%s/lib/python%s/site-packages' % (HBPython38FrameworkPath, pythonHBVer, pythonHBVer)
|
||||
|
||||
print( "" )
|
||||
print( " [9] Optional deployment of Python from %s ..." % HBPython37FrameworkPath )
|
||||
print( " [9] Optional deployment of Python from %s ..." % HBPython38FrameworkPath )
|
||||
print( " [9.1] Copying Python Framework" )
|
||||
|
||||
cmd1 = "rm -rf %s" % pythonFrameworkPath
|
||||
cmd2 = "rsync -a --safe-links %s/ %s" % (HBPython37FrameworkPath, pythonFrameworkPath)
|
||||
cmd3 = "mkdir %s/Versions/3.7/lib/python3.7/site-packages/" % pythonFrameworkPath
|
||||
cmd4 = "cp -RL %s/Versions/3.7/lib/python3.7/site-packages/{pip*,pkg_resources,setuptools*,wheel*} " % \
|
||||
HBPython37FrameworkPath
|
||||
cmd4 += "%s/Versions/3.7/lib/python3.7/site-packages/" % pythonFrameworkPath
|
||||
cmd5 = "rm -rf %s/Versions/3.7/lib/python3.7/test" % pythonFrameworkPath
|
||||
cmd6 = "rm -rf %s/Versions/3.7/Resources" % pythonFrameworkPath
|
||||
cmd7 = "rm -rf %s/Versions/3.7/bin" % pythonFrameworkPath
|
||||
cmd01 = "rm -rf %s" % pythonFrameworkPath
|
||||
cmd02 = "rsync -a --safe-links %s/ %s" % (HBPython38FrameworkPath, pythonFrameworkPath)
|
||||
|
||||
cmd03 = "rm -rf %s" % testTarget
|
||||
cmd04 = "rm -rf %s" % resourceTarget1
|
||||
cmd05 = "unlink %s" % resourceTarget2
|
||||
cmd06 = "rm -rf %s" % binTarget
|
||||
|
||||
cmd07 = "mkdir %s" % sitepackagesTarget
|
||||
cmd08 = "cp -RL %s/{pip*,pkg_resources,setuptools*,wheel*} %s" % (sitepackagesSource, sitepackagesTarget)
|
||||
|
||||
shell_commands = list()
|
||||
shell_commands.append(cmd1)
|
||||
shell_commands.append(cmd2)
|
||||
shell_commands.append(cmd3)
|
||||
shell_commands.append(cmd4)
|
||||
shell_commands.append(cmd5)
|
||||
shell_commands.append(cmd6)
|
||||
shell_commands.append(cmd7)
|
||||
shell_commands.append(cmd01)
|
||||
shell_commands.append(cmd02)
|
||||
shell_commands.append(cmd03)
|
||||
shell_commands.append(cmd04)
|
||||
shell_commands.append(cmd05)
|
||||
shell_commands.append(cmd06)
|
||||
shell_commands.append(cmd07)
|
||||
shell_commands.append(cmd08)
|
||||
|
||||
for command in shell_commands:
|
||||
if subprocess.call( command, shell=True ) != 0:
|
||||
|
|
@ -973,14 +983,15 @@ def DeployBinariesForBundle():
|
|||
sys.exit(1)
|
||||
|
||||
shutil.copy2( sourceDir2 + "/start-console.py", targetDirM )
|
||||
shutil.copy2( sourceDir2 + "/klayout_console", targetDirM )
|
||||
os.chmod( targetDirM + "/klayout_console", 0o0755 )
|
||||
shutil.copy2( sourceDir2 + "/klayout_console", targetDirM )
|
||||
os.chmod( targetDirM + "/start-console.py", 0o0755 )
|
||||
os.chmod( targetDirM + "/klayout_console", 0o0755 )
|
||||
|
||||
print(" [9.2] Relinking dylib dependencies inside Python.framework" )
|
||||
print(" [9.2.1] Patching Python Framework" )
|
||||
depdict = WalkFrameworkPaths( pythonFrameworkPath )
|
||||
appPythonFrameworkPath = '@executable_path/../Frameworks/Python.framework/'
|
||||
PerformChanges(depdict, [(HBPython37FrameworkPath, appPythonFrameworkPath, False)], bundleExecPathAbs)
|
||||
PerformChanges(depdict, [(HBPython38FrameworkPath, appPythonFrameworkPath, False)], bundleExecPathAbs)
|
||||
|
||||
print(" [9.2.2] Patching /usr/local/opt/ libs")
|
||||
usrLocalPath = '/usr/local/opt/'
|
||||
|
|
@ -989,17 +1000,16 @@ def DeployBinariesForBundle():
|
|||
depdict = WalkFrameworkPaths(pythonFrameworkPath, search_path_filter=r'\t+/usr/local/(opt|Cellar)')
|
||||
PerformChanges(depdict, replacePairs, bundleExecPathAbs)
|
||||
|
||||
print(" [9.2.3] Patching openssl, gdbm, readline, sqlite, tcl-tk, xz")
|
||||
print(" [9.2.3] Patching openssl@1.1, gdbm, readline, sqlite, xz")
|
||||
usrLocalPath = '/usr/local/opt'
|
||||
appUsrLocalPath = '@executable_path/../Frameworks/'
|
||||
replacePairs = [(usrLocalPath, appUsrLocalPath, True)]
|
||||
replacePairs.extend([(openssl_version, '@executable_path/../Frameworks/openssl', True)
|
||||
for openssl_version in glob.glob('/usr/local/Cellar/openssl/*')])
|
||||
depdict = WalkFrameworkPaths([pythonFrameworkPath + '/../openssl',
|
||||
replacePairs.extend([(openssl_version, '@executable_path/../Frameworks/openssl@1.1', True)
|
||||
for openssl_version in glob.glob('/usr/local/Cellar/openssl@1.1/*')])
|
||||
depdict = WalkFrameworkPaths([pythonFrameworkPath + '/../openssl@1.1',
|
||||
pythonFrameworkPath + '/../gdbm',
|
||||
pythonFrameworkPath + '/../readline',
|
||||
pythonFrameworkPath + '/../sqlite',
|
||||
pythonFrameworkPath + '/../tcl-tk',
|
||||
pythonFrameworkPath + '/../xz'], search_path_filter=r'\t+/usr/local/(opt|Cellar)')
|
||||
|
||||
PerformChanges(depdict, replacePairs, bundleExecPathAbs)
|
||||
|
|
@ -1007,21 +1017,21 @@ def DeployBinariesForBundle():
|
|||
print(" [9.3] Relinking dylib dependencies for klayout")
|
||||
klayoutPath = bundleExecPathAbs
|
||||
depdict = WalkFrameworkPaths(klayoutPath, filter_regex=r'klayout$')
|
||||
PerformChanges(depdict, [(HBPython37FrameworkPath, appPythonFrameworkPath, False)], bundleExecPathAbs)
|
||||
PerformChanges(depdict, [(HBPython38FrameworkPath, appPythonFrameworkPath, False)], bundleExecPathAbs)
|
||||
|
||||
libKlayoutPath = bundleExecPathAbs + '../Frameworks'
|
||||
depdict = WalkFrameworkPaths(libKlayoutPath, filter_regex=r'libklayout')
|
||||
PerformChanges(depdict, [(HBPython37FrameworkPath, appPythonFrameworkPath, False)], bundleExecPathAbs)
|
||||
PerformChanges(depdict, [(HBPython38FrameworkPath, appPythonFrameworkPath, False)], bundleExecPathAbs)
|
||||
|
||||
print(" [9.4] Patching site.py, pip/, and distutils/")
|
||||
site_module = "%s/Versions/3.7/lib/python3.7/site.py" % pythonFrameworkPath
|
||||
site_module = "%s/Versions/%s/lib/python%s/site.py" % (pythonFrameworkPath, pythonHBVer, pythonHBVer)
|
||||
with open(site_module, 'r') as site:
|
||||
buf = site.readlines()
|
||||
with open(site_module, 'w') as site:
|
||||
import re
|
||||
for line in buf:
|
||||
# This will fool pip into thinking it's inside a virtual environment
|
||||
# and install new packates to the correct site-packages
|
||||
# and install new packages to the correct site-packages
|
||||
if re.match("^PREFIXES", line) is not None:
|
||||
line = line + "sys.real_prefix = sys.prefix\n"
|
||||
# do not allow installation in the user folder.
|
||||
|
|
@ -1029,7 +1039,24 @@ def DeployBinariesForBundle():
|
|||
line = "ENABLE_USER_SITE = False\n"
|
||||
site.write(line)
|
||||
|
||||
pip_module = "%s/Versions/3.7/lib/python3.7/site-packages/pip/__init__.py" % pythonFrameworkPath
|
||||
#----------------------------------------------------------------------------------
|
||||
# Typical usage of 'pip' after installation of the DMG package
|
||||
#
|
||||
# $ /Applications/klayout.app/Contents/MacOS/start-console.py
|
||||
# Warning: Populating font family aliases took 195 ms. Replace uses of missing font\
|
||||
# family "Monospace" with one that exists to avoid this cost.
|
||||
# Python 3.7.8 (default, Jul 4 2020, 10:17:17)
|
||||
# [Clang 11.0.3 (clang-1103.0.32.62)] on darwin
|
||||
# Type "help", "copyright", "credits" or "license" for more information.
|
||||
# (KLayout Python Console)
|
||||
# >>> import pip
|
||||
# >>> pip.main( ['install', 'numpy'] )
|
||||
# >>> pip.main( ['install', 'scipy'] )
|
||||
# >>> pip.main( ['install', 'pandas'] )
|
||||
# >>> pip.main( ['install', 'matplotlib'] )
|
||||
#----------------------------------------------------------------------------------
|
||||
pip_module = "%s/Versions/%s/lib/python%s/site-packages/pip/__init__.py" % \
|
||||
(pythonFrameworkPath, pythonHBVer, pythonHBVer)
|
||||
with open(pip_module, 'r') as pip:
|
||||
buf = pip.readlines()
|
||||
with open(pip_module, 'w') as pip:
|
||||
|
|
@ -1039,7 +1066,8 @@ def DeployBinariesForBundle():
|
|||
line = re.sub("return isolated$", "return isolated or True", line)
|
||||
pip.write(line)
|
||||
|
||||
distutilsconfig = "%s/Versions/3.7/lib/python3.7/distutils/distutils.cfg" % pythonFrameworkPath
|
||||
distutilsconfig = "%s/Versions/%s/lib/python%s/distutils/distutils.cfg" % \
|
||||
(pythonFrameworkPath, pythonHBVer, pythonHBVer)
|
||||
with open(distutilsconfig, 'r') as file:
|
||||
buf = file.readlines()
|
||||
with open(distutilsconfig, 'w') as file:
|
||||
|
|
@ -1051,7 +1079,7 @@ def DeployBinariesForBundle():
|
|||
file.write(line)
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# [10] Special deployment of Ruby2.6 from Homebrew?
|
||||
# [10] Special deployment of Ruby2.7 from Homebrew?
|
||||
#-------------------------------------------------------------
|
||||
deploymentRuby26HB = (ModuleRuby == 'Ruby27Brew')
|
||||
if deploymentRuby26HB and NonOSStdLang:
|
||||
|
|
@ -1059,7 +1087,7 @@ def DeployBinariesForBundle():
|
|||
print( "" )
|
||||
print( " [10] You have reached optional deployment of Ruby from %s ..." % HBRuby27Path )
|
||||
print( " [!!!] Sorry, the deployed package will not work properly since deployment of" )
|
||||
print( " Ruby2.6 from Homebrew is not yet supported." )
|
||||
print( " Ruby2.7 from Homebrew is not yet supported." )
|
||||
print( " Since you have Homebrew development environment, there two options:" )
|
||||
print( " (1) Retry to make a package with '-Y|--DEPLOY' option." )
|
||||
print( " This will not deploy any of Qt5, Python, and Ruby from Homebrew." )
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ RubyDictionary = { 'nil' : None,
|
|||
#-----------------------------------------------------
|
||||
PythonNil = [ 'nil' ]
|
||||
PythonSys = [ 'PythonElCapitan', 'PythonSierra', 'PythonHighSierra', 'PythonMojave', 'PythonCatalina' ]
|
||||
PythonExt = [ 'Python37MacPorts', 'Python37Brew', 'PythonAnaconda3' ]
|
||||
PythonExt = [ 'Python38MacPorts', 'Python38Brew', 'PythonAnaconda3' ]
|
||||
Pythons = PythonNil + PythonSys + PythonExt
|
||||
|
||||
#-----------------------------------------------------
|
||||
|
|
@ -204,30 +204,30 @@ PythonCatalina = { 'exe': '/System/Library/Frameworks/Python.framework/Versions
|
|||
'lib': '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib'
|
||||
}
|
||||
|
||||
# Python 3.7 from MacPorts (https://www.macports.org/) *+*+*+ EXPERIMENTAL *+*+*+
|
||||
# install with 'sudo port install python37'
|
||||
# [Key Type Name] = 'MP37'
|
||||
Python37MacPorts= { 'exe': '/opt/local/Library/Frameworks/Python.framework/Versions/3.7/bin/python3.7m',
|
||||
'inc': '/opt/local/Library/Frameworks/Python.framework/Versions/3.7/include/python3.7m',
|
||||
'lib': '/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/libpython3.7m.dylib'
|
||||
# Python 3.8 from MacPorts (https://www.macports.org/) *+*+*+ EXPERIMENTAL *+*+*+
|
||||
# install with 'sudo port install python38'
|
||||
# [Key Type Name] = 'MP38'
|
||||
Python38MacPorts= { 'exe': '/opt/local/Library/Frameworks/Python.framework/Versions/3.8/bin/python3.8',
|
||||
'inc': '/opt/local/Library/Frameworks/Python.framework/Versions/3.8/include/python3.8',
|
||||
'lib': '/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/libpython3.8.dylib'
|
||||
}
|
||||
|
||||
# Python 3.7 from Homebrew *+*+*+ EXPERIMENTAL *+*+*+
|
||||
# Python 3.8 from Homebrew *+*+*+ EXPERIMENTAL *+*+*+
|
||||
# install with 'brew install python'
|
||||
# [Key Type Name] = 'HB37'
|
||||
HBPython37FrameworkPath = '/usr/local/opt/python3/Frameworks/Python.framework'
|
||||
Python37Brew = { 'exe': '%s/Versions/3.7/bin/python3.7m' % HBPython37FrameworkPath,
|
||||
'inc': '%s/Versions/3.7/include/python3.7m' % HBPython37FrameworkPath,
|
||||
'lib': '%s/Versions/3.7/lib/libpython3.7m.dylib' % HBPython37FrameworkPath
|
||||
# [Key Type Name] = 'HB38'
|
||||
HBPython38FrameworkPath = '/usr/local/opt/python3/Frameworks/Python.framework'
|
||||
Python38Brew = { 'exe': '%s/Versions/3.8/bin/python3.8' % HBPython38FrameworkPath,
|
||||
'inc': '%s/Versions/3.8/include/python3.8' % HBPython38FrameworkPath,
|
||||
'lib': '%s/Versions/3.8/lib/libpython3.8.dylib' % HBPython38FrameworkPath
|
||||
}
|
||||
|
||||
# Python 3.7 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/.
|
||||
# If so, you need to make a symbolic link: /Applications/anaconda3 ---> $HOME/opt/anaconda3/
|
||||
# [Key Type Name] = 'Ana3'
|
||||
PythonAnaconda3 = { 'exe': '/Applications/anaconda3/bin/python3.7m',
|
||||
'inc': '/Applications/anaconda3/include/python3.7m',
|
||||
'lib': '/Applications/anaconda3/lib/libpython3.7m.dylib'
|
||||
PythonAnaconda3 = { 'exe': '/Applications/anaconda3/bin/python3.8',
|
||||
'inc': '/Applications/anaconda3/include/python3.8',
|
||||
'lib': '/Applications/anaconda3/lib/libpython3.8.dylib'
|
||||
}
|
||||
|
||||
# Consolidated dictionary kit for Python
|
||||
|
|
@ -237,8 +237,8 @@ PythonDictionary= { 'nil' : None,
|
|||
'PythonHighSierra': PythonHighSierra,
|
||||
'PythonMojave' : PythonMojave,
|
||||
'PythonCatalina' : PythonCatalina,
|
||||
'Python37MacPorts': Python37MacPorts,
|
||||
'Python37Brew' : Python37Brew,
|
||||
'Python38MacPorts': Python38MacPorts,
|
||||
'Python38Brew' : Python38Brew,
|
||||
'PythonAnaconda3' : PythonAnaconda3
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#! /usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#===============================================================================
|
||||
#========================================================================================
|
||||
# File: "macbuild/build4mac_util.py"
|
||||
#
|
||||
# Here are utility functions and classes ...
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
# version 0.26.1 or later on different Apple Mac OSX platforms.
|
||||
#
|
||||
# This file is imported by 'build4mac.py' script.
|
||||
#===============================================================================
|
||||
#========================================================================================
|
||||
from __future__ import print_function # to use print() of Python 3 in Python >= 2.7
|
||||
import sys
|
||||
import os
|
||||
|
|
@ -18,14 +18,14 @@ import string
|
|||
import subprocess
|
||||
import shutil
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------
|
||||
## To import global dictionaries of different modules
|
||||
#-------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------
|
||||
mydir = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.append( mydir )
|
||||
from build4mac_env import *
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------
|
||||
## To decompose strings obtained by 'otool -L <*.dylib>' command and to
|
||||
# generate a dictionary of KLayout's inter-library dependency.
|
||||
#
|
||||
|
|
@ -41,7 +41,7 @@ from build4mac_env import *
|
|||
# :
|
||||
#
|
||||
# @return a dictionary
|
||||
#------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------
|
||||
def DecomposeLibraryDependency( depstr ):
|
||||
alllines = depstr.split('\n')
|
||||
numlines = len(alllines)
|
||||
|
|
@ -53,13 +53,13 @@ def DecomposeLibraryDependency( depstr ):
|
|||
supporters.append(supporter)
|
||||
return { dependent: supporters }
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------
|
||||
## To print the contents of a library dependency dictionary
|
||||
#
|
||||
# @param[in] depdic dictionary
|
||||
# @param[in] pathdic path dictionary
|
||||
# @param[in] namedic dictionary name
|
||||
#------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------
|
||||
def PrintLibraryDependencyDictionary( depdic, pathdic, namedic ):
|
||||
keys = depdic.keys()
|
||||
print("")
|
||||
|
|
@ -73,13 +73,13 @@ def PrintLibraryDependencyDictionary( depdic, pathdic, namedic ):
|
|||
if itemName != keyName and (itemName in pathdic):
|
||||
print( " %s (%s)" % (item, pathdic[itemName]) )
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------
|
||||
## To set and change identification name of KLayout's dylib
|
||||
#
|
||||
# @param[in] libdic inter-library dependency dictionary
|
||||
#
|
||||
# @return 0 on success; non-zero on failure
|
||||
#------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------
|
||||
def SetChangeIdentificationNameOfDyLib( libdic, pathDic ):
|
||||
cmdNameId = XcodeToolChain['nameID']
|
||||
cmdNameChg = XcodeToolChain['nameCH']
|
||||
|
|
@ -115,7 +115,7 @@ def SetChangeIdentificationNameOfDyLib( libdic, pathDic ):
|
|||
# for-lib
|
||||
return 0
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------
|
||||
## To set the identification names of KLayout's libraries to an executable
|
||||
# and make the application aware of the library locations
|
||||
#
|
||||
|
|
@ -146,7 +146,7 @@ def SetChangeIdentificationNameOfDyLib( libdic, pathDic ):
|
|||
# +-- 'strmxor'
|
||||
#
|
||||
# @return 0 on success; non-zero on failure
|
||||
#------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------
|
||||
def SetChangeLibIdentificationName( executable, relativedir ):
|
||||
cmdNameId = XcodeToolChain['nameID']
|
||||
cmdNameChg = XcodeToolChain['nameCH']
|
||||
|
|
@ -181,15 +181,21 @@ def SetChangeLibIdentificationName( executable, relativedir ):
|
|||
# for-lib
|
||||
return 0
|
||||
|
||||
def WalkLibDependencyTree( dylibPath, depth=0, filter_regex=r'\t+/usr/local/opt'):
|
||||
NOTHINGTODO = [] # return empty list if nothing to do.
|
||||
cmdNameId = XcodeToolChain['nameID']
|
||||
cmdNameChg = XcodeToolChain['nameCH']
|
||||
otoolCm = 'otool -L %s | grep -E "%s"' % (dylibPath, filter_regex)
|
||||
otoolOut = os.popen( otoolCm ).read()
|
||||
exedepdic = DecomposeLibraryDependency( dylibPath + ":\n" + otoolOut )
|
||||
keys = exedepdic.keys()
|
||||
deplibs = exedepdic[ list(keys)[0] ]
|
||||
#----------------------------------------------------------------------------------------
|
||||
## To make a library dependency dictionary by recursively walk down the lib hierarchy
|
||||
#
|
||||
# @param[in] dylibPath: dylib path
|
||||
# @param[in] depth: hierarchy depth (< 5)
|
||||
# @param[in] filter_regex: filter regular expression
|
||||
#
|
||||
# @return a dictionary
|
||||
#----------------------------------------------------------------------------------------
|
||||
def WalkLibDependencyTree( dylibPath, depth=0, filter_regex=r'\t+/usr/local/opt' ):
|
||||
otoolCm = 'otool -L %s | grep -E "%s"' % (dylibPath, filter_regex)
|
||||
otoolOut = os.popen( otoolCm ).read()
|
||||
exedepdic = DecomposeLibraryDependency( dylibPath + ":\n" + otoolOut )
|
||||
keys = exedepdic.keys()
|
||||
deplibs = exedepdic[ list(keys)[0] ]
|
||||
|
||||
if depth < 5:
|
||||
if len(deplibs) > 0:
|
||||
|
|
@ -201,9 +207,19 @@ def WalkLibDependencyTree( dylibPath, depth=0, filter_regex=r'\t+/usr/local/opt'
|
|||
return deplibs
|
||||
return exedepdic
|
||||
else:
|
||||
raise RuntimeError("Exceeded maximum recursion depth.")
|
||||
raise RuntimeError( "Exceeded maximum recursion depth." )
|
||||
|
||||
def WalkFrameworkPaths(frameworkPaths, filter_regex=r'\.(so|dylib)$', search_path_filter=r'\t+/usr/local/opt'):
|
||||
#----------------------------------------------------------------------------------------
|
||||
## To make a library dependency dictionary by recursively walk down the Framework
|
||||
#
|
||||
# @param[in] frameworkPaths: Framework path
|
||||
# @param[in] filter_regex: filter regular expression
|
||||
# @param[in] search_path_filter: search path filter regular expression
|
||||
#
|
||||
# @return a dictionary
|
||||
#----------------------------------------------------------------------------------------
|
||||
def WalkFrameworkPaths( frameworkPaths, filter_regex=r'\.(so|dylib)$',
|
||||
search_path_filter=r'\t+/usr/local/opt' ):
|
||||
|
||||
if isinstance(frameworkPaths, str):
|
||||
frameworkPathsIter = [frameworkPaths]
|
||||
|
|
@ -225,7 +241,15 @@ def WalkFrameworkPaths(frameworkPaths, filter_regex=r'\.(so|dylib)$', search_pat
|
|||
dependency_dict[frameworkPath].append(dict_file)
|
||||
return dependency_dict
|
||||
|
||||
def WalkDictTree(dependencyDict, visited_files):
|
||||
#----------------------------------------------------------------------------------------
|
||||
## To make a list of changed libraries
|
||||
#
|
||||
# @param[in] dependencyDict: library dependency dictionary
|
||||
# @param[in] visited_files: list of visited files
|
||||
#
|
||||
# @return a list
|
||||
#----------------------------------------------------------------------------------------
|
||||
def WalkDictTree( dependencyDict, visited_files ):
|
||||
libNameChanges = list()
|
||||
for lib, dependencies in dependencyDict.items():
|
||||
if lib in visited_files:
|
||||
|
|
@ -253,31 +277,69 @@ def WalkDictTree(dependencyDict, visited_files):
|
|||
visited_files.append(lib)
|
||||
return libNameChanges
|
||||
|
||||
|
||||
def FindFramework(path, root_path):
|
||||
#----------------------------------------------------------------------------------------
|
||||
## To find the Framework name from a library name
|
||||
#
|
||||
# @param[in] path: path to a library
|
||||
# @param[in] root_path: root path
|
||||
#
|
||||
# @return the path to a Framework
|
||||
#----------------------------------------------------------------------------------------
|
||||
def FindFramework( path, root_path ):
|
||||
relPath = os.path.relpath(path, root_path)
|
||||
return os.path.join(root_path, relPath.split(os.sep)[0])
|
||||
def ResolveExecutablePath(path, executable_path):
|
||||
frmPath = os.path.join(root_path, relPath.split(os.sep)[0])
|
||||
#print( "###", frmPath, path, root_path )
|
||||
return frmPath
|
||||
|
||||
#----------------------------------------------------------------------------------------
|
||||
## To resolve an executable path
|
||||
#
|
||||
# @param[in] path: a path to resolve
|
||||
# @param[in] executable_path: an executable path
|
||||
#
|
||||
# @return the resolved path
|
||||
#----------------------------------------------------------------------------------------
|
||||
def ResolveExecutablePath( path, executable_path ):
|
||||
""" Transforms @executable_path into executable_path"""
|
||||
p = path.replace("@executable_path", "/%s/" % executable_path)
|
||||
return p
|
||||
|
||||
#----------------------------------------------------------------------------------------
|
||||
## To detect the changed library names
|
||||
#
|
||||
# @param[in] frameworkDependencyDict: framework dependency dictionary
|
||||
#
|
||||
# @return a list of changes, each of which is stored in the form of
|
||||
# * ('lib.dylib', ['dep1.dylib', ...])
|
||||
# OR
|
||||
# * ('lib.dylib',)
|
||||
#----------------------------------------------------------------------------------------
|
||||
def DetectChanges(frameworkDependencyDict):
|
||||
visited_files = list()
|
||||
libNameChanges = list()
|
||||
for framework, libraries in frameworkDependencyDict.items():
|
||||
for libraryDict in libraries:
|
||||
libNameChanges.extend(WalkDictTree(libraryDict, visited_files))
|
||||
# Changes are stored in libNameChanges in the form of ('lib.dylib', ['dep1.dylib', ...])
|
||||
|
||||
return libNameChanges
|
||||
|
||||
def PerformChanges(frameworkDependencyDict, replaceFromToPairs=None, executable_path="/tmp/klayout"):
|
||||
#----------------------------------------------------------------------------------------
|
||||
## To perform the required changes
|
||||
#
|
||||
# @param[in] frameworkDependencyDict: framework dependency dictionary
|
||||
# @param[in] replaceFromToPairs: (from, to)-pair for replacement
|
||||
# @param[in] executable_path: executable path
|
||||
#
|
||||
# @return 0 on success; > 0 on failure
|
||||
#----------------------------------------------------------------------------------------
|
||||
def PerformChanges( frameworkDependencyDict, replaceFromToPairs=None, executable_path="/tmp/klayout" ):
|
||||
libNameChanges = DetectChanges(frameworkDependencyDict)
|
||||
cmdNameId = XcodeToolChain['nameID']
|
||||
#print(libNameChanges)
|
||||
cmdNameId = XcodeToolChain['nameID']
|
||||
cmdNameChg = XcodeToolChain['nameCH']
|
||||
|
||||
if replaceFromToPairs is not None:
|
||||
if replaceFromToPairs is None:
|
||||
return 0
|
||||
else:
|
||||
for libNameChange in libNameChanges:
|
||||
libNameChangeIterator = iter(libNameChange)
|
||||
lib = next(libNameChangeIterator)
|
||||
|
|
@ -300,8 +362,8 @@ def PerformChanges(frameworkDependencyDict, replaceFromToPairs=None, executable_
|
|||
destFrameworkPath = ResolveExecutablePath(destFrameworkPath, executable_path)
|
||||
|
||||
if not os.path.exists(fileName):
|
||||
print (lib.replace(replaceFrom, replaceTo), "DOES NOT EXIST")
|
||||
print ("COPY", frameworkPath, " -> ", destFrameworkPath)
|
||||
print( " NOT FOUND:", lib.replace(replaceFrom, replaceTo) )
|
||||
print( " COPYING:", frameworkPath, " -> ", destFrameworkPath )
|
||||
shutil.copytree(frameworkPath, destFrameworkPath)
|
||||
|
||||
nameId = lib.replace(replaceFrom, replaceTo)
|
||||
|
|
@ -316,8 +378,8 @@ def PerformChanges(frameworkDependencyDict, replaceFromToPairs=None, executable_
|
|||
|
||||
for dependency in dependencies:
|
||||
if dependency.find(replaceFrom) >= 0:
|
||||
print("\tIn:", fileName)
|
||||
print("\tRENAME", dependency, " -> ", dependency.replace(replaceFrom, replaceTo))
|
||||
print( " IN:", fileName )
|
||||
print( " RENAMING:", dependency, " -> ", dependency.replace(replaceFrom, replaceTo) )
|
||||
|
||||
# Try changing id first
|
||||
nameId = dependency.replace(replaceFrom, replaceTo)
|
||||
|
|
@ -342,15 +404,15 @@ def PerformChanges(frameworkDependencyDict, replaceFromToPairs=None, executable_
|
|||
msg = "!!! Failed to set the new identification name to <%s> !!!"
|
||||
print( msg % fileName, file=sys.stderr )
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------
|
||||
## To get KLayout's version from a file; most likely from 'version.sh'
|
||||
#
|
||||
# @param[in] verfile version file from which version is retrieved
|
||||
#
|
||||
# @return version string
|
||||
#------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------
|
||||
def GetKLayoutVersionFrom( verfile='version.h' ):
|
||||
version = "?.?.?"
|
||||
try:
|
||||
|
|
@ -372,14 +434,14 @@ def GetKLayoutVersionFrom( verfile='version.h' ):
|
|||
return version
|
||||
return version
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------
|
||||
## To generate the contents of "Info.plist" file from a template
|
||||
#
|
||||
# @param[in] keydic dictionary of four key words ['exe', 'icon', 'bname', 'ver']
|
||||
# @param[in] templfile template file ("macbuild/Resources/Info.plist.template")
|
||||
#
|
||||
# @return generated strings
|
||||
#------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------
|
||||
def GenerateInfoPlist( keydic, templfile ):
|
||||
val_exe = keydic['exe']
|
||||
val_icon = keydic['icon']
|
||||
|
|
|
|||
|
|
@ -0,0 +1,278 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#===============================================================================
|
||||
# File: "macbuild/macQAT.py"
|
||||
#
|
||||
# The top Python script to run "ut_runner" after building KLayout
|
||||
# (http://www.klayout.de/index.php) version 0.26.1 or later on different Apple
|
||||
# ßMac OSX platforms.
|
||||
#
|
||||
# This script must be copied to a "*.macQAT/" directory to run.
|
||||
#===============================================================================
|
||||
from __future__ import print_function # to use print() of Python 3 in Python >= 2.7
|
||||
import sys
|
||||
import os
|
||||
import datetime
|
||||
from time import sleep
|
||||
import six
|
||||
import shutil
|
||||
import glob
|
||||
import platform
|
||||
import optparse
|
||||
import subprocess
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
## To set global variables including present directory and platform info.
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
def SetGlobals():
|
||||
global ProjectDir # project directory where "ut_runner" exists
|
||||
global RunnerUsage # True to print the usage of 'ut_runner'
|
||||
global Run # True to run this script
|
||||
global ContinueOnError # True to continue after an error
|
||||
global TestsExcluded # list of tests to exclude
|
||||
global Arguments # other arguments
|
||||
global GitSHA1 # Git's short SHA1 value of the HEAD
|
||||
global TimeStamp # time stamp
|
||||
global WorkDir # work directory name
|
||||
global LogFile # log file name
|
||||
global Usage # string on usage
|
||||
# auxiliary variables on platform
|
||||
global System # 6-tuple from platform.uname()
|
||||
global Node # - do -
|
||||
global Release # - do -
|
||||
global Version # - do -
|
||||
global Machine # - do -
|
||||
global Processor # - do -
|
||||
global Bit # machine bit-size
|
||||
|
||||
Usage = "\n"
|
||||
Usage += "----------------------------------------------------------------------------------------\n"
|
||||
Usage += "<< Usage of 'macQAT.py' >>\n"
|
||||
Usage += " for running 'ut_runner' after building KLayout.\n"
|
||||
Usage += "\n"
|
||||
Usage += "$ [python] ./macQAT.py \n"
|
||||
Usage += " option & argument : descriptions | default value\n"
|
||||
Usage += " -----------------------------------------------------------------+---------------\n"
|
||||
Usage += " [-u|--usage] : print usage of 'ut_runner'and exit | disabled \n"
|
||||
Usage += " | \n"
|
||||
Usage += " <-r|--run> : run this script | disabled \n"
|
||||
Usage += " [-s|--stop] : stop on error | disabled \n"
|
||||
Usage += " [-x|--exclude <tests>] : exclude test(s) such as 'pymod,pya' | '' \n"
|
||||
Usage += " [-a|--args <string>] : arguments other than '-x' and '-c' | '' \n"
|
||||
Usage += " [-?|--?] : print this usage and exit | disabled \n"
|
||||
Usage += "--------------------------------------------------------------------+-------------------\n"
|
||||
|
||||
ProjectDir = os.getcwd()
|
||||
RunnerUsage = False
|
||||
Run = False
|
||||
ContinueOnError = True
|
||||
TestsExcluded = list()
|
||||
Arguments = ""
|
||||
GitSHA1 = GetGitShortSHA1()
|
||||
TimeStamp = GetTimeStamp()
|
||||
WorkDir = "QATest_%s_%s__%s" % (GitSHA1, TimeStamp, os.path.basename(ProjectDir) )
|
||||
LogFile = WorkDir + ".log"
|
||||
|
||||
(System, Node, Release, Version, Machine, Processor) = platform.uname()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
## Get git's short SHA1 value of the HEAD
|
||||
#
|
||||
# @return SHA1 value string
|
||||
#-------------------------------------------------------------------------------
|
||||
def GetGitShortSHA1():
|
||||
command = "git rev-parse --short HEAD 2>/dev/null"
|
||||
sha1val = os.popen( command ).read().strip()
|
||||
return sha1val
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
## Get the time stamp
|
||||
#
|
||||
# @return time stamp string
|
||||
#-------------------------------------------------------------------------------
|
||||
def GetTimeStamp():
|
||||
ts = datetime.datetime.today()
|
||||
return "%04d_%02d%02d_%02d%02d" % (ts.year, ts.month, ts.day, ts.hour, ts.minute)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
## To parse the command line arguments
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
def ParseCommandLineArguments():
|
||||
global Usage
|
||||
global RunnerUsage
|
||||
global Run
|
||||
global ContinueOnError
|
||||
global TestsExcluded
|
||||
global Arguments
|
||||
|
||||
p = optparse.OptionParser( usage=Usage )
|
||||
p.add_option( '-u', '--usage',
|
||||
action='store_true',
|
||||
dest='runner_usage',
|
||||
default=False,
|
||||
help="print usage of 'ut_runner' and exit (false)" )
|
||||
|
||||
p.add_option( '-r', '--run',
|
||||
action='store_true',
|
||||
dest='runme',
|
||||
default=False,
|
||||
help='run this script (false)' )
|
||||
|
||||
p.add_option( '-s', '--stop',
|
||||
action='store_true',
|
||||
dest='stop_on_error',
|
||||
default=False,
|
||||
help='stop on error (false)' )
|
||||
|
||||
p.add_option( '-x', '--exclude',
|
||||
dest='exclude_tests',
|
||||
help="exclude test(s) such as 'pymod,pya' ('')" )
|
||||
|
||||
p.add_option( '-a', '--args',
|
||||
dest='arguments',
|
||||
help="arguments other than '-x' and '-c' ('')" )
|
||||
|
||||
p.add_option( '-?', '--??',
|
||||
action='store_true',
|
||||
dest='checkusage',
|
||||
default=False,
|
||||
help='check usage (false)' )
|
||||
|
||||
p.set_defaults( runner_usage = False,
|
||||
runme = False,
|
||||
stop_on_error = False,
|
||||
exclude_tests = "",
|
||||
arguments = "",
|
||||
checkusage = False )
|
||||
|
||||
opt, args = p.parse_args()
|
||||
if opt.checkusage:
|
||||
print(Usage)
|
||||
quit()
|
||||
|
||||
RunnerUsage = opt.runner_usage
|
||||
Run = opt.runme
|
||||
ContinueOnError = not opt.stop_on_error
|
||||
if not opt.exclude_tests == "":
|
||||
TestsExcluded = [ item.strip() for item in opt.exclude_tests.split(',') ]
|
||||
else:
|
||||
TestsExcluded = []
|
||||
Arguments = opt.arguments
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
## Hide/Show the private directory
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
def HidePrivateDir():
|
||||
if os.path.isdir( "../private" ):
|
||||
os.rename( "../private", "../private.stash" )
|
||||
|
||||
def ShowPrivateDir():
|
||||
if os.path.isdir( "../private.stash" ):
|
||||
os.rename( "../private.stash", "../private" )
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
## Export environment variables for "ut_runner"
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
def ExportEnvVariables():
|
||||
global ProjectDir
|
||||
global WorkDir
|
||||
global MyEnviron # my environment variables; can be independently used later
|
||||
|
||||
# In older versions of subprocess module, 'env=None' argument is not provided
|
||||
MyEnviron = os.environ.copy()
|
||||
MyEnviron[ 'TESTSRC' ] = ".."
|
||||
MyEnviron[ 'TESTTMP' ] = WorkDir
|
||||
if System == "Darwin":
|
||||
MyEnviron[ 'DYLD_LIBRARY_PATH' ] = "%s:%s/db_plugins" % (ProjectDir, ProjectDir)
|
||||
for env in [ 'TESTSRC', 'TESTTMP', 'DYLD_LIBRARY_PATH' ]:
|
||||
os.environ[env] = MyEnviron[env]
|
||||
else:
|
||||
MyEnviron[ 'LD_LIBRARY_PATH' ] = "%s:%s/db_plugins" % (ProjectDir, ProjectDir)
|
||||
for env in [ 'TESTSRC', 'TESTTMP', 'LD_LIBRARY_PATH' ]:
|
||||
os.environ[env] = MyEnviron[env]
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
## Run the tester
|
||||
#
|
||||
# @param[in] command command string to run
|
||||
# @param[in] logfile log file name
|
||||
#-------------------------------------------------------------------------------
|
||||
def RunTester( command, logfile="" ):
|
||||
if six.PY3:
|
||||
proc = subprocess.Popen( command.split(), stdout=subprocess.PIPE, \
|
||||
stderr=subprocess.STDOUT, \
|
||||
universal_newlines=True )
|
||||
else:
|
||||
proc = subprocess.Popen( command.split(), stdout=subprocess.PIPE, \
|
||||
stderr=subprocess.STDOUT )
|
||||
|
||||
if not logfile == "":
|
||||
with proc.stdout, open( logfile, 'w' ) as file:
|
||||
for line in proc.stdout:
|
||||
sys.stdout.write(line)
|
||||
file.write(line)
|
||||
proc.wait()
|
||||
else:
|
||||
with proc.stdout:
|
||||
for line in proc.stdout:
|
||||
sys.stdout.write(line)
|
||||
proc.wait()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Main function
|
||||
#-------------------------------------------------------------------------------
|
||||
def Main():
|
||||
#-------------------------------------------------------
|
||||
# [1] Initialize
|
||||
#-------------------------------------------------------
|
||||
SetGlobals()
|
||||
ParseCommandLineArguments()
|
||||
ExportEnvVariables()
|
||||
|
||||
#-------------------------------------------------------
|
||||
# [2] Print the runner's usage
|
||||
#-------------------------------------------------------
|
||||
if RunnerUsage:
|
||||
command = './ut_runner --help-all'
|
||||
RunTester( command )
|
||||
quit()
|
||||
|
||||
#-------------------------------------------------------
|
||||
# [3] Run the unit tester
|
||||
#-------------------------------------------------------
|
||||
if not Run:
|
||||
print( "! pass <-r|--run> option to run" )
|
||||
print(Usage)
|
||||
quit()
|
||||
|
||||
command = './ut_runner'
|
||||
if ContinueOnError:
|
||||
command += " -c"
|
||||
for item in TestsExcluded:
|
||||
command += ' -x %s' % item
|
||||
if not Arguments == "":
|
||||
command += " %s" % Arguments
|
||||
|
||||
print( "" )
|
||||
print( "### Dumping the log to <%s>" % LogFile )
|
||||
print( "------------------------------------------------------------" )
|
||||
print( " Git SHA1 = %s" % GitSHA1 )
|
||||
print( " Time stamp = %s" % TimeStamp )
|
||||
print( "------------------------------------------------------------" )
|
||||
sleep( 1.0 )
|
||||
HidePrivateDir()
|
||||
RunTester( command, logfile=LogFile )
|
||||
ShowPrivateDir()
|
||||
|
||||
#===================================================================================
|
||||
if __name__ == "__main__":
|
||||
Main()
|
||||
|
||||
#---------------
|
||||
# End of file
|
||||
#---------------
|
||||
|
|
@ -179,8 +179,8 @@ def SetGlobals():
|
|||
# The package directory name should look like:
|
||||
# * ST-qt5MP.pkg.macos-Catalina-release-RsysPsys --- (1)
|
||||
# * LW-qt5Ana3.pkg.macos-Catalina-release-Rana3Pana3
|
||||
# * LW-qt5Brew.pkg.macos-Catalina-release-Rhb26Phb37
|
||||
# * LW-qt5MP.pkg.macos-Catalina-release-Rmp26Pmp37
|
||||
# * LW-qt5Brew.pkg.macos-Catalina-release-Rhb26Phb38
|
||||
# * LW-qt5MP.pkg.macos-Catalina-release-Rmp26Pmp38
|
||||
#
|
||||
# Generated DMG will be, for example,
|
||||
# (1) ---> ST-klayout-0.26.1-macOS-Catalina-1-qt5MP-RsysPsys.dmg
|
||||
|
|
@ -221,9 +221,9 @@ def CheckPkgDirectory():
|
|||
#
|
||||
# * ST-qt5MP.pkg.macos-Catalina-release-RsysPsys
|
||||
# * LW-qt5Ana3.pkg.macos-Catalina-release-Rana3Pana3
|
||||
# * LW-qt5Brew.pkg.macos-Catalina-release-Rhb27Phb37
|
||||
# * HW-qt5Brew.pkg.macos-Catalina-release-RsysPhb37
|
||||
# * EX-qt5MP.pkg.macos-Catalina-release-Rmp26Pmp37
|
||||
# * LW-qt5Brew.pkg.macos-Catalina-release-Rhb27Phb38
|
||||
# * HW-qt5Brew.pkg.macos-Catalina-release-RsysPhb38
|
||||
# * EX-qt5MP.pkg.macos-Catalina-release-Rmp26Pmp38
|
||||
#-----------------------------------------------------------------------------
|
||||
patQRP = u'(ST|LW|HW|EX)([-])(qt5[0-9A-Za-z]+)([.]pkg[.])([A-Za-z]+[-][A-Za-z]+[-]release[-])([0-9A-Za-z]+)'
|
||||
regQRP = re.compile(patQRP)
|
||||
|
|
@ -243,12 +243,12 @@ def CheckPkgDirectory():
|
|||
LatestOSMacPorts = Platform == LatestOS
|
||||
LatestOSMacPorts &= PackagePrefix == "LW"
|
||||
LatestOSMacPorts &= QtIdentification == "qt5MP"
|
||||
LatestOSMacPorts &= RubyPythonID == "Rmp26Pmp37"
|
||||
LatestOSMacPorts &= RubyPythonID == "Rmp26Pmp38"
|
||||
|
||||
LatestOSHomebrew = Platform == LatestOS
|
||||
LatestOSHomebrew &= PackagePrefix == "LW"
|
||||
LatestOSHomebrew &= QtIdentification == "qt5Brew"
|
||||
LatestOSHomebrew &= RubyPythonID == "Rhb27Phb37"
|
||||
LatestOSHomebrew &= RubyPythonID == "Rhb27Phb38"
|
||||
|
||||
LatestOSAnaconda3 = Platform == LatestOS
|
||||
LatestOSAnaconda3 &= PackagePrefix == "LW"
|
||||
|
|
|
|||
Loading…
Reference in New Issue