Merge branch 'master' into lefdef

This commit is contained in:
Matthias Koefferlein 2020-12-14 21:38:55 +01:00
commit 6a9a024d64
42 changed files with 3169 additions and 2506 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

@ -162,37 +162,6 @@ matrix:
directories: directories:
- ccache - ccache
- name: "cp34-cp34m-manylinux1_x86_64.whl"
os: linux
sudo: true
language: python
python: '3.4'
services:
- docker
env:
- DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64"
- PY_VERSION="cp34-cp34m"
- DOCKER_BUILD=true
- TEST_IN_HOST=true
- MATRIX_EVAL=""
cache:
directories:
- ccache
- name: "cp34-cp34m-manylinux1_i686.whl"
os: linux
sudo: true
services:
- docker
env:
- DOCKER_IMAGE="quay.io/pypa/manylinux1_i686"
- PY_VERSION="cp34-cp34m"
- DOCKER_BUILD=true
- MATRIX_EVAL=""
cache:
directories:
- ccache
- name: "cp27-cp27mu-manylinux1_x86_64.whl" - name: "cp27-cp27mu-manylinux1_x86_64.whl"
os: linux os: linux
sudo: true sudo: true
@ -255,6 +224,229 @@ matrix:
directories: directories:
- ccache - ccache
# python 3 osx
# MacOS 10.15
# MacOS 10.15, Python 3.9
- name: "cp39-cp39m-macosx_10_15_x86_64.whl"
os: osx
osx_image: xcode12 # macOS 10.15
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.9
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.9/bin/python3'; alias pip='/usr/local/opt/python@3.9/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.15, Python 3.8
- name: "cp38-cp38m-macosx_10_15_x86_64.whl"
os: osx
osx_image: xcode12 # macOS 10.15
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.8
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.8/bin/python3'; alias pip='/usr/local/opt/python@3.8/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.15, Python 3.7
- name: "cp37-cp37m-macosx_10_15_x86_64.whl"
os: osx
osx_image: xcode12 # macOS 10.15
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.7
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.7/bin/python3'; alias pip='/usr/local/opt/python@3.7/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.14
# MacOS 10.14, Python 3.9
- name: "cp39-cp39m-macosx_10_14_x86_64.whl"
os: osx
osx_image: xcode11 # macOS 10.14
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.9
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.9/bin/python3'; alias pip='/usr/local/opt/python@3.9/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.14, Python 3.8
- name: "cp38-cp38m-macosx_10_14_x86_64.whl"
os: osx
osx_image: xcode11 # macOS 10.14
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.8
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.8/bin/python3'; alias pip='/usr/local/opt/python@3.8/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.14, Python 3.7
- name: "cp37-cp37m-macosx_10_14_x86_64.whl"
os: osx
osx_image: xcode11 # macOS 10.14
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.7
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.7/bin/python3'; alias pip='/usr/local/opt/python@3.7/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.13
# MacOS 10.13, Python 3.9
- name: "cp39-cp39m-macosx_10_13_x86_64.whl"
os: osx
osx_image: xcode10.1 # macOS 10.13
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.9
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.9/bin/python3'; alias pip='/usr/local/opt/python@3.9/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.13, Python 3.8
- name: "cp38-cp38m-macosx_10_13_x86_64.whl"
os: osx
osx_image: xcode10.1 # macOS 10.13
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.8
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.8/bin/python3'; alias pip='/usr/local/opt/python@3.8/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.13, Python 3.7
- name: "cp37-cp37m-macosx_10_13_x86_64.whl"
os: osx
osx_image: xcode10.1 # macOS 10.13
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.7
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.7/bin/python3'; alias pip='/usr/local/opt/python@3.7/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.12, Python 3.7
# - name: "klayout python3 osx10.12"
- name: "cp37-cp37m-macosx_10_12_x86_64.whl"
os: osx
osx_image: xcode9.2 # macOS 10.12
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python3
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='python3'; alias pip='pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
exclude:
# No XCode 8.2.1 for Mac OS 10.11
# - name: "klayout python3 osx10.11"
- name: "cp37-cp37m-macosx_10_11_x86_64.whl"
os: osx
osx_image: xcode8 # macOS 10.11
cache:
directories:
- ccache
addons:
homebrew:
packages:
- ccache
update: true
env:
- MATRIX_EVAL="brew update; brew config; brew upgrade python; brew postinstall python; ls -l /usr/local/opt/python/libexec/bin/; shopt -s expand_aliases; alias python='/usr/local/opt/python/libexec/bin/python'; alias pip='/usr/local/opt/python/libexec/bin/pip';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# Python 2 is EOL
# python 2 osx # python 2 osx
@ -312,99 +504,7 @@ matrix:
- PIP_UPDATE="1" - PIP_UPDATE="1"
- PYTHON_BUILD=true - PYTHON_BUILD=true
# python 3 osx # KLayout builds not enabled for now on MacOS
# - name: "klayout python3 osx10.13"
- name: "cp37-cp37m-macosx_10_13_x86_64.whl"
os: osx
osx_image: xcode9.4 # macOS 10.13
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python3
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='python3'; alias pip='pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# - name: "klayout python3.6.6 osx10.13"
- name: "cp36-cp36m-macosx_10_13_x86_64.whl"
os: osx
osx_image: xcode9.4 # macOS 10.13
cache:
directories:
- ccache
addons:
homebrew:
packages:
- ccache
update: true
env:
- MATRIX_EVAL="brew update; brew tap sashkab/python; brew install sashkab/python/python36; brew link --force --overwrite python36; shopt -s expand_aliases; alias python='/usr/local/opt/python36/bin/python3.6'; alias pip='/usr/local/opt/python36/bin/pip3.6';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# - name: "klayout python3.5.6 osx10.13"
- name: "cp35-cp35m-macosx_10_13_x86_64.whl"
os: osx
osx_image: xcode9.4 # macOS 10.13
cache:
directories:
- ccache
addons:
homebrew:
packages:
- ccache
update: true
env:
- MATRIX_EVAL="brew update; brew tap sashkab/python; brew install sashkab/python/python35; brew link --force --overwrite python35; shopt -s expand_aliases; alias python='/usr/local/opt/python35/bin/python3.5'; alias pip='/usr/local/opt/python35/bin/pip3.5';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# - name: "klayout python3 osx10.12"
- name: "cp37-cp37m-macosx_10_12_x86_64.whl"
os: osx
osx_image: xcode8.3 # macOS 10.12
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python3
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='python3'; alias pip='pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# - name: "klayout python3 osx10.11"
- name: "cp37-cp37m-macosx_10_11_x86_64.whl"
os: osx
osx_image: xcode8 # macOS 10.11
cache:
directories:
- ccache
addons:
homebrew:
packages:
- ccache
update: true
env:
- MATRIX_EVAL="brew update; brew config; brew upgrade python; brew postinstall python; ls -l /usr/local/opt/python/libexec/bin/; shopt -s expand_aliases; alias python='/usr/local/opt/python/libexec/bin/python'; alias pip='/usr/local/opt/python/libexec/bin/pip';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# KLayout builds for mac # KLayout builds for mac
# Python 3 # Python 3

View File

@ -9,3 +9,4 @@ include src/plugins/*/*/db_plugin/*.cc
include src/plugins/*/db_plugin/*.h include src/plugins/*/db_plugin/*.h
include src/plugins/*/*/db_plugin/*.h include src/plugins/*/*/db_plugin/*.h
recursive-include src/plugins/common *.h recursive-include src/plugins/common *.h
include version.sh

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)"
@ -32,8 +32,8 @@ deploy:
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

@ -28,6 +28,9 @@ jobs:
cp38-cp38-win_amd64.whl: cp38-cp38-win_amd64.whl:
python.version: '3.8' python.version: '3.8'
python.architecture: 'x64' python.architecture: 'x64'
cp39-cp39-win_amd64.whl:
python.version: '3.9'
python.architecture: 'x64'
cp35-cp35m-win32.whl: cp35-cp35m-win32.whl:
python.version: '3.5' python.version: '3.5'
python.architecture: 'x86' python.architecture: 'x86'
@ -40,6 +43,9 @@ jobs:
cp38-cp38-win32.whl: cp38-cp38-win32.whl:
python.version: '3.8' python.version: '3.8'
python.architecture: 'x86' python.architecture: 'x86'
cp39-cp39-win32.whl:
python.version: '3.9'
python.architecture: 'x86'
maxParallel: 6 maxParallel: 6
steps: steps:
@ -123,6 +129,11 @@ jobs:
vmImage: 'vs2017-win2016' # other options: 'macOS-10.13', 'ubuntu-16.04' vmImage: 'vs2017-win2016' # other options: 'macOS-10.13', 'ubuntu-16.04'
steps: steps:
- checkout: none #skip checking out the default repository resource - checkout: none #skip checking out the default repository resource
- task: DownloadBuildArtifacts@0
displayName: 'Download Build Artifacts wheel-3.9.x64'
inputs:
artifactName: 'wheel-3.9.x64'
downloadPath: '$(System.DefaultWorkingDirectory)'
- task: DownloadBuildArtifacts@0 - task: DownloadBuildArtifacts@0
displayName: 'Download Build Artifacts wheel-3.8.x64' displayName: 'Download Build Artifacts wheel-3.8.x64'
inputs: inputs:
@ -143,6 +154,11 @@ jobs:
inputs: inputs:
artifactName: 'wheel-3.5.x64' artifactName: 'wheel-3.5.x64'
downloadPath: '$(System.DefaultWorkingDirectory)' downloadPath: '$(System.DefaultWorkingDirectory)'
- task: DownloadBuildArtifacts@0
displayName: 'Download Build Artifacts wheel-3.9.x86'
inputs:
artifactName: 'wheel-3.9.x86'
downloadPath: '$(System.DefaultWorkingDirectory)'
- task: DownloadBuildArtifacts@0 - task: DownloadBuildArtifacts@0
displayName: 'Download Build Artifacts wheel-3.8.x86' displayName: 'Download Build Artifacts wheel-3.8.x86'
inputs: inputs:

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"

View File

@ -3,7 +3,7 @@ Version=1.0
Name=Klayout, viewer and editor of mask layouts. Name=Klayout, viewer and editor of mask layouts.
GenericName=layout viewer GenericName=layout viewer
Comment=Klayout is a viewer (and editor) of mask layout in a.o. GDSII and CIF format. Comment=Klayout is a viewer (and editor) of mask layout in a.o. GDSII and CIF format.
Exec=klayout Exec=klayout %f
Icon=klayout Icon=klayout
Type=Application Type=Application
Categories=Development;Engineering;Electronics; Categories=Development;Engineering;Electronics;

1
macbuild/.gitignore vendored
View File

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

View File

@ -1,27 +1,28 @@
Relevant KLayout version: 0.26.7 Relevant KLayout version: 0.26.9
# 1. Introduction # 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: 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:
* El Capitan (10.11) * El Capitan (10.11)
* Sierra (10.12) * Sierra (10.12)
* High Sierra (10.13) * High Sierra (10.13)
* Mojave (10.14) * Mojave (10.14)
* Catalina (10.15) * Catalina (10.15) : the primary development environment
* Big Sur (11.0) : under development for the future support
# 2. Qt5 Frameworks # 2. Qt5 Frameworks
By default, Qt frameworks are "Qt5" from MacPorts (https://www.macports.org/) which is usually located under: By default, the Qt framework is "Qt5" from MacPorts (https://www.macports.org/), which is usually located under:
``` ```
/opt/local/libexec/qt5/ /opt/local/libexec/qt5/
``` ```
Alternatively, you can use "Qt5" from Homebrew (https://brew.sh/) which is usually located under: Alternatively, you can use "Qt5" from Homebrew (https://brew.sh/), which is usually located under:
``` ```
/usr/local/opt/qt/ /usr/local/opt/qt/
``` ```
OR OR
"Qt5" from Anaconda3 (https://www.anaconda.com/) which is usually located under: "Qt5" from Anaconda3 (https://www.anaconda.com/), which is usually located under:
``` ```
$HOME/opt/anaconda3/pkgs/qt-{version} $HOME/opt/anaconda3/pkgs/qt-{version}
``` ```
@ -41,9 +42,9 @@ $ /usr/bin/ruby -v
$ /usr/bin/python --version $ /usr/bin/python --version
Python 2.7.16 Python 2.7.16
``` ```
Even in the latest OS as of today (December 2019), Python 3.x is not bundled with the OS, and this is the main reason why users want non-OS-standard script language support. Even in the latest OS (11.0 Big Sur) as of today (November 2020), Python 3.x is not bundled with the OS, which is why users want non-OS-standard script language support.
To meet such a requirement, the build script **`build4mac.py`** provides several possible combinations of Qt5, Ruy and Python module.<br> To meet such a requirement, the build script **`build4mac.py`** provides several possible combinations of Qt5, Ruy, and Python module.<br>
Some typical use cases are described in Section 6. Some typical use cases are described in Section 6.
# 4. Prerequisites # 4. Prerequisites
@ -66,22 +67,24 @@ $ [python] ./build4mac.py
: Qt5MacPorts: use Qt5 from MacPorts | : Qt5MacPorts: use Qt5 from MacPorts |
: Qt5Brew: use Qt5 from Homebrew | : Qt5Brew: use Qt5 from Homebrew |
: Qt5Ana3: use Qt5 from Anaconda3 | : Qt5Ana3: use Qt5 from Anaconda3 |
[-r|--ruby <type>] : case-insensitive type=['nil', 'Sys', 'MP26', 'HB27', 'Ana3'] | sys [-r|--ruby <type>] : case-insensitive type=['nil', 'Sys', 'MP27', 'HB27', 'Ana3'] | sys
: nil: don't bind Ruby | : nil: don't bind Ruby |
: Sys: use OS-bundled Ruby [2.0 - 2.6] depending on OS | : Sys: use OS-bundled Ruby [2.0 - 2.6] depending on OS |
: MP26: use Ruby 2.6 from MacPorts | : MP27: use Ruby 2.7 from MacPorts |
: HB27: use Ruby 2.7 from Homebrew | : HB27: use Ruby 2.7 from Homebrew |
: Ana3: use Ruby 2.5 from Anaconda3 | : Ana3: use Ruby 2.5 from Anaconda3 |
[-p|--python <type>] : case-insensitive type=['nil', 'Sys', 'MP38', 'HB38', 'Ana3'] | sys [-p|--python <type>] : case-insensitive type=['nil', 'Sys', 'MP38', 'HB38', 'Ana3', | sys
: 'HBAuto'] |
: nil: don't bind Python | : nil: don't bind Python |
: Sys: use OS-bundled Python 2.7 [ElCapitan -- Catalina] | : Sys: use OS-bundled Python 2.7 [ElCapitan -- BigSur] |
: MP38: use Python 3.8 from MacPorts | : MP38: use Python 3.8 from MacPorts |
: HB38: use Python 3.8 from Homebrew | : HB38: use Python 3.8 from Homebrew |
: Ana3: use Python 3.8 from Anaconda3 | : Ana3: use Python 3.7 from Anaconda3 |
: HBAuto: use the latest Python 3.x auto-detected from Homebrew |
[-n|--noqtbinding] : don't create Qt bindings for ruby scripts | disabled [-n|--noqtbinding] : don't create Qt bindings for ruby scripts | disabled
[-m|--make <option>] : option passed to 'make' | '-j4' [-m|--make <option>] : option passed to 'make' | '-j4'
[-d|--debug] : enable debug mode build | disabled [-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 including Qt's Frameworks | disabled
[-Y|--DEPLOY] : deploy executables and dylibs for those who built KLayout | 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 | : from the source code and use the tools in the same machine |
@ -98,7 +101,7 @@ $ [python] ./build4mac.py
``` ```
# 6. Use-cases # 6. Use-cases
In this section, the actual file- and directory names are those obtained on macOS Catalina.<br> In this section, the actual file names and directory names are those obtained on macOS Catalina.<br>
On different OS, those names differ accordingly. On different OS, those names differ accordingly.
### 6A. Standard build using the OS-bundled Ruby and Python ### 6A. Standard build using the OS-bundled Ruby and Python
@ -108,40 +111,40 @@ $ cd /where/'build.sh'/exists
$ ./build4mac.py $ ./build4mac.py
``` ```
2. Confirm successful build (it will take about one hour depending on your machine spec). 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) under **`klayout.app`** bundle.<br> 3. Run **`build4mac.py`** again with the same options used in 1. PLUS "-y" to deploy executables and libraries (including Qt's framework) under **`klayout.app`** bundle.<br>
The buddy command-line tools (strm*) will also be deployed in this step. The buddy command-line tools (strm*) will also be deployed in this step.
``` ```
$ ./build4mac.py -y $ ./build4mac.py -y
``` ```
The application bundle **`klayout.app`** is located under:<br> The application bundle **`klayout.app`** is located under:<br>
**`ST-qt5MP.pkg.macos-Catalina-release-RsysPsys`** directory, where the three parts below are important. **`ST-qt5MP.pkg.macos-Catalina-release-RsysPsys`** directory, where the three name parts below are important.
* "ST-" means that this is a standard package (LW-, HW-, and EX- are other possibilities explained below). * "ST-" means that this is a standard package (LW-, HW-, and EX- are other possibilities explained below).
* "qt5MP" means that Qt5 from MacPorts is used. * "qt5MP" means that Qt5 from MacPorts is used.
* "RsysPsys" means that Ruby is OS-bundled; Python is OS-bundled. * "RsysPsys" means that Ruby is OS-bundled; Python is OS-bundled.
4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation. 4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation.
If you use "-Y" option instead of "-y" in Step-3, Qt5 frameworks is NOT deployed in the application bundle.<br> If you use the "-Y" option instead of the "-y" in Step-3, the Qt5 framework is NOT deployed in the application bundle.<br>
Then the directory name will be **`LW-qt5MP.pkg.macos-Catalina-release-RsysPsys`**, where Then the directory name will be **`LW-qt5MP.pkg.macos-Catalina-release-RsysPsys`**, where
* "LW-" means that this is a lightweight package. * "LW-" means that this is a lightweight package.
#### If you build KLayout from the source code AND use it on the same machine, "-Y" option is highly recommended. #### #### If you build KLayout from the source code AND run it on the same machine, the "-Y" option is highly recommended. ####
### 6B. Fully MacPorts-flavored build with MacPorts Ruby 2.6 and MacPorts Python 3.8 ### 6B. Fully MacPorts-flavored build with MacPorts Ruby 2.7 and MacPorts Python 3.8
``` ```
$ cd /where/'build.sh'/exists $ cd /where/'build.sh'/exists
$ ./build4mac.py -q qt5macports -r mp26 -p mp38 $ ./build4mac.py -q qt5macports -r mp27 -p mp38
``` ```
2. Confirm successful build (it will take about one hour depending on your machine spec). 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> 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. The buddy command-line tools (strm*) will also be deployed in this step.
``` ```
$ ./build4mac.py -q qt5macports -r mp26 -p mp38 -Y $ ./build4mac.py -q qt5macports -r mp27 -p mp38 -Y
``` ```
The application bundle **`klayout.app`** is located under:<br> The application bundle **`klayout.app`** is located under:<br>
**`LW-qt5MP.pkg.macos-Catalina-release-Rmp26Pmp38`** directory, where **`LW-qt5MP.pkg.macos-Catalina-release-Rmp27Pmp38`** directory, where
* "LW-" means that this is a lightweight package. * "LW-" means that this is a lightweight package.
* "qt5MP" means that Qt5 from MacPorts is used. * "qt5MP" means that Qt5 from MacPorts is used.
* "Rmp26Pmp38" means that Ruby is 2.6 from MacPorts; Python is 3.8 from MacPorts. * "Rmp27Pmp38" means that Ruby is 2.7 from MacPorts; Python is 3.8 from MacPorts.
4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation. 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.8 ### 6C. Fully Homebrew-flavored build with Homebrew Ruby 2.7 and Homebrew Python 3.8
@ -168,7 +171,7 @@ $ cd /where/'build.sh'/exists
$ ./build4mac.py -q qt5brew -r sys -p hb38 $ ./build4mac.py -q qt5brew -r sys -p hb38
``` ```
2. Confirm successful build (it will take about one hour depending on your machine spec). 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> 3. Run **`build4mac.py`** again with the same options used in 1. PLUS "-y" to deploy executables and libraries (including Qt's framework and Python framework) under **`klayout.app`** bundle.<br>
The buddy command-line tools (strm*) will also be deployed in this step. The buddy command-line tools (strm*) will also be deployed in this step.
``` ```
$ ./build4mac.py -q qt5brew -r sys -p hb38 -y $ ./build4mac.py -q qt5brew -r sys -p hb38 -y
@ -180,8 +183,8 @@ $ ./build4mac.py -q qt5brew -r sys -p hb38 -y
* "RsysPhb38" means that Ruby is OS-bundled; Python is 3.8 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. 4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation.
### Important ### ### Important ###
So far, deployment of Homebrew Ruby is not supported. <br> So far, the deployment of Homebrew Ruby is not supported. <br>
Therefore, if you intend to use "-y" option, you need to use "-r sys" for building. Therefore, if you intend to use the "-y" option for deployment, you need to use the "-r sys" option for building.
### 6E. Fully Anaconda3-flavored build with Anaconda3 Ruby 2.5 and Anaconda3 Python 3.8 ### 6E. Fully Anaconda3-flavored build with Anaconda3 Ruby 2.5 and Anaconda3 Python 3.8
``` ```
@ -225,8 +228,8 @@ $ cd /where/'build.sh'/exists
$ ./makeDMG4mac.py -p ST-qt5MP.pkg.macos-Catalina-release-RsysPsys -m $ ./makeDMG4mac.py -p ST-qt5MP.pkg.macos-Catalina-release-RsysPsys -m
``` ```
This command will generate the two files below:<br> This command will generate the two files below:<br>
* **`ST-klayout-0.26.5-macOS-Catalina-1-qt5MP-RsysPsys.dmg`** ---(1) the main DMG file * **`ST-klayout-0.26.9-macOS-Catalina-1-qt5MP-RsysPsys.dmg`** ---(1) the main DMG file
* **`ST-klayout-0.26.5-macOS-Catalina-1-qt5MP-RsysPsys.dmg.md5`** ---(2) MD5-value text file * **`ST-klayout-0.26.9-macOS-Catalina-1-qt5MP-RsysPsys.dmg.md5`** ---(2) MD5-value text file
# Known issues # Known issues
Because we assume some specific versions of non-OS-standard Ruby and Python, updating MacPorts, Homebrew, or Anaconda3 may cause build- and link errors.<br> Because we assume some specific versions of non-OS-standard Ruby and Python, updating MacPorts, Homebrew, or Anaconda3 may cause build- and link errors.<br>
@ -234,7 +237,7 @@ In such cases, you need to update the dictionary contents of **`build4mac_env.py
# Final comments # Final comments
No need to say, KLayout is a great tool! <br> No need to say, KLayout is a great tool! <br>
With the object-oriented script language (both Ruby and Python) support, our error-prone jobs can be simplified and speed-up.<br> With the object-oriented script language (both Ruby and Python) support, our error-prone jobs can be greatly simplified and speed-up.<br>
Building KLayout from its source code is not difficult. Try it with your favorite environment! Building KLayout from its source code is not difficult. Try it with your favorite environment!
[End of File] [End of File]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

After

Width:  |  Height:  |  Size: 205 KiB

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

@ -11,7 +11,7 @@
# This file is imported by 'build4mac.py' script. # This file is imported by 'build4mac.py' script.
#=============================================================================== #===============================================================================
import os import os
MyHome = os.environ['HOME'] import glob
#----------------------------------------------------- #-----------------------------------------------------
# [0] Xcode's tools # [0] Xcode's tools
@ -54,8 +54,8 @@ Qt5Ana3 = { 'qmake' : '/Applications/anaconda3/bin/qmake',
# [2] Ruby # [2] Ruby
#----------------------------------------------------- #-----------------------------------------------------
RubyNil = [ 'nil' ] RubyNil = [ 'nil' ]
RubySys = [ 'RubyElCapitan', 'RubySierra', 'RubyHighSierra', 'RubyMojave', 'RubyCatalina' ] RubySys = [ 'RubyElCapitan', 'RubySierra', 'RubyHighSierra', 'RubyMojave', 'RubyCatalina', 'RubyBigSur' ]
RubyExt = [ 'Ruby26MacPorts', 'Ruby27Brew', 'RubyAnaconda3' ] RubyExt = [ 'Ruby27MacPorts', 'Ruby27Brew', 'RubyAnaconda3' ]
Rubies = RubyNil + RubySys + RubyExt Rubies = RubyNil + RubySys + RubyExt
#----------------------------------------------------- #-----------------------------------------------------
@ -103,19 +103,43 @@ RubyMojave = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2
# Bundled with Catalina (10.15) # Bundled with Catalina (10.15)
# !!! 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.
#
# With the major release of "macOS Big Sur (11.0)" in November 2020, Xcode has been updated, too.
# (base) MacBookPro2{kazzz-s}(1)$ pwd
# /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/include/ruby-2.6.0
#
# (base) MacBookPro2{kazzz-s}(2)$ ll
# total 4
# drwxr-xr-x 6 root wheel 192 11 15 20:57 .
# drwxr-xr-x 3 root wheel 96 10 20 05:33 ..
# drwxr-xr-x 23 root wheel 736 10 24 11:57 ruby
# -rw-r--r-- 1 root wheel 868 10 19 19:32 ruby.h
# lrwxr-xr-x 1 root wheel 19 11 15 20:57 universal-darwin19 -> universal-darwin20/ <=== manually created this symbolic link
# drwxr-xr-x 6 root wheel 192 10 20 05:33 universal-darwin20
# [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/MacOSX.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,
'lib': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.dylib' 'inc2': '%s/System/Library/Frameworks/Ruby.framework/Headers/ruby' % CatalinaSDK,
'lib': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.dylib'
} }
# Ruby 2.6 from MacPorts (https://www.macports.org/) *+*+*+ EXPERIMENTAL *+*+*+ # Bundled with Big Sur (11.0)
# install with 'sudo port install ruby26' # Refer to the "Catalina" section above
# [Key Type Name] = 'MP26' # [Key Type Name] = 'Sys'
Ruby26MacPorts = { 'exe': '/opt/local/bin/ruby2.6', BigSurSDK = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
'inc': '/opt/local/include/ruby-2.6.0', RubyBigSur = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby',
'lib': '/opt/local/lib/libruby.2.6.dylib' 'inc': '%s/System/Library/Frameworks/Ruby.framework/Headers' % BigSurSDK,
'inc2': '%s/System/Library/Frameworks/Ruby.framework/Headers/ruby' % BigSurSDK,
'lib': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.dylib'
}
# Ruby 2.7 from MacPorts (https://www.macports.org/) *+*+*+ EXPERIMENTAL *+*+*+
# install with 'sudo port install ruby27'
# [Key Type Name] = 'MP27'
Ruby27MacPorts = { 'exe': '/opt/local/bin/ruby2.7',
'inc': '/opt/local/include/ruby-2.7.0',
'lib': '/opt/local/lib/libruby.2.7.dylib'
} }
# Ruby 2.7 from Homebrew *+*+*+ EXPERIMENTAL *+*+*+ # Ruby 2.7 from Homebrew *+*+*+ EXPERIMENTAL *+*+*+
@ -144,7 +168,8 @@ RubyDictionary = { 'nil' : None,
'RubyHighSierra': RubyHighSierra, 'RubyHighSierra': RubyHighSierra,
'RubyMojave' : RubyMojave, 'RubyMojave' : RubyMojave,
'RubyCatalina' : RubyCatalina, 'RubyCatalina' : RubyCatalina,
'Ruby26MacPorts': Ruby26MacPorts, 'RubyBigSur' : RubyBigSur,
'Ruby27MacPorts': Ruby27MacPorts,
'Ruby27Brew' : Ruby27Brew, 'Ruby27Brew' : Ruby27Brew,
'RubyAnaconda3' : RubyAnaconda3 'RubyAnaconda3' : RubyAnaconda3
} }
@ -153,8 +178,8 @@ RubyDictionary = { 'nil' : None,
# [3] Python # [3] Python
#----------------------------------------------------- #-----------------------------------------------------
PythonNil = [ 'nil' ] PythonNil = [ 'nil' ]
PythonSys = [ 'PythonElCapitan', 'PythonSierra', 'PythonHighSierra', 'PythonMojave', 'PythonCatalina' ] PythonSys = [ 'PythonElCapitan', 'PythonSierra', 'PythonHighSierra', 'PythonMojave', 'PythonCatalina', 'PythonBigSur' ]
PythonExt = [ 'Python38MacPorts', 'Python38Brew', 'PythonAnaconda3' ] PythonExt = [ 'Python38MacPorts', 'Python38Brew', 'PythonAnaconda3', 'PythonAutoBrew' ]
Pythons = PythonNil + PythonSys + PythonExt Pythons = PythonNil + PythonSys + PythonExt
#----------------------------------------------------- #-----------------------------------------------------
@ -197,13 +222,20 @@ PythonMojave = { 'exe': '/System/Library/Frameworks/Python.framework/Versions
'lib': '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib' 'lib': '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib'
} }
# Bundled with Mojave (10.15) # Bundled with Catalina (10.15)
# [Key Type Name] = 'Sys' # [Key Type Name] = 'Sys'
PythonCatalina = { 'exe': '/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python', PythonCatalina = { 'exe': '/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python',
'inc': '/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7', 'inc': '/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7',
'lib': '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib' 'lib': '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib'
} }
# Bundled with Big Sur (11.0)
# [Key Type Name] = 'Sys'
PythonBigSur = { 'exe': '/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python',
'inc': '/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7',
'lib': '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib'
}
# Python 3.8 from MacPorts (https://www.macports.org/) *+*+*+ EXPERIMENTAL *+*+*+ # Python 3.8 from MacPorts (https://www.macports.org/) *+*+*+ EXPERIMENTAL *+*+*+
# install with 'sudo port install python38' # install with 'sudo port install python38'
# [Key Type Name] = 'MP38' # [Key Type Name] = 'MP38'
@ -215,7 +247,7 @@ Python38MacPorts= { 'exe': '/opt/local/Library/Frameworks/Python.framework/Versi
# Python 3.8 from Homebrew *+*+*+ EXPERIMENTAL *+*+*+ # Python 3.8 from Homebrew *+*+*+ EXPERIMENTAL *+*+*+
# install with 'brew install python' # install with 'brew install python'
# [Key Type Name] = 'HB38' # [Key Type Name] = 'HB38'
HBPython38FrameworkPath = '/usr/local/opt/python3/Frameworks/Python.framework' HBPython38FrameworkPath = '/usr/local/opt/python@3.8/Frameworks/Python.framework'
Python38Brew = { 'exe': '%s/Versions/3.8/bin/python3.8' % HBPython38FrameworkPath, Python38Brew = { 'exe': '%s/Versions/3.8/bin/python3.8' % HBPython38FrameworkPath,
'inc': '%s/Versions/3.8/include/python3.8' % HBPython38FrameworkPath, 'inc': '%s/Versions/3.8/include/python3.8' % HBPython38FrameworkPath,
'lib': '%s/Versions/3.8/lib/libpython3.8.dylib' % HBPython38FrameworkPath 'lib': '%s/Versions/3.8/lib/libpython3.8.dylib' % HBPython38FrameworkPath
@ -230,17 +262,42 @@ PythonAnaconda3 = { 'exe': '/Applications/anaconda3/bin/python3.8',
'lib': '/Applications/anaconda3/lib/libpython3.8.dylib' 'lib': '/Applications/anaconda3/lib/libpython3.8.dylib'
} }
# Latest Python from Homebrew *+*+*+ EXPERIMENTAL *+*+*+
# install with 'brew install python'
# There can be multiple candidates such as: (python, python3, python@3, python@3.8, python@3.9)
# Hard to tell which is going to be available to the user. Picking the last one.
# [Key Type Name] = 'HBAuto'
HBPythonAutoFrameworkPath = ""
HBPythonAutoVersion = ""
try:
HBPythonAutoFrameworkPath = glob.glob( "/usr/local/opt/python*/Frameworks/Python.framework" )[-1]
# expand 3* into HBPythonAutoVersion, there should be only one, but I am taking no chances.
HBAutoFrameworkVersionPath, HBPythonAutoVersion = os.path.split( glob.glob( "%s/Versions/3*" % HBPythonAutoFrameworkPath )[0] )
PythonAutoBrew = { 'exe': '%s/%s/bin/python%s' % ( HBAutoFrameworkVersionPath, HBPythonAutoVersion, HBPythonAutoVersion ),
'inc': '%s/%s/include/python%s' % ( HBAutoFrameworkVersionPath, HBPythonAutoVersion, HBPythonAutoVersion ),
'lib': glob.glob( "%s/%s/lib/*.dylib" % ( HBAutoFrameworkVersionPath, HBPythonAutoVersion ) )[0]
}
except Exception as e:
_have_Homebrew_Python = False
print( " WARNING!!! Since you don't have the Homebrew Python Frameworks, you cannot use the '-p HBAuto' option. " )
pass
else:
_have_Homebrew_Python = True
# Consolidated dictionary kit for Python # Consolidated dictionary kit for Python
PythonDictionary= { 'nil' : None, PythonDictionary = { 'nil' : None,
'PythonElCapitan' : PythonElCapitan, 'PythonElCapitan' : PythonElCapitan,
'PythonSierra' : PythonSierra, 'PythonSierra' : PythonSierra,
'PythonHighSierra': PythonHighSierra, 'PythonHighSierra': PythonHighSierra,
'PythonMojave' : PythonMojave, 'PythonMojave' : PythonMojave,
'PythonCatalina' : PythonCatalina, 'PythonCatalina' : PythonCatalina,
'Python38MacPorts': Python38MacPorts, 'PythonBigSur' : PythonBigSur,
'Python38Brew' : Python38Brew, 'Python38MacPorts': Python38MacPorts,
'PythonAnaconda3' : PythonAnaconda3 'Python38Brew' : Python38Brew,
} 'PythonAnaconda3' : PythonAnaconda3
}
if _have_Homebrew_Python:
PythonDictionary['PythonAutoBrew'] = PythonAutoBrew
#----------------------------------------------------- #-----------------------------------------------------
# [4] KLayout executables including buddy tools # [4] KLayout executables including buddy tools

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

@ -16,8 +16,6 @@ import os
import datetime import datetime
from time import sleep from time import sleep
import six import six
import shutil
import glob
import platform import platform
import optparse import optparse
import subprocess import subprocess
@ -27,55 +25,55 @@ import subprocess
# #
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def SetGlobals(): def SetGlobals():
global ProjectDir # project directory where "ut_runner" exists global ProjectDir # project directory where "ut_runner" exists
global RunnerUsage # True to print the usage of 'ut_runner' global RunnerUsage # True to print the usage of 'ut_runner'
global Run # True to run this script global Run # True to run this script
global ContinueOnError # True to continue after an error global ContinueOnError # True to continue after an error
global TestsExcluded # list of tests to exclude global TestsExcluded # list of tests to exclude
global Arguments # other arguments global Arguments # other arguments
global GitSHA1 # Git's short SHA1 value of the HEAD global GitSHA1 # Git's short SHA1 value of the HEAD
global TimeStamp # time stamp global TimeStamp # time stamp
global WorkDir # work directory name global WorkDir # work directory name
global LogFile # log file name global LogFile # log file name
global Usage # string on usage global Usage # string on usage
# auxiliary variables on platform # auxiliary variables on platform
global System # 6-tuple from platform.uname() global System # 6-tuple from platform.uname()
global Node # - do - global Node # - do -
global Release # - do - global Release # - do -
global Version # - do - global Version # - do -
global Machine # - do - global Machine # - do -
global Processor # - do - global Processor # - do -
global Bit # machine bit-size global Bit # machine bit-size
Usage = "\n" Usage = "\n"
Usage += "----------------------------------------------------------------------------------------\n" Usage += "----------------------------------------------------------------------------------------\n"
Usage += "<< Usage of 'macQAT.py' >>\n" Usage += "<< Usage of 'macQAT.py' >>\n"
Usage += " for running 'ut_runner' after building KLayout.\n" Usage += " for running 'ut_runner' after building KLayout.\n"
Usage += "\n" Usage += "\n"
Usage += "$ [python] ./macQAT.py \n" Usage += "$ [python] ./macQAT.py \n"
Usage += " option & argument : descriptions | default value\n" Usage += " option & argument : descriptions | default value\n"
Usage += " -----------------------------------------------------------------+---------------\n" Usage += " -----------------------------------------------------------------+---------------\n"
Usage += " [-u|--usage] : print usage of 'ut_runner'and exit | disabled \n" Usage += " [-u|--usage] : print usage of 'ut_runner'and exit | disabled \n"
Usage += " | \n" Usage += " | \n"
Usage += " <-r|--run> : run this script | disabled \n" Usage += " <-r|--run> : run this script | disabled \n"
Usage += " [-s|--stop] : stop on error | disabled \n" Usage += " [-s|--stop] : stop on error | disabled \n"
Usage += " [-x|--exclude <tests>] : exclude test(s) such as 'pymod,pya' | '' \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 += " [-a|--args <string>] : arguments other than '-x' and '-c' | '' \n"
Usage += " [-?|--?] : print this usage and exit | disabled \n" Usage += " [-?|--?] : print this usage and exit | disabled \n"
Usage += "--------------------------------------------------------------------+-------------------\n" Usage += "--------------------------------------------------------------------+-------------------\n"
ProjectDir = os.getcwd() ProjectDir = os.getcwd()
RunnerUsage = False RunnerUsage = False
Run = False Run = False
ContinueOnError = True ContinueOnError = True
TestsExcluded = list() TestsExcluded = list()
Arguments = "" Arguments = ""
GitSHA1 = GetGitShortSHA1() GitSHA1 = GetGitShortSHA1()
TimeStamp = GetTimeStamp() TimeStamp = GetTimeStamp()
WorkDir = "QATest_%s_%s__%s" % (GitSHA1, TimeStamp, os.path.basename(ProjectDir) ) WorkDir = "QATest_%s_%s__%s" % (GitSHA1, TimeStamp, os.path.basename(ProjectDir) )
LogFile = WorkDir + ".log" LogFile = WorkDir + ".log"
(System, Node, Release, Version, Machine, Processor) = platform.uname() (System, Node, Release, Version, Machine, Processor) = platform.uname()
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
## Get git's short SHA1 value of the HEAD ## Get git's short SHA1 value of the HEAD
@ -83,9 +81,9 @@ def SetGlobals():
# @return SHA1 value string # @return SHA1 value string
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def GetGitShortSHA1(): def GetGitShortSHA1():
command = "git rev-parse --short HEAD 2>/dev/null" command = "git rev-parse --short HEAD 2>/dev/null"
sha1val = os.popen( command ).read().strip() sha1val = os.popen( command ).read().strip()
return sha1val return sha1val
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
## Get the time stamp ## Get the time stamp
@ -93,108 +91,108 @@ def GetGitShortSHA1():
# @return time stamp string # @return time stamp string
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def GetTimeStamp(): def GetTimeStamp():
ts = datetime.datetime.today() ts = datetime.datetime.today()
return "%04d_%02d%02d_%02d%02d" % (ts.year, ts.month, ts.day, ts.hour, ts.minute) return "%04d_%02d%02d_%02d%02d" % (ts.year, ts.month, ts.day, ts.hour, ts.minute)
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
## To parse the command line arguments ## To parse the command line arguments
# #
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def ParseCommandLineArguments(): def ParseCommandLineArguments():
global Usage global Usage
global RunnerUsage global RunnerUsage
global Run global Run
global ContinueOnError global ContinueOnError
global TestsExcluded global TestsExcluded
global Arguments global Arguments
p = optparse.OptionParser( usage=Usage ) p = optparse.OptionParser( usage=Usage )
p.add_option( '-u', '--usage', p.add_option( '-u', '--usage',
action='store_true', action='store_true',
dest='runner_usage', dest='runner_usage',
default=False, default=False,
help="print usage of 'ut_runner' and exit (false)" ) help="print usage of 'ut_runner' and exit (false)" )
p.add_option( '-r', '--run', p.add_option( '-r', '--run',
action='store_true', action='store_true',
dest='runme', dest='runme',
default=False, default=False,
help='run this script (false)' ) help='run this script (false)' )
p.add_option( '-s', '--stop', p.add_option( '-s', '--stop',
action='store_true', action='store_true',
dest='stop_on_error', dest='stop_on_error',
default=False, default=False,
help='stop on error (false)' ) help='stop on error (false)' )
p.add_option( '-x', '--exclude', p.add_option( '-x', '--exclude',
dest='exclude_tests', dest='exclude_tests',
help="exclude test(s) such as 'pymod,pya' ('')" ) help="exclude test(s) such as 'pymod,pya' ('')" )
p.add_option( '-a', '--args', p.add_option( '-a', '--args',
dest='arguments', dest='arguments',
help="arguments other than '-x' and '-c' ('')" ) help="arguments other than '-x' and '-c' ('')" )
p.add_option( '-?', '--??', p.add_option( '-?', '--??',
action='store_true', action='store_true',
dest='checkusage', dest='checkusage',
default=False, default=False,
help='check usage (false)' ) help='check usage (false)' )
p.set_defaults( runner_usage = False, p.set_defaults( runner_usage = False,
runme = False, runme = False,
stop_on_error = False, stop_on_error = False,
exclude_tests = "", exclude_tests = "",
arguments = "", arguments = "",
checkusage = False ) checkusage = False )
opt, args = p.parse_args() opt, args = p.parse_args()
if opt.checkusage: if opt.checkusage:
print(Usage) print(Usage)
quit() quit()
RunnerUsage = opt.runner_usage RunnerUsage = opt.runner_usage
Run = opt.runme Run = opt.runme
ContinueOnError = not opt.stop_on_error ContinueOnError = not opt.stop_on_error
if not opt.exclude_tests == "": if not opt.exclude_tests == "":
TestsExcluded = [ item.strip() for item in opt.exclude_tests.split(',') ] TestsExcluded = [ item.strip() for item in opt.exclude_tests.split(',') ]
else: else:
TestsExcluded = [] TestsExcluded = []
Arguments = opt.arguments Arguments = opt.arguments
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
## Hide/Show the private directory ## Hide/Show the private directory
# #
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def HidePrivateDir(): def HidePrivateDir():
if os.path.isdir( "../private" ): if os.path.isdir( "../private" ):
os.rename( "../private", "../private.stash" ) os.rename( "../private", "../private.stash" )
def ShowPrivateDir(): def ShowPrivateDir():
if os.path.isdir( "../private.stash" ): if os.path.isdir( "../private.stash" ):
os.rename( "../private.stash", "../private" ) os.rename( "../private.stash", "../private" )
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
## Export environment variables for "ut_runner" ## Export environment variables for "ut_runner"
# #
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def ExportEnvVariables(): def ExportEnvVariables():
global ProjectDir global ProjectDir
global WorkDir global WorkDir
global MyEnviron # my environment variables; can be independently used later global MyEnviron # my environment variables; can be independently used later
# In older versions of subprocess module, 'env=None' argument is not provided # In older versions of subprocess module, 'env=None' argument is not provided
MyEnviron = os.environ.copy() MyEnviron = os.environ.copy()
MyEnviron[ 'TESTSRC' ] = ".." MyEnviron[ 'TESTSRC' ] = ".."
MyEnviron[ 'TESTTMP' ] = WorkDir MyEnviron[ 'TESTTMP' ] = WorkDir
if System == "Darwin": if System == "Darwin":
MyEnviron[ 'DYLD_LIBRARY_PATH' ] = "%s:%s/db_plugins" % (ProjectDir, ProjectDir) MyEnviron[ 'DYLD_LIBRARY_PATH' ] = "%s:%s/db_plugins" % (ProjectDir, ProjectDir)
for env in [ 'TESTSRC', 'TESTTMP', 'DYLD_LIBRARY_PATH' ]: for env in [ 'TESTSRC', 'TESTTMP', 'DYLD_LIBRARY_PATH' ]:
os.environ[env] = MyEnviron[env] os.environ[env] = MyEnviron[env]
else: else:
MyEnviron[ 'LD_LIBRARY_PATH' ] = "%s:%s/db_plugins" % (ProjectDir, ProjectDir) MyEnviron[ 'LD_LIBRARY_PATH' ] = "%s:%s/db_plugins" % (ProjectDir, ProjectDir)
for env in [ 'TESTSRC', 'TESTTMP', 'LD_LIBRARY_PATH' ]: for env in [ 'TESTSRC', 'TESTTMP', 'LD_LIBRARY_PATH' ]:
os.environ[env] = MyEnviron[env] os.environ[env] = MyEnviron[env]
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
## Run the tester ## Run the tester
@ -203,75 +201,77 @@ def ExportEnvVariables():
# @param[in] logfile log file name # @param[in] logfile log file name
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def RunTester( command, logfile="" ): def RunTester( command, logfile="" ):
if six.PY3: if six.PY3:
proc = subprocess.Popen( command.split(), stdout=subprocess.PIPE, \ proc = subprocess.Popen( command.split(),
stderr=subprocess.STDOUT, \ stdout=subprocess.PIPE, \
universal_newlines=True ) stderr=subprocess.STDOUT, \
else: universal_newlines=True )
proc = subprocess.Popen( command.split(), stdout=subprocess.PIPE, \ else:
stderr=subprocess.STDOUT ) proc = subprocess.Popen( command.split(),
stdout=subprocess.PIPE, \
stderr=subprocess.STDOUT )
if not logfile == "": if not logfile == "":
with proc.stdout, open( logfile, 'w' ) as file: with proc.stdout, open( logfile, 'w' ) as file:
for line in proc.stdout: for line in proc.stdout:
sys.stdout.write(line) sys.stdout.write(line)
file.write(line) file.write(line)
proc.wait() proc.wait()
else: else:
with proc.stdout: with proc.stdout:
for line in proc.stdout: for line in proc.stdout:
sys.stdout.write(line) sys.stdout.write(line)
proc.wait() proc.wait()
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# Main function # Main function
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def Main(): def Main():
#------------------------------------------------------- #-------------------------------------------------------
# [1] Initialize # [1] Initialize
#------------------------------------------------------- #-------------------------------------------------------
SetGlobals() SetGlobals()
ParseCommandLineArguments() ParseCommandLineArguments()
ExportEnvVariables() ExportEnvVariables()
#------------------------------------------------------- #-------------------------------------------------------
# [2] Print the runner's usage # [2] Print the runner's usage
#------------------------------------------------------- #-------------------------------------------------------
if RunnerUsage: if RunnerUsage:
command = './ut_runner --help-all' command = './ut_runner --help-all'
RunTester( command ) RunTester( command )
quit() quit()
#------------------------------------------------------- #-------------------------------------------------------
# [3] Run the unit tester # [3] Run the unit tester
#------------------------------------------------------- #-------------------------------------------------------
if not Run: if not Run:
print( "! pass <-r|--run> option to run" ) print( "! pass <-r|--run> option to run" )
print(Usage) print(Usage)
quit() quit()
command = './ut_runner' command = './ut_runner'
if ContinueOnError: if ContinueOnError:
command += " -c" command += " -c"
for item in TestsExcluded: for item in TestsExcluded:
command += ' -x %s' % item command += ' -x %s' % item
if not Arguments == "": if not Arguments == "":
command += " %s" % Arguments command += " %s" % Arguments
print( "" ) print( "" )
print( "### Dumping the log to <%s>" % LogFile ) print( "### Dumping the log to <%s>" % LogFile )
print( "------------------------------------------------------------" ) print( "------------------------------------------------------------" )
print( " Git SHA1 = %s" % GitSHA1 ) print( " Git SHA1 = %s" % GitSHA1 )
print( " Time stamp = %s" % TimeStamp ) print( " Time stamp = %s" % TimeStamp )
print( "------------------------------------------------------------" ) print( "------------------------------------------------------------" )
sleep( 1.0 ) sleep( 1.0 )
HidePrivateDir() HidePrivateDir()
RunTester( command, logfile=LogFile ) RunTester( command, logfile=LogFile )
ShowPrivateDir() ShowPrivateDir()
#=================================================================================== #===================================================================================
if __name__ == "__main__": if __name__ == "__main__":
Main() Main()
#--------------- #---------------
# End of file # End of file

View File

@ -14,23 +14,23 @@
# Functions # Functions
#---------------------------------------------------------------- #----------------------------------------------------------------
function GetPresentDir() { function GetPresentDir() {
path=$1 path=$1
array=( `echo $path | tr -s '/' ' '`) array=( `echo $path | tr -s '/' ' '`)
last_index=`expr ${#array[@]} - 1` last_index=`expr ${#array[@]} - 1`
echo ${array[${last_index}]} echo ${array[${last_index}]}
return 0 return 0
} }
function HidePrivateDir() { function HidePrivateDir() {
if [ -d "../private" ]; then if [ -d "../private" ]; then
ret=$(/bin/mv ../private ../private.stash) ret=$(/bin/mv ../private ../private.stash)
fi fi
} }
function ShowPrivateDir() { function ShowPrivateDir() {
if [ -d "../private.stash" ]; then if [ -d "../private.stash" ]; then
ret=$(/bin/mv ../private.stash ../private) ret=$(/bin/mv ../private.stash ../private)
fi fi
} }
#---------------------------------------------------------------- #----------------------------------------------------------------
@ -52,17 +52,28 @@ export DYLD_LIBRARY_PATH=$(pwd):$(pwd)/db_plugins
# Environment variables for "ut_runner" # Environment variables for "ut_runner"
#---------------------------------------------------------------- #----------------------------------------------------------------
if [ $# -eq 1 ]; then if [ $# -eq 1 ]; then
if [ "$1" == "-h" ]; then if [ "$1" == "-h" ]; then
./ut_runner -h ./ut_runner -h
exit 0 exit 0
fi fi
if [ "$1" == "-r" ]; then if [ "$1" == "-r" ]; then
echo "### Dumping the log to" $logfile "..." echo "### Dumping the log to" $logfile "..."
HidePrivateDir HidePrivateDir
./ut_runner -x pymod -c 2>&1 | tee $logfile ./ut_runner -x pymod -c 2>&1 | tee $logfile
ShowPrivateDir ShowPrivateDir
exit 0 exit 0
else else
echo ""
echo " Git SHA1 = ${gitSHA1}"
echo " Time stamp = ${timestamp}"
echo " Log file = ${logfile}"
echo " Usage:"
echo " ./QATest.sh -h: to get the help of 'ut_runner'"
echo " ./QATest.sh -r: to run the tests with '-c' option: continues after an error"
echo ""
exit 0
fi
else
echo "" echo ""
echo " Git SHA1 = ${gitSHA1}" echo " Git SHA1 = ${gitSHA1}"
echo " Time stamp = ${timestamp}" echo " Time stamp = ${timestamp}"
@ -72,17 +83,6 @@ if [ $# -eq 1 ]; then
echo " ./QATest.sh -r: to run the tests with '-c' option: continues after an error" echo " ./QATest.sh -r: to run the tests with '-c' option: continues after an error"
echo "" echo ""
exit 0 exit 0
fi
else
echo ""
echo " Git SHA1 = ${gitSHA1}"
echo " Time stamp = ${timestamp}"
echo " Log file = ${logfile}"
echo " Usage:"
echo " ./QATest.sh -h: to get the help of 'ut_runner'"
echo " ./QATest.sh -r: to run the tests with '-c' option: continues after an error"
echo ""
exit 0
fi fi
#-------------- #--------------

File diff suppressed because it is too large Load Diff

View File

@ -6,245 +6,461 @@ import sys
import os import os
import shutil import shutil
import glob import glob
import platform
import optparse import optparse
import subprocess import subprocess
Variation = [ 'std', 'ports', 'brew', 'ana3' ] #------------------------------------------------------------------------------
## To populate the build target dictionary
#
# @return a dictionary; key=integer, value=mnemonic
#------------------------------------------------------------------------------
def Get_Build_Target_Dict():
buildTargetDic = dict()
buildTargetDic[0] = 'std'
buildTargetDic[1] = 'ports'
buildTargetDic[2] = 'brew'
buildTargetDic[3] = 'brewHW'
buildTargetDic[4] = 'ana3'
Usage = "\n" buildTargetDic[5] = 'brewA'
Usage += "------------------------------------------------------------------------------------------\n" buildTargetDic[6] = 'brewAHW'
Usage += " nightyCatalina.py [EXPERIMENTAL] \n" return buildTargetDic
Usage += " << To execute the jobs for making KLatyout's DMGs for macOS Catalina >> \n"
Usage += "\n"
Usage += "$ [python] nightyCatalina.py \n"
Usage += " option & argument : comment on option if any | default value\n"
Usage += " -------------------------------------------------------------------+--------------\n"
Usage += " [--build] : build and deploy | disabled\n"
Usage += " [--makedmg <srlno>] : make DMG | disabled\n"
Usage += " [--cleandmg <srlno>] : clean DMG | disabled\n"
Usage += " [--upload <dropbox>] : upload to $HOME/Dropbox/klayout/<dropbox> | disabled\n"
Usage += " [-?|--?] : print this usage and exit | disabled\n"
Usage += "----------------------------------------------------------------------+-------------------\n"
def ParseCommandLineArguments(): #------------------------------------------------------------------------------
global Usage ## To get the build option dictionary
global Build # operation flag #
global MakeDMG # operation flag # @param[in] targetDic build target dictionary
global CleanDMG # operation flag #
global Upload # operation flag # @return a dictionary; key=mnemonic, value=build option list
global SrlDMG # DMG serial number #------------------------------------------------------------------------------
global Dropbox # Dropbox directory def Get_Build_Options( targetDic ):
buildOp = dict()
for key in targetDic.keys():
target = targetDic[key]
if target == "std": # use 'Qt5Brew' that provides Qt 5.15.1 to run on "Big Sur", too
buildOp["std"] = [ '-q', 'Qt5Brew', '-r', 'sys', '-p', 'sys' ]
elif target == "ports":
buildOp["ports"] = [ '-q', 'Qt5MacPorts', '-r', 'MP27', '-p', 'MP38' ]
elif target == "brew":
buildOp["brew"] = [ '-q', 'Qt5Brew', '-r', 'HB27', '-p', 'HB38' ]
elif target == "brewHW":
buildOp["brewHW"] = [ '-q', 'Qt5Brew', '-r', 'sys', '-p', 'HB38' ]
elif target == "ana3":
buildOp["ana3"] = [ '-q', 'Qt5Ana3', '-r', 'Ana3', '-p', 'Ana3' ]
elif target == "brewA":
buildOp["brewA"] = [ '-q', 'Qt5Brew', '-r', 'HB27', '-p', 'HBAuto' ]
elif target == "brewAHW":
buildOp["brewAHW"] = [ '-q', 'Qt5Brew', '-r', 'sys', '-p', 'HBAuto' ]
return buildOp
p = optparse.OptionParser( usage=Usage ) #------------------------------------------------------------------------------
p.add_option( '--build', ## To get the ".macQAT" dictionary for QA Test
action='store_true', #
dest='build', # @param[in] targetDic build target dictionary
default=False, #
help='build and deploy' ) # @return a dictionary; key=mnemonic, value=".macQAT" directory
#------------------------------------------------------------------------------
def Get_QAT_Directory( targetDic ):
dirQAT = dict()
for key in targetDic.keys():
target = targetDic[key]
if target == "std":
dirQAT["std"] = 'qt5Brew.build.macos-Catalina-release-RsysPsys.macQAT'
elif target == "ports":
dirQAT["ports"] = 'qt5MP.build.macos-Catalina-release-Rmp27Pmp38.macQAT'
elif target == "brew":
dirQAT["brew"] = 'qt5Brew.build.macos-Catalina-release-Rhb27Phb38.macQAT'
elif target == "brewHW":
dirQAT["brewHW"] = 'qt5Brew.build.macos-Catalina-release-RsysPhb38.macQAT'
elif target == "ana3":
dirQAT["ana3"] = 'qt5Ana3.build.macos-Catalina-release-Rana3Pana3.macQAT'
elif target == "brewA":
dirQAT["brewA"] = 'qt5Brew.build.macos-Catalina-release-Rhb27Phbauto.macQAT'
elif target == "brewAHW":
dirQAT["brewAHW"] = 'qt5Brew.build.macos-Catalina-release-RsysPhbauto.macQAT'
return dirQAT
p.add_option( '--makedmg', #------------------------------------------------------------------------------
dest='makedmg', ## To get the build option dictionary for making/cleaning DMG
help='make DMG' ) #
# @param[in] targetDic build target dictionary
# @param[in] srlDMG serial number of DMG
# @param[in] makeflag True to make; False to clean
#
# @return a dictionary; key=mnemonic, value=build option list
#------------------------------------------------------------------------------
def Get_Package_Options( targetDic, srlDMG, makeflag ):
if makeflag:
flag = '-m'
else:
flag = '-c'
p.add_option( '--cleandmg', packOp = dict()
dest='cleandmg', for key in targetDic.keys():
help='clean DMG' ) target = targetDic[key]
if target == "std":
packOp["std"] = [ '-p', 'ST-qt5Brew.pkg.macos-Catalina-release-RsysPsys', '-s', '%d' % srlDMG, '%s' % flag ]
elif target == "ports":
packOp["ports"] = [ '-p', 'LW-qt5MP.pkg.macos-Catalina-release-Rmp27Pmp38', '-s', '%d' % srlDMG, '%s' % flag ]
elif target == "brew":
packOp["brew"] = [ '-p', 'LW-qt5Brew.pkg.macos-Catalina-release-Rhb27Phb38', '-s', '%d' % srlDMG, '%s' % flag ]
elif target == "brewHW":
packOp["brewHW"] = [ '-p', 'HW-qt5Brew.pkg.macos-Catalina-release-RsysPhb38', '-s', '%d' % srlDMG, '%s' % flag ]
elif target == "ana3":
packOp["ana3"] = [ '-p', 'LW-qt5Ana3.pkg.macos-Catalina-release-Rana3Pana3', '-s', '%d' % srlDMG, '%s' % flag ]
elif target == "brewA":
packOp["brewA"] = [ '-p', 'LW-qt5Brew.pkg.macos-Catalina-release-Rhb27Phbauto', '-s', '%d' % srlDMG, '%s' % flag ]
elif target == "brewAHW":
packOp["brewAHW"] = [ '-p', 'HW-qt5Brew.pkg.macos-Catalina-release-RsysPhbauto', '-s', '%d' % srlDMG, '%s' % flag ]
return packOp
p.add_option( '--upload', #------------------------------------------------------------------------------
dest='upload', ## To parse the command line arguments
help='upload to Dropbox' ) #------------------------------------------------------------------------------
def Parse_CommandLine_Arguments():
global Usage # usage
global Target # target list
global Build # operation flag
global QATest # operation flag
global QACheck # operation flag
global MakeDMG # operation flag
global CleanDMG # operation flag
global Upload # operation flag
global SrlDMG # DMG serial number
global Dropbox # Dropbox directory
p.add_option( '-?', '--??', Usage = "\n"
action='store_true', Usage += "--------------------------------------------------------------------------------------------\n"
dest='checkusage', Usage += " nightyCatalina.py [EXPERIMENTAL] \n"
default=False, Usage += " << To execute the jobs for making KLatyout's DMGs for macOS Catalina >> \n"
help='check usage (false)' ) Usage += "\n"
Usage += "$ [python] nightyCatalina.py \n"
Usage += " option & argument : comment on option if any | default value\n"
Usage += " ------------------------------------------------------------------------+--------------\n"
Usage += " [--target <list>] : 0='std', 1='ports', 2='brew', 3='brewHW', 4='ana3', | '0,1,2,3,4'\n"
Usage += " 5='brewA', 6='brewAHW' | \n"
Usage += " [--build] : build and deploy | disabled\n"
Usage += " [--test] : run the QA Test | disabled\n"
Usage += " [--check] : check the QA Test results | disabled\n"
Usage += " [--makedmg|--cleandmg <srlno>] : make or clean DMGs | disabled\n"
Usage += " [--upload <dropbox>] : upload DMGs to $HOME/Dropbox/klayout/<dropbox> | disabled\n"
Usage += " [-?|--?] : print this usage and exit | disabled\n"
Usage += " | \n"
Usage += " Standard sequence for using this script: | \n"
Usage += " (1) $ ./nightyCatalina.py --build | \n"
Usage += " (2) (confirm the build results) | \n"
Usage += " (3) $ ./nightyCatalina.py --test | \n"
Usage += " (4) $ ./nightyCatalina.py --check (confirm the QA Test results) | \n"
Usage += " (5) $ ./nightyCatalina.py --makedmg 1 | \n"
Usage += " (6) $ ./nightyCatalina.py --upload '0.26.9' | \n"
Usage += " (7) $ ./nightyCatalina.py --cleandmg 1 | \n"
Usage += "---------------------------------------------------------------------------+----------------\n"
p.set_defaults( build = False, p = optparse.OptionParser( usage=Usage )
makedmg = "", p.add_option( '--target',
cleandmg = "", dest='targets',
upload = "", help='build target list' )
checkusage = False )
opt, args = p.parse_args() p.add_option( '--build',
if opt.checkusage: action='store_true',
print(Usage) dest='build',
quit() default=False,
help='build and deploy' )
Build = False p.add_option( '--test',
MakeDMG = False action='store_true',
CleanDMG = False dest='qa_test',
Upload = False default=False,
help='run the QA Test' )
Build = opt.build p.add_option( '--check',
action='store_true',
dest='qa_check',
default=False,
help='check the QA Test results' )
if not opt.makedmg == "": p.add_option( '--makedmg',
MakeDMG = True dest='makedmg',
CleanDMG = False help='make DMG' )
SrlDMG = int(opt.makedmg)
if not opt.cleandmg == "": p.add_option( '--cleandmg',
dest='cleandmg',
help='clean DMG' )
p.add_option( '--upload',
dest='upload',
help='upload to Dropbox' )
p.add_option( '-?', '--??',
action='store_true',
dest='checkusage',
default=False,
help='check usage' )
p.set_defaults( targets = "0,1,2,3,4",
build = False,
qa_test = False,
qa_check = False,
makedmg = "",
cleandmg = "",
upload = "",
checkusage = False )
opt, args = p.parse_args()
if opt.checkusage:
print(Usage)
quit()
targetDic = Get_Build_Target_Dict()
Target = list()
for idx in sorted( list( set( [ int(item) for item in opt.targets.split(",") ] ) ) ):
if idx in range(0, 7):
Target.append( targetDic[idx] )
Build = opt.build
QATest = opt.qa_test
QACheck = opt.qa_check
MakeDMG = False MakeDMG = False
CleanDMG = True CleanDMG = False
SrlDMG = int(opt.cleandmg) Upload = False
if not opt.upload == "": if not opt.makedmg == "":
Upload = True MakeDMG = True
Dropbox = opt.upload SrlDMG = int(opt.makedmg)
if not (Build or MakeDMG or CleanDMG or Upload): if not opt.cleandmg == "":
print( "! No option selected" ) CleanDMG = True
print(Usage) SrlDMG = int(opt.cleandmg)
quit()
if MakeDMG and CleanDMG:
print( "! --makedmg and --cleandmg cannot be used simultaneously" )
print(Usage)
quit()
def BuildDeploy(): if not opt.upload == "":
PyBuild = "./build4mac.py" Upload = True
Dropbox = opt.upload
Build = dict() if not (Build or QATest or QACheck or MakeDMG or CleanDMG or Upload):
Build["std"] = [ '-q', 'Qt5MacPorts', '-r', 'sys', '-p', 'sys' ] print( "! No option selected" )
Build["ports"] = [ '-q', 'Qt5MacPorts', '-r', 'MP26', '-p', 'MP37' ] print(Usage)
Build["brew"] = [ '-q', 'Qt5Brew', '-r', 'HB27', '-p', 'HB37' ] quit()
Build["ana3"] = [ '-q', 'Qt5Ana3', '-r', 'Ana3', '-p', 'Ana3' ]
for key in Variation: #------------------------------------------------------------------------------
command1 = [ PyBuild ] + Build[key] ## To build and deploy
if key == "std": #------------------------------------------------------------------------------
command2 = [ PyBuild ] + Build[key] + ['-y'] def Build_Deploy():
else: pyBuilder = "./build4mac.py"
command2 = [ PyBuild ] + Build[key] + ['-Y'] buildOp = Get_Build_Options( Get_Build_Target_Dict() )
print(command1)
print(command2)
#continue
if subprocess.call( command1, shell=False ) != 0: for key in Target:
print( "", file=sys.stderr ) command1 = [ pyBuilder ] + buildOp[key]
print( "-----------------------------------------------------------------", file=sys.stderr ) if key in [ "std", "brewHW", "brewAHW" ] :
print( "!!! <%s>: failed to build KLayout" % PyBuild, file=sys.stderr ) command2 = [ pyBuilder ] + buildOp[key] + ['-y']
print( "-----------------------------------------------------------------", file=sys.stderr ) else:
print( "", file=sys.stderr ) command2 = [ pyBuilder ] + buildOp[key] + ['-Y']
sys.exit(1) print(command1)
else: print(command2)
print( "", file=sys.stderr ) #continue
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "### <%s>: successfully built KLayout" % PyBuild, file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "", file=sys.stderr )
if subprocess.call( command2, shell=False ) != 0: if subprocess.call( command1, shell=False ) != 0:
print( "", file=sys.stderr ) print( "", file=sys.stderr )
print( "-----------------------------------------------------------------", file=sys.stderr ) print( "-----------------------------------------------------------------", file=sys.stderr )
print( "!!! <%s>: failed to deploy KLayout" % PyBuild, file=sys.stderr ) print( "!!! <%s>: failed to build KLayout" % pyBuilder, file=sys.stderr )
print( "-----------------------------------------------------------------", file=sys.stderr ) print( "-----------------------------------------------------------------", file=sys.stderr )
print( "", file=sys.stderr ) print( "", file=sys.stderr )
sys.exit(1) sys.exit(1)
else: else:
print( "", file=sys.stderr ) print( "", file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr ) print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "### <%s>: successfully deployed KLayout" % PyBuild, file=sys.stderr ) print( "### <%s>: successfully built KLayout" % pyBuilder, file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr ) print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "", file=sys.stderr ) print( "", file=sys.stderr )
if subprocess.call( command2, shell=False ) != 0:
print( "", file=sys.stderr )
print( "-----------------------------------------------------------------", file=sys.stderr )
print( "!!! <%s>: failed to deploy KLayout" % pyBuilder, file=sys.stderr )
print( "-----------------------------------------------------------------", file=sys.stderr )
print( "", file=sys.stderr )
sys.exit(1)
else:
print( "", file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "### <%s>: successfully deployed KLayout" % pyBuilder, file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "", file=sys.stderr )
#------------------------------------------------------------------------------
## To run the QA tests
#
# @param[in] exclude test to exclude such as 'pymod,pya'
#------------------------------------------------------------------------------
def Run_QATest( exclude ):
pyRunnerQAT = "./macQAT.py"
dirQAT = Get_QAT_Directory( Get_Build_Target_Dict() )
for key in Target:
command1 = [ pyRunnerQAT ] + [ '--run', '--exclude', '%s' % exclude ]
print( dirQAT[key], command1 )
#continue
os.chdir( dirQAT[key] )
if subprocess.call( command1, shell=False ) != 0:
print( "", file=sys.stderr )
print( "-----------------------------------------------------------------", file=sys.stderr )
print( "!!! <%s>: failed to run the QA Test" % pyRunnerQAT, file=sys.stderr )
print( "-----------------------------------------------------------------", file=sys.stderr )
print( "", file=sys.stderr )
sys.exit(1)
else:
print( "", file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "### <%s>: successfully ran the QA Test" % pyRunnerQAT, file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "", file=sys.stderr )
os.chdir( "../" )
#------------------------------------------------------------------------------
## To check the QA test results
#
# @param[in] lines number of lines to dump from the tail
#------------------------------------------------------------------------------
def Check_QATest_Results( lines ):
tailCommand = "/usr/bin/tail"
dirQAT = Get_QAT_Directory( Get_Build_Target_Dict() )
for key in Target:
os.chdir( dirQAT[key] )
logfile = glob.glob( "*.log" )
command1 = [ tailCommand ] + [ '-n', '%d' % lines ] + logfile
print( dirQAT[key], command1 )
#continue
if subprocess.call( command1, shell=False ) != 0:
print( "", file=sys.stderr )
print( "-----------------------------------------------------------------", file=sys.stderr )
print( "!!! <%s>: failed to check the QA Test results" % tailCommand, file=sys.stderr )
print( "-----------------------------------------------------------------", file=sys.stderr )
print( "", file=sys.stderr )
sys.exit(1)
else:
print( "", file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "### <%s>: successfully checked the QA Test results" % tailCommand, file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "", file=sys.stderr )
os.chdir( "../" )
#------------------------------------------------------------------------------
## To make DMGs
#
# @param[in] srlDMG DMG's serial number
#------------------------------------------------------------------------------
def DMG_Make( srlDMG ): def DMG_Make( srlDMG ):
PyDMG = "./makeDMG4mac.py" pyDMGmaker = "./makeDMG4mac.py"
Stash = "./DMGStash" stashDMG = "./DMGStash"
packOp = Get_Package_Options( Get_Build_Target_Dict(), srlDMG, makeflag=True )
Pack = dict() if os.path.isdir( stashDMG ):
Pack["std"] = [ '-p', 'ST-qt5MP.pkg.macos-Catalina-release-RsysPsys', '-s', '%d' % srlDMG, '-m' ] shutil.rmtree( stashDMG )
Pack["ports"] = [ '-p', 'LW-qt5MP.pkg.macos-Catalina-release-Rmp26Pmp37', '-s', '%d' % srlDMG, '-m' ] os.mkdir( stashDMG )
Pack["brew"] = [ '-p', 'LW-qt5Brew.pkg.macos-Catalina-release-Rhb27Phb37', '-s', '%d' % srlDMG, '-m' ]
Pack["ana3"] = [ '-p', 'LW-qt5Ana3.pkg.macos-Catalina-release-Rana3Pana3', '-s', '%d' % srlDMG, '-m' ]
if os.path.isdir( Stash ): for key in Target:
shutil.rmtree( Stash ) command1 = [ pyDMGmaker ] + packOp[key]
os.mkdir( Stash ) print(command1)
#continue
for key in Variation: if subprocess.call( command1, shell=False ) != 0:
command3 = [ PyDMG ] + Pack[key] print( "", file=sys.stderr )
print(command3) print( "-----------------------------------------------------------------", file=sys.stderr )
#continue print( "!!! <%s>: failed to make KLayout DMG" % pyDMGmaker, file=sys.stderr )
print( "-----------------------------------------------------------------", file=sys.stderr )
if subprocess.call( command3, shell=False ) != 0: print( "", file=sys.stderr )
print( "", file=sys.stderr ) sys.exit(1)
print( "-----------------------------------------------------------------", file=sys.stderr ) else:
print( "!!! <%s>: failed to make KLayout DMG" % PyDMG, file=sys.stderr ) print( "", file=sys.stderr )
print( "-----------------------------------------------------------------", file=sys.stderr ) print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "", file=sys.stderr ) print( "### <%s>: successfully made KLayout DMG" % pyDMGmaker, file=sys.stderr )
sys.exit(1) print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
else: print( "", file=sys.stderr )
print( "", file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "### <%s>: successfully made KLayout DMG" % PyDMG, file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "", file=sys.stderr )
dmgs = glob.glob( "*.dmg*" )
for item in dmgs:
shutil.move( item, Stash )
dmgs = glob.glob( "*.dmg*" )
for item in dmgs:
shutil.move( item, stashDMG )
#------------------------------------------------------------------------------
## To clean up DMGs
#
# @param[in] srlDMG DMG's serial number
#------------------------------------------------------------------------------
def DMG_Clean( srlDMG ): def DMG_Clean( srlDMG ):
PyDMG = "./makeDMG4mac.py" pyDMGmaker = "./makeDMG4mac.py"
Stash = "./DMGStash" stashDMG = "./DMGStash"
packOp = Get_Package_Options( Get_Build_Target_Dict(), srlDMG, makeflag=False )
Pack = dict() if os.path.isdir( stashDMG ):
Pack["std"] = [ '-p', 'ST-qt5MP.pkg.macos-Catalina-release-RsysPsys', '-s', '%d' % srlDMG, '-c' ] shutil.rmtree( stashDMG )
Pack["ports"] = [ '-p', 'LW-qt5MP.pkg.macos-Catalina-release-Rmp26Pmp37', '-s', '%d' % srlDMG, '-c' ]
Pack["brew"] = [ '-p', 'LW-qt5Brew.pkg.macos-Catalina-release-Rhb27Phb37', '-s', '%d' % srlDMG, '-c' ]
Pack["ana3"] = [ '-p', 'LW-qt5Ana3.pkg.macos-Catalina-release-Rana3Pana3', '-s', '%d' % srlDMG, '-c' ]
if os.path.isdir( Stash ): for key in Target:
shutil.rmtree( Stash ) command1 = [ pyDMGmaker ] + packOp[key]
print(command1)
#continue
for key in Variation: if subprocess.call( command1, shell=False ) != 0:
command3 = [ PyDMG ] + Pack[key] print( "", file=sys.stderr )
print(command3) print( "-----------------------------------------------------------------", file=sys.stderr )
#continue print( "!!! <%s>: failed to clean KLayout DMG" % pyDMGmaker, file=sys.stderr )
print( "-----------------------------------------------------------------", file=sys.stderr )
print( "", file=sys.stderr )
sys.exit(1)
else:
print( "", file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "### <%s>: successfully cleaned KLayout DMG" % pyDMGmaker, file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "", file=sys.stderr )
if subprocess.call( command3, shell=False ) != 0: #------------------------------------------------------------------------------
print( "", file=sys.stderr ) ## To upload DMGs to Dropbox
print( "-----------------------------------------------------------------", file=sys.stderr ) #
print( "!!! <%s>: failed to clean KLayout DMG" % PyDMG, file=sys.stderr ) # @param[in] targetdir existing target directory such as "0.26.9"
print( "-----------------------------------------------------------------", file=sys.stderr ) #------------------------------------------------------------------------------
print( "", file=sys.stderr ) def Upload_To_Dropbox( targetdir ):
sys.exit(1) stashDMG = "./DMGStash"
else:
print( "", file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "### <%s>: successfully cleaned KLayout DMG" % PyDMG, file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "", file=sys.stderr )
distDir = os.environ["HOME"] + "/Dropbox/klayout/" + targetdir
if not os.path.isdir(distDir):
os.makedirs(distDir)
def UploadToDropbox( targetdir ): dmgs = glob.glob( "%s/*.dmg*" % stashDMG )
Stash = "./DMGStash" for item in dmgs:
shutil.copy2( item, distDir )
distDir = os.environ["HOME"] + "/Dropbox/klayout/" + targetdir
if not os.path.isdir(distDir):
os.makedirs(distDir)
dmgs = glob.glob( "%s/*.dmg*" % Stash )
for item in dmgs:
shutil.copy2( item, distDir )
#------------------------------------------------------------------------------
## The main function
#------------------------------------------------------------------------------
def Main(): def Main():
ParseCommandLineArguments() Parse_CommandLine_Arguments()
if Build: if Build:
BuildDeploy() Build_Deploy()
elif MakeDMG: if QATest:
DMG_Make( SrlDMG ) Run_QATest( 'pymod,pya' )
elif CleanDMG: if QACheck:
DMG_Clean( SrlDMG ) Check_QATest_Results( 20 )
elif Upload: elif MakeDMG:
UploadToDropbox( Dropbox ) DMG_Make( SrlDMG )
elif Upload:
Upload_To_Dropbox( Dropbox )
elif CleanDMG:
DMG_Clean( SrlDMG )
#=================================================================================== #===================================================================================
if __name__ == "__main__": if __name__ == "__main__":
Main() Main()
#--------------- #---------------
# End of file # End of file

View File

@ -59,6 +59,7 @@ from setuptools.extension import Extension, Library
import glob import glob
import os import os
import re import re
import sys
import platform import platform
from distutils.errors import CompileError from distutils.errors import CompileError
import distutils.command.build_ext import distutils.command.build_ext
@ -102,12 +103,20 @@ def parallelCCompile(self, sources, output_dir=None, macros=None, include_dirs=N
# only if python version > 2.6, somehow the travis compiler hangs in 2.6 # only if python version > 2.6, somehow the travis compiler hangs in 2.6
import sys if sys.version_info[0] * 100 + sys.version_info[1] > 206:
if sys.version_info[0] * 10 + sys.version_info[1] > 26:
import distutils.ccompiler import distutils.ccompiler
distutils.ccompiler.CCompiler.compile = parallelCCompile distutils.ccompiler.CCompiler.compile = parallelCCompile
# put a path in quotes if required
def quote_path(path):
# looks like disutils don't need path quoting in version >= 3.9:
if " " in path and sys.version_info[0] * 100 + sys.version_info[1] < 309:
return "\"" + path + "\""
else:
return path
# TODO: delete (Obsolete) # TODO: delete (Obsolete)
# patch get_ext_filename # patch get_ext_filename
from distutils.command.build_ext import build_ext from distutils.command.build_ext import build_ext
@ -252,10 +261,10 @@ class Config(object):
if platform.system() == "Windows": if platform.system() == "Windows":
bits = os.getenv("KLAYOUT_BITS") bits = os.getenv("KLAYOUT_BITS")
if bits: if bits:
return ["\"-I" + os.path.join(bits, "zlib", "include") + "\"", return [quote_path("-I" + os.path.join(bits, "zlib", "include")),
"\"-I" + os.path.join(bits, "ptw", "include") + "\"", quote_path("-I" + os.path.join(bits, "ptw", "include")),
"\"-I" + os.path.join(bits, "expat", "include") + "\"", quote_path("-I" + os.path.join(bits, "expat", "include")),
"\"-I" + os.path.join(bits, "curl", "include") + "\""] quote_path("-I" + os.path.join(bits, "curl", "include"))]
else: else:
return [] return []
elif platform.system() == "Darwin": elif platform.system() == "Darwin":
@ -285,10 +294,10 @@ class Config(object):
args = ["/DLL"] args = ["/DLL"]
bits = os.getenv("KLAYOUT_BITS") bits = os.getenv("KLAYOUT_BITS")
if bits: if bits:
args += ["\"/LIBPATH:" + os.path.join(bits, "zlib", "libraries") + "\"", args += [quote_path("/LIBPATH:" + os.path.join(bits, "zlib", "libraries")),
"\"/LIBPATH:" + os.path.join(bits, "ptw", "libraries") + "\"", quote_path("/LIBPATH:" + os.path.join(bits, "ptw", "libraries")),
"\"/LIBPATH:" + os.path.join(bits, "expat", "libraries") + "\"", quote_path("/LIBPATH:" + os.path.join(bits, "expat", "libraries")),
"\"/LIBPATH:" + os.path.join(bits, "curl", "libraries") + "\""] quote_path("/LIBPATH:" + os.path.join(bits, "curl", "libraries"))]
return args return args
elif platform.system() == "Darwin": elif platform.system() == "Darwin":
# For the dependency modules, make sure we produce a dylib. # For the dependency modules, make sure we produce a dylib.

View File

@ -272,6 +272,7 @@ Layout::Layout (db::Manager *manager)
m_properties_repository (this), m_properties_repository (this),
m_guiding_shape_layer (-1), m_guiding_shape_layer (-1),
m_waste_layer (-1), m_waste_layer (-1),
m_do_cleanup (false),
m_editable (db::default_editable_mode ()) m_editable (db::default_editable_mode ())
{ {
// .. nothing yet .. // .. nothing yet ..
@ -287,6 +288,7 @@ Layout::Layout (bool editable, db::Manager *manager)
m_properties_repository (this), m_properties_repository (this),
m_guiding_shape_layer (-1), m_guiding_shape_layer (-1),
m_waste_layer (-1), m_waste_layer (-1),
m_do_cleanup (false),
m_editable (editable) m_editable (editable)
{ {
// .. nothing yet .. // .. nothing yet ..
@ -306,6 +308,7 @@ Layout::Layout (const db::Layout &layout)
m_properties_repository (this), m_properties_repository (this),
m_guiding_shape_layer (-1), m_guiding_shape_layer (-1),
m_waste_layer (-1), m_waste_layer (-1),
m_do_cleanup (false),
m_editable (layout.m_editable) m_editable (layout.m_editable)
{ {
*this = layout; *this = layout;
@ -1285,6 +1288,12 @@ Layout::allocate_new_cell ()
void void
Layout::cleanup (const std::set<db::cell_index_type> &keep) Layout::cleanup (const std::set<db::cell_index_type> &keep)
{ {
// only managed layouts will receive cleanup requests. Never library container layouts - these
// cannot know if their proxies are not referenced by other proxies.
if (! m_do_cleanup) {
return;
}
// deleting cells may create new top cells which need to be deleted as well, hence we iterate // deleting cells may create new top cells which need to be deleted as well, hence we iterate
// until there are no more cells to delete // until there are no more cells to delete
while (true) { while (true) {

View File

@ -539,6 +539,21 @@ public:
*/ */
Layout &operator= (const Layout &d); Layout &operator= (const Layout &d);
/**
* @brief Specifies, if the layout participates in cleanup
*
* "cleanup" will be called to get rid of top level proxies.
* This flag controls whether cleanup happens or not. Library
* layouts for example must not loose proxies as they might
* themselves be referenced.
*
* The default is OFF.
*/
void do_cleanup (bool f)
{
m_do_cleanup = f;
}
/** /**
* @brief Clear the layout * @brief Clear the layout
*/ */
@ -1761,6 +1776,7 @@ private:
lib_proxy_map m_lib_proxy_map; lib_proxy_map m_lib_proxy_map;
int m_guiding_shape_layer; int m_guiding_shape_layer;
int m_waste_layer; int m_waste_layer;
bool m_do_cleanup;
bool m_editable; bool m_editable;
meta_info m_meta_info; meta_info m_meta_info;
tl::Mutex m_lock; tl::Mutex m_lock;

View File

@ -103,7 +103,8 @@ Library::unregister_proxy (db::LibraryProxy *lib_proxy, db::Layout *ly)
db::cell_index_type ci = c->first; db::cell_index_type ci = c->first;
m_refcount.erase (c); m_refcount.erase (c);
// remove cells which are itself proxies and are no longer used // remove cells which are itself proxies and are no longer used
if (layout ().cell (ci).is_proxy () && layout ().cell (ci).parent_cells () == 0) { db::Cell *lib_cell = &layout ().cell (ci);
if (lib_cell && lib_cell->is_proxy () && lib_cell->parent_cells () == 0) {
layout ().delete_cell (ci); layout ().delete_cell (ci);
} }
} }
@ -190,6 +191,7 @@ Library::remap_to (db::Library *other)
if (! pn.first) { if (! pn.first) {
// substitute by static layout cell
std::string name = r->first->cell_name (ci); std::string name = r->first->cell_name (ci);
db::Cell *old_cell = r->first->take_cell (ci); db::Cell *old_cell = r->first->take_cell (ci);
r->first->insert_cell (ci, name, new db::Cell (*old_cell)); r->first->insert_cell (ci, name, new db::Cell (*old_cell));
@ -201,6 +203,7 @@ Library::remap_to (db::Library *other)
const db::PCellDeclaration *new_pcell_decl = other->layout ().pcell_declaration (pn.second); const db::PCellDeclaration *new_pcell_decl = other->layout ().pcell_declaration (pn.second);
if (! old_pcell_decl || ! new_pcell_decl) { if (! old_pcell_decl || ! new_pcell_decl) {
// substitute by static layout cell
std::string name = r->first->cell_name (ci); std::string name = r->first->cell_name (ci);
db::Cell *old_cell = r->first->take_cell (ci); db::Cell *old_cell = r->first->take_cell (ci);
r->first->insert_cell (ci, name, new db::Cell (*old_cell)); r->first->insert_cell (ci, name, new db::Cell (*old_cell));
@ -229,7 +232,7 @@ Library::remap_to (db::Library *other)
if (! cn.first) { if (! cn.first) {
// unlink this proxy // unlink this proxy: substitute by static layout cell
std::string name = r->first->cell_name (ci); std::string name = r->first->cell_name (ci);
db::Cell *old_cell = r->first->take_cell (ci); db::Cell *old_cell = r->first->take_cell (ci);
r->first->insert_cell (ci, name, new db::Cell (*old_cell)); r->first->insert_cell (ci, name, new db::Cell (*old_cell));

View File

@ -238,7 +238,12 @@ LibraryProxy::get_basic_name () const
{ {
Library *lib = LibraryManager::instance ().lib (lib_id ()); Library *lib = LibraryManager::instance ().lib (lib_id ());
if (lib) { if (lib) {
return lib->layout ().cell (library_cell_index ()).get_basic_name (); const db::Cell *lib_cell = &lib->layout ().cell (library_cell_index ());
if (! lib_cell) {
return "<defunct>";
} else {
return lib_cell->get_basic_name ();
}
} else { } else {
return Cell::get_basic_name (); return Cell::get_basic_name ();
} }
@ -249,7 +254,12 @@ LibraryProxy::get_display_name () const
{ {
Library *lib = LibraryManager::instance ().lib (lib_id ()); Library *lib = LibraryManager::instance ().lib (lib_id ());
if (lib) { if (lib) {
return lib->get_name () + "." + lib->layout ().cell (library_cell_index ()).get_display_name (); const db::Cell *lib_cell = &lib->layout ().cell (library_cell_index ());
if (! lib_cell) {
return lib->get_name () + "." + "<defunct>";
} else {
return lib->get_name () + "." + lib_cell->get_display_name ();
}
} else { } else {
return Cell::get_display_name (); return Cell::get_display_name ();
} }
@ -260,7 +270,12 @@ LibraryProxy::get_qualified_name () const
{ {
Library *lib = LibraryManager::instance ().lib (lib_id ()); Library *lib = LibraryManager::instance ().lib (lib_id ());
if (lib) { if (lib) {
return lib->get_name () + "." + lib->layout ().cell (library_cell_index ()).get_qualified_name (); const db::Cell *lib_cell = &lib->layout ().cell (library_cell_index ());
if (! lib_cell) {
return lib->get_name () + "." + "<defunct>";
} else {
return lib->get_name () + "." + lib_cell->get_qualified_name ();
}
} else { } else {
return Cell::get_qualified_name (); return Cell::get_qualified_name ();
} }

View File

@ -147,13 +147,20 @@ Manager::last_transaction_id () const
void void
Manager::cancel () Manager::cancel ()
{ {
// equivalent to commit and undo. But takes care that an empty commit is not followed by undo
// (which would undo the previous transaction!)
if (m_enabled) { if (m_enabled) {
// commit and undo - revert changes done so far tl_assert (m_opened);
commit (); tl_assert (! m_replay);
undo (); m_opened = false;
// delete all following transactions if (m_current->first.begin () != m_current->first.end ()) {
++m_current;
undo ();
}
// wipe following history as we don't want the cancelled operation to be redoable
erase_transactions (m_current, m_transactions.end ()); erase_transactions (m_current, m_transactions.end ());
m_current = m_transactions.end (); m_current = m_transactions.end ();

View File

@ -174,9 +174,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="clearButtonEnabled">
<bool>false</bool>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>

View File

@ -439,7 +439,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
appl->add (new ChangeTargetCellApplicator (inst_cell_index)); appl->add (new ChangeTargetCellApplicator (inst_cell_index));
} }
} catch (tl::Exception &ex) { } catch (tl::Exception &) {
has_pcell_error = true; has_pcell_error = true;
} }

View File

@ -61,18 +61,18 @@ void get_text_options (std::vector < std::pair<std::string, std::string> > &opti
options.push_back (std::pair<std::string, std::string> (cfg_edit_text_valign, "bottom")); options.push_back (std::pair<std::string, std::string> (cfg_edit_text_valign, "bottom"));
} }
edt::RecentConfigurationPage::ConfigurationDescriptor text_cfg_descriptors[] =
{
edt::RecentConfigurationPage::ConfigurationDescriptor ("", tl::to_string (tr ("Layer")), edt::RecentConfigurationPage::Layer),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_string, tl::to_string (tr ("Text")), edt::RecentConfigurationPage::Text),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_size, tl::to_string (tr ("Size")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_halign, tl::to_string (tr ("Hor. align")), edt::RecentConfigurationPage::Text),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_valign, tl::to_string (tr ("Vert. align")), edt::RecentConfigurationPage::Text)
};
static static
void get_text_editor_options_pages (std::vector<lay::EditorOptionsPage *> &ret, lay::LayoutView *view, lay::Dispatcher *dispatcher) void get_text_editor_options_pages (std::vector<lay::EditorOptionsPage *> &ret, lay::LayoutView *view, lay::Dispatcher *dispatcher)
{ {
static edt::RecentConfigurationPage::ConfigurationDescriptor text_cfg_descriptors[] =
{
edt::RecentConfigurationPage::ConfigurationDescriptor ("", tl::to_string (tr ("Layer")), edt::RecentConfigurationPage::Layer),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_string, tl::to_string (tr ("Text")), edt::RecentConfigurationPage::Text),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_size, tl::to_string (tr ("Size")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_halign, tl::to_string (tr ("Hor. align")), edt::RecentConfigurationPage::Text),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_valign, tl::to_string (tr ("Vert. align")), edt::RecentConfigurationPage::Text)
};
ret.push_back (new RecentConfigurationPage (view, dispatcher, "edit-recent-text-param", ret.push_back (new RecentConfigurationPage (view, dispatcher, "edit-recent-text-param",
&text_cfg_descriptors[0], &text_cfg_descriptors[sizeof (text_cfg_descriptors) / sizeof (text_cfg_descriptors[0])])); &text_cfg_descriptors[0], &text_cfg_descriptors[sizeof (text_cfg_descriptors) / sizeof (text_cfg_descriptors[0])]));
ret.push_back (new edt::EditorOptionsText (dispatcher)); ret.push_back (new edt::EditorOptionsText (dispatcher));
@ -87,18 +87,18 @@ void get_path_options (std::vector < std::pair<std::string, std::string> > &opti
options.push_back (std::pair<std::string, std::string> (cfg_edit_path_ext_var_end, "0.0")); options.push_back (std::pair<std::string, std::string> (cfg_edit_path_ext_var_end, "0.0"));
} }
edt::RecentConfigurationPage::ConfigurationDescriptor path_cfg_descriptors[] =
{
edt::RecentConfigurationPage::ConfigurationDescriptor ("", tl::to_string (tr ("Layer")), edt::RecentConfigurationPage::Layer),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_width, tl::to_string (tr ("Width")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_ext_type, tl::to_string (tr ("Ends")), edt::RecentConfigurationPage::Int),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_ext_var_begin, tl::to_string (tr ("Begin ext.")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_ext_var_end, tl::to_string (tr ("End ext.")), edt::RecentConfigurationPage::Double)
};
static static
void get_path_editor_options_pages (std::vector<lay::EditorOptionsPage *> &ret, lay::LayoutView *view, lay::Dispatcher *dispatcher) void get_path_editor_options_pages (std::vector<lay::EditorOptionsPage *> &ret, lay::LayoutView *view, lay::Dispatcher *dispatcher)
{ {
static edt::RecentConfigurationPage::ConfigurationDescriptor path_cfg_descriptors[] =
{
edt::RecentConfigurationPage::ConfigurationDescriptor ("", tl::to_string (tr ("Layer")), edt::RecentConfigurationPage::Layer),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_width, tl::to_string (tr ("Width")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_ext_type, tl::to_string (tr ("Ends")), edt::RecentConfigurationPage::Int),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_ext_var_begin, tl::to_string (tr ("Begin ext.")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_ext_var_end, tl::to_string (tr ("End ext.")), edt::RecentConfigurationPage::Double)
};
ret.push_back (new RecentConfigurationPage (view, dispatcher, "edit-recent-path-param", ret.push_back (new RecentConfigurationPage (view, dispatcher, "edit-recent-path-param",
&path_cfg_descriptors[0], &path_cfg_descriptors[sizeof (path_cfg_descriptors) / sizeof (path_cfg_descriptors[0])])); &path_cfg_descriptors[0], &path_cfg_descriptors[sizeof (path_cfg_descriptors) / sizeof (path_cfg_descriptors[0])]));
ret.push_back (new EditorOptionsPath (dispatcher)); ret.push_back (new EditorOptionsPath (dispatcher));
@ -123,26 +123,26 @@ void get_inst_options (std::vector < std::pair<std::string, std::string> > &opti
options.push_back (std::pair<std::string, std::string> (cfg_edit_show_shapes_of_instances, "true")); options.push_back (std::pair<std::string, std::string> (cfg_edit_show_shapes_of_instances, "true"));
} }
edt::RecentConfigurationPage::ConfigurationDescriptor inst_cfg_descriptors[] =
{
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_lib_name, tl::to_string (tr ("Library")), edt::RecentConfigurationPage::CellLibraryName),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_cell_name, tl::to_string (tr ("Cell")), edt::RecentConfigurationPage::CellDisplayName),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_angle, tl::to_string (tr ("Angle")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_mirror, tl::to_string (tr ("Mirror")), edt::RecentConfigurationPage::Bool),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_scale, tl::to_string (tr ("Scale")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_array, tl::to_string (tr ("Array")), edt::RecentConfigurationPage::ArrayFlag),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_rows, tl::to_string (tr ("Rows")), edt::RecentConfigurationPage::IntIfArray),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_row_x, tl::to_string (tr ("Row step (x)")), edt::RecentConfigurationPage::DoubleIfArray),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_row_y, tl::to_string (tr ("Row step (y)")), edt::RecentConfigurationPage::DoubleIfArray),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_columns, tl::to_string (tr ("Columns")), edt::RecentConfigurationPage::IntIfArray),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_column_x, tl::to_string (tr ("Column step (x)")), edt::RecentConfigurationPage::DoubleIfArray),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_column_y, tl::to_string (tr ("Column step (y)")), edt::RecentConfigurationPage::DoubleIfArray),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_pcell_parameters, tl::to_string (tr ("PCell parameters")), edt::RecentConfigurationPage::PCellParameters)
};
static static
void get_inst_editor_options_pages (std::vector<lay::EditorOptionsPage *> &ret, lay::LayoutView *view, lay::Dispatcher *dispatcher) void get_inst_editor_options_pages (std::vector<lay::EditorOptionsPage *> &ret, lay::LayoutView *view, lay::Dispatcher *dispatcher)
{ {
static edt::RecentConfigurationPage::ConfigurationDescriptor inst_cfg_descriptors[] =
{
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_lib_name, tl::to_string (tr ("Library")), edt::RecentConfigurationPage::CellLibraryName),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_cell_name, tl::to_string (tr ("Cell")), edt::RecentConfigurationPage::CellDisplayName),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_angle, tl::to_string (tr ("Angle")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_mirror, tl::to_string (tr ("Mirror")), edt::RecentConfigurationPage::Bool),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_scale, tl::to_string (tr ("Scale")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_array, tl::to_string (tr ("Array")), edt::RecentConfigurationPage::ArrayFlag),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_rows, tl::to_string (tr ("Rows")), edt::RecentConfigurationPage::IntIfArray),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_row_x, tl::to_string (tr ("Row step (x)")), edt::RecentConfigurationPage::DoubleIfArray),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_row_y, tl::to_string (tr ("Row step (y)")), edt::RecentConfigurationPage::DoubleIfArray),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_columns, tl::to_string (tr ("Columns")), edt::RecentConfigurationPage::IntIfArray),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_column_x, tl::to_string (tr ("Column step (x)")), edt::RecentConfigurationPage::DoubleIfArray),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_column_y, tl::to_string (tr ("Column step (y)")), edt::RecentConfigurationPage::DoubleIfArray),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_pcell_parameters, tl::to_string (tr ("PCell parameters")), edt::RecentConfigurationPage::PCellParameters)
};
ret.push_back (new RecentConfigurationPage (view, dispatcher, "edit-recent-inst-param", ret.push_back (new RecentConfigurationPage (view, dispatcher, "edit-recent-inst-param",
&inst_cfg_descriptors[0], &inst_cfg_descriptors[sizeof (inst_cfg_descriptors) / sizeof (inst_cfg_descriptors[0])])); &inst_cfg_descriptors[0], &inst_cfg_descriptors[sizeof (inst_cfg_descriptors) / sizeof (inst_cfg_descriptors[0])]));
ret.push_back (new EditorOptionsInstPCellParam (dispatcher)); ret.push_back (new EditorOptionsInstPCellParam (dispatcher));

View File

@ -160,10 +160,10 @@ equals(HAVE_QT, "0") {
} else { } else {
DEFINES += HAVE_QT DEFINES += HAVE_QT
QT += core network xml sql widgets QT += core network xml sql
equals(HAVE_QT5, "1") { equals(HAVE_QT5, "1") {
QT += designer printsupport QT += designer printsupport widgets
equals(HAVE_QTBINDINGS, "1") { equals(HAVE_QTBINDINGS, "1") {
QT += multimedia multimediawidgets xmlpatterns svg gui QT += multimedia multimediawidgets xmlpatterns svg gui
} }

View File

@ -200,7 +200,7 @@ add_orientation_condition (std::string &expr, QComboBox *op, QComboBox *value, c
expr += attribute; expr += attribute;
expr += " "; expr += " ";
expr += tl::to_string (op->currentText ()); expr += tl::to_string (op->currentText ());
expr += " Trans." + v; expr += " Trans." + v + ".rot";
} }
} }
@ -308,6 +308,7 @@ add_orientation_assignment (std::string &expr, QComboBox *value, const char *att
expr += attribute; expr += attribute;
expr += " = Trans."; expr += " = Trans.";
expr += v; expr += v;
expr += ".rot";
} }
} }

View File

@ -77,7 +77,7 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<widget class="QFrame" name="frame_2"> <widget class="QFrame" name="navigation_frame">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -232,11 +232,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLineEdit" name="on_page_search_edit"> <widget class="QLineEdit" name="on_page_search_edit"/>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item> </item>
<item> <item>
<widget class="QToolButton" name="search_close_button"> <widget class="QToolButton" name="search_close_button">
@ -431,9 +427,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item row="0" column="10"> <item row="0" column="10">

View File

@ -110,6 +110,11 @@ BrowserPanel::init ()
mp_ui = new Ui::BrowserPanel (); mp_ui = new Ui::BrowserPanel ();
mp_ui->setupUi (this); mp_ui->setupUi (this);
#if QT_VERSION >= 0x050200
mp_ui->on_page_search_edit->setClearButtonEnabled (true);
mp_ui->search_edit->setClearButtonEnabled (true);
#endif
mp_ui->browser->setReadOnly (true); mp_ui->browser->setReadOnly (true);
mp_ui->browser->set_panel (this); mp_ui->browser->set_panel (this);
mp_ui->browser->setWordWrapMode (QTextOption::WordWrap); mp_ui->browser->setWordWrapMode (QTextOption::WordWrap);
@ -147,7 +152,9 @@ BrowserPanel::init ()
connect (mp_ui->browser_bookmark_view, SIGNAL (itemDoubleClicked (QTreeWidgetItem *, int)), this, SLOT (bookmark_item_selected (QTreeWidgetItem *))); connect (mp_ui->browser_bookmark_view, SIGNAL (itemDoubleClicked (QTreeWidgetItem *, int)), this, SLOT (bookmark_item_selected (QTreeWidgetItem *)));
mp_completer = new QCompleter (this); mp_completer = new QCompleter (this);
#if QT_VERSION >= 0x050200
mp_completer->setFilterMode (Qt::MatchStartsWith); mp_completer->setFilterMode (Qt::MatchStartsWith);
#endif
mp_completer->setCaseSensitivity (Qt::CaseInsensitive); mp_completer->setCaseSensitivity (Qt::CaseInsensitive);
mp_completer->setCompletionMode (QCompleter::UnfilteredPopupCompletion); mp_completer->setCompletionMode (QCompleter::UnfilteredPopupCompletion);
mp_completer_model = new QStringListModel (mp_completer); mp_completer_model = new QStringListModel (mp_completer);
@ -323,6 +330,8 @@ BrowserPanel::refresh_bookmark_list ()
item->setData (0, Qt::ToolTipRole, tl::to_qstring (i->title)); item->setData (0, Qt::ToolTipRole, tl::to_qstring (i->title));
item->setData (0, Qt::DecorationRole, QIcon (":/bookmark_16.png")); item->setData (0, Qt::DecorationRole, QIcon (":/bookmark_16.png"));
} }
update_navigation_panel ();
} }
void void
@ -475,7 +484,7 @@ BrowserPanel::set_home (const std::string &url)
QList<int> sizes = mp_ui->splitter->sizes (); QList<int> sizes = mp_ui->splitter->sizes ();
if (sizes.size () >= 2) { if (sizes.size () >= 2) {
int size_outline = 150; int size_outline = 150;
sizes[1] += sizes[0] - size_outline; sizes[1] += std::max (width () - 10 - size_outline, 10);
sizes[0] = size_outline; sizes[0] = size_outline;
} }
mp_ui->splitter->setSizes (sizes); mp_ui->splitter->setSizes (sizes);
@ -608,6 +617,13 @@ update_item_with_outline (const BrowserOutline &ol, QTreeWidgetItem *item)
} }
} }
void
BrowserPanel::update_navigation_panel ()
{
bool navigation_visible = mp_ui->outline_tree->topLevelItemCount () > 0 || mp_ui->browser_bookmark_view->topLevelItemCount () > 0;
mp_ui->navigation_frame->setVisible (navigation_visible);
}
void void
BrowserPanel::set_outline (const BrowserOutline &ol) BrowserPanel::set_outline (const BrowserOutline &ol)
{ {
@ -634,6 +650,8 @@ BrowserPanel::set_outline (const BrowserOutline &ol)
mp_ui->outline_tree->expandAll (); mp_ui->outline_tree->expandAll ();
} }
update_navigation_panel ();
} }
QVariant QVariant

View File

@ -477,6 +477,7 @@ private:
void add_bookmark (const BookmarkItem &item); void add_bookmark (const BookmarkItem &item);
void refresh_bookmark_list (); void refresh_bookmark_list ();
void store_bookmarks (); void store_bookmarks ();
void update_navigation_panel ();
}; };
} }

View File

@ -59,6 +59,9 @@ LayoutHandle::LayoutHandle (db::Layout *layout, const std::string &filename)
m_dirty (false), m_dirty (false),
m_save_options_valid (false) m_save_options_valid (false)
{ {
// layouts in the managed layouts space participate in spare proxy cleanup
layout->do_cleanup (true);
file_watcher ().add_file (m_filename); file_watcher ().add_file (m_filename);
if (! m_filename.empty ()) { if (! m_filename.empty ()) {

View File

@ -25,6 +25,7 @@
#define HDR_layLayerTreeModel #define HDR_layLayerTreeModel
#include "dbBox.h" #include "dbBox.h"
#include "laybasicCommon.h"
#include <vector> #include <vector>
#include <set> #include <set>
@ -77,7 +78,7 @@ private:
* representation or a hierarchical one. * representation or a hierarchical one.
*/ */
class LayerTreeModel class LAYBASIC_PUBLIC LayerTreeModel
: public QAbstractItemModel : public QAbstractItemModel
{ {
Q_OBJECT Q_OBJECT

View File

@ -167,7 +167,7 @@ MoveService::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool
return true; return true;
} }
if (prio && (buttons & lay::LeftButton) != 0) { if (prio && (buttons & lay::LeftButton) != 0) {
if (handle_dragging (p, buttons, false, 0)) { if (handle_click (p, buttons, false, 0)) {
return true; return true;
} }
} }
@ -184,10 +184,17 @@ bool
MoveService::mouse_double_click_event (const db::DPoint &p, unsigned int buttons, bool prio) MoveService::mouse_double_click_event (const db::DPoint &p, unsigned int buttons, bool prio)
{ {
if (prio) { if (prio) {
// stop dragging if required
if (m_dragging) {
handle_click (p, buttons, false, 0);
}
lay::SelectionService *selector = mp_view->selection_service (); lay::SelectionService *selector = mp_view->selection_service ();
if (selector) { if (selector) {
return selector->mouse_double_click_event (p, buttons, prio); return selector->mouse_double_click_event (p, buttons, prio);
} }
} }
return false; return false;
} }
@ -220,7 +227,7 @@ bool
MoveService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio) MoveService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio)
{ {
if (prio && (buttons & lay::LeftButton) != 0) { if (prio && (buttons & lay::LeftButton) != 0) {
if (handle_dragging (p, buttons, false, 0)) { if (handle_click (p, buttons, false, 0)) {
return true; return true;
} }
} }
@ -273,11 +280,11 @@ MoveService::begin_move (db::Transaction *transaction, bool selected_after_move)
pstart.set_y (std::min (pstart.y (), bbox.p2 ().y ())); pstart.set_y (std::min (pstart.y (), bbox.p2 ().y ()));
} }
return handle_dragging (pstart, 0, drag_transient, trans_holder.release ()); return handle_click (pstart, 0, drag_transient, trans_holder.release ());
} }
bool bool
MoveService::handle_dragging (const db::DPoint &p, unsigned int buttons, bool drag_transient, db::Transaction *transaction) MoveService::handle_click (const db::DPoint &p, unsigned int buttons, bool drag_transient, db::Transaction *transaction)
{ {
std::auto_ptr<db::Transaction> trans_holder (transaction); std::auto_ptr<db::Transaction> trans_holder (transaction);

View File

@ -62,7 +62,7 @@ private:
virtual void drag_cancel (); virtual void drag_cancel ();
virtual void deactivated (); virtual void deactivated ();
bool handle_dragging (const db::DPoint &p, unsigned int buttons, bool drag_transient, db::Transaction *transaction); bool handle_click (const db::DPoint &p, unsigned int buttons, bool drag_transient, db::Transaction *transaction);
bool m_dragging; bool m_dragging;
bool m_dragging_transient; bool m_dragging_transient;

View File

@ -30,6 +30,15 @@ namespace lay
// time delay until the first snapshot is taken // time delay until the first snapshot is taken
const int first_snapshot_delay = 20; const int first_snapshot_delay = 20;
// -------------------------------------------------------------
static inline db::Box safe_transformed_box (const db::Box &box, const db::ICplxTrans &t)
{
db::DBox db = db::CplxTrans (t) * box;
db &= db::DBox (db::Box::world ());
return db::Box (db);
}
// ------------------------------------------------------------- // -------------------------------------------------------------
// RedrawThreadWorker implementation // RedrawThreadWorker implementation
@ -816,7 +825,7 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
test_snapshot (0); test_snapshot (0);
db::ICplxTrans t (cell_inst.complex_trans (*p)); db::ICplxTrans t (cell_inst.complex_trans (*p));
db::Box new_vp = db::Box (t.inverted () * *v); db::Box new_vp = safe_transformed_box (*v, t.inverted ());
draw_boxes (drawing_context, new_ci, trans * t, new_vp, level + 1); draw_boxes (drawing_context, new_ci, trans * t, new_vp, level + 1);
if (p.quad_id () > 0 && p.quad_id () != qid) { if (p.quad_id () > 0 && p.quad_id () != qid) {
@ -990,7 +999,7 @@ RedrawThreadWorker::draw_box_properties (bool drawing_context, db::cell_index_ty
test_snapshot (0); test_snapshot (0);
db::ICplxTrans t (cell_inst.complex_trans (*p)); db::ICplxTrans t (cell_inst.complex_trans (*p));
db::Box new_vp = db::Box (t.inverted () * *v); db::Box new_vp = safe_transformed_box (*v, t.inverted ());
draw_box_properties (drawing_context, new_ci, trans * t, new_vp, level + 1, cell_inst_prop); draw_box_properties (drawing_context, new_ci, trans * t, new_vp, level + 1, cell_inst_prop);
} }
@ -1474,7 +1483,7 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c
p.index_a () <= 0 || (unsigned long)p.index_a () == amax - 1 || p.index_b () <= 0 || (unsigned long)p.index_b () == bmax - 1) { p.index_a () <= 0 || (unsigned long)p.index_a () == amax - 1 || p.index_b () <= 0 || (unsigned long)p.index_b () == bmax - 1) {
db::ICplxTrans t (cell_inst.complex_trans (*p)); db::ICplxTrans t (cell_inst.complex_trans (*p));
db::Box new_vp = db::Box (t.inverted () * *v); db::Box new_vp = safe_transformed_box (*v, t.inverted ());
draw_text_layer (drawing_context, new_ci, trans * t, new_vp, level + 1, fill, frame, vertex, text, opt_bitmap); draw_text_layer (drawing_context, new_ci, trans * t, new_vp, level + 1, fill, frame, vertex, text, opt_bitmap);
} }
@ -1779,7 +1788,7 @@ RedrawThreadWorker::draw_layer_wo_cache (int from_level, int to_level, db::cell_
p.index_a () <= 0 || (unsigned long)p.index_a () == amax - 1 || p.index_b () <= 0 || (unsigned long)p.index_b () == bmax - 1) { p.index_a () <= 0 || (unsigned long)p.index_a () == amax - 1 || p.index_b () <= 0 || (unsigned long)p.index_b () == bmax - 1) {
db::ICplxTrans t (cell_inst.complex_trans (*p)); db::ICplxTrans t (cell_inst.complex_trans (*p));
db::Box new_vp = db::Box (t.inverted () * *v); db::Box new_vp = safe_transformed_box (*v, t.inverted ());
draw_layer (from_level, to_level, new_ci, trans * t, new_vp, level + 1, fill, frame, vertex, text, update_snapshot); draw_layer (from_level, to_level, new_ci, trans * t, new_vp, level + 1, fill, frame, vertex, text, update_snapshot);
if (p.quad_id () > 0 && p.quad_id () != qid) { if (p.quad_id () > 0 && p.quad_id () != qid) {

View File

@ -298,7 +298,7 @@ HEADERS = \
layDispatcher.h \ layDispatcher.h \
laySelectCellViewForm.h \ laySelectCellViewForm.h \
layLayoutStatisticsForm.h \ layLayoutStatisticsForm.h \
layD25TechnologyComponent.h layD25TechnologyComponent.h \
layLayoutViewFunctions.h layLayoutViewFunctions.h
INCLUDEPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC $$LYM_INC INCLUDEPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC $$LYM_INC

View File

@ -71,7 +71,11 @@ AuthenticationHandler::authenticationRequired (QNetworkReply *reply, QAuthentica
// expect UTF-8 today. So do them a favor and encode UTF8 into Latin1, so it gets valid UTF8 when turned into Latin1 ... // expect UTF-8 today. So do them a favor and encode UTF8 into Latin1, so it gets valid UTF8 when turned into Latin1 ...
// We do this for Digest and Basic as they apparently both use Latin 1 encoding. But it's unclear whether all servers // We do this for Digest and Basic as they apparently both use Latin 1 encoding. But it's unclear whether all servers
// expect UTF-8 encoding. // expect UTF-8 encoding.
#if QT_VERSION >= 0x040700
bool is_basic_or_digest = ! auth->option (QString::fromUtf8 ("realm")).isNull (); bool is_basic_or_digest = ! auth->option (QString::fromUtf8 ("realm")).isNull ();
#else
bool is_basic_or_digest = true;
#endif
if (is_basic_or_digest) { if (is_basic_or_digest) {
auth->setPassword (QString::fromLatin1 (passwd.c_str ())); auth->setPassword (QString::fromLatin1 (passwd.c_str ()));
auth->setUser (QString::fromLatin1 (user.c_str ())); auth->setUser (QString::fromLatin1 (user.c_str ()));
@ -98,7 +102,11 @@ AuthenticationHandler::proxyAuthenticationRequired (const QNetworkProxy &proxy,
// expect UTF-8 today. So do them a favor and encode UTF8 into Latin1, so it gets valid UTF8 when turned into Latin1 ... // expect UTF-8 today. So do them a favor and encode UTF8 into Latin1, so it gets valid UTF8 when turned into Latin1 ...
// We do this for Digest and Basic as they apparently both use Latin 1 encoding. But it's unclear whether all servers // We do this for Digest and Basic as they apparently both use Latin 1 encoding. But it's unclear whether all servers
// expect UTF-8 encoding. // expect UTF-8 encoding.
#if QT_VERSION >= 0x040700
bool is_basic_or_digest = ! auth->option (QString::fromUtf8 ("realm")).isNull (); bool is_basic_or_digest = ! auth->option (QString::fromUtf8 ("realm")).isNull ();
#else
bool is_basic_or_digest = true;
#endif
if (is_basic_or_digest) { if (is_basic_or_digest) {
auth->setPassword (QString::fromLatin1 (passwd.c_str ())); auth->setPassword (QString::fromLatin1 (passwd.c_str ()));
auth->setUser (QString::fromLatin1 (user.c_str ())); auth->setUser (QString::fromLatin1 (user.c_str ()));