mirror of https://github.com/KLayout/klayout.git
Merge remote-tracking branch 'origin/master' into dvb
This commit is contained in:
commit
feb2b69aa9
541
.travis.yml
541
.travis.yml
|
|
@ -1,269 +1,531 @@
|
|||
matrix:
|
||||
include:
|
||||
# python manylinux packages
|
||||
|
||||
- name: "cp37-cp37m-manylinux1_x86_64.whl"
|
||||
os: linux
|
||||
sudo: true
|
||||
language: python
|
||||
python: '3.7-dev'
|
||||
services:
|
||||
- docker
|
||||
env:
|
||||
- DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64"
|
||||
- PY_VERSION="cp37-cp37m"
|
||||
- DOCKER_BUILD=true
|
||||
- TEST_IN_HOST=true
|
||||
- MATRIX_EVAL=""
|
||||
cache:
|
||||
directories:
|
||||
- ccache
|
||||
|
||||
- name: "cp37-cp37m-manylinux1_i686.whl"
|
||||
os: linux
|
||||
sudo: true
|
||||
services:
|
||||
- docker
|
||||
env:
|
||||
- DOCKER_IMAGE="quay.io/pypa/manylinux1_i686"
|
||||
- PY_VERSION="cp37-cp37m"
|
||||
- DOCKER_BUILD=true
|
||||
- MATRIX_EVAL=""
|
||||
cache:
|
||||
directories:
|
||||
- ccache
|
||||
|
||||
- name: "cp36-cp36m-manylinux1_x86_64.whl"
|
||||
os: linux
|
||||
sudo: true
|
||||
language: python
|
||||
python: '3.6'
|
||||
services:
|
||||
- docker
|
||||
env:
|
||||
- DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64"
|
||||
- PY_VERSION="cp36-cp36m"
|
||||
- DOCKER_BUILD=true
|
||||
- TEST_IN_HOST=true
|
||||
- MATRIX_EVAL=""
|
||||
cache:
|
||||
directories:
|
||||
- ccache
|
||||
|
||||
- name: "cp36-cp36m-manylinux1_i686.whl"
|
||||
os: linux
|
||||
sudo: true
|
||||
services:
|
||||
- docker
|
||||
env:
|
||||
- DOCKER_IMAGE="quay.io/pypa/manylinux1_i686"
|
||||
- PY_VERSION="cp36-cp36m"
|
||||
- DOCKER_BUILD=true
|
||||
- MATRIX_EVAL=""
|
||||
cache:
|
||||
directories:
|
||||
- ccache
|
||||
|
||||
- name: "cp35-cp35m-manylinux1_x86_64.whl"
|
||||
os: linux
|
||||
sudo: true
|
||||
language: python
|
||||
python: '3.5'
|
||||
services:
|
||||
- docker
|
||||
env:
|
||||
- DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64"
|
||||
- PY_VERSION="cp35-cp35m"
|
||||
- DOCKER_BUILD=true
|
||||
- TEST_IN_HOST=true
|
||||
- MATRIX_EVAL=""
|
||||
cache:
|
||||
directories:
|
||||
- ccache
|
||||
|
||||
- name: "cp35-cp35m-manylinux1_i686.whl"
|
||||
os: linux
|
||||
sudo: true
|
||||
services:
|
||||
- docker
|
||||
env:
|
||||
- DOCKER_IMAGE="quay.io/pypa/manylinux1_i686"
|
||||
- PY_VERSION="cp35-cp35m"
|
||||
- DOCKER_BUILD=true
|
||||
- MATRIX_EVAL=""
|
||||
cache:
|
||||
directories:
|
||||
- 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"
|
||||
os: linux
|
||||
sudo: true
|
||||
language: python
|
||||
python: '2.7'
|
||||
services:
|
||||
- docker
|
||||
env:
|
||||
- DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64"
|
||||
- PY_VERSION="cp27-cp27mu"
|
||||
- DOCKER_BUILD=true
|
||||
- TEST_IN_HOST=true
|
||||
- MATRIX_EVAL=""
|
||||
cache:
|
||||
directories:
|
||||
- ccache
|
||||
|
||||
- name: "cp27-cp27mu-manylinux1_i686.whl"
|
||||
os: linux
|
||||
sudo: true
|
||||
services:
|
||||
- docker
|
||||
env:
|
||||
- DOCKER_IMAGE="quay.io/pypa/manylinux1_i686"
|
||||
- PY_VERSION="cp27-cp27mu"
|
||||
- DOCKER_BUILD=true
|
||||
- MATRIX_EVAL=""
|
||||
cache:
|
||||
directories:
|
||||
- ccache
|
||||
|
||||
- name: "cp27-cp27m-manylinux1_x86_64.whl"
|
||||
os: linux
|
||||
sudo: true
|
||||
language: python
|
||||
python: '2.7'
|
||||
services:
|
||||
- docker
|
||||
env:
|
||||
- DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64"
|
||||
- PY_VERSION="cp27-cp27m"
|
||||
- DOCKER_BUILD=true
|
||||
- TEST_IN_HOST=false # travis's python 2.7 uses ucs4 (mu), so this test fails.
|
||||
- MATRIX_EVAL=""
|
||||
cache:
|
||||
directories:
|
||||
- ccache
|
||||
|
||||
- name: "cp27-cp27m-manylinux1_i686.whl"
|
||||
os: linux
|
||||
sudo: true
|
||||
services:
|
||||
- docker
|
||||
env:
|
||||
- DOCKER_IMAGE="quay.io/pypa/manylinux1_i686"
|
||||
- PY_VERSION="cp27-cp27m"
|
||||
- DOCKER_BUILD=true
|
||||
- MATRIX_EVAL=""
|
||||
cache:
|
||||
directories:
|
||||
- ccache
|
||||
|
||||
|
||||
# python 2 osx
|
||||
|
||||
- name: "klayout python2 osx10.13"
|
||||
# - name: "klayout python2 osx10.13"
|
||||
- name: "cp27-cp27m-macosx_10_13_x86_64.whl"
|
||||
os: osx
|
||||
osx_image: xcode9.4 # macOS 10.13
|
||||
cache: ccache
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- ccache
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- ARCHFLAGS="-std=c++11"
|
||||
- PIP_UPDATE="1"
|
||||
- PYTHON_BUILD=true
|
||||
- BREW_BUNDLE=false
|
||||
|
||||
- name: "klayout python2 osx10.12"
|
||||
# - name: "klayout python2 osx10.12"
|
||||
- name: "cp27-cp27m-macosx_10_12_x86_64.whl"
|
||||
os: osx
|
||||
osx_image: xcode8.3 # macOS 10.12
|
||||
cache: ccache
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- ccache
|
||||
env:
|
||||
- MATRIX_EVAL="brew install python2 || brew link --overwrite python@2" # deficient python2 in travis's xcode8.3 (no ssl)
|
||||
- ARCHFLAGS="-std=c++11"
|
||||
- PIP_UPDATE="1"
|
||||
- PYTHON_BUILD=true
|
||||
- BREW_BUNDLE=false
|
||||
|
||||
- name: "klayout python2 osx10.11"
|
||||
# - name: "klayout python2 osx10.11"
|
||||
- name: "cp27-cp27m-macosx_10_11_x86_64.whl"
|
||||
os: osx
|
||||
osx_image: xcode8 # macOS 10.11
|
||||
cache: ccache
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- ccache
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- ARCHFLAGS="-std=c++11"
|
||||
- PIP_UPDATE="1"
|
||||
- PYTHON_BUILD=true
|
||||
- BREW_BUNDLE=false
|
||||
|
||||
# python 3 osx
|
||||
|
||||
- name: "klayout python3 osx10.13"
|
||||
# - name: "klayout python3 osx10.13"
|
||||
- name: "cp37-cp37m-macosx_10_13_x86_64.whl"
|
||||
os: osx
|
||||
osx_image: xcode9.4 # macOS 10.13
|
||||
cache: 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
|
||||
- BREW_BUNDLE=true
|
||||
|
||||
- name: "klayout python3.6.6 osx10.13"
|
||||
# - 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: ccache
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- ccache
|
||||
env:
|
||||
- MATRIX_EVAL="brew update; 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
|
||||
- BREW_BUNDLE=false
|
||||
|
||||
- name: "klayout python3.5.6 osx10.13"
|
||||
# - 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: ccache
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- ccache
|
||||
env:
|
||||
- MATRIX_EVAL="brew update; 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
|
||||
- BREW_BUNDLE=false
|
||||
|
||||
- name: "klayout python3.4.9 osx10.13"
|
||||
# - name: "klayout python3.4.9 osx10.13"
|
||||
- name: "cp34-cp34m-macosx_10_13_x86_64.whl"
|
||||
os: osx
|
||||
osx_image: xcode9.4 # macOS 10.13
|
||||
cache: ccache
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- ccache
|
||||
env:
|
||||
- MATRIX_EVAL="brew update; brew install sashkab/python/python34; brew link --force --overwrite python34; shopt -s expand_aliases; alias python='/usr/local/opt/python34/bin/python3.4'; alias pip='/usr/local/opt/python34/bin/pip3.4';"
|
||||
- ARCHFLAGS="-std=c++11"
|
||||
- PIP_UPDATE="1"
|
||||
- PYTHON_BUILD=true
|
||||
- BREW_BUNDLE=false
|
||||
|
||||
- name: "klayout python3 osx10.12"
|
||||
# - name: "klayout python3 osx10.12"
|
||||
- name: "cp37-cp37m-macosx_10_12_x86_64.whl"
|
||||
os: osx
|
||||
osx_image: xcode8.3 # macOS 10.12
|
||||
cache: 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
|
||||
- BREW_BUNDLE=true
|
||||
|
||||
- name: "klayout python3 osx10.11"
|
||||
# - name: "klayout python3 osx10.11"
|
||||
- name: "cp37-cp37m-macosx_10_11_x86_64.whl"
|
||||
os: osx
|
||||
osx_image: xcode8 # macOS 10.11
|
||||
cache: ccache
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- ccache
|
||||
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
|
||||
- BREW_BUNDLE=false
|
||||
|
||||
- name: "klayout python3.7 package"
|
||||
os: linux
|
||||
dist: trusty # Ubuntu 14.04
|
||||
sudo: false
|
||||
language: python
|
||||
python: '3.7-dev'
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- PIP_UPDATE="1"
|
||||
- PYTHON_BUILD=true
|
||||
- BREW_BUNDLE=false
|
||||
- CC=clang
|
||||
- CXX=clang++
|
||||
# - name: "klayout python3.7 package"
|
||||
# os: linux
|
||||
# dist: trusty # Ubuntu 14.04
|
||||
# sudo: false
|
||||
# language: python
|
||||
# python: '3.7-dev'
|
||||
# env:
|
||||
# - MATRIX_EVAL=""
|
||||
# - PIP_UPDATE="1"
|
||||
# - PYTHON_BUILD=true
|
||||
# - CC=clang
|
||||
# - CXX=clang++
|
||||
|
||||
- name: "klayout python3.6 package"
|
||||
os: linux
|
||||
dist: trusty # Ubuntu 14.04
|
||||
sudo: false
|
||||
language: python
|
||||
python: '3.6'
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- PIP_UPDATE="1"
|
||||
- PYTHON_BUILD=true
|
||||
- BREW_BUNDLE=false
|
||||
- CC=clang
|
||||
- CXX=clang++
|
||||
# - name: "klayout python3.6 package"
|
||||
# os: linux
|
||||
# dist: trusty # Ubuntu 14.04
|
||||
# sudo: false
|
||||
# language: python
|
||||
# python: '3.6'
|
||||
# env:
|
||||
# - MATRIX_EVAL=""
|
||||
# - PIP_UPDATE="1"
|
||||
# - PYTHON_BUILD=true
|
||||
# - CC=clang
|
||||
# - CXX=clang++
|
||||
|
||||
- name: "klayout python2.7 package"
|
||||
os: linux
|
||||
dist: trusty # Ubuntu 14.04
|
||||
sudo: false
|
||||
language: python
|
||||
python: '2.7'
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- PIP_UPDATE="1"
|
||||
- PYTHON_BUILD=true
|
||||
- BREW_BUNDLE=false
|
||||
- CC=clang
|
||||
- CXX=clang++
|
||||
# - name: "klayout python2.7 package"
|
||||
# os: linux
|
||||
# dist: trusty # Ubuntu 14.04
|
||||
# sudo: false
|
||||
# language: python
|
||||
# python: '2.7'
|
||||
# env:
|
||||
# - MATRIX_EVAL=""
|
||||
# - PIP_UPDATE="1"
|
||||
# - PYTHON_BUILD=true
|
||||
# - CC=clang
|
||||
# - CXX=clang++
|
||||
|
||||
- name: "klayout python2.6 package"
|
||||
os: linux
|
||||
dist: trusty # Ubuntu 14.04
|
||||
sudo: false
|
||||
language: python
|
||||
python: '2.6'
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- PIP_UPDATE="0" # setuptools installed from last pip has syntax error on py 2.6
|
||||
- PYTHON_BUILD=true
|
||||
- BREW_BUNDLE=false
|
||||
- CC=clang
|
||||
- CXX=clang++
|
||||
# - name: "klayout python2.6 package"
|
||||
# os: linux
|
||||
# dist: trusty # Ubuntu 14.04
|
||||
# sudo: false
|
||||
# language: python
|
||||
# python: '2.6'
|
||||
# env:
|
||||
# - MATRIX_EVAL=""
|
||||
# - PIP_UPDATE="0" # setuptools installed from last pip has syntax error on py 2.6
|
||||
# - PYTHON_BUILD=true
|
||||
# - CC=clang
|
||||
# - CXX=clang++
|
||||
|
||||
- name: "klayout python3.3 package"
|
||||
os: linux
|
||||
dist: trusty # Ubuntu 14.04
|
||||
sudo: false
|
||||
language: python
|
||||
python: '3.3'
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- PIP_UPDATE="1"
|
||||
- PYTHON_BUILD=true
|
||||
- BREW_BUNDLE=false
|
||||
- CC=clang
|
||||
- CXX=clang++
|
||||
# - name: "klayout python3.3 package"
|
||||
# os: linux
|
||||
# dist: trusty # Ubuntu 14.04
|
||||
# sudo: false
|
||||
# language: python
|
||||
# python: '3.3'
|
||||
# env:
|
||||
# - MATRIX_EVAL=""
|
||||
# - PIP_UPDATE="1"
|
||||
# - PYTHON_BUILD=true
|
||||
# - CC=clang
|
||||
# - CXX=clang++
|
||||
|
||||
- name: "klayout python3.4 package"
|
||||
os: linux
|
||||
dist: trusty # Ubuntu 14.04
|
||||
sudo: false
|
||||
language: python
|
||||
python: '3.4'
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- PIP_UPDATE="1"
|
||||
- PYTHON_BUILD=true
|
||||
- BREW_BUNDLE=false
|
||||
- CC=clang
|
||||
- CXX=clang++
|
||||
# - name: "klayout python3.4 package"
|
||||
# os: linux
|
||||
# dist: trusty # Ubuntu 14.04
|
||||
# sudo: false
|
||||
# language: python
|
||||
# python: '3.4'
|
||||
# env:
|
||||
# - MATRIX_EVAL=""
|
||||
# - PIP_UPDATE="1"
|
||||
# - PYTHON_BUILD=true
|
||||
# - CC=clang
|
||||
# - CXX=clang++
|
||||
|
||||
- name: "klayout python3.5 package"
|
||||
os: linux
|
||||
dist: trusty # Ubuntu 14.04
|
||||
sudo: false
|
||||
language: python
|
||||
python: '3.5'
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- PIP_UPDATE="1"
|
||||
- PYTHON_BUILD=true
|
||||
- BREW_BUNDLE=false
|
||||
- CC=clang
|
||||
- CXX=clang++
|
||||
# - name: "klayout python3.5 package"
|
||||
# os: linux
|
||||
# dist: trusty # Ubuntu 14.04
|
||||
# sudo: false
|
||||
# language: python
|
||||
# python: '3.5'
|
||||
# env:
|
||||
# - MATRIX_EVAL=""
|
||||
# - PIP_UPDATE="1"
|
||||
# - PYTHON_BUILD=true
|
||||
# - CC=clang
|
||||
# - CXX=clang++
|
||||
|
||||
# KLayout builds for mac
|
||||
# Python 3
|
||||
- name: "KLayout macOS 10.13 with py3.7"
|
||||
os: osx
|
||||
osx_image: xcode9.4 # macOS 10.13
|
||||
cache: ccache
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- python3
|
||||
- qt
|
||||
- ccache
|
||||
update: true
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- PYTHON_VERSION=B37
|
||||
- MACOS_VERSION=HighSierra
|
||||
- KLAYOUT_BUILD=true
|
||||
- BREW_BUNDLE=true
|
||||
|
||||
- name: "KLayout macOS 10.12 with py3.7"
|
||||
os: osx
|
||||
osx_image: xcode8.3 # macOS 10.12
|
||||
cache: ccache
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- python3
|
||||
- qt
|
||||
- ccache
|
||||
update: true
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- PYTHON_VERSION=B37
|
||||
- MACOS_VERSION=Sierra
|
||||
- KLAYOUT_BUILD=true
|
||||
- BREW_BUNDLE=true
|
||||
|
||||
- name: "KLayout macOS 10.11 with py3.7"
|
||||
os: osx
|
||||
osx_image: xcode8 # macOS 10.11
|
||||
cache: ccache
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- python3
|
||||
update: true
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- MATRIX_EVAL="brew update; brew config; brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/56c500b569c724b049be7ab9e12d9693f85522f9/Formula/qt.rb" # Qt 5.11.2
|
||||
- PYTHON_VERSION=B37
|
||||
- MACOS_VERSION=ElCapitan
|
||||
- KLAYOUT_BUILD=true
|
||||
- BREW_BUNDLE=true
|
||||
|
||||
# Python 2
|
||||
- name: "KLayout macOS 10.13 with py2.7"
|
||||
os: osx
|
||||
osx_image: xcode9.4 # macOS 10.13
|
||||
cache: ccache
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- qt
|
||||
- ccache
|
||||
update: true
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- PYTHON_VERSION=Sys
|
||||
- MACOS_VERSION=HighSierra
|
||||
- KLAYOUT_BUILD=true
|
||||
- BREW_BUNDLE=true
|
||||
|
||||
- name: "KLayout macOS 10.12 with py2.7"
|
||||
os: osx
|
||||
osx_image: xcode8.3 # macOS 10.12
|
||||
cache: ccache
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- qt
|
||||
- ccache
|
||||
update: true
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- PYTHON_VERSION=Sys
|
||||
- MACOS_VERSION=Sierra
|
||||
- KLAYOUT_BUILD=true
|
||||
- BREW_BUNDLE=true
|
||||
|
||||
- name: "KLayout macOS 10.11 with py2.7"
|
||||
os: osx
|
||||
osx_image: xcode8 # macOS 10.11
|
||||
cache: ccache
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- ccache
|
||||
update: true
|
||||
env:
|
||||
- MATRIX_EVAL=""
|
||||
- MATRIX_EVAL="brew update; brew config; brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/56c500b569c724b049be7ab9e12d9693f85522f9/Formula/qt.rb" # Qt 5.11.2
|
||||
- PYTHON_VERSION=Sys
|
||||
- MACOS_VERSION=ElCapitan
|
||||
- KLAYOUT_BUILD=true
|
||||
- BREW_BUNDLE=true
|
||||
|
||||
before_install:
|
||||
- env
|
||||
- gem install dropbox-deployment
|
||||
- eval "${MATRIX_EVAL}"
|
||||
- if [ "$BREW_BUNDLE" = true ]; then
|
||||
find "$(brew --prefix)/Caskroom/"*'/.metadata' -type f -name '*.rb' | xargs grep 'EOS.undent' --files-with-matches | xargs sed -i '' 's/EOS.undent/EOS/';
|
||||
brew update;
|
||||
brew bundle;
|
||||
fi
|
||||
- if [ "${PIP_UPDATE}" == "1" ]; then
|
||||
pip --version;
|
||||
pip install --upgrade pip || sudo pip install --upgrade pip;
|
||||
|
|
@ -271,15 +533,42 @@ before_install:
|
|||
pip install --upgrade setuptools wheel || sudo pip install --upgrade setuptools wheel;
|
||||
fi
|
||||
- python -c "import distutils.sysconfig as sysconfig; print(sysconfig.__file__)"
|
||||
- if [ "${TRAVIS_OS_NAME}" == "osx" ]; then
|
||||
export PATH="/usr/local/opt/ccache/libexec:$PATH";
|
||||
fi
|
||||
|
||||
script:
|
||||
install:
|
||||
- if [ "$DOCKER_BUILD" = true ]; then
|
||||
docker pull $DOCKER_IMAGE;
|
||||
fi
|
||||
|
||||
script:
|
||||
- if [ "$DOCKER_BUILD" = true ]; then
|
||||
mkdir -p ccache;
|
||||
mkdir -p wheelhouse;
|
||||
docker run --rm -e DOCKER_IMAGE -e PY_VERSION -v `pwd`:/io $DOCKER_IMAGE $PRE_CMD "/io/ci-scripts/docker/docker_build.sh";
|
||||
klayout_version=$(python -c 'import setup; print(setup.Config().version())');
|
||||
mkdir -p deploy/dist-pymod/$klayout_version;
|
||||
cp -a wheelhouse/klayout-*manylinux1*.whl deploy/dist-pymod/$klayout_version;
|
||||
if [ "$TEST_IN_HOST" = true ]; then
|
||||
pip install klayout --no-index -f ./wheelhouse;
|
||||
python testdata/pymod/import_db.py;
|
||||
python testdata/pymod/import_rdb.py;
|
||||
python testdata/pymod/import_tl.py;
|
||||
python testdata/pymod/pya_tests.py;
|
||||
fi
|
||||
fi
|
||||
- if [ "$PYTHON_BUILD" = true ]; then
|
||||
python setup.py build;
|
||||
python setup.py bdist_wheel;
|
||||
python setup.py install;
|
||||
python -m unittest testdata/pymod/import_db.py testdata/pymod/import_rdb.py testdata/pymod/import_tl.py;
|
||||
mkdir -p deploy/dist-pymod;
|
||||
cp -a dist/* deploy/dist-pymod/;
|
||||
python testdata/pymod/import_db.py;
|
||||
python testdata/pymod/import_rdb.py;
|
||||
python testdata/pymod/import_tl.py;
|
||||
python testdata/pymod/pya_tests.py;
|
||||
klayout_version=$(python -c 'import setup; print(setup.Config().version())');
|
||||
mkdir -p deploy/dist-pymod/$klayout_version;
|
||||
cp -a dist/*.whl deploy/dist-pymod/$klayout_version;
|
||||
python -c 'import klayout.db as db; print(dir(db))';
|
||||
python -c 'import klayout.rdb as rdb; print(dir(rdb))';
|
||||
python -c 'import klayout.tl as tl; print(dir(tl))';
|
||||
|
|
|
|||
4
Brewfile
4
Brewfile
|
|
@ -1,4 +0,0 @@
|
|||
tap "homebrew/core"
|
||||
brew "python3"
|
||||
brew "python@2", link: false
|
||||
brew "qt"
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
# https://aka.ms/yaml
|
||||
jobs:
|
||||
- job: Build
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016' # other options: 'macOS-10.13', 'ubuntu-16.04'
|
||||
strategy:
|
||||
matrix:
|
||||
# Python27:
|
||||
# python.version: '2.7'
|
||||
cp35-cp35m-win_amd64.whl:
|
||||
python.version: '3.5'
|
||||
python.architecture: 'x64'
|
||||
cp36-cp36m-win_amd64.whl:
|
||||
python.version: '3.6'
|
||||
python.architecture: 'x64'
|
||||
cp37-cp37m-win_amd64.whl:
|
||||
python.version: '3.7'
|
||||
python.architecture: 'x64'
|
||||
cp35-cp35m-win32.whl:
|
||||
python.version: '3.5'
|
||||
python.architecture: 'x86'
|
||||
cp36-cp36m-win32.whl:
|
||||
python.version: '3.6'
|
||||
python.architecture: 'x86'
|
||||
cp37-cp37m-win32.whl:
|
||||
python.version: '3.7'
|
||||
python.architecture: 'x86'
|
||||
maxParallel: 6
|
||||
|
||||
steps:
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: '$(python.version)'
|
||||
architecture: '$(python.architecture)'
|
||||
|
||||
# Add additional tasks to run using each Python version in the matrix above
|
||||
|
||||
# PowerShell
|
||||
# Run a PowerShell script on Windows, macOS, or Linux.
|
||||
- task: PowerShell@2
|
||||
inputs:
|
||||
targetType: 'inline' # Optional. Options: filePath, inline
|
||||
#arguments: # Optional
|
||||
script: | # Required when targetType == Inline
|
||||
pwd
|
||||
Invoke-WebRequest -Uri "https://dl.bintray.com/lightwave-lab/klayout/klayout-microbits-1.0.zip" -OutFile klayout-microbits-1.0.zip
|
||||
dir
|
||||
Expand-Archive klayout-microbits-1.0.zip -DestinationPath klayout-microbits
|
||||
dir klayout-microbits
|
||||
#errorActionPreference: 'stop' # Optional. Options: stop, continue, silentlyContinue
|
||||
#failOnStderr: false # Optional
|
||||
#ignoreLASTEXITCODE: false # Optional
|
||||
#pwsh: false # Optional
|
||||
#workingDirectory: # Optional
|
||||
displayName: 'Download and Extract KLayout bits'
|
||||
|
||||
# - script: |
|
||||
# curl https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi -o VCForPython27.msi
|
||||
# msiexec /i VCForPython27.msi /quiet
|
||||
# set "VS90COMNTOOLS=C:\Users\VssAdministrator\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python\9.0\VC"
|
||||
# curl https://raw.githubusercontent.com/mattn/gntp-send/master/include/msinttypes/stdint.h -o "%VS90COMNTOOLS%\Include\stdint.h"
|
||||
# dir "%VS90COMNTOOLS%\Include"
|
||||
# condition: eq(variables['python.version'], '2.7')
|
||||
# displayName: 'Install Microsoft Visual C++ Compiler for Python 2.7'
|
||||
|
||||
- script: |
|
||||
python -m pip install --upgrade pip setuptools wheel
|
||||
displayName: 'Update pip, setuptools and wheel'
|
||||
|
||||
- script: |
|
||||
python -V
|
||||
set "KLAYOUT_BITS=%cd%\klayout-microbits\klayout-microbits-1.0\msvc2017\%PYTHON_ARCHITECTURE%"
|
||||
echo KLAYOUT_BITS=%KLAYOUT_BITS%
|
||||
python setup.py bdist_wheel
|
||||
displayName: 'Build KLayout'
|
||||
|
||||
- bash: |
|
||||
bash `pwd`/ci-scripts/windows/fix_wheel.sh `pwd`/dist/*.whl "`pwd`/klayout-microbits/klayout-microbits-1.0/msvc2017/$PYTHON_ARCHITECTURE"
|
||||
displayName: 'Copy klayout bits dlls into wheel'
|
||||
|
||||
- script: |
|
||||
echo PATH=%PATH%
|
||||
pip install klayout --no-index -f dist
|
||||
python testdata/pymod/import_db.py
|
||||
python testdata/pymod/import_rdb.py
|
||||
python testdata/pymod/import_tl.py
|
||||
python testdata/pymod/pya_tests.py
|
||||
displayName: 'Test KLayout pymod'
|
||||
|
||||
- task: CopyFiles@2
|
||||
condition: always()
|
||||
inputs:
|
||||
sourceFolder: '$(Build.SourcesDirectory)'
|
||||
targetFolder: '$(Build.ArtifactStagingDirectory)'
|
||||
contents: '**/?(*.whl)'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
condition: always()
|
||||
inputs:
|
||||
pathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
artifactName: 'wheel-$(python.version).$(python.architecture)'
|
||||
|
||||
- job: 'Deploy'
|
||||
displayName: 'Combine Windows wheels'
|
||||
dependsOn: Build
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016' # other options: 'macOS-10.13', 'ubuntu-16.04'
|
||||
steps:
|
||||
- checkout: none #skip checking out the default repository resource
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download Build Artifacts wheel-3.7.x64'
|
||||
inputs:
|
||||
artifactName: 'wheel-3.7.x64'
|
||||
downloadPath: '$(System.DefaultWorkingDirectory)'
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download Build Artifacts wheel-3.6.x64'
|
||||
inputs:
|
||||
artifactName: 'wheel-3.6.x64'
|
||||
downloadPath: '$(System.DefaultWorkingDirectory)'
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download Build Artifacts wheel-3.5.x64'
|
||||
inputs:
|
||||
artifactName: 'wheel-3.5.x64'
|
||||
downloadPath: '$(System.DefaultWorkingDirectory)'
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download Build Artifacts wheel-3.7.x86'
|
||||
inputs:
|
||||
artifactName: 'wheel-3.7.x86'
|
||||
downloadPath: '$(System.DefaultWorkingDirectory)'
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download Build Artifacts wheel-3.6.x86'
|
||||
inputs:
|
||||
artifactName: 'wheel-3.6.x86'
|
||||
downloadPath: '$(System.DefaultWorkingDirectory)'
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download Build Artifacts wheel-3.5.x86'
|
||||
inputs:
|
||||
artifactName: 'wheel-3.5.x86'
|
||||
downloadPath: '$(System.DefaultWorkingDirectory)'
|
||||
- task: CopyFiles@2
|
||||
condition: always()
|
||||
inputs:
|
||||
sourceFolder: '$(System.DefaultWorkingDirectory)'
|
||||
targetFolder: '$(Build.ArtifactStagingDirectory)'
|
||||
contents: '**/?(*.whl)'
|
||||
flattenFolders: true
|
||||
- task: PublishBuildArtifacts@1
|
||||
condition: always()
|
||||
inputs:
|
||||
pathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
artifactName: 'windows_wheels'
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
Author: Thomas Ferreira de Lima
|
||||
email: thomas@tlima.me
|
||||
|
||||
This folder contains scripts to be run inside docker images. See instructions on how to test this yourself in ci-scripts/docker/development_notes.
|
||||
|
||||
## docker_build.sh
|
||||
|
||||
We need two environment variables to get going:
|
||||
|
||||
```bash
|
||||
DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64"
|
||||
PY_VERSION="cp37-cp37m"
|
||||
```
|
||||
|
||||
The script must be run inside an image pulled from $DOCKER_IMAGE and with klayout's git repo cloned in /io. Inside the git clone folder, run:
|
||||
|
||||
```bash
|
||||
docker run --rm -e DOCKER_IMAGE -e PY_VERSION -v `pwd`:/io $DOCKER_IMAGE $PRE_CMD "/io/ci-scripts/docker/docker_build.sh";
|
||||
# $PRE_CMD is empty for now (useless currently).
|
||||
```
|
||||
|
||||
This command will generate a wheel and place it in `wheelhouse/klayout-*manylinux1*.whl`. This is the wheel that needs to be uploaded to PyPI via twine. See ci-scripts/twine/README.md.
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
FROM quay.io/pypa/manylinux1_i686
|
||||
MAINTAINER Thomas Ferreira de Lima (thomas@tlima.me)
|
||||
|
||||
# Install a system package required by our library
|
||||
RUN linux32 yum install -y zlib-devel
|
||||
RUN linux32 yum install -y ccache
|
||||
RUN ln -s /usr/bin/ccache /usr/lib/ccache/c++
|
||||
RUN ln -s /usr/bin/ccache /usr/lib/ccache/cc
|
||||
RUN ln -s /usr/bin/ccache /usr/lib/ccache/gcc
|
||||
RUN ln -s /usr/bin/ccache /usr/lib/ccache/g++
|
||||
|
||||
# Add ccache to PATH
|
||||
RUN mkdir -p /persist/.ccache
|
||||
ENV CCACHE_DIR="/persist/.ccache"
|
||||
|
||||
# Need zip to fix wheel
|
||||
RUN linux32 yum install -y zip
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
FROM quay.io/pypa/manylinux1_x86_64
|
||||
MAINTAINER Thomas Ferreira de Lima (thomas@tlima.me)
|
||||
|
||||
# Install a system package required by our library
|
||||
RUN yum install -y zlib-devel
|
||||
RUN yum install -y ccache
|
||||
RUN ln -s /usr/bin/ccache /usr/lib64/ccache/c++
|
||||
RUN ln -s /usr/bin/ccache /usr/lib64/ccache/cc
|
||||
RUN ln -s /usr/bin/ccache /usr/lib64/ccache/gcc
|
||||
RUN ln -s /usr/bin/ccache /usr/lib64/ccache/g++
|
||||
|
||||
# Add ccache to PATH
|
||||
RUN mkdir -p /persist/.ccache
|
||||
ENV CCACHE_DIR="/persist/.ccache"
|
||||
|
||||
# Need zip to fix wheel
|
||||
RUN yum install -y zip
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
Author: Thomas Ferreira de Lima
|
||||
email: thomas@tlima.me
|
||||
|
||||
I wrote these notes as I was learning how to use docker and how to build python packages inside a docker image prepared by the pypa team. They require us to build there to allow wheels to have the `manylinux1` tag, meaning that these wheels would be compatible with most linux distributions around. Chapter 1 is about testing in my own computer (MacOS Mojave) and Chapter 2 is about how to automate this build using travis-ci.org.
|
||||
|
||||
# Chapter 1. Testing on your own computer
|
||||
## Step 1.
|
||||
|
||||
Make sure you have the quay.io/pypa/manylinux1_x86_64 image.
|
||||
|
||||
```bash
|
||||
$ docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
quay.io/pypa/manylinux1_x86_64 latest 1c8429c548f2 2 months ago 879MB
|
||||
hello-world latest 4ab4c602aa5e 3 months ago 1.84kB
|
||||
# My image was old:
|
||||
$ docker pull quay.io/pypa/manylinux1_x86_64
|
||||
Using default tag: latest
|
||||
latest: Pulling from pypa/manylinux1_x86_64
|
||||
7d0d9526f38a: Already exists
|
||||
3324bfadf9cb: Pull complete
|
||||
20f27c7e3062: Pull complete
|
||||
5bc21fc5fe97: Pull complete
|
||||
Digest: sha256:a13b2719fb21daebfe25c0173d80f8a85a2326dd994510d7879676e7a2193500
|
||||
Status: Downloaded newer image for quay.io/pypa/manylinux1_x86_64:latest
|
||||
```
|
||||
|
||||
## Step 2.
|
||||
|
||||
This step was inspired by https://dev.to/jibinliu/how-to-persist-data-in-docker-container-2m72
|
||||
Create a volume for klayout. This is necessary because docker containers don't persist data.
|
||||
|
||||
```bash
|
||||
$ docker volume create klayout-persist
|
||||
$ docker volume inspect klayout-persist
|
||||
[
|
||||
{
|
||||
"CreatedAt": "2018-12-18T15:01:48Z",
|
||||
"Driver": "local",
|
||||
"Labels": {},
|
||||
"Mountpoint": "/var/lib/docker/volumes/klayout-persist/_data",
|
||||
"Name": "klayout-persist",
|
||||
"Options": {},
|
||||
"Scope": "local"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Step 3.
|
||||
|
||||
Build image `myimage` with:
|
||||
|
||||
```bash
|
||||
$ docker build -t myimage:latest -f Dockerfile.x86_64 .
|
||||
```
|
||||
|
||||
This creates an image called `myimage` (temporary). This image will not overwrite old ones. Tip: prune old, unused images with `docker image prune`.
|
||||
|
||||
Then I run the docker with a terminal shell and load the volume klayout-persist in /persist:
|
||||
|
||||
```bash
|
||||
$ docker run --name klayout --mount source=klayout-persist,target=/persist -it myimage
|
||||
```
|
||||
|
||||
## Step 4.
|
||||
|
||||
In the shell, pull master from klayout.
|
||||
|
||||
```bash
|
||||
cd /persist
|
||||
git clone https://github.com/lightwave-lab/klayout.git
|
||||
mkdir -p wheelhouse
|
||||
cd klayout
|
||||
# make wheel with python 3.6 (for example)
|
||||
/opt/python/cp36-cp36m/bin/python setup.py bdist_wheel -d /persist/wheelhouse/
|
||||
cd /persist
|
||||
auditwheel repair "wheelhouse/klayout-0.26.0.dev8-cp36-cp36m-linux_x86_64.whl" -w wheelhouse/
|
||||
# Need to manually fix the wheel
|
||||
#/opt/python/cp36-cp36m/bin/pip install klayout --no-index -f /wheelhouse
|
||||
```
|
||||
|
||||
The produced wheel from auditwheel, klayout-0.26.0.dev8-cp36-cp36m-manylinux1_x86_64.whl, is defective in the following way: dbcore.so etc. have RPATHs reset to `$ORIGIN/.libs`, so we need to move all .so's `lib_*` into `.libs`, as well as `db_plugins`. We also need to change the dist-info/RECORD file paths. This is a bug from auditwheel, it should either have added a new RPATH, $ORIGIN/.libs, where it places libz, libcurl, libexpat, instead of renaming the existing ones, or moved the files to the right place.
|
||||
|
||||
|
||||
Procedure to fix the wheel:
|
||||
|
||||
```bash
|
||||
unzip wheelhouse/klayout-0.26.0.dev8-cp36-cp36m-manylinux1_x86_64.whl -d tempwheel
|
||||
cd tempwheel/klayout
|
||||
mv lib_* db_plugins .libs/
|
||||
cd ../klayout-0.26.0.dev8.dist-info/
|
||||
sed -i 's/^klayout\/lib_/klayout\/.libs\/lib_/g' RECORD
|
||||
sed -i 's/^klayout\/db_plugins/klayout\/.libs\/db_plugins/g' RECORD
|
||||
cd ../
|
||||
rm -f ../wheelhouse/klayout-0.26.0.dev8-cp36-cp36m-manylinux1_x86_64.whl
|
||||
zip -r ../wheelhouse/klayout-0.26.0.dev8-cp36-cp36m-manylinux1_x86_64.whl ./*
|
||||
cd ..
|
||||
rm -rf tempwheel
|
||||
```
|
||||
|
||||
Now we can install and test:
|
||||
```bash
|
||||
/opt/python/cp36-cp36m/bin/pip install klayout --no-index -f /persist/wheelhouse
|
||||
cd /persist/klayout
|
||||
/opt/python/cp36-cp36m/bin/python -m unittest testdata/pymod/import_db.py testdata/pymod/import_rdb.py testdata/pymod/import_tl.py
|
||||
# Tests passed!
|
||||
```
|
||||
|
||||
Encoded this behavior in a script called fix_wheel.sh. now you only need to run `./fix_wheel.sh wheelhouse/klayout-0.26.0.dev8-cp36-cp36m-manylinux1_x86_64.whl`, and it will overwrite the wheel.
|
||||
|
||||
## Step 5. Iterate over all python versions.
|
||||
|
||||
For that, we need something like:
|
||||
|
||||
```bash
|
||||
# Compile wheels
|
||||
for PYBIN in /opt/python/*/bin; do
|
||||
"${PYBIN}/python" setup.py bdist_wheel -d /persist/wheelhouse/
|
||||
done
|
||||
|
||||
# Bundle external shared libraries into the wheels via auditwheel
|
||||
for whl in /persist/wheelhouse/*linux_*.whl; do
|
||||
auditwheel repair "$whl" -w /persist/wheelhouse/
|
||||
done
|
||||
|
||||
# Fix each wheel generated by auditwheel
|
||||
for whl in /persist/wheelhouse/*manylinux1_*.whl; do
|
||||
./ci-scripts/docker/fix_wheel.sh "$whl"
|
||||
done
|
||||
|
||||
# Install packages and test
|
||||
TEST_HOME=/persist/klayout/testdata
|
||||
for PYBIN in /opt/python/*/bin/; do
|
||||
"${PYBIN}/pip" install klayout --no-index -f /persist/wheelhouse
|
||||
"${PYBIN}/python" $TEST_HOME/pymod/import_db.py
|
||||
"${PYBIN}/python" $TEST_HOME/pymod/import_rdb.py
|
||||
"${PYBIN}/python" $TEST_HOME/pymod/import_tl.py
|
||||
|
||||
```
|
||||
|
||||
I tested step 1-5 with both quay.io/pypa/manylinux1_x86_64 and quay.io/pypa/manylinux1_i686. So far the only failure was with `cp27-cp27mu` which gave this import error:
|
||||
|
||||
`ImportError: /opt/python/cp27-cp27mu/lib/python2.7/site-packages/klayout/.libs/lib_pya.so: undefined symbol: PyUnicodeUCS2_AsUTF8String`
|
||||
|
||||
I noticed that the ccache folder ended up with 800MB. I was hoping that the gcc compilation could reuse a lot of previously built objects but that didn't happen. I think that's because each python comes with its own header. So going forward it doesn't make sense to create a docker image for every python version. I will just cache a ccache folder via travis.
|
||||
The ccache folder after a single build has 657MB. Go figure.
|
||||
|
||||
I discovered that fix_wheel script was actually not properly working. So instead I looked into fixing `auditwheel` directly. Here's the commit that fixes it: https://github.com/thomaslima/auditwheel/tree/87f5306ec02cc68020afaa9933543c898b1d47c1
|
||||
|
||||
So now the plan is to change the `docker_build.sh` script so it uses the proper auditwheel, instead of their default.
|
||||
|
||||
# Chapter 2. Testing CI flow with docker
|
||||
|
||||
# Step 1. Testing commands in own computer
|
||||
|
||||
First cloned with:
|
||||
```bash
|
||||
git clone git@github.com:lightwave-lab/klayout.git -b tmp/manylinux
|
||||
cd klayout
|
||||
```
|
||||
|
||||
Let's work with a few environment variables, like in https://github.com/pypa/python-manylinux-demo/blob/master/.travis.yml
|
||||
|
||||
DOCKER_IMAGE options: quay.io/pypa/manylinux1_x86_64 quay.io/pypa/manylinux1_i686
|
||||
|
||||
PY_VERSION options: cp27-cp27m cp27-cp27mu cp34-cp34m cp35-cp35m cp36-cp36m cp37-cp37m
|
||||
|
||||
Total of 2x6 = 12 possibilities
|
||||
|
||||
```bash
|
||||
export DOCKER_IMAGE=quay.io/pypa/manylinux1_x86_64
|
||||
export PY_VERSION="cp36-cp36m"
|
||||
docker pull $DOCKER_IMAGE
|
||||
mkdir -p ccache
|
||||
mkdir -p wheelhouse
|
||||
docker run --name klayout -v `pwd` -it $DOCKER_IMAGE
|
||||
```
|
||||
|
||||
Inside docker shell:
|
||||
```bash
|
||||
yum install -y zlib-devel
|
||||
yum install -y zip
|
||||
|
||||
yum install -y ccache
|
||||
ln -s /usr/bin/ccache /usr/lib64/ccache/c++
|
||||
ln -s /usr/bin/ccache /usr/lib64/ccache/cc
|
||||
ln -s /usr/bin/ccache /usr/lib64/ccache/gcc
|
||||
ln -s /usr/bin/ccache /usr/lib64/ccache/g++
|
||||
echo $PATH
|
||||
# /usr/lib64/ccache:/opt/rh/devtoolset-2/root/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
export CCACHE_DIR="/io/ccache"
|
||||
|
||||
# Compile wheel
|
||||
/opt/python/$PY_VERSION/bin/python setup.py bdist_wheel -d /io/wheelhouse/
|
||||
|
||||
# Bundle external shared libraries into the wheels via auditwheel
|
||||
for whl in /io/wheelhouse/*linux_*.whl; do
|
||||
auditwheel repair "$whl" -w /io/wheelhouse/
|
||||
done
|
||||
|
||||
# Fix each wheel generated by auditwheel
|
||||
for whl in /io/wheelhouse/*manylinux1_*.whl; do
|
||||
./ci-scripts/docker/fix_wheel.sh "$whl"
|
||||
done
|
||||
|
||||
```
|
||||
|
||||
# Step 2. Automating step 1 in travis (CI).
|
||||
DOCKER_IMAGE options: quay.io/pypa/manylinux1_x86_64 quay.io/pypa/manylinux1_i686
|
||||
|
||||
PY_VERSION options: cp27-cp27m cp27-cp27mu cp34-cp34m cp35-cp35m cp36-cp36m cp37-cp37m
|
||||
|
||||
Build: spawn 12 travis jobs, one for each combination of word-size and python version.
|
||||
Output: populated ./ccache with compiled objects and wheels inside ./wheelhouse/, one useless, `*linux_*.whl` and one useful `*manylinux1_*.whl`.
|
||||
Post-build:
|
||||
- cache `./ccache`
|
||||
- deploy `./wheelhouse/*manylinux1_*.whl` to dropbox (./deploy folder)
|
||||
|
||||
# Step 3. Automating deployment to PyPI:
|
||||
|
||||
TBD
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
SCRIPT_NAME=`basename "$0"`
|
||||
TMP_WHEEL="/tmp/klayout_tempwheel"
|
||||
|
||||
display_usage() {
|
||||
echo "This script fixes auditwheel-repaired wheels."
|
||||
echo "Caution: This will delete the original wheel."
|
||||
echo -e "\nUsage:\n./${SCRIPT_NAME} [--help|-h] klayout-...-manylinux1_x86_64.whl \n"
|
||||
}
|
||||
|
||||
if [[ ( $1 == "--help") || $1 == "-h" ]]
|
||||
then
|
||||
display_usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check number of arguments
|
||||
if [ $# -eq 0 ]; then
|
||||
>&2 echo -e "ERROR: No filename supplied\n"
|
||||
display_usage
|
||||
exit 1
|
||||
elif [ ! $# -eq 1 ]; then
|
||||
>&2 echo -e "ERROR: Too many files supplied. Provide one filename at at time.\n"
|
||||
display_usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Read wheel file from argument
|
||||
WHL="$1"
|
||||
|
||||
# Check WHL is a valid file
|
||||
if [[ ! -f "$WHL" ]]; then
|
||||
>&2 echo -e "ERROR: $WHL is not a file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Convert to absolute path (linux only)
|
||||
WHL=$(readlink -f $WHL)
|
||||
|
||||
# Record old current directory
|
||||
OLD_PWD=$PWD
|
||||
|
||||
# The produced wheel from auditwheel, klayout-*-manylinux1_x86_64.whl, is defective in the following way: dbcore.so etc. have RPATHs reset to `$ORIGIN/.libs`, so we need to move all .so's `lib_*` into `.libs`, as well as `db_plugins`. We also need to change the dist-info/RECORD file paths. This is a bug from auditwheel, it should either have added a new RPATH, $ORIGIN/.libs, where it places libz, libcurl, libexpat, instead of renaming the existing ones, or moved the files to the right place.
|
||||
|
||||
# Checking if it was previously patched
|
||||
if unzip -l $WHL | grep -q 'patched_after_auditwheel_repair'; then
|
||||
echo "$(basename $WHL) is already patched. Doing nothing."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Repair script below
|
||||
if [[ -d $TMP_WHEEL ]]; then
|
||||
rm -rf $TMP_WHEEL
|
||||
fi
|
||||
echo "Unpacking $WHL into $TMP_WHEEL"
|
||||
unzip -q $WHL -d $TMP_WHEEL
|
||||
|
||||
cd $TMP_WHEEL/klayout
|
||||
echo "Moving files: mv lib_* db_plugins .libs/"
|
||||
mv lib_* db_plugins .libs/ 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
>&2 echo "ERROR: lib_*.so or db_plubins not found. Quitting."
|
||||
exit 1
|
||||
fi
|
||||
cd ../klayout-*.dist-info/
|
||||
echo "Patching klayout-*.dist-info/RECORD"
|
||||
sed -i 's/^klayout\/lib_/klayout\/.libs\/lib_/g' RECORD
|
||||
sed -i 's/^klayout\/db_plugins/klayout\/.libs\/db_plugins/g' RECORD
|
||||
cd ../
|
||||
touch $TMP_WHEEL/patched_after_auditwheel_repair
|
||||
echo "Packing $WHL from $TMP_WHEEL"
|
||||
rm -f $WHL
|
||||
zip -rq $WHL ./*
|
||||
echo "Done. $(basename $WHL) is patched."
|
||||
# Cleanup (should always execute)
|
||||
cd $OLD_PWD
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#!/bin/bash
|
||||
# run with docker run --rm -v `pwd`:/io $DOCKER_IMAGE $PRE_CMD /io/ci-scripts/manylinux-docker.sh
|
||||
# see https://github.com/pypa/python-manylinux-demo/blob/master/.travis.yml
|
||||
# cache using https://github.com/travis-ci/travis-ci/issues/5358
|
||||
set -e -x
|
||||
|
||||
# Install a system package required by our library
|
||||
yum install -y zlib-devel
|
||||
yum install -y ccache
|
||||
ln -s /usr/bin/ccache /usr/lib64/ccache/c++
|
||||
ln -s /usr/bin/ccache /usr/lib64/ccache/cc
|
||||
ln -s /usr/bin/ccache /usr/lib64/ccache/gcc
|
||||
ln -s /usr/bin/ccache /usr/lib64/ccache/g++
|
||||
# export PATH=/usr/lib64/ccache:$PATH # unnecessary
|
||||
|
||||
# Compile wheels
|
||||
for PYBIN in /opt/python/*/bin; do
|
||||
"${PYBIN}/python" setup.py bdist_wheel -d /persist/wheelhouse/
|
||||
done
|
||||
|
||||
# Bundle external shared libraries into the wheels via auditwheel
|
||||
for whl in /persist/wheelhouse/*linux_*.whl; do
|
||||
auditwheel repair "$whl" -w /persist/wheelhouse/
|
||||
done
|
||||
|
||||
# Fix each wheel generated by auditwheel
|
||||
for whl in /persist/wheelhouse/*manylinux1_*.whl; do
|
||||
./ci-scripts/docker/fix_wheel.sh "$whl"
|
||||
done
|
||||
|
||||
# Install packages and test
|
||||
TEST_HOME=/persist/klayout/testdata
|
||||
for PYBIN in /opt/python/*/bin/; do
|
||||
"${PYBIN}/pip" install klayout --no-index -f /persist/wheelhouse
|
||||
"${PYBIN}/python" $TEST_HOME/pymod/import_db.py
|
||||
"${PYBIN}/python" $TEST_HOME/pymod/import_rdb.py
|
||||
"${PYBIN}/python" $TEST_HOME/pymod/import_tl.py
|
||||
done
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
if [[ -z $PY_VERSION ]]; then
|
||||
echo '$PY_VERSION is not set'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z $DOCKER_IMAGE ]]; then
|
||||
echo '$DOCKER_IMAGE is not set'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo PY_VERSION=$PY_VERSION
|
||||
echo DOCKER_IMAGE=$DOCKER_IMAGE
|
||||
|
||||
# sometimes the epel server is down. retry 5 times
|
||||
for i in $(seq 1 5); do
|
||||
yum install -y zlib-devel ccache zip git && s=0 && break || s=$? && sleep 15;
|
||||
done
|
||||
|
||||
[ $s -eq 0 ] || exit $s
|
||||
|
||||
if [[ $DOCKER_IMAGE == "quay.io/pypa/manylinux1_x86_64" ]]; then
|
||||
ln -s /usr/bin/ccache /usr/lib64/ccache/c++
|
||||
ln -s /usr/bin/ccache /usr/lib64/ccache/cc
|
||||
ln -s /usr/bin/ccache /usr/lib64/ccache/gcc
|
||||
ln -s /usr/bin/ccache /usr/lib64/ccache/g++
|
||||
export PATH="/usr/lib64/ccache/:$PATH"
|
||||
elif [[ $DOCKER_IMAGE == "quay.io/pypa/manylinux1_i686" ]]; then
|
||||
ln -s /usr/bin/ccache /usr/lib/ccache/c++
|
||||
ln -s /usr/bin/ccache /usr/lib/ccache/cc
|
||||
ln -s /usr/bin/ccache /usr/lib/ccache/gcc
|
||||
ln -s /usr/bin/ccache /usr/lib/ccache/g++
|
||||
export PATH="/usr/lib/ccache/:$PATH"
|
||||
fi
|
||||
echo $PATH
|
||||
export CCACHE_DIR="/io/ccache"
|
||||
|
||||
# Download proper auditwheel program
|
||||
git clone https://github.com/thomaslima/auditwheel.git /tmp/auditwheel
|
||||
cd /tmp/auditwheel
|
||||
git checkout 87f5306ec02cc68020afaa9933543c898b1d47c1 # patched version
|
||||
AUDITWHEEL_PYTHON=$(cat `which auditwheel` | head -1 | sed -e 's/#!\(.*\)/\1/')
|
||||
# Install auditwheel, replacing the system's auditwheel binary
|
||||
$AUDITWHEEL_PYTHON -m pip install .
|
||||
|
||||
|
||||
# Show ccache stats
|
||||
echo "Cache stats:"
|
||||
ccache -s
|
||||
|
||||
# Compile wheel
|
||||
cd /io
|
||||
"/opt/python/$PY_VERSION/bin/python" setup.py bdist_wheel -d /io/wheelhouse/ || exit 1
|
||||
|
||||
# Show ccache stats
|
||||
echo "Cache stats:"
|
||||
ccache -s
|
||||
|
||||
# Bundle external shared libraries into the wheels via auditwheel
|
||||
for whl in /io/wheelhouse/*linux_*.whl; do
|
||||
auditwheel -v repair "$whl" -w /io/wheelhouse/ || exit 1
|
||||
done
|
||||
|
||||
# Install packages and test
|
||||
TEST_HOME=/io/testdata
|
||||
"/opt/python/$PY_VERSION/bin/pip" install klayout --no-index -f /io/wheelhouse || exit 1
|
||||
"/opt/python/$PY_VERSION/bin/python" $TEST_HOME/pymod/import_db.py || exit 1
|
||||
"/opt/python/$PY_VERSION/bin/python" $TEST_HOME/pymod/import_rdb.py || exit 1
|
||||
"/opt/python/$PY_VERSION/bin/python" $TEST_HOME/pymod/import_tl.py || exit 1
|
||||
"/opt/python/$PY_VERSION/bin/python" $TEST_HOME/pymod/pya_tests.py || exit 1
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
After building all the travis wheels, go to the folder where the wheels were deployed. In my case, for example, `/Users/tlima/Dropbox/Apps/travis-deploy/Builds/klayout/dist-pymod/0.26.0.dev10`.
|
||||
|
||||
Then, run the command
|
||||
|
||||
```bash
|
||||
travis upload *.whl
|
||||
```
|
||||
|
||||
, which will ask for an username and password related to your account.
|
||||
|
||||
After this upload was successful, you can upload the source tarball. Go to klayout's git folder and run `python setup.py sdist`. Inside `dist/`, you'll find a tarball named, e.g., `klayout-0.26.0.dev10.tar.gz`. So just run
|
||||
|
||||
```bash
|
||||
travis upload klayout-0.26.0.dev10.tar.gz
|
||||
```
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
SCRIPT_NAME=`basename "$0"`
|
||||
TMP_WHEEL="$PWD/tmp/klayout_tempwheel"
|
||||
|
||||
display_usage() {
|
||||
echo "This script includes external libraries in windows-based wheels."
|
||||
echo "Caution: This will delete the original wheel."
|
||||
echo -e "\nUsage:\n./${SCRIPT_NAME} [--help|-h] klayout-...-win_amd64.whl \n"
|
||||
}
|
||||
|
||||
if [[ ( $1 == "--help") || $1 == "-h" ]]
|
||||
then
|
||||
display_usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check number of arguments
|
||||
if [ $# -eq 0 ]; then
|
||||
>&2 echo -e "ERROR: No filename supplied\n"
|
||||
display_usage
|
||||
exit 1
|
||||
elif [ ! $# -eq 2 ]; then
|
||||
>&2 echo -e "ERROR: Too many files supplied. Provide one filename at at time.\n"
|
||||
display_usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Read wheel file from argument
|
||||
WHL="$1"
|
||||
WHL=$(echo $WHL | sed 's/\\/\//g' | sed 's/://')
|
||||
KLAYOUT_BITS="$2"
|
||||
KLAYOUT_BITS=$(echo $KLAYOUT_BITS | sed 's/\\/\//g' | sed 's/://')
|
||||
|
||||
|
||||
# Check WHL is a valid file
|
||||
if [[ ! -f "$WHL" ]]; then
|
||||
>&2 echo -e "ERROR: $WHL is not a file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Convert to absolute path (linux only)
|
||||
WHL=$(readlink -f $WHL)
|
||||
|
||||
# Record old current directory
|
||||
OLD_PWD=$PWD
|
||||
|
||||
# Need to include external DLLs (klayout bits) into wheel
|
||||
|
||||
# # Checking if it was previously patched
|
||||
# if unzip -l $WHL | grep -q 'patch_external_libraries_included'; then
|
||||
# echo "$(basename $WHL) is already patched. Doing nothing."
|
||||
# exit 0
|
||||
# fi
|
||||
|
||||
# Repair script below
|
||||
if [[ -d $TMP_WHEEL ]]; then
|
||||
rm -rf $TMP_WHEEL
|
||||
else
|
||||
mkdir -p $TMP_WHEEL
|
||||
fi
|
||||
echo "Unpacking $WHL inside $TMP_WHEEL"
|
||||
wheel unpack $WHL -d $TMP_WHEEL || exit 1
|
||||
TMP_WHEEL="$TMP_WHEEL/`ls $TMP_WHEEL`"
|
||||
|
||||
cd $TMP_WHEEL/klayout
|
||||
echo "Copying libraries: libcurl.dll, expat.dll, pthreadVCE2.dll, zlib1.dll"
|
||||
echo pwd: `pwd`
|
||||
cp -v $KLAYOUT_BITS/curl/bin/* .
|
||||
cp -v $KLAYOUT_BITS/expat/bin/* .
|
||||
cp -v $KLAYOUT_BITS/ptw/bin/* .
|
||||
cp -v $KLAYOUT_BITS/zlib/bin/* .
|
||||
# if [ $? -ne 0 ]; then
|
||||
# >&2 echo "ERROR: lib not found. Quitting."
|
||||
# exit 1
|
||||
# fi
|
||||
cd $TMP_WHEEL
|
||||
# touch $TMP_WHEEL/patch_external_libraries_included
|
||||
echo "Packing $WHL from $TMP_WHEEL"
|
||||
rm -f $WHL
|
||||
wheel pack $TMP_WHEEL -d `dirname $WHL` || exit 1
|
||||
echo "Done. $(basename $WHL) is patched."
|
||||
# Cleanup (should always execute)
|
||||
cd $OLD_PWD
|
||||
27
setup.py
27
setup.py
|
|
@ -59,13 +59,13 @@ from setuptools.extension import Extension, Library
|
|||
import glob
|
||||
import os
|
||||
import platform
|
||||
import distutils.sysconfig as sysconfig
|
||||
from distutils.errors import CompileError
|
||||
import distutils.command.build_ext
|
||||
import setuptools.command.build_ext
|
||||
import multiprocessing
|
||||
N_cores = multiprocessing.cpu_count()
|
||||
|
||||
|
||||
# monkey-patch for parallel compilation
|
||||
# from https://stackoverflow.com/questions/11013851/speeding-up-build-process-with-distutils
|
||||
def parallelCCompile(self, sources, output_dir=None, macros=None, include_dirs=None, debug=0, extra_preargs=None, extra_postargs=None, depends=None):
|
||||
|
|
@ -88,6 +88,7 @@ def parallelCCompile(self, sources, output_dir=None, macros=None, include_dirs=N
|
|||
n_tries = 2
|
||||
while n_tries > 0:
|
||||
try:
|
||||
print("Building", obj)
|
||||
self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
|
||||
except CompileError:
|
||||
n_tries -= 1
|
||||
|
|
@ -95,7 +96,7 @@ def parallelCCompile(self, sources, output_dir=None, macros=None, include_dirs=N
|
|||
else:
|
||||
break
|
||||
# convert to list, imap is evaluated on-demand
|
||||
list(multiprocessing.pool.ThreadPool(N).imap(_single_compile, objects))
|
||||
list(multiprocessing.pool.ThreadPool(N).map(_single_compile, objects))
|
||||
return objects
|
||||
|
||||
|
||||
|
|
@ -155,10 +156,10 @@ distutils.ccompiler.CCompiler.library_filename = patched_library_filename
|
|||
# for this ... We're patching this back now.
|
||||
|
||||
def always_link_shared_object(
|
||||
self, objects, output_libname, output_dir=None, libraries=None,
|
||||
library_dirs=None, runtime_library_dirs=None, export_symbols=None,
|
||||
debug=0, extra_preargs=None, extra_postargs=None, build_temp=None,
|
||||
target_lang=None):
|
||||
self, objects, output_libname, output_dir=None, libraries=None,
|
||||
library_dirs=None, runtime_library_dirs=None, export_symbols=None,
|
||||
debug=0, extra_preargs=None, extra_postargs=None, build_temp=None,
|
||||
target_lang=None):
|
||||
self.link(
|
||||
self.SHARED_LIBRARY, objects, output_libname,
|
||||
output_dir, libraries, library_dirs, runtime_library_dirs,
|
||||
|
|
@ -166,6 +167,7 @@ def always_link_shared_object(
|
|||
build_temp, target_lang
|
||||
)
|
||||
|
||||
|
||||
setuptools.command.build_ext.libtype = "shared"
|
||||
setuptools.command.build_ext.link_shared_object = always_link_shared_object
|
||||
|
||||
|
|
@ -320,7 +322,7 @@ class Config(object):
|
|||
"""
|
||||
Gets the version string
|
||||
"""
|
||||
return "0.26.0.dev8"
|
||||
return "0.26.0.dev11"
|
||||
|
||||
|
||||
config = Config()
|
||||
|
|
@ -496,6 +498,17 @@ if __name__ == '__main__':
|
|||
long_description='TODO',
|
||||
author='Matthias Koefferlein',
|
||||
author_email='matthias@klayout.de',
|
||||
classifiers=[
|
||||
# Recommended classifiers
|
||||
"Programming Language :: Python :: 2",
|
||||
"Programming Language :: Python :: 3",
|
||||
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
||||
"Operating System :: MacOS :: MacOS X",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
# Optional classifiers
|
||||
"Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
|
||||
],
|
||||
url='https://github.com/klayoutmatthias/klayout',
|
||||
packages=find_packages('src/pymod/distutils_src'),
|
||||
package_dir={'': 'src/pymod/distutils_src'}, # https://github.com/pypa/setuptools/issues/230
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ gsi::Class<db::Technology> technology_decl ("db", "Technology",
|
|||
gsi::method ("load", &db::Technology::load, gsi::arg ("file"),
|
||||
"@brief Loads the technology definition from a file\n"
|
||||
) +
|
||||
gsi::method ("load", &db::Technology::save, gsi::arg ("file"),
|
||||
gsi::method ("save", &db::Technology::save, gsi::arg ("file"),
|
||||
"@brief Saves the technology definition to a file\n"
|
||||
) +
|
||||
gsi::method ("technology_names", &technology_names,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ A &A::operator= (const A &a)
|
|||
return *this;
|
||||
}
|
||||
|
||||
int A::a0 ()
|
||||
int A::instance_count ()
|
||||
{
|
||||
return a_count;
|
||||
}
|
||||
|
|
@ -780,6 +780,7 @@ static gsi::QFlagsClass<Enum> decl_qflags_enum ("", "Enums");
|
|||
|
||||
static gsi::Class<A> decl_a ("", "A",
|
||||
gsi::constructor ("new_a|new", &a_ctor) +
|
||||
gsi::method ("instance_count", &A::instance_count) +
|
||||
gsi::method ("br", &A::br) +
|
||||
gsi::method ("get_e", &A::get_e) +
|
||||
gsi::method ("get_eptr", &A::get_eptr) +
|
||||
|
|
@ -814,7 +815,6 @@ static gsi::Class<A> decl_a ("", "A",
|
|||
gsi::method ("af?|af", &A::af1) +
|
||||
gsi::method ("aa", &A::a) +
|
||||
gsi::method ("aa", &A::a_static) +
|
||||
gsi::method ("a0", &A::a0) +
|
||||
gsi::method ("a1", &A::a1) +
|
||||
gsi::method ("a1c", &A::a1c) +
|
||||
gsi::method ("a2", &A::a2) +
|
||||
|
|
@ -904,22 +904,22 @@ static gsi::Class<B> decl_b ("", "B",
|
|||
gsi::method ("b5", &B::b5) +
|
||||
gsi::method ("b5a", &B::b5a) +
|
||||
gsi::method ("b5b", &B::b5b) +
|
||||
gsi::method ("b6|make_a", &B::b6) +
|
||||
gsi::method ("b8|set_an", &B::b8) +
|
||||
gsi::method ("b9|an", &B::b9) +
|
||||
gsi::method ("b8cref|set_an_cref", &B::b8) +
|
||||
gsi::method ("b9cref|an_cref", &B::b9) +
|
||||
gsi::method ("make_a", &B::make_a) +
|
||||
gsi::method ("set_an", &B::set_an) +
|
||||
gsi::method ("an", &B::an) +
|
||||
gsi::method ("set_an_cref", &B::set_an_cref) +
|
||||
gsi::method ("an_cref", &B::an_cref) +
|
||||
// implemented by extension below:
|
||||
// gsi::iterator_ext ("b10", &b10b_ext, &b10e_ext) +
|
||||
gsi::iterator ("b10_nc", &B::b10b_nc, &B::b10e_nc) +
|
||||
gsi::iterator ("b11", &B::b11b, &B::b11e) +
|
||||
gsi::iterator ("b12", &B::b12b, &B::b12e) +
|
||||
gsi::iterator ("b13", &B::b13b, &B::b13e) +
|
||||
gsi::method ("b14a|amember_or_nil", &B::amember_or_nil) +
|
||||
gsi::method ("b14b|amember_ptr", &B::amember_ptr) +
|
||||
gsi::method ("b7|b14c|amember_cptr", &B::amember_cptr) +
|
||||
gsi::method ("b7c|amember_cref", &B::amember_cref) +
|
||||
gsi::method ("b7d|amember_ref", &B::amember_ref) +
|
||||
gsi::method ("amember_or_nil_alt|amember_or_nil", &B::amember_or_nil) +
|
||||
gsi::method ("amember_ptr_alt|amember_ptr", &B::amember_ptr) +
|
||||
gsi::method ("xxx|amember_cptr", &B::amember_cptr) +
|
||||
gsi::method ("yyy|amember_cref", &B::amember_cref) +
|
||||
gsi::method ("zzz|amember_ref", &B::amember_ref) +
|
||||
gsi::method ("b15|arg_is_not_nil", &B::b15) +
|
||||
gsi::method ("b16a|av", &B::b16a) +
|
||||
gsi::method ("b16b|av_cref", &B::b16b) +
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ struct A
|
|||
void set_af (bool _f) { f = _f; }
|
||||
bool af1 (bool /*dummy*/) { return f; }
|
||||
|
||||
static int a0 ();
|
||||
static int instance_count ();
|
||||
int a1 () {
|
||||
return n;
|
||||
}
|
||||
|
|
@ -465,26 +465,26 @@ struct B
|
|||
return m.c_str ();
|
||||
}
|
||||
|
||||
A b6 (int n) {
|
||||
A make_a (int n) {
|
||||
return A(n);
|
||||
}
|
||||
|
||||
void b8 (int n)
|
||||
void set_an (int n)
|
||||
{
|
||||
a.n = n;
|
||||
}
|
||||
|
||||
int b9 (A a)
|
||||
int an (A a)
|
||||
{
|
||||
return a.n;
|
||||
}
|
||||
|
||||
void b8cref (const int &n)
|
||||
void set_an_cref (const int &n)
|
||||
{
|
||||
a.n = n;
|
||||
}
|
||||
|
||||
const int &b9cref (const A &a)
|
||||
const int &an_cref (const A &a)
|
||||
{
|
||||
return a.n;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,14 +38,14 @@ TEST(1)
|
|||
tl::Eval e;
|
||||
tl::Variant v;
|
||||
|
||||
v = e.parse ("A.a0").execute ();
|
||||
v = e.parse ("A.instance_count").execute ();
|
||||
int base_insts = v.to_int ();
|
||||
EXPECT_EQ (base_insts, 0);
|
||||
|
||||
v = e.parse ("A.new(35).to_s").execute ();
|
||||
EXPECT_EQ (v.to_string (), std::string ("A: 35"));
|
||||
|
||||
EXPECT_EQ (e.parse ("A.a0").execute ().to_int (), 0);
|
||||
EXPECT_EQ (e.parse ("A.instance_count").execute ().to_int (), 0);
|
||||
|
||||
// mapping of to_string to to_s method
|
||||
v = e.parse ("A.new(35)").execute ();
|
||||
|
|
@ -97,11 +97,11 @@ TEST(1)
|
|||
EXPECT_EQ (v.to_string (), std::string ("0.125"));
|
||||
v = e.parse ("a.a4([5, 1, -1.25])").execute ();
|
||||
EXPECT_EQ (v.to_string (), std::string ("-1.25"));
|
||||
v = e.parse ("A.a0").execute ();
|
||||
v = e.parse ("A.instance_count").execute ();
|
||||
EXPECT_EQ (v.to_int (), base_insts + 1); // one instance more
|
||||
v = e.parse ("a=1; A.a0").execute ();
|
||||
v = e.parse ("a=1; A.instance_count").execute ();
|
||||
EXPECT_EQ (v.to_int (), base_insts); // remaining instances
|
||||
v = e.parse ("A.a0").execute ();
|
||||
v = e.parse ("A.instance_count").execute ();
|
||||
EXPECT_EQ (v.to_int (), base_insts); // remaining instances
|
||||
|
||||
v = e.parse ("var a1=A.new; a1.a5(-15); var a2=a1.dup; a2.a5(107); a1.a1").execute ();
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@
|
|||
<version>Version</version>
|
||||
<title>Title of the package</title>
|
||||
<doc>A brief description</doc>
|
||||
<doc_url>Documentation URL</doc_url>
|
||||
<doc-url>Documentation URL</doc-url>
|
||||
<url>Download URL</url>
|
||||
<license>License model</license>
|
||||
<icon>Icon image: base64-encoded, 64x64 max, PNG preferred</icon>
|
||||
|
|
|
|||
|
|
@ -450,7 +450,7 @@ void install_signal_handlers ()
|
|||
act.sa_sigaction = signal_handler;
|
||||
sigemptyset (&act.sa_mask);
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
#if !defined(__APPLE__)
|
||||
#if !defined(__APPLE__) && !defined(__OpenBSD__)
|
||||
act.sa_restorer = 0;
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -33,17 +33,14 @@
|
|||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<widget class="QFrame" name="tech_frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
|
|
@ -56,17 +53,17 @@
|
|||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="tech_cbx"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="tech_cbx_label">
|
||||
<property name="text">
|
||||
<string>Technology to be associated with layout</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="tech_cbx"/>
|
||||
</item>
|
||||
<item>
|
||||
<item row="0" column="2">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
|
@ -79,25 +76,25 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ LoadLayoutOptionsDialog::update ()
|
|||
}
|
||||
|
||||
const db::Technology *tech = m_tech_array [m_technology_index];
|
||||
mp_ui->options_tab->setEnabled (tech && tech->is_persisted ());
|
||||
mp_ui->options_tab->setEnabled (!tech || tech->is_persisted ());
|
||||
|
||||
for (std::vector< std::pair<StreamReaderOptionsPage *, std::string> >::iterator page = m_pages.begin (); page != m_pages.end (); ++page) {
|
||||
if (page->first) {
|
||||
|
|
@ -240,6 +240,7 @@ LoadLayoutOptionsDialog::edit_global_options (lay::PluginRoot *config_root, db::
|
|||
|
||||
mp_ui->tech_cbx->blockSignals (false);
|
||||
mp_ui->tech_cbx->show ();
|
||||
mp_ui->tech_frame->show ();
|
||||
|
||||
if (get_options_internal ()) {
|
||||
|
||||
|
|
@ -271,7 +272,7 @@ LoadLayoutOptionsDialog::edit_global_options (lay::PluginRoot *config_root, db::
|
|||
bool
|
||||
LoadLayoutOptionsDialog::get_options (db::LoadLayoutOptions &options)
|
||||
{
|
||||
mp_ui->tech_cbx->hide ();
|
||||
mp_ui->tech_frame->hide ();
|
||||
mp_ui->always_cbx->hide ();
|
||||
|
||||
m_opt_array.clear ();
|
||||
|
|
|
|||
|
|
@ -154,11 +154,11 @@ BasicText::produce (const db::Layout &layout, const std::vector<unsigned int> &l
|
|||
const db::TextGenerator &font = db::TextGenerator::generators ()[f];
|
||||
|
||||
double m = parameters [p_magnification].to_double ();
|
||||
db::Coord b = parameters [p_bias].to_double ();
|
||||
double b = parameters [p_bias].to_double ();
|
||||
bool inv = parameters [p_inverse].to_bool ();
|
||||
|
||||
db::Coord dx = parameters [p_char_spacing].to_double ();
|
||||
db::Coord dy = parameters [p_line_spacing].to_double ();
|
||||
double dx = parameters [p_char_spacing].to_double ();
|
||||
double dy = parameters [p_line_spacing].to_double ();
|
||||
|
||||
std::string t = parameters [p_text].to_string ();
|
||||
|
||||
|
|
|
|||
|
|
@ -538,7 +538,7 @@ PYAObjectBase::destroy ()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!m_can_destroy && m_obj) {
|
||||
if (! (m_owned || m_can_destroy) && m_obj) {
|
||||
throw tl::Exception (tl::to_string (tr ("Object cannot be destroyed explicitly")));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
# klayout library definition file
|
||||
|
||||
__all__ = [ "tl", "db", "lay", "rdb" ]
|
||||
__all__ = [ "tl", "db", "rdb" ]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
# import all packages from klayout, such as klayout.db and klayout.tl
|
||||
# WARNING: doing it manually until it becomes impractical
|
||||
# TODO: We need a specification document explaining what should go into pya
|
||||
|
||||
import klayout
|
||||
import importlib
|
||||
|
||||
__all__ = []
|
||||
for m in klayout.__all__:
|
||||
mod = importlib.import_module("klayout." + m)
|
||||
for mm in mod.__all__:
|
||||
globals()[mm] = getattr(mod, mm)
|
||||
|
||||
from klayout.db import * # noqa
|
||||
from klayout.tl import * # noqa
|
||||
from klayout.rdb import * # noqa
|
||||
|
|
|
|||
|
|
@ -364,7 +364,7 @@ Proxy::destroy ()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!m_can_destroy && m_obj) {
|
||||
if (! (m_owned || m_can_destroy) && m_obj) {
|
||||
throw tl::Exception (tl::to_string (tr ("Object cannot be destroyed explicitly")));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -135,10 +135,10 @@ class BasicTest(unittest.TestCase):
|
|||
def test_00(self):
|
||||
|
||||
# all references of PA are released now:
|
||||
ac0 = pya.A.a0()
|
||||
ic0 = pya.A.instance_count()
|
||||
|
||||
a = pya.A.new_a(100)
|
||||
self.assertEqual( pya.A.a0(), ac0 + 1 )
|
||||
self.assertEqual( pya.A.instance_count(), ic0 + 1 )
|
||||
|
||||
a = pya.A()
|
||||
self.assertEqual(a.a1(), 17)
|
||||
|
|
@ -146,28 +146,28 @@ class BasicTest(unittest.TestCase):
|
|||
self.assertEqual(a.a1(), 110)
|
||||
|
||||
a = None
|
||||
self.assertEqual( pya.A.a0(), ac0 )
|
||||
self.assertEqual( pya.A.instance_count(), ic0 )
|
||||
|
||||
a = pya.A()
|
||||
self.assertEqual( pya.A.a0(), ac0 ) # delayed instantiation of detached objects - A is actually created if it is used first
|
||||
self.assertEqual( pya.A.instance_count(), ic0 ) # delayed instantiation of detached objects - A is actually created if it is used first
|
||||
a.a2() # just check, if it can be called
|
||||
self.assertEqual( pya.A.a0(), ac0 + 1 )
|
||||
self.assertEqual( pya.A.instance_count(), ic0 + 1 )
|
||||
|
||||
# open question: with ruby 1.8, aa is not deleted if the self.assertEqual is missing. Why?
|
||||
# maybe the GC does not like to be called that frequently?
|
||||
aa = a.dup()
|
||||
self.assertEqual( pya.A.a0(), ac0 + 2 )
|
||||
self.assertEqual( pya.A.instance_count(), ic0 + 2 )
|
||||
|
||||
aa = None
|
||||
self.assertEqual( pya.A.a0(), ac0 + 1 )
|
||||
self.assertEqual( pya.A.instance_count(), ic0 + 1 )
|
||||
|
||||
a = None
|
||||
self.assertEqual( pya.A.a0(), ac0 )
|
||||
self.assertEqual( pya.A.instance_count(), ic0 )
|
||||
|
||||
a = pya.A()
|
||||
self.assertEqual( pya.A.a0(), ac0 ) # delayed instantiation of detached objects - A is actually created if it is used first
|
||||
self.assertEqual( pya.A.instance_count(), ic0 ) # delayed instantiation of detached objects - A is actually created if it is used first
|
||||
a.a2() # just check, if it can be called
|
||||
self.assertEqual( pya.A.a0(), ac0 + 1 )
|
||||
self.assertEqual( pya.A.instance_count(), ic0 + 1 )
|
||||
|
||||
# static and non-static methods can be mixed, but they will be made non-ambiguous too
|
||||
self.assertEqual( pya.A.aa(), "static_a" )
|
||||
|
|
@ -219,7 +219,7 @@ class BasicTest(unittest.TestCase):
|
|||
self.assertEqual(arr, [5, 1, -1.25])
|
||||
|
||||
a.destroy()
|
||||
self.assertEqual( pya.A.a0(), ac0 )
|
||||
self.assertEqual( pya.A.instance_count(), ic0 )
|
||||
|
||||
if not leak_check:
|
||||
|
||||
|
|
@ -237,13 +237,13 @@ class BasicTest(unittest.TestCase):
|
|||
error_caught = True
|
||||
self.assertEqual( error_caught, True )
|
||||
|
||||
self.assertEqual( pya.A.a0(), ac0 )
|
||||
self.assertEqual( pya.A.instance_count(), ic0 )
|
||||
a = pya.A.new_a( 55 )
|
||||
self.assertEqual( pya.A.a0(), ac0 + 1 )
|
||||
self.assertEqual( pya.A.instance_count(), ic0 + 1 )
|
||||
self.assertEqual( a.a1(), 55 )
|
||||
self.assertEqual( a.a_vp1( a.a_vp2() ), "abc" )
|
||||
a.destroy()
|
||||
self.assertEqual( pya.A.a0(), ac0 )
|
||||
self.assertEqual( pya.A.instance_count(), ic0 )
|
||||
|
||||
a = pya.A.new_a(0)
|
||||
self.assertEqual( str(a.a9a(5)), "True" )
|
||||
|
|
@ -594,12 +594,12 @@ class BasicTest(unittest.TestCase):
|
|||
|
||||
err_caught = False
|
||||
try:
|
||||
b.b7().a1() # cannot call non-const method on const reference
|
||||
b.amember_cptr().a1() # cannot call non-const method on const reference
|
||||
except:
|
||||
err_caught = True
|
||||
self.assertEqual( err_caught, True )
|
||||
|
||||
b.b7().a2()
|
||||
b.amember_cptr().a2()
|
||||
|
||||
self.assertEqual( b.b1(), 5 )
|
||||
self.assertEqual( b.b2(), "" )
|
||||
|
|
@ -973,50 +973,58 @@ class BasicTest(unittest.TestCase):
|
|||
# test copies of objects being returned
|
||||
|
||||
b = pya.B()
|
||||
b._create() # force constructor of B to allocate some A instances internally
|
||||
|
||||
a = b.b6( 1971 );
|
||||
a_count = pya.A.instance_count()
|
||||
a = b.make_a( 1971 );
|
||||
self.assertEqual( pya.A.instance_count(), a_count + 1 )
|
||||
self.assertEqual( a.a1(), 1971 );
|
||||
self.assertEqual( b.b9( a ), 1971 );
|
||||
self.assertEqual( b.an( a ), 1971 );
|
||||
|
||||
aa = b.b6( -61 );
|
||||
self.assertEqual( b.b9cref( aa ), -61 );
|
||||
aa = b.make_a( -61 );
|
||||
self.assertEqual( pya.A.instance_count(), a_count + 2 )
|
||||
self.assertEqual( b.an_cref( aa ), -61 );
|
||||
self.assertEqual( a.a1(), 1971 );
|
||||
self.assertEqual( b.b9( a ), 1971 );
|
||||
self.assertEqual( b.an( a ), 1971 );
|
||||
self.assertEqual( aa.a1(), -61 );
|
||||
self.assertEqual( b.b9( aa ), -61 );
|
||||
self.assertEqual( b.an( aa ), -61 );
|
||||
|
||||
aa.a5(98);
|
||||
a.a5(100);
|
||||
|
||||
self.assertEqual( a.a1(), 100 );
|
||||
self.assertEqual( b.b9( a ), 100 );
|
||||
self.assertEqual( b.an( a ), 100 );
|
||||
self.assertEqual( aa.a1(), 98 );
|
||||
self.assertEqual( b.b9( aa ), 98 );
|
||||
self.assertEqual( b.an( aa ), 98 );
|
||||
|
||||
a._destroy()
|
||||
aa = None
|
||||
self.assertEqual( pya.A.instance_count(), a_count )
|
||||
|
||||
def test_18(self):
|
||||
|
||||
# Test references to objects (returned by b.b7)
|
||||
# Test references to objects (returned by b.amember_cptr)
|
||||
|
||||
b = pya.B()
|
||||
b.b8( 77 )
|
||||
self.assertEqual( b.b7().a1c(), 77 );
|
||||
b.set_an( 77 )
|
||||
self.assertEqual( b.amember_cptr().a1c(), 77 );
|
||||
|
||||
b.b8cref( 79 )
|
||||
self.assertEqual( b.b7().a1c(), 79 );
|
||||
b.set_an_cref( 79 )
|
||||
self.assertEqual( b.amember_cptr().a1c(), 79 );
|
||||
|
||||
aref = b.b7()
|
||||
aref = b.amember_cptr()
|
||||
err_caught = False
|
||||
|
||||
if not leak_check:
|
||||
|
||||
try:
|
||||
x = aref.a1() # cannot call non-const method on const reference (as delivered by b7)
|
||||
x = aref.a1() # cannot call non-const method on const reference (as delivered by amember_cptr)
|
||||
except:
|
||||
err_caught = True
|
||||
self.assertEqual( err_caught, True )
|
||||
self.assertEqual( aref.a1c(), 79 );
|
||||
|
||||
b.b8( -1 )
|
||||
b.set_an( -1 )
|
||||
self.assertEqual( aref.a1c(), -1 );
|
||||
|
||||
def test_19(self):
|
||||
|
|
@ -1068,19 +1076,19 @@ class BasicTest(unittest.TestCase):
|
|||
|
||||
b = pya.B()
|
||||
|
||||
a1 = b.b14a( True )
|
||||
a2 = b.b14b()
|
||||
a1 = b.amember_or_nil_alt( True )
|
||||
a2 = b.amember_ptr_alt()
|
||||
self.assertEqual( a1.a1(), 17 )
|
||||
self.assertEqual( a2.a1(), 17 )
|
||||
a1.a5( 761 )
|
||||
self.assertEqual( a1.a1(), 761 )
|
||||
self.assertEqual( a2.a1(), 761 )
|
||||
|
||||
a1 = b.b14a( False )
|
||||
a1 = b.amember_or_nil( False )
|
||||
self.assertEqual( a1, None )
|
||||
|
||||
self.assertEqual( b.b15( b.b14b() ), True )
|
||||
self.assertEqual( b.b15( b.b14a( False ) ), False )
|
||||
self.assertEqual( b.b15( b.amember_ptr() ), True )
|
||||
self.assertEqual( b.b15( b.amember_or_nil( False ) ), False )
|
||||
self.assertEqual( b.b15( None ), False )
|
||||
|
||||
def test_21(self):
|
||||
|
|
@ -1094,9 +1102,9 @@ class BasicTest(unittest.TestCase):
|
|||
|
||||
b = pya.B()
|
||||
|
||||
# b14b() returns a pya.A object, but it cannot be extended dynamically by a method s ...
|
||||
b.b14b().s( 117 )
|
||||
self.assertEqual( b.b14b().g(), 117 )
|
||||
# amember_ptr() returns a pya.A object, but it cannot be extended dynamically by a method s ...
|
||||
b.amember_ptr().s( 117 )
|
||||
self.assertEqual( b.amember_ptr().g(), 117 )
|
||||
|
||||
n = 0
|
||||
|
||||
|
|
@ -1247,9 +1255,9 @@ class BasicTest(unittest.TestCase):
|
|||
self.assertEqual( b.bx("a", 15), 20.5 )
|
||||
self.assertEqual( b.b32("b", 25), 20.5 )
|
||||
|
||||
na = pya.A.a0() # instance count
|
||||
na = pya.A.instance_count() # instance count
|
||||
self.assertEqual(b.bx(a, 15), "aref+i")
|
||||
self.assertEqual(pya.A.a0(), na)
|
||||
self.assertEqual(pya.A.instance_count(), na)
|
||||
err_caught = False
|
||||
try:
|
||||
# cannot cast second argument to int
|
||||
|
|
@ -1258,7 +1266,7 @@ class BasicTest(unittest.TestCase):
|
|||
err_caught = True
|
||||
self.assertEqual(err_caught, True)
|
||||
# the exception thrown before must not leave an instance on the call stack:
|
||||
self.assertEqual(pya.A.a0(), na)
|
||||
self.assertEqual(pya.A.instance_count(), na)
|
||||
|
||||
err_caught = False
|
||||
try:
|
||||
|
|
@ -1368,52 +1376,52 @@ class BasicTest(unittest.TestCase):
|
|||
|
||||
# destruction of an instance via c++
|
||||
pya.A.a20(None)
|
||||
ac0 = pya.A.a0()
|
||||
ic0 = pya.A.instance_count()
|
||||
a = pya.A()
|
||||
a.create()
|
||||
self.assertEqual(a.destroyed(), False)
|
||||
self.assertEqual(pya.A.a0(), ac0 + 1)
|
||||
self.assertEqual(pya.A.instance_count(), ic0 + 1)
|
||||
pya.A.a20(a) # install static instance of A
|
||||
self.assertEqual(a.destroyed(), False)
|
||||
pya.A.a20(None)
|
||||
self.assertEqual(a.destroyed(), True)
|
||||
self.assertEqual(pya.A.a0(), ac0)
|
||||
self.assertEqual(pya.A.instance_count(), ic0)
|
||||
|
||||
a = pya.A()
|
||||
a.create()
|
||||
self.assertEqual(a.destroyed(), False)
|
||||
self.assertEqual(pya.A.a0(), ac0 + 1)
|
||||
self.assertEqual(pya.A.instance_count(), ic0 + 1)
|
||||
pya.A.a20(a) # install static instance of A
|
||||
self.assertEqual(a.destroyed(), False)
|
||||
self.assertEqual(pya.A.a0(), ac0 + 1)
|
||||
self.assertEqual(pya.A.instance_count(), ic0 + 1)
|
||||
pya.A.a20(a) # re-install static instance of A
|
||||
self.assertEqual(a.destroyed(), False)
|
||||
self.assertEqual(pya.A.a0(), ac0 + 1)
|
||||
self.assertEqual(pya.A.instance_count(), ic0 + 1)
|
||||
|
||||
# install another instance
|
||||
aa = pya.A()
|
||||
aa.create()
|
||||
self.assertEqual(aa.destroyed(), False)
|
||||
self.assertEqual(pya.A.a0(), ac0 + 2)
|
||||
self.assertEqual(pya.A.instance_count(), ic0 + 2)
|
||||
pya.A.a20(aa) # install static instance of A
|
||||
|
||||
# original one is destroyed now, only new instance remains
|
||||
self.assertEqual(a.destroyed(), True)
|
||||
self.assertEqual(aa.destroyed(), False)
|
||||
self.assertEqual(pya.A.a0(), ac0 + 1)
|
||||
self.assertEqual(pya.A.instance_count(), ic0 + 1)
|
||||
pya.A.a20(None) # discard installed instance
|
||||
self.assertEqual(aa.destroyed(), True)
|
||||
self.assertEqual(pya.A.a0(), ac0)
|
||||
self.assertEqual(pya.A.instance_count(), ic0)
|
||||
|
||||
# the same without create .. should work too, but not create an instance because of late
|
||||
# instantiation in default ctor
|
||||
a = pya.A()
|
||||
self.assertEqual(a.destroyed(), False)
|
||||
self.assertEqual(pya.A.a0(), ac0)
|
||||
self.assertEqual(pya.A.instance_count(), ic0)
|
||||
pya.A.a20(a) # install static instance of A
|
||||
self.assertEqual(a.destroyed(), False)
|
||||
pya.A.a20(None)
|
||||
self.assertEqual(pya.A.a0(), ac0)
|
||||
self.assertEqual(pya.A.instance_count(), ic0)
|
||||
self.assertEqual(a.destroyed(), True)
|
||||
|
||||
def test_26(self):
|
||||
|
|
@ -1463,36 +1471,36 @@ class BasicTest(unittest.TestCase):
|
|||
|
||||
# destruction of an instance via c++
|
||||
pya.A.a20(None)
|
||||
ac0 = pya.A.a0()
|
||||
ic0 = pya.A.instance_count()
|
||||
|
||||
a = pya.A()
|
||||
a._create()
|
||||
self.assertEqual(a._destroyed(), False)
|
||||
self.assertEqual(pya.A.a0(), ac0 + 1)
|
||||
self.assertEqual(pya.A.instance_count(), ic0 + 1)
|
||||
pya.A.a20(a)
|
||||
self.assertEqual(pya.A.a20_get() == None, False)
|
||||
# release A instance -> will delete it
|
||||
a = None
|
||||
self.assertEqual(pya.A.a0(), ac0)
|
||||
self.assertEqual(pya.A.instance_count(), ic0)
|
||||
self.assertEqual(pya.A.a20_get() == None, True)
|
||||
|
||||
a = pya.A()
|
||||
a._create()
|
||||
self.assertEqual(a.destroyed(), False)
|
||||
self.assertEqual(pya.A.a0(), ac0 + 1)
|
||||
self.assertEqual(pya.A.instance_count(), ic0 + 1)
|
||||
pya.A.a20(a) # install static instance of A
|
||||
self.assertEqual(pya.A.a20_get() == None, False)
|
||||
a._unmanage()
|
||||
# release A instance -> won't delete it since it is unmanaged
|
||||
a = None
|
||||
self.assertEqual(pya.A.a0(), ac0 + 1)
|
||||
self.assertEqual(pya.A.instance_count(), ic0 + 1)
|
||||
self.assertEqual(pya.A.a20_get() == None, False)
|
||||
|
||||
a = pya.A.a20_get()
|
||||
a._manage()
|
||||
# release A instance -> will be deleted since now it's managed again
|
||||
a = None
|
||||
self.assertEqual(pya.A.a0(), ac0)
|
||||
self.assertEqual(pya.A.instance_count(), ic0)
|
||||
self.assertEqual(pya.A.a20_get() == None, True)
|
||||
|
||||
def test_28(self):
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@ class Basic_TestClass < TestBase
|
|||
GC.start
|
||||
|
||||
# all references of A are released now:
|
||||
ac0 = RBA::A::a0
|
||||
assert_equal( ac0, 0 )
|
||||
ic0 = RBA::A::instance_count
|
||||
assert_equal( ic0, 0 )
|
||||
|
||||
a = RBA::A.new_a(100)
|
||||
assert_equal( RBA::A::a0, ac0 + 1 )
|
||||
assert_equal( RBA::A::instance_count, ic0 + 1 )
|
||||
|
||||
a = RBA::A.new
|
||||
assert_equal(a.a1, 17)
|
||||
|
|
@ -27,26 +27,26 @@ class Basic_TestClass < TestBase
|
|||
|
||||
a = nil
|
||||
GC.start
|
||||
assert_equal( RBA::A::a0, ac0 )
|
||||
assert_equal( RBA::A::instance_count, ic0 )
|
||||
|
||||
a = RBA::A.new
|
||||
assert_equal( RBA::A::a0, ac0 ) # delayed instantiation of detached objects - A is actually created if it is used first
|
||||
assert_equal( RBA::A::instance_count, ic0 ) # delayed instantiation of detached objects - A is actually created if it is used first
|
||||
a.a2 # just check, if it can be called
|
||||
assert_equal( RBA::A::a0, ac0 + 1 )
|
||||
assert_equal( RBA::A::instance_count, ic0 + 1 )
|
||||
|
||||
# open question: with ruby 1.8, aa is not deleted if the assert_equal is missing. Why?
|
||||
# maybe the GC does not like to be called that frequently?
|
||||
aa = a.dup
|
||||
assert_equal( RBA::A::a0, ac0 + 2 )
|
||||
assert_equal( RBA::A::instance_count, ic0 + 2 )
|
||||
|
||||
aa = nil
|
||||
GC.start
|
||||
|
||||
if RUBY_VERSION >= "1.9.0"
|
||||
# GC works differently in >=1.9.x - but no leak (verified with valgrind)
|
||||
ac0 = RBA::A::a0
|
||||
ic0 = RBA::A::instance_count
|
||||
else
|
||||
assert_equal( RBA::A::a0, ac0 + 1 )
|
||||
assert_equal( RBA::A::instance_count, ic0 + 1 )
|
||||
end
|
||||
|
||||
a = nil
|
||||
|
|
@ -54,15 +54,15 @@ class Basic_TestClass < TestBase
|
|||
|
||||
if RUBY_VERSION >= "1.9.0"
|
||||
# GC works differently in >=1.9.x - but no leak (verified with valgrind)
|
||||
ac0 = RBA::A::a0
|
||||
ic0 = RBA::A::instance_count
|
||||
else
|
||||
assert_equal( RBA::A::a0, ac0 )
|
||||
assert_equal( RBA::A::instance_count, ic0 )
|
||||
end
|
||||
|
||||
a = RBA::A.new
|
||||
assert_equal( RBA::A::a0, ac0 ) # delayed instantiation of detached objects - A is actually created if it is used first
|
||||
assert_equal( RBA::A::instance_count, ic0 ) # delayed instantiation of detached objects - A is actually created if it is used first
|
||||
a.a2 # just check, if it can be called
|
||||
assert_equal( RBA::A::a0, ac0 + 1 )
|
||||
assert_equal( RBA::A::instance_count, ic0 + 1 )
|
||||
|
||||
# mix of getters, setters, predicates
|
||||
assert_equal( a.af, false )
|
||||
|
|
@ -116,7 +116,7 @@ class Basic_TestClass < TestBase
|
|||
assert_equal(arr, [5, 1, -1.25])
|
||||
|
||||
a.destroy
|
||||
assert_equal( RBA::A::a0, ac0 )
|
||||
assert_equal( RBA::A::instance_count, ic0 )
|
||||
|
||||
if !$leak_check
|
||||
|
||||
|
|
@ -138,13 +138,13 @@ class Basic_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
assert_equal( RBA::A::a0, ac0 )
|
||||
assert_equal( RBA::A::instance_count, ic0 )
|
||||
a = RBA::A::new_a( 55 )
|
||||
assert_equal( RBA::A::a0, ac0 + 1 )
|
||||
assert_equal( RBA::A::instance_count, ic0 + 1 )
|
||||
assert_equal( a.a1, 55 )
|
||||
assert_equal( a.a_vp1( a.a_vp2 ), "abc" )
|
||||
a.destroy
|
||||
assert_equal( RBA::A::a0, ac0 )
|
||||
assert_equal( RBA::A::instance_count, ic0 )
|
||||
|
||||
a = RBA::A::new_a(0)
|
||||
assert_equal( a.a9a(5).to_s, "true" )
|
||||
|
|
@ -506,7 +506,7 @@ class Basic_TestClass < TestBase
|
|||
|
||||
err_caught = false
|
||||
begin
|
||||
b.b7.a1 # cannot call non-const method on const reference
|
||||
b.amember_cptr.a1 # cannot call non-const method on const reference
|
||||
rescue
|
||||
err_caught = true
|
||||
end
|
||||
|
|
@ -514,7 +514,7 @@ class Basic_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
b.b7.a2
|
||||
b.amember_cptr.a2
|
||||
|
||||
assert_equal( b.b1, 5 )
|
||||
assert_equal( b.b2, "" )
|
||||
|
|
@ -857,46 +857,57 @@ class Basic_TestClass < TestBase
|
|||
# test copies of objects being returned
|
||||
|
||||
b = RBA::B.new
|
||||
b._create
|
||||
|
||||
a = b.b6( 1971 );
|
||||
assert_equal( a.a1, 1971 );
|
||||
assert_equal( b.b9( a ), 1971 );
|
||||
GC.start
|
||||
a_count = RBA::A.instance_count
|
||||
a = b.make_a( 1971 );
|
||||
assert_equal( RBA::A.instance_count, a_count + 1 )
|
||||
|
||||
aa = b.b6( -61 );
|
||||
assert_equal( b.b9cref( aa ), -61 );
|
||||
assert_equal( a.a1, 1971 );
|
||||
assert_equal( b.b9( a ), 1971 );
|
||||
assert_equal( b.an( a ), 1971 );
|
||||
|
||||
aa = b.make_a( -61 );
|
||||
assert_equal( RBA::A.instance_count, a_count + 2 )
|
||||
assert_equal( b.an_cref( aa ), -61 );
|
||||
assert_equal( a.a1, 1971 );
|
||||
assert_equal( b.an( a ), 1971 );
|
||||
assert_equal( aa.a1, -61 );
|
||||
assert_equal( b.b9( aa ), -61 );
|
||||
assert_equal( b.an( aa ), -61 );
|
||||
|
||||
aa.a5 98;
|
||||
a.a5 100;
|
||||
|
||||
assert_equal( a.a1, 100 );
|
||||
assert_equal( b.b9( a ), 100 );
|
||||
assert_equal( b.an( a ), 100 );
|
||||
assert_equal( aa.a1, 98 );
|
||||
assert_equal( b.b9( aa ), 98 );
|
||||
assert_equal( b.an( aa ), 98 );
|
||||
|
||||
a._destroy
|
||||
aa = nil
|
||||
GC.start
|
||||
assert_equal( RBA::A.instance_count, a_count )
|
||||
|
||||
end
|
||||
|
||||
def test_18
|
||||
|
||||
# Test references to objects (returned by b.b7)
|
||||
# Test references to objects (returned by b.amember_cptr)
|
||||
|
||||
b = RBA::B.new
|
||||
b.b8( 77 )
|
||||
assert_equal( b.b7.a1c, 77 );
|
||||
b.set_an( 77 )
|
||||
assert_equal( b.amember_cptr.a1c, 77 );
|
||||
|
||||
b.b8cref( 79 )
|
||||
assert_equal( b.b7.a1c, 79 );
|
||||
b.set_an_cref( 79 )
|
||||
assert_equal( b.amember_cptr.a1c, 79 );
|
||||
|
||||
aref = b.b7
|
||||
aref = b.amember_cptr
|
||||
err_caught = false
|
||||
|
||||
if !$leak_check
|
||||
|
||||
begin
|
||||
x = aref.a1 # cannot call non-const method on const reference (as delivered by b7)
|
||||
x = aref.a1 # cannot call non-const method on const reference (as delivered by amember_cptr)
|
||||
rescue
|
||||
err_caught = true
|
||||
end
|
||||
|
|
@ -905,7 +916,7 @@ class Basic_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
b.b8( -1 )
|
||||
b.set_an( -1 )
|
||||
assert_equal( aref.a1c, -1 );
|
||||
|
||||
end
|
||||
|
|
@ -973,19 +984,19 @@ class Basic_TestClass < TestBase
|
|||
|
||||
b = RBA::B.new
|
||||
|
||||
a1 = b.b14a( true )
|
||||
a2 = b.b14b
|
||||
a1 = b.amember_or_nil( true )
|
||||
a2 = b.amember_ptr
|
||||
assert_equal( a1.a1, 17 )
|
||||
assert_equal( a2.a1, 17 )
|
||||
a1.a5( 761 )
|
||||
assert_equal( a1.a1, 761 )
|
||||
assert_equal( a2.a1, 761 )
|
||||
|
||||
a1 = b.b14a( false )
|
||||
a1 = b.amember_or_nil( false )
|
||||
assert_equal( a1, nil )
|
||||
|
||||
assert_equal( b.b15( b.b14b ), true )
|
||||
assert_equal( b.b15( b.b14a( false ) ), false )
|
||||
assert_equal( b.b15( b.amember_ptr ), true )
|
||||
assert_equal( b.b15( b.amember_or_nil( false ) ), false )
|
||||
assert_equal( b.b15( nil ), false )
|
||||
|
||||
end
|
||||
|
|
@ -996,8 +1007,8 @@ class Basic_TestClass < TestBase
|
|||
|
||||
b = RBA::B.new
|
||||
|
||||
b.b14b.s( 117 )
|
||||
assert_equal( b.b14b.g, 117 )
|
||||
b.amember_ptr.s( 117 )
|
||||
assert_equal( b.amember_ptr.g, 117 )
|
||||
|
||||
n = 0
|
||||
b.b10_nc { |a| a.s( n ); n += 1 }
|
||||
|
|
@ -1138,10 +1149,10 @@ class Basic_TestClass < TestBase
|
|||
assert_equal( b.b32( "b", 25 ), 20.5 )
|
||||
|
||||
GC.start
|
||||
na = RBA::A::a0 # instance count
|
||||
na = RBA::A::instance_count # instance count
|
||||
assert_equal( b.bx( a, 15 ), "aref+i" )
|
||||
GC.start
|
||||
assert_equal( RBA::A::a0, na )
|
||||
assert_equal( RBA::A::instance_count, na )
|
||||
err_caught = false
|
||||
begin
|
||||
# cannot cast second argument to int
|
||||
|
|
@ -1152,7 +1163,7 @@ class Basic_TestClass < TestBase
|
|||
assert_equal( err_caught, true )
|
||||
# the exception thrown before must not leave an instance on the call stack:
|
||||
GC.start
|
||||
assert_equal( RBA::A::a0, na )
|
||||
assert_equal( RBA::A::instance_count, na )
|
||||
|
||||
err_caught = false
|
||||
begin
|
||||
|
|
@ -1254,53 +1265,53 @@ class Basic_TestClass < TestBase
|
|||
|
||||
# destruction of an instance via c++
|
||||
GC.start
|
||||
ac0 = RBA::A.a0
|
||||
ic0 = RBA::A.instance_count
|
||||
|
||||
a = RBA::A::new
|
||||
a.create
|
||||
assert_equal(a.destroyed?, false)
|
||||
assert_equal(RBA::A.a0, ac0 + 1)
|
||||
assert_equal(RBA::A.instance_count, ic0 + 1)
|
||||
RBA::A.a20(a) # install static instance of A
|
||||
assert_equal(a.destroyed?, false)
|
||||
RBA::A.a20(nil)
|
||||
assert_equal(RBA::A.a0, ac0)
|
||||
assert_equal(RBA::A.instance_count, ic0)
|
||||
assert_equal(a.destroyed?, true)
|
||||
|
||||
a = RBA::A::new
|
||||
a.create
|
||||
assert_equal(a.destroyed?, false)
|
||||
assert_equal(RBA::A.a0, ac0 + 1)
|
||||
assert_equal(RBA::A.instance_count, ic0 + 1)
|
||||
RBA::A.a20(a) # install static instance of A
|
||||
assert_equal(a.destroyed?, false)
|
||||
assert_equal(RBA::A.a0, ac0 + 1)
|
||||
assert_equal(RBA::A.instance_count, ic0 + 1)
|
||||
RBA::A.a20(a) # re-install static instance of A
|
||||
assert_equal(a.destroyed?, false)
|
||||
assert_equal(RBA::A.a0, ac0 + 1)
|
||||
assert_equal(RBA::A.instance_count, ic0 + 1)
|
||||
|
||||
# install another instance
|
||||
aa = RBA::A::new
|
||||
aa.create
|
||||
assert_equal(aa.destroyed?, false)
|
||||
assert_equal(RBA::A.a0, ac0 + 2)
|
||||
assert_equal(RBA::A.instance_count, ic0 + 2)
|
||||
RBA::A.a20(aa) # install static instance of A
|
||||
|
||||
# original one is destroyed now, only new instance remains
|
||||
assert_equal(a.destroyed?, true)
|
||||
assert_equal(aa.destroyed?, false)
|
||||
assert_equal(RBA::A.a0, ac0 + 1)
|
||||
assert_equal(RBA::A.instance_count, ic0 + 1)
|
||||
RBA::A.a20(nil) # discard installed instance
|
||||
assert_equal(aa.destroyed, true)
|
||||
assert_equal(RBA::A.a0, ac0)
|
||||
assert_equal(RBA::A.instance_count, ic0)
|
||||
|
||||
# the same without create .. should work too, but not create an instance because of late
|
||||
# instantiation in default ctor
|
||||
a = RBA::A::new
|
||||
assert_equal(a.destroyed?, false)
|
||||
assert_equal(RBA::A.a0, ac0)
|
||||
assert_equal(RBA::A.instance_count, ic0)
|
||||
RBA::A.a20(a) # install static instance of A
|
||||
assert_equal(a.destroyed?, false)
|
||||
RBA::A.a20(nil)
|
||||
assert_equal(RBA::A.a0, ac0)
|
||||
assert_equal(RBA::A.instance_count, ic0)
|
||||
assert_equal(a.destroyed?, true)
|
||||
|
||||
end
|
||||
|
|
@ -1309,13 +1320,13 @@ class Basic_TestClass < TestBase
|
|||
|
||||
# destruction of an instance via c++
|
||||
GC.start
|
||||
ac0 = RBA::A.a0
|
||||
ic0 = RBA::A.instance_count
|
||||
|
||||
1.times do
|
||||
a = RBA::A::new
|
||||
a._create
|
||||
assert_equal(a.destroyed?, false)
|
||||
assert_equal(RBA::A.a0, ac0 + 1)
|
||||
assert_equal(RBA::A.instance_count, ic0 + 1)
|
||||
RBA::A.a20(a) # install static instance of A
|
||||
assert_equal(RBA::A.a20_get == nil, false)
|
||||
end
|
||||
|
|
@ -1323,7 +1334,7 @@ class Basic_TestClass < TestBase
|
|||
# makes sure the objects inside the block before are deleted
|
||||
GC.start
|
||||
|
||||
assert_equal(RBA::A.a0, ac0)
|
||||
assert_equal(RBA::A.instance_count, ic0)
|
||||
assert_equal(RBA::A.a20_get == nil, true)
|
||||
|
||||
# "unmanage" will freeze the object and not make it destroyed by the GC
|
||||
|
|
@ -1331,7 +1342,7 @@ class Basic_TestClass < TestBase
|
|||
a = RBA::A::new
|
||||
a._create
|
||||
assert_equal(a.destroyed?, false)
|
||||
assert_equal(RBA::A.a0, ac0 + 1)
|
||||
assert_equal(RBA::A.instance_count, ic0 + 1)
|
||||
RBA::A.a20(a) # install static instance of A
|
||||
assert_equal(RBA::A.a20_get == nil, false)
|
||||
a._unmanage
|
||||
|
|
@ -1340,7 +1351,7 @@ class Basic_TestClass < TestBase
|
|||
# makes sure the objects inside the block before are deleted
|
||||
GC.start
|
||||
|
||||
assert_equal(RBA::A.a0, ac0 + 1)
|
||||
assert_equal(RBA::A.instance_count, ic0 + 1)
|
||||
assert_equal(RBA::A.a20_get == nil, false)
|
||||
|
||||
# after "manage" the object gets volatile again
|
||||
|
|
@ -1352,7 +1363,7 @@ class Basic_TestClass < TestBase
|
|||
# makes sure the objects inside the block before are deleted
|
||||
GC.start
|
||||
|
||||
assert_equal(RBA::A.a0, ac0)
|
||||
assert_equal(RBA::A.instance_count, ic0)
|
||||
assert_equal(RBA::A.a20_get == nil, true)
|
||||
|
||||
end
|
||||
|
|
@ -1786,7 +1797,7 @@ class Basic_TestClass < TestBase
|
|||
assert_equal(1, yy.size)
|
||||
assert_equal("RBA::Y", yy[0].class.to_s)
|
||||
assert_equal(true, yy[0] != nil)
|
||||
yy[0].destroy
|
||||
yy[0]._destroy
|
||||
assert_equal(true, yy[0].destroyed?)
|
||||
assert_equal(yc, y.vx_dyn_count)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue