Skip to content

Commit 192364e

Browse files
Merged #138 pull request to 0.26 too.
Merge commit '896f7347f0b2cf947492ff3cc5d708df1b81af29' into 0.26
2 parents 89e8fb0 + 896f734 commit 192364e

8 files changed

+278
-57
lines changed

macbuild/ReadMe.md

+3
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ Homebrew's installation of python3 (`brew install python3`) places a `Python.fra
9797
```
9898
# Build step
9999
./build4mac.py -p B36 -q Qt5Brew
100+
# build with log
101+
./build4mac.py -p B36 -q Qt5Brew 2>&1 | tee qt5.build.macos-HighSierra-release-version.log
102+
100103
101104
# Deploy step
102105
./build4mac.py -p B36 -q Qt5Brew -y # normal deploy

macbuild/Resources/klayout_console

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env bash
2+
if [ "$1" != "" ]; then
3+
/Applications/klayout.app/Contents/MacOS/klayout $1 -r /Applications/klayout.app/Contents/MacOS/start-console.py
4+
else
5+
/Applications/klayout.app/Contents/MacOS/klayout -z -r /Applications/klayout.app/Contents/MacOS/start-console.py
6+
fi

macbuild/Resources/start-console.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/Applications/klayout.app/Contents/MacOS/klayout -b -r
2+
import readline
3+
import code
4+
import sys
5+
import os
6+
pwd = os.getcwd()
7+
sys.path.append(pwd)
8+
9+
variables = globals().copy()
10+
variables.update(locals())
11+
shell = code.InteractiveConsole(variables)
12+
cprt = 'Type "help", "copyright", "credits" or "license" for more information.'
13+
banner = "Python %s on %s\n%s\n(%s)" % (sys.version, sys.platform,
14+
cprt, "KLayout Python Console")
15+
exit_msg = 'now exiting %s...' % "KLayout Python Console"
16+
shell.interact(banner, exit_msg)

macbuild/build4mac.py

+101-33
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#! /usr/bin/env python
1+
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
33

44
#===============================================================================
@@ -538,8 +538,8 @@ def DeployBinariesForBundle():
538538
if not DeploymentF and not DeploymentP:
539539
return 1
540540
if DeploymentF and NonOSStdLang:
541-
print( "WARNING!!! You chose <-y|--deploy> while using non-OS-standard script language.", file=sys.stderr )
542-
print( " Use <-Y|--DEPLOY> instead", file=sys.stderr )
541+
print( " WARNING!!! You chose <-y|--deploy> while using non-OS-standard script language.", file=sys.stderr )
542+
print( " Consider using <-Y|--DEPLOY> instead", file=sys.stderr )
543543
#return 1
544544
if not os.path.isfile(MacBuildLog):
545545
print( "!!! Build log file <%s> does not present !!!" % MacBuildLog, file=sys.stderr )
@@ -756,51 +756,119 @@ def DeployBinariesForBundle():
756756
os.chdir(ProjectDir)
757757
os.chdir(MacPkgDir)
758758
command = "%s %s %s" % ( deploytool, app_bundle, options )
759-
print(command)
760759
if subprocess.call( command, shell=True ) != 0:
761760
msg = "!!! Failed to deploy applications on OSX !!!"
762761
print( msg, file=sys.stderr )
763762
print("")
764763
os.chdir(ProjectDir)
765764
return 1
766765

767-
deploymentPython = False
768-
if deploymentPython:
769-
# TODO Code incomplete! To be finished.
770-
from macbuild.build4mac_util import WalkFrameworkPaths, PerformChanges, DetectChanges
771-
772-
bundlePath = 'qt5.pkg.macos-HighSierra-release/klayout.app'
773-
bundleExecPathAbs = os.getcwd() + '/%s/Contents/MacOS/' % bundlePath
774-
775-
# rsync -a --safe-links /usr/local/opt/python/Frameworks/Python.framework/ qt5.pkg.macos-HighSierra-release/klayout.app/Contents/Frameworks/Python.framework
776-
# cp -RL /usr/local/opt/python/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages qt5.pkg.macos-HighSierra-release/klayout.app/Contents/Frameworks/Python.framework/Versions/3.6/lib/python3.6/
777-
# rm -rf qt5.pkg.macos-HighSierra-release/klayout.app/Contents/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/test
766+
deploymentPython = True
767+
if deploymentPython and NonOSStdLang:
768+
from build4mac_util import WalkFrameworkPaths, PerformChanges, DetectChanges
769+
from pathlib import Path
778770

771+
bundlePath = AbsMacPkgDir + '/klayout.app'
772+
# bundlePath = os.getcwd() + '/qt5.pkg.macos-HighSierra-release/klayout.app'
773+
bundleExecPathAbs = '%s/Contents/MacOS/' % bundlePath
774+
pythonOriginalFrameworkPath = '/usr/local/opt/python/Frameworks/Python.framework'
779775
pythonFrameworkPath = '%s/Contents/Frameworks/Python.framework' % bundlePath
780-
depdict = WalkFrameworkPaths(pythonFrameworkPath)
781776

782-
pythonOriginalFrameworkPath = '/usr/local/opt/python/Frameworks/Python.framework'
777+
print(f" [8.1] Deploying Python from {pythonOriginalFrameworkPath} ..." )
778+
print(" [1] Copying Python Framework")
779+
shell_commands = list()
780+
shell_commands.append(f"rm -rf {pythonFrameworkPath}")
781+
shell_commands.append(f"rsync -a --safe-links {pythonOriginalFrameworkPath}/ {pythonFrameworkPath}")
782+
shell_commands.append(f"mkdir {pythonFrameworkPath}/Versions/3.6/lib/python3.6/site-packages/")
783+
shell_commands.append(f"cp -RL {pythonOriginalFrameworkPath}/Versions/3.6/lib/python3.6/site-packages/{{pip*,pkg_resources,setuptools*,wheel*}} " +
784+
f"{pythonFrameworkPath}/Versions/3.6/lib/python3.6/site-packages/")
785+
shell_commands.append(f"rm -rf {pythonFrameworkPath}/Versions/3.6/lib/python3.6/test")
786+
shell_commands.append(f"rm -rf {pythonFrameworkPath}/Versions/3.6/Resources")
787+
shell_commands.append(f"rm -rf {pythonFrameworkPath}/Versions/3.6/bin")
788+
789+
for command in shell_commands:
790+
if subprocess.call( command, shell=True ) != 0:
791+
msg = "command failed: %s"
792+
print( msg % command, file=sys.stderr )
793+
exit(1)
794+
795+
shutil.copy2( sourceDir2 + "/start-console.py", targetDirM )
796+
shutil.copy2( sourceDir2 + "/klayout_console", targetDirM )
797+
os.chmod( targetDirM + "/klayout_console", 0o0755 )
798+
799+
print(" [2] Relinking dylib dependencies inside Python.framework")
800+
print(" [2.1] Patching Python Framework")
801+
depdict = WalkFrameworkPaths(pythonFrameworkPath)
783802
appPythonFrameworkPath = '@executable_path/../Frameworks/Python.framework/'
784-
PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath)], bundleExecPathAbs)
785-
786-
klayoutPath = bundleExecPathAbs
787-
depdict = WalkFrameworkPaths(klayoutPath, filter_regex=r'klayout$')
788-
PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath)], bundleExecPathAbs)
789-
790-
klayoutPath = bundleExecPathAbs + '../Frameworks'
791-
depdict = WalkFrameworkPaths(klayoutPath, filter_regex=r'libklayout')
792-
PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath)], bundleExecPathAbs)
793-
803+
PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath, False)], bundleExecPathAbs)
794804

805+
print(" [2.2] Patching /usr/local/opt/ libs")
795806
usrLocalPath = '/usr/local/opt/'
796807
appUsrLocalPath = '@executable_path/../Frameworks/'
797-
depdict = WalkFrameworkPaths(pythonFrameworkPath)
798-
PerformChanges(depdict, [(usrLocalPath, appUsrLocalPath)], bundleExecPathAbs)
808+
replacePairs = [(usrLocalPath, appUsrLocalPath, True)]
809+
depdict = WalkFrameworkPaths(pythonFrameworkPath, search_path_filter=r'\t+/usr/local/(opt|Cellar)')
810+
PerformChanges(depdict, replacePairs, bundleExecPathAbs)
799811

800-
# usrLocalPath = '/usr/local/lib/'
801-
# appUsrLocalPath = '@executable_path/../Frameworks/'
802-
# depdict = WalkFrameworkPaths(pythonFrameworkPath)
803-
# PerformChanges(depdict, [(usrLocalPath, appUsrLocalPath)], bundleExecPathAbs)
812+
print(" [2.3] Patching openssl, gdbm, readline, sqlite, tcl-tk, xz")
813+
usrLocalPath = '/usr/local/opt'
814+
appUsrLocalPath = '@executable_path/../Frameworks/'
815+
replacePairs = [(usrLocalPath, appUsrLocalPath, True)]
816+
replacePairs.extend([(openssl_version, '@executable_path/../Frameworks/openssl', True)
817+
for openssl_version in list(Path('/usr/local/Cellar/openssl').glob('*'))])
818+
depdict = WalkFrameworkPaths([pythonFrameworkPath + '/../openssl',
819+
pythonFrameworkPath + '/../gdbm',
820+
pythonFrameworkPath + '/../readline',
821+
pythonFrameworkPath + '/../sqlite',
822+
pythonFrameworkPath + '/../tcl-tk',
823+
pythonFrameworkPath + '/../xz'], search_path_filter=r'\t+/usr/local/(opt|Cellar)')
824+
825+
PerformChanges(depdict, replacePairs, bundleExecPathAbs)
826+
827+
print(" [3] Relinking dylib dependencies for klayout")
828+
klayoutPath = bundleExecPathAbs
829+
depdict = WalkFrameworkPaths(klayoutPath, filter_regex=r'klayout$')
830+
PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath, False)], bundleExecPathAbs)
831+
832+
libKlayoutPath = bundleExecPathAbs + '../Frameworks'
833+
depdict = WalkFrameworkPaths(libKlayoutPath, filter_regex=r'libklayout')
834+
PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath, False)], bundleExecPathAbs)
835+
836+
print(" [4] Patching site.py, pip/, and distutils/")
837+
site_module = f"{pythonFrameworkPath}/Versions/3.6/lib/python3.6/site.py"
838+
with open(site_module, 'r') as site:
839+
buf = site.readlines()
840+
with open(site_module, 'w') as site:
841+
import re
842+
for line in buf:
843+
# This will fool pip into thinking it's inside a virtual environment
844+
# and install new packates to the correct site-packages
845+
if re.match("^PREFIXES", line) is not None:
846+
line = line + "sys.real_prefix = sys.prefix\n"
847+
# do not allow installation in the user folder.
848+
if re.match("^ENABLE_USER_SITE", line) is not None:
849+
line = "ENABLE_USER_SITE = False\n"
850+
site.write(line)
851+
852+
pip_module = f"{pythonFrameworkPath}/Versions/3.6/lib/python3.6/site-packages/pip/__init__.py"
853+
with open(pip_module, 'r') as pip:
854+
buf = pip.readlines()
855+
with open(pip_module, 'w') as pip:
856+
import re
857+
for line in buf:
858+
# this will reject user's configuration of pip, forcing the isolated mode
859+
line = re.sub("return isolated$", "return isolated or True", line)
860+
pip.write(line)
861+
862+
distutilsconfig = f"{pythonFrameworkPath}/Versions/3.6/lib/python3.6/distutils/distutils.cfg"
863+
with open(distutilsconfig, 'r') as file:
864+
buf = file.readlines()
865+
with open(distutilsconfig, 'w') as file:
866+
import re
867+
for line in buf:
868+
# This will cause all packages to be installed to sys.prefix
869+
if re.match('prefix=', line) is not None:
870+
continue
871+
file.write(line)
804872

805873
else:
806874
print( " [8] Skipped deploying Qt's Frameworks ..." )

macbuild/build4mac_util.py

+24-23
Original file line numberDiff line numberDiff line change
@@ -200,32 +200,32 @@ def WalkLibDependencyTree( dylibPath, depth=0, filter_regex=r'\t+/usr/local/opt'
200200
lib = str(Path(lib))
201201
if lib != list(keys)[0]:
202202
deplibs[idx] = WalkLibDependencyTree(lib, depth+1, filter_regex)
203-
else:
204-
return NOTHINGTODO
205203
if depth == 0:
206204
return deplibs
207205
return exedepdic
208206
else:
209207
raise RuntimeError("Exceeded maximum recursion depth.")
210208

211-
def WalkFrameworkPaths(frameworkPaths, filter_regex=r'\.(so|dylib)$'):
212-
try:
213-
frameworkPathsIter = iter(frameworkPaths)
214-
except TypeError:
209+
def WalkFrameworkPaths(frameworkPaths, filter_regex=r'\.(so|dylib)$', search_path_filter=r'\t+/usr/local/opt'):
210+
211+
if isinstance(frameworkPaths, str):
215212
frameworkPathsIter = [frameworkPaths]
213+
else:
214+
frameworkPathsIter = frameworkPaths
216215

217216
dependency_dict = dict()
218217

219-
for frameworkPath in frameworkPaths:
218+
for frameworkPath in frameworkPathsIter:
220219
frameworkPath = str(Path(frameworkPath))
220+
# print("Calling:", 'find %s -type f | grep -E "%s"' % (frameworkPath, filter_regex))
221221
find_grep_results = os.popen('find %s -type f | grep -E "%s"' % (frameworkPath, filter_regex)).read().split('\n')
222222
framework_files = filter(lambda x: x != '',
223223
map(lambda x: x.strip(),
224224
find_grep_results))
225225

226226
dependency_dict[frameworkPath] = list()
227227
for idx, file in enumerate(framework_files):
228-
dict_file = {file: WalkLibDependencyTree(file)}
228+
dict_file = {file: WalkLibDependencyTree(file, filter_regex=search_path_filter)}
229229
dependency_dict[frameworkPath].append(dict_file)
230230
return dependency_dict
231231

@@ -263,15 +263,12 @@ def FindFramework(path, root_path):
263263
relPath = path.relative_to(root_path)
264264
return str(root_path / relPath.parts[0])
265265

266-
def ReplaceExecutablePath(path, executable_path):
266+
def ResolveExecutablePath(path, executable_path):
267+
""" Transforms @executable_path into executable_path"""
267268
executable_path = str(executable_path)
268269
p = Path(str(path).replace("@executable_path", "/%s/" % executable_path))
269270
return p
270271

271-
def FileExists(file_path, executable_path):
272-
p = ReplaceExecutablePath(file_path, executable_path)
273-
return p.exists()
274-
275272
def DetectChanges(frameworkDependencyDict):
276273
visited_files = list()
277274
libNameChanges = list()
@@ -282,7 +279,7 @@ def DetectChanges(frameworkDependencyDict):
282279

283280
return libNameChanges
284281

285-
def PerformChanges(frameworkDependencyDict, replaceFromToPairs=None, executable_path="/tmp/klayout", libdir=False):
282+
def PerformChanges(frameworkDependencyDict, replaceFromToPairs=None, executable_path="/tmp/klayout"):
286283
libNameChanges = DetectChanges(frameworkDependencyDict)
287284
cmdNameId = XcodeToolChain['nameID']
288285
cmdNameChg = XcodeToolChain['nameCH']
@@ -295,45 +292,49 @@ def PerformChanges(frameworkDependencyDict, replaceFromToPairs=None, executable_
295292
dependencies = next(libNameChangeIterator)
296293
except StopIteration:
297294
dependencies = list()
298-
for replaceFrom, replaceTo in replaceFromToPairs:
295+
for replaceFrom, replaceTo, libdir in replaceFromToPairs:
299296
replaceFrom = str(Path(replaceFrom))
300297
replaceTo = str(Path(replaceTo))
301298

299+
fileName = ResolveExecutablePath(lib.replace(replaceFrom, replaceTo), executable_path)
300+
if str(fileName).startswith('/usr'):
301+
# print(f'skipping fileName: {fileName}')
302+
continue
303+
302304
if lib.find(replaceFrom) >= 0:
303305
if libdir:
304306
frameworkPath = FindFramework(lib, replaceFrom)
305307
else:
306308
frameworkPath = lib
307309
destFrameworkPath = frameworkPath.replace(replaceFrom, replaceTo)
308-
destFrameworkPath = ReplaceExecutablePath(destFrameworkPath, executable_path)
309-
if not FileExists(lib.replace(replaceFrom, replaceTo), executable_path):
310+
destFrameworkPath = ResolveExecutablePath(destFrameworkPath, executable_path)
311+
312+
if not fileName.exists():
310313
print (lib.replace(replaceFrom, replaceTo), "DOES NOT EXIST")
311314
print ("COPY", frameworkPath, " -> ", destFrameworkPath)
312315
shutil.copytree(frameworkPath, destFrameworkPath)
313316

314-
fileName = ReplaceExecutablePath(lib.replace(replaceFrom, replaceTo), executable_path)
315317
nameId = lib.replace(replaceFrom, replaceTo)
316318
command = "%s %s %s" % ( cmdNameId, nameId, fileName )
317319
if not os.access(fileName, os.W_OK):
318320
command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName)
319-
print("\t%s" % command)
321+
# print("\t%s" % command)
320322
if subprocess.call( command, shell=True ) != 0:
321323
msg = "!!! Failed to set the new identification name to <%s> !!!"
322324
print( msg % fileName, file=sys.stderr )
323325
return 1
324326

325-
fileName = ReplaceExecutablePath(lib.replace(replaceFrom, replaceTo), executable_path)
326327
for dependency in dependencies:
327328
if dependency.find(replaceFrom) >= 0:
328-
print("In:", fileName)
329+
print("\tIn:", fileName)
329330
print("\tRENAME", dependency, " -> ", dependency.replace(replaceFrom, replaceTo))
330331

331332
# Try changing id first
332333
nameId = dependency.replace(replaceFrom, replaceTo)
333334
command = "%s %s %s" % ( cmdNameId, nameId, fileName )
334335
if not os.access(fileName, os.W_OK):
335336
command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName)
336-
print("\t%s" % command)
337+
# print("\t%s" % command)
337338
if subprocess.call( command, shell=True ) != 0:
338339
msg = "!!! Failed to set the new identification name to <%s> !!!"
339340
print( msg % fileName, file=sys.stderr )
@@ -346,7 +347,7 @@ def PerformChanges(frameworkDependencyDict, replaceFromToPairs=None, executable_
346347
if not os.access(fileName, os.W_OK):
347348
command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName)
348349

349-
print("\t%s" % command)
350+
# print("\t%s" % command)
350351
if subprocess.call( command, shell=True ) != 0:
351352
msg = "!!! Failed to set the new identification name to <%s> !!!"
352353
print( msg % fileName, file=sys.stderr )

src/lay/lay/laySaltDownloadManager.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ ConfirmationDialog::add_info (const std::string &name, bool update, const std::s
6868
item->setText (3, tl::to_qstring (url));
6969

7070
for (int column = 0; column < list->colorCount (); ++column) {
71-
item->setData (column, Qt::ForegroundRole, QVariant (QBrush (update ? Qt::blue : Qt::black)));
71+
item->setData (column, Qt::ForegroundRole, QVariant (QBrush (update ? QColor (Qt::blue) : QColor (Qt::black))));
7272
}
7373
}
7474

0 commit comments

Comments
 (0)