diff --git a/macbuild/ReadMe.md b/macbuild/ReadMe.md
index c5f20d882..ce1ca3410 100644
--- a/macbuild/ReadMe.md
+++ b/macbuild/ReadMe.md
@@ -1,39 +1,37 @@
-Relevant KLayout version: 0.28.6
+Relevant KLayout version: 0.28.13
Author: Kazzz-S
-Last modified: 2023-03-19
+Last modified: 2023-11-11
# 1. Introduction
-This directory **`macbuild`** contains various files required for building KLayout (http://www.klayout.de/) version 0.28.6 or later for different 64-bit macOS, including:
-* Catalina (10.15.7) : the primary development environment
-* Big Sur (11.x) : experimental; Apple (M1|M2) chip is not tested since the author does not own an (M1|M2) Mac
-* Monterey (12.x) : -- ditto --
-* Ventura (13.x) : -- ditto --
+This directory **`macbuild`** contains various files required for building KLayout (http://www.klayout.de/) version 0.28.13 or later for different 64-bit macOS, including:
+* Monterey (12.x) : the primary development environment
+* Ventura (13.x) : experimental
+* Sonoma (14.x) : -- ditto --
-Building KLayout for the previous operating systems listed below should still be possible.
-However, they are not actively supported, and DMG packages are not provided.
+Building KLayout for the previous operating systems listed below has been discontinued.
+Pre-built DMG packages are also not provided.
+* Big Sur (11.7.10)
+* Catalina (10.15.7)
* Mojave (10.14)
* High Sierra (10.13)
* Sierra (10.12)
* El Capitan (10.11)
-Throughout this document, the primary target machine is **Intel x86_64** with **macOS Catalina**.
-A **((Notes))** marker indicates special notes for specific operating systems.
+Throughout this document, the primary target machine is **Intel x86_64** with **macOS Monterey**.
+All Apple (M1|M2|M3) chips are still untested, as the author does not own an (M1|M2|M3) Mac.
# 2. Qt Frameworks
-**((Notes))** For **Catalina**
-
-The default Qt framework is "Qt5" from MacPorts (https://www.macports.org/), which is usually located under:
-```
-/opt/local/libexec/qt5/
-```
-
-**((Notes))** For **Big Sur**, **Monterey**, and **Ventura**
The default Qt framework is "Qt5" from Homebrew (https://brew.sh/), which is usually located under:
```
/usr/local/opt/qt@5/
```
+If you prefer **MacPorts** (https://www.macports.org/), "Qt5" is usually located under:
+```
+/opt/local/libexec/qt5/
+```
+
You can also choose "Qt5" from Anaconda3 (https://www.anaconda.com/), which is usually located under:
```
$HOME/opt/anaconda3/pkgs/qt-{version}
@@ -46,91 +44,26 @@ If you have installed Anaconda3 under $HOME/opt/anaconda3/, make a symbolic link
The migration work to "Qt6" is ongoing. You can try to use it; however, you will encounter some build and runtime errors.
# 3. Script language support: Ruby and Python
-Earlier, by default, supported script languages, i.e., Ruby and Python, were those standard ones bundled with the OS.
-```
-$ /usr/bin/ruby -v
- ruby 2.6.3p62 (2019-04-16 revision 67580) [universal.x86_64-darwin19]
-$ /usr/bin/python --version
- Python 2.7.16
-```
-Note that this configuration for backward compatibility is possible only for macOS Catalina (10.15.7).
-In contrast, Homebrew's Ruby 3.2 and Python 3.9 are the default environment for Big Sur, Monterey, and Ventura.
-Since Python 2.7 is already deprecated, using MacPorts' or Homebrew's Ruby 3.2 and Python 3.9 are also recommended for Catalina.
-
-The build script **`build4mac.py`** provides several possible combinations of Qt5, Ruy, and Python modules to accommodate such a slightly complex environment.
+The build script **`build4mac.py`** provides several possible combinations of Qt5, Ruby, and Python modules to suit the user's needs and preferences.
Some typical use cases are described in Section 6.
# 4. Prerequisites
You need to have the followings:
* The latest Xcode and command-line tool kit compliant with each OS
-* Qt5 package from MacPorts, Homebrew, or Anaconda3
-* Optionally, Ruby and Python packages from MacPorts, Homebrew, or Anaconda3
+* Qt5 package from Homebrew, MacPorts, or Anaconda3
+* Optionally, Ruby and Python packages from Homebrew, MacPorts, or Anaconda3
#### For matching versions of Ruby and Python, please also refer to `build4mac_env.py`.
# 5. Command-line options of **`build4mac.py`**
-**((Notes))** For **Catalina**
+
+**`build4mac.py`** is the top level Python script for for building KLayout for a macOS.
+The operating system type is detected automatically.
+
```
---------------------------------------------------------------------------------------------------------
<< Usage of 'build4mac.py' >>
- for building KLayout 0.28.6 or later on different Apple macOS / Mac OSX platforms.
-
-$ [python] ./build4mac.py
- option & argument : descriptions (refer to 'macbuild/build4mac_env.py' for details)| default value
- --------------------------------------------------------------------------------------+---------------
- [-q|--qt ] : case-insensitive type=['Qt5MacPorts', 'Qt5Brew', 'Qt5Ana3', | qt5macports
- : 'Qt6MacPorts', 'Qt6Brew'] |
- : Qt5MacPorts: use Qt5 from MacPorts |
- : Qt5Brew: use Qt5 from Homebrew |
- : Qt5Ana3: use Qt5 from Anaconda3 |
- : Qt6MacPorts: use Qt6 from MacPorts (*) |
- : Qt6Brew: use Qt6 from Homebrew (*) |
- : (*) migration to Qt6 is ongoing |
- [-r|--ruby ] : case-insensitive type=['nil', 'Sys', 'MP31', 'HB31', 'Ana3', | sys
- : 'MP32', HB32'] |
- : nil: don't bind Ruby |
- : Sys: use OS-bundled Ruby [2.0 - 2.6] depending on OS |
- : MP31: use Ruby 3.1 from MacPorts |
- : HB31: use Ruby 3.1 from Homebrew |
- : Ana3: use Ruby 3.1 from Anaconda3 |
- : MP32: use Ruby 3.2 from MacPorts |
- : HB32: use Ruby 3.2 from Homebrew |
- [-p|--python ] : case-insensitive type=['nil', 'Sys', 'MP38', 'HB38', 'Ana3', | sys
- : 'MP39', HB39', 'HBAuto'] |
- : nil: don't bind Python |
- : Sys: use OS-bundled Python 2.7 up to Catalina |
- : MP38: use Python 3.8 from MacPorts |
- : HB38: use Python 3.8 from Homebrew |
- : Ana3: use Python 3.9 from Anaconda3 |
- : MP39: use Python 3.9 from MacPorts |
- : HB39: use Python 3.9 from Homebrew |
- : HBAuto: use the latest Python 3.x auto-detected from Homebrew |
- [-P|--buildPymod] : build and deploy Pymod (*.whl and *.egg) for LW-*.dmg | disabled
- [-n|--noqtbinding] : don't create Qt bindings for ruby scripts | disabled
- [-u|--noqtuitools] : don't include uitools in Qt binding | disabled
- [-m|--make ] : option passed to 'make' | '--jobs=4'
- [-d|--debug] : enable debug mode build | disabled
- [-c|--checkcom] : check command-line and exit without building | disabled
- [-y|--deploy] : deploy executables and dylibs, including Qt's Frameworks | disabled
- [-Y|--DEPLOY] : deploy executables and dylibs for those who built KLayout | disabled
- : from the source code and use the tools in the same machine |
- : ! After confirmation of the successful build of 'klayout.app', |
- : rerun this script with BOTH: |
- : 1) the same options used for building AND |
- : 2) <-y|--deploy> OR <-Y|--DEPLOY> |
- : optionally with [-v|--verbose <0-3>] |
- [-v|--verbose <0-3>] : verbose level of `macdeployqt' (effective with -y only) | 1
- : 0 = no output, 1 = error/warning (default), |
- : 2 = normal, 3 = debug |
- [-?|--?] : print this usage and exit; in zsh, quote like '-?' or '--?' | disabled
------------------------------------------------------------------------------------------+---------------
-```
-
-**((Notes))** For **Big Sur**, **Monterey**, and **Ventura**
-```
----------------------------------------------------------------------------------------------------------
-<< Usage of 'build4mac.py' >>
- for building KLayout 0.28.6 or later on different Apple macOS / Mac OSX platforms.
+ for building KLayout 0.28.13 or later on different Apple macOS platforms.
$ [python] ./build4mac.py
option & argument : descriptions (refer to 'macbuild/build4mac_env.py' for details)| default value
@@ -143,28 +76,26 @@ $ [python] ./build4mac.py
: Qt6MacPorts: use Qt6 from MacPorts (*) |
: Qt6Brew: use Qt6 from Homebrew (*) |
: (*) migration to Qt6 is ongoing |
- [-r|--ruby ] : case-insensitive type=['nil', 'Sys', 'MP31', 'HB31', 'Ana3', | hb32
- : 'MP32', HB32'] |
+ [-r|--ruby ] : case-insensitive type=['nil', 'Sys', 'MP32', 'HB32', 'Ana3'] | hb32
: nil: don't bind Ruby |
- : Sys: use OS-bundled Ruby [2.0 - 2.6] depending on OS |
- : MP31: use Ruby 3.1 from MacPorts |
- : HB31: use Ruby 3.1 from Homebrew |
- : Ana3: use Ruby 3.1 from Anaconda3 |
+ : Sys: use [Sonoma|Ventura|Monterey]-bundled Ruby 2.6 |
: MP32: use Ruby 3.2 from MacPorts |
- : HB32: use Ruby 3.2 from Homebrew |
- [-p|--python ] : case-insensitive type=['nil', 'Sys', 'MP38', 'HB38', 'Ana3', | hb39
- : 'MP39', HB39', 'HBAuto'] |
+ : HB32: use Ruby 3.2 from Homebrew |
+ : Ana3: use Ruby 3.1 from Anaconda3 |
+ [-p|--python ] : case-insensitive type=['nil', 'MP311', 'HB311', 'Ana3', | hb311
+ : 'MP39', 'hb311', 'HBAuto'] |
: nil: don't bind Python |
- : Sys: use OS-bundled Python 2.7 up to Catalina |
- : MP38: use Python 3.8 from MacPorts |
- : HB38: use Python 3.8 from Homebrew |
- : Ana3: use Python 3.9 from Anaconda3 |
- : MP39: use Python 3.9 from MacPorts |
- : HB39: use Python 3.9 from Homebrew |
+ : MP311: use Python 3.11 from MacPorts |
+ : HB311: use Python 3.11 from Homebrew |
+ : Ana3: use Python 3.11 from Anaconda3 |
+ : MP39: use Python 3.9 from MacPorts (+) |
+ : hb311: use Python 3.9 from Homebrew (+) |
+ : (+) for the backward compatibility tests |
: HBAuto: use the latest Python 3.x auto-detected from Homebrew |
- [-P|--buildPymod] : build and deploy Pymod (*.whl and *.egg) for LW-*.dmg | disabled
+ [-P|--buildPymod] : build and deploy Pymod (*.whl) for LW-*.dmg | disabled
[-n|--noqtbinding] : don't create Qt bindings for ruby scripts | disabled
[-u|--noqtuitools] : don't include uitools in Qt binding | disabled
+ [-g|--nolibgit2] : don't include libgit2 for Git package support | disabled
[-m|--make ] : option passed to 'make' | '--jobs=4'
[-d|--debug] : enable debug mode build | disabled
[-c|--checkcom] : check command-line and exit without building | disabled
@@ -184,81 +115,27 @@ $ [python] ./build4mac.py
```
# 6. Use-cases
-In this section, the actual file and directory names are those obtained on macOS Catalina.
+In this section, the actual file and directory names are those obtained on macOS Monterey.
On different OS, those names differ accordingly.
-### 6A. Standard build using the OS-bundled Ruby and Python **((Notes))** only for Catalina
-0. Install MacPorts, then install Qt5 by
-```
-$ sudo port install coreutils
-$ sudo port install findutils
-$ sudo port install qt5
-```
-1. Invoke **`build4mac.py`** with the default options: **((Notes))** only for Catalina
-```
-$ cd /where/'build.sh'/exists
-$ ./build4mac.py
-```
-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 framework) under **`klayout.app`** bundle.
- The buddy command-line tools (strm*) will also be deployed in this step.
-```
-$ ./build4mac.py -y
-```
- The application bundle **`klayout.app`** is located under:
- **`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).
-* "qt5MP" means that Qt5 from MacPorts is used.
-* "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.
+### 6A. Standard build using the OS-bundled Ruby and Python with MacPorts
+This build has been discontinued.
-If you use the "-Y" option instead of the "-y" in Step-3, the Qt5 framework is NOT deployed in the application bundle.
-Then the directory name will be **`LW-qt5MP.pkg.macos-Catalina-release-RsysPsys`**, where
-* "LW-" means that this is a lightweight package.
-
-#### 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 3.2 and MacPorts Python 3.9
-0. Install MacPorts, then install Qt5, Ruby 3.2, and Python 3.9 by
-```
-$ sudo port install coreutils
-$ sudo port install findutils
-$ sudo port install qt5
-$ sudo port install ruby32
-$ sudo port install python39
-$ sudo port install py39-pip
-```
-1. Invoke **`build4mac.py`** with the following options:
-```
-$ cd /where/'build.sh'/exists
-$ ./build4mac.py -q qt5macports -r mp32 -p mp39
-```
-2. Confirm successful build (it will take about one hour, depending on your machine spec).
-3. Rerun **`build4mac.py`** with the same options used in 1. PLUS "-Y" to deploy executables and libraries under **`klayout.app`** bundle.
- The buddy command-line tools (strm*) will also be deployed under **klayout.app/Contents/Buddy/** in this step.
- If you use `--buildPymod` option in Step-1 and Step-3, the KLayout Python Module (\*.whl) will be built and deployed under **klayout.app/Contents/pymod-dist/**.
-
-```
-$ ./build4mac.py -q qt5macports -r mp32 -p mp39 -Y
-```
- The application bundle **`klayout.app`** is located under:
- **`LW-qt5MP.pkg.macos-Catalina-release-Rmp32Pmp39`** directory, where
-* "LW-" means this is a lightweight package.
-* "qt5MP" means that Qt5 from MacPorts is used.
-* "Rmp32Pmp39" means that Ruby is 3.2 from MacPorts; Python is 3.9 from MacPorts.
-4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation.
-
-### 6C. Fully Homebrew-flavored build with Homebrew Ruby 3.2 and Homebrew Python 3.9
-0. Install Homebrew, then install Qt5, Ruby 3.2, and Python 3.9 by
+### 6B. Fully Homebrew-flavored build with Homebrew Ruby 3.2 and Homebrew Python 3.11
+0. Install Homebrew, then install Qt5, Ruby 3.2, Python 3.11, and libgit2 by
```
$ brew install qt@5
$ brew install ruby@3.2
-$ brew install python@3.9
+$ brew install python@3.11
+$ brew install libgit2
+$ cd /where/'build.sh'/exists
+$ cd macbuild
+$ ./python3HB.py -v 3.11
```
-1. Invoke **`build4mac.py`** with the following options: **((Notes))** These options are the default for Big Sur, Monterey, and Ventura.
+1. Invoke **`build4mac.py`** with the following options: **((Notes))** These options are the default values for Monterey, Ventura, and Sonoma.
```
$ cd /where/'build.sh'/exists
-$ ./build4mac.py -q qt5brew -r hb32 -p hb39
+$ ./build4mac.py -q qt5brew -r hb32 -p hb311
```
2. Confirm successful build (it will take about one hour, depending on your machine spec).
3. Rerun **`build4mac.py`** with the same options used in 1. PLUS "-Y" to deploy executables and libraries under **`klayout.app`** bundle.
@@ -266,48 +143,85 @@ $ ./build4mac.py -q qt5brew -r hb32 -p hb39
If you use `--buildPymod` option in Step-1 and Step-3, the KLayout Python Module (\*.whl) will be built and deployed under **klayout.app/Contents/pymod-dist/**.
```
-$ ./build4mac.py -q qt5brew -r hb32 -p hb39 -Y
+$ ./build4mac.py -q qt5brew -r hb32 -p hb311 -Y
```
The application bundle **`klayout.app`** is located under:
- **`LW-qt5Brew.pkg.macos-Catalina-release-Rhb32Phb39`** directory, where
+ **`LW-qt5Brew.pkg.macos-Monterey-release-Rhb32Phb311`** directory, where
* "LW-" means this is a lightweight package.
* "qt5Brew" means that Qt5 from Homebrew is used.
-* "Rhb32Phb39" means that Ruby is 3.2 from Homebrew; Python is 3.9 from Homebrew.
+* "Rhb32Phb311" means that Ruby is 3.2 from Homebrew; Python is 3.11 from Homebrew.
4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation.
-### 6D. Partially Homebrew-flavored build with System Ruby and Homebrew Python 3.9
-0. Install Homebrew, then install Qt5 and Python 3.9 by
+### 6C. Partially Homebrew-flavored build with System Ruby and Homebrew Python 3.11
+0. Install Homebrew, then install Qt5, Python 3.11, and libgit2 by
```
$ brew install qt@5
-$ brew install python@3.9
+$ brew install python@3.11
+$ brew install libgit2
+$ cd /where/'build.sh'/exists
+$ cd macbuild
+$ ./python3HB.py -v 3.11
```
1. Invoke **`build4mac.py`** with the following options:
```
$ cd /where/'build.sh'/exists
-$ ./build4mac.py -q qt5brew -r sys -p hb39
+$ ./build4mac.py -q qt5brew -r sys -p hb311
```
2. Confirm successful build (it will take about one hour, depending on your machine spec).
3. Rerun **`build4mac.py`** with the same options used in 1. PLUS "-y" to deploy executables and libraries (including Qt and Python frameworks) under the **`klayout.app`** bundle.
The buddy command-line tools (strm*) will also be deployed under **klayout.app/Contents/Buddy/** in this step.
```
-$ ./build4mac.py -q qt5brew -r sys -p hb39 -y
+$ ./build4mac.py -q qt5brew -r sys -p hb311 -y
```
The application bundle **`klayout.app`** is located under:
- **`HW-qt5Brew.pkg.macos-Catalina-release-RsysPhb39`** directory, where
+ **`HW-qt5Brew.pkg.macos-Monterey-release-RsysPhb311`** directory, where
* "HW-" means this is a heavyweight package because both Qt5 and Python Frameworks are deployed.
* "qt5Brew" means that Qt5 from Homebrew is used.
-* "RsysPhb39" means that Ruby is OS-bundled; Python is 3.9 from Homebrew.
+* "RsysPhb311" means that Ruby is OS-bundled; Python is 3.11 from Homebrew.
4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation.
### Important
-So far, the deployment of Homebrew Ruby is not supported.
+So far, the deployment of Homebrew Ruby is not supported.
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 3.1 and Anaconda3 Python 3.9
-0. Install Anaconda3, then install Ruby 3.1 by
+### 6D. Fully MacPorts-flavored build with MacPorts Ruby 3.2 and MacPorts Python 3.11
+0. Install MacPorts, then install Qt5, Ruby 3.2, Python 3.11, and libgit2 by
```
-$ conda install ruby=3.1.2
+$ sudo port install coreutils
+$ sudo port install findutils
+$ sudo port install qt5
+$ sudo port install ruby32
+$ sudo port install python311
+$ sudo port install py311-pip
+$ sudo port install libgit2
```
+1. Invoke **`build4mac.py`** with the following options:
+```
+$ cd /where/'build.sh'/exists
+$ ./build4mac.py -q qt5macports -r mp32 -p mp311
+```
+2. Confirm successful build (it will take about one hour, depending on your machine spec).
+3. Rerun **`build4mac.py`** with the same options used in 1. PLUS "-Y" to deploy executables and libraries under **`klayout.app`** bundle.
+ The buddy command-line tools (strm*) will also be deployed under **klayout.app/Contents/Buddy/** in this step.
+ If you use `--buildPymod` option in Step-1 and Step-3, the KLayout Python Module (\*.whl) will be built and deployed under **klayout.app/Contents/pymod-dist/**.
+
+```
+$ ./build4mac.py -q qt5macports -r mp32 -p mp311 -Y
+```
+ The application bundle **`klayout.app`** is located under:
+ **`LW-qt5MP.pkg.macos-Monterey-release-Rmp32Pmp311`** directory, where
+* "LW-" means this is a lightweight package.
+* "qt5MP" means that Qt5 from MacPorts is used.
+* "Rmp32Pmp311" means that Ruby is 3.2 from MacPorts; Python is 3.11 from MacPorts.
+4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation.
+
+### 6E. Fully Anaconda3-flavored build with Anaconda3 Ruby 3.1 and Anaconda3 Python 3.11
+0. Install Anaconda3 (Anaconda3-2023.09-0-MacOSX-x86_64.pkg), then install Ruby 3.1 and libgit2 by
+```
+$ conda install ruby=3.1.4
+$ conda install -c conda-forge libgit2
+```
+
1. Invoke **`build4mac.py`** with the following options:
```
$ cd /where/'build.sh'/exists
@@ -322,10 +236,10 @@ $ ./build4mac.py -q qt5ana3 -r ana3 -p ana3
$ ./build4mac.py -q qt5ana3 -r ana3 -p ana3 -Y
```
The application bundle **`klayout.app`** is located under:
- **`LW-qt5Ana3.pkg.macos-Catalina-release-Rana3Pana3`** directory, where
+ **`LW-qt5Ana3.pkg.macos-Monterey-release-Rana3Pana3`** directory, where
* "LW-" means this is a lightweight package.
* "qt5Ana3" means that Qt5 from Anaconda3 is used.
-* "Rana3Pana3" means that Ruby (3.1) is from Anaconda3; Python (3.9) is from Anaconda3.
+* "Rana3Pana3" means that Ruby (3.1) is from Anaconda3; Python (3.11) is from Anaconda3.
4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation.
5. You may have to set the `PYTHONHOME` environment variable like:
```
@@ -333,14 +247,14 @@ export PYTHONHOME=$HOME/opt/anaconda3
```
### 6F. Other combinations
-Logically, several module combinations other than 6A through 6E are possible, including `nil` choice.
+Logically, several module combinations other than 6B through 6E are possible, including `nil` choice.
The resultant package directory name will begin with **`EX-`** (exceptional) if you choose such a combination.
----
# 7. Making a DMG installer
You can make a DMG installer using another Python script **`makeDMG4mac.py`**.
-This script requires a directory generated by **`build4mac.py`** with the [-y|-Y] option (refer to 6A through 6D).
+This script requires a directory generated by **`build4mac.py`** with the [-y|-Y] option (refer to 6B through 6E).
1. Make a symbolic link (if it does not exist) from the parent directory (where **`build.sh`** exists) to **`makeDMG4mac.py`**, that is,
```
@@ -349,18 +263,18 @@ makeDMG4mac.py -> macbuild/makeDMG4mac.py
2. Invoke **`makeDMG4mac.py`** with -p and -m options, for example,
```
$ cd /where/'build.sh'/exists
-$ ./makeDMG4mac.py -p LW-qt5MP.pkg.macos-Catalina-release-Rmp32Pmp39 -m
+$ ./makeDMG4mac.py -p LW-qt5MP.pkg.macos-Monterey-release-Rmp32Pmp311 -m
```
This command will generate the two files below:
-* **`LW-klayout-0.28.6-macOS-Catalina-1-qt5MP-Rmp32Pmp39.dmg`** ---(1) the main DMG file
-* **`LW-klayout-0.28.6-macOS-Catalina-1-qt5MP-Rmp32Pmp39.dmg.md5`** ---(2) MD5-value text file
+* **`LW-klayout-0.28.13-macOS-Monterey-1-qt5MP-Rmp32Pmp311.dmg`** ---(1) the main DMG file
+* **`LW-klayout-0.28.13-macOS-Monterey-1-qt5MP-Rmp32Pmp311.dmg.md5`** ---(2) MD5-value text file
# 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.
+Because we assume some specific versions of non-OS-standard Ruby and Python, updating Homebrew, MacPorts, or Anaconda3 may cause build- and link errors.
In such cases, you need to update the dictionary contents of **`build4mac_env.py`**.
# Final comments
-No need to say KLayout is a great tool!
+No need to say KLayout is a great tool!
With the object-oriented script language (both Ruby and Python) support, our error-prone layout jobs can be significantly simplified and sped up.
Building KLayout from its source code is not difficult. Try it with your favorite environment!
diff --git a/macbuild/Resources/KLayoutDMG-BackQt5.logoist b/macbuild/Resources/KLayoutDMG-BackQt5.logoist
index 1c9f04f1d..ece5f072a 100644
Binary files a/macbuild/Resources/KLayoutDMG-BackQt5.logoist and b/macbuild/Resources/KLayoutDMG-BackQt5.logoist differ
diff --git a/macbuild/Resources/KLayoutDMG-BackQt5.png b/macbuild/Resources/KLayoutDMG-BackQt5.png
index 8e92a89a3..deed96a58 100644
Binary files a/macbuild/Resources/KLayoutDMG-BackQt5.png and b/macbuild/Resources/KLayoutDMG-BackQt5.png differ
diff --git a/macbuild/Resources/KLayoutDMG-BackQt6.logoist b/macbuild/Resources/KLayoutDMG-BackQt6.logoist
index e0e2913d0..efd151db3 100644
Binary files a/macbuild/Resources/KLayoutDMG-BackQt6.logoist and b/macbuild/Resources/KLayoutDMG-BackQt6.logoist differ
diff --git a/macbuild/Resources/KLayoutDMG-BackQt6.png b/macbuild/Resources/KLayoutDMG-BackQt6.png
index 54729fc7f..3f22d12c7 100644
Binary files a/macbuild/Resources/KLayoutDMG-BackQt6.png and b/macbuild/Resources/KLayoutDMG-BackQt6.png differ
diff --git a/macbuild/Resources/script-bundle-A.zip b/macbuild/Resources/script-bundle-A.zip
index e2d9b79a3..8bafd8ffa 100644
Binary files a/macbuild/Resources/script-bundle-A.zip and b/macbuild/Resources/script-bundle-A.zip differ
diff --git a/macbuild/Resources/script-bundle-B.zip b/macbuild/Resources/script-bundle-B.zip
index db93f4476..79409fe35 100644
Binary files a/macbuild/Resources/script-bundle-B.zip and b/macbuild/Resources/script-bundle-B.zip differ
diff --git a/macbuild/Resources/script-bundle-H.zip b/macbuild/Resources/script-bundle-H.zip
index c44ceedbe..51449c949 100644
Binary files a/macbuild/Resources/script-bundle-H.zip and b/macbuild/Resources/script-bundle-H.zip differ
diff --git a/macbuild/Resources/script-bundle-P.zip b/macbuild/Resources/script-bundle-P.zip
index 779b9a8f9..1a0909756 100644
Binary files a/macbuild/Resources/script-bundle-P.zip and b/macbuild/Resources/script-bundle-P.zip differ
diff --git a/macbuild/Resources/script-bundles.zip b/macbuild/Resources/script-bundles.zip
index 99fdc745c..15b4f3cf1 100644
Binary files a/macbuild/Resources/script-bundles.zip and b/macbuild/Resources/script-bundles.zip differ
diff --git a/macbuild/Resources/start-console.py b/macbuild/Resources/start-console.py
index 5880e2eed..93fa917f4 100644
--- a/macbuild/Resources/start-console.py
+++ b/macbuild/Resources/start-console.py
@@ -6,6 +6,25 @@ import os
pwd = os.getcwd()
sys.path.append(pwd)
+piphelpstr = """
+--------------------------------------------------------------------------------
+(1) Install ['pandas', 'scipy', 'matplotlib']
+>>> import pip
+>>> pip.main( ['install', 'pandas', 'scipy', 'matplotlib'] )
+
+(2) List modules
+>>> import pip
+>>> pip.main( ['list'] )
+
+(3) Uninstall ['scipy']
+>>> import pip
+>>> pip.main( ['uninstall', 'scipy'] )
+--------------------------------------------------------------------------------
+"""
+def howtopip():
+ print(piphelpstr)
+
+
variables = globals().copy()
variables.update(locals())
shell = code.InteractiveConsole(variables)
diff --git a/macbuild/Resources/template-start-console.py b/macbuild/Resources/template-start-console.py
new file mode 100644
index 000000000..06f65d00d
--- /dev/null
+++ b/macbuild/Resources/template-start-console.py
@@ -0,0 +1,39 @@
+#!/Applications/klayout.app/Contents/MacOS/klayout -b -r
+import readline
+import code
+import sys
+import os
+pwd = os.getcwd()
+sys.path.append(pwd)
+
+rootPython = "/Applications/klayout.app/Contents/Frameworks/Python.framework/Versions"
+verPython = "${PYTHON_VER}"
+piptarget = [ "--target", "%s/%s/lib/python%s/site-packages" % (rootPython, verPython, verPython) ]
+
+piphelpstr = """
+--------------------------------------------------------------------------------
+(1) Install ['pandas', 'scipy', 'matplotlib']
+>>> import pip
+>>> pip.main( ['install', 'pandas', 'scipy', 'matplotlib'] + piptarget )
+
+(2) List modules
+>>> import pip
+>>> pip.main( ['list'] )
+
+(3) Uninstall ['scipy']
+>>> import pip
+>>> pip.main( ['uninstall', 'scipy'] )
+--------------------------------------------------------------------------------
+"""
+def howtopip():
+ print(piphelpstr)
+
+
+variables = globals().copy()
+variables.update(locals())
+shell = code.InteractiveConsole(variables)
+cprt = 'Type "help", "copyright", "credits" or "license" for more information.'
+banner = "Python %s on %s\n%s\n(%s)" % (sys.version, sys.platform,
+ cprt, "KLayout Python Console")
+exit_msg = 'now exiting %s...' % "KLayout Python Console"
+shell.interact(banner, exit_msg)
diff --git a/macbuild/build4mac.py b/macbuild/build4mac.py
index cf224a3e2..78e32c20d 100755
--- a/macbuild/build4mac.py
+++ b/macbuild/build4mac.py
@@ -5,10 +5,11 @@
# File: "macbuild/build4mac.py"
#
# The top Python script for building KLayout (http://www.klayout.de/index.php)
-# version 0.26.1 or later on different Apple Mac OSX platforms.
+# version 0.28.13 or later on different Apple Mac OSX platforms.
#===============================================================================
import sys
import os
+import re
import codecs
import shutil
import glob
@@ -33,69 +34,64 @@ from build4mac_util import *
# @return (usage, moduleset)-tuple
#-------------------------------------------------------------------------------
def GenerateUsage(platform):
- if platform.upper() in [ "VENTURA", "MONTEREY", "BIGSUR" ]: # with Xcode [13.1 .. ]
+ if platform.upper() in [ "SONOMA", "VENTURA", "MONTEREY" ]: # with Xcode [13.1 .. ]
myQt56 = "qt5brew"
myRuby = "hb32"
- myPython = "hb39"
- moduleset = ('qt5Brew', 'HB32', 'HB39')
- else: # with Xcode [ .. 12.4]; 'sys' for Python has been restored in 0.28.3
- myQt56 = "qt5macports"
- myRuby = "sys"
- myPython = "sys"
- moduleset = ('qt5MP', 'Sys', 'Sys')
+ myPython = "hb311"
+ moduleset = ('qt5Brew', 'HB32', 'HB311')
+ else: # too obsolete
+ raise Exception( "! Too obsolete platform <%s>" % platform )
usage = "\n"
usage += "---------------------------------------------------------------------------------------------------------\n"
usage += "<< Usage of 'build4mac.py' >>\n"
- usage += " for building KLayout 0.28.6 or later on different Apple macOS / Mac OSX platforms.\n"
+ usage += " for building KLayout 0.28.13 or later on different Apple macOS platforms.\n"
usage += "\n"
usage += "$ [python] ./build4mac.py\n"
usage += " option & argument : descriptions (refer to 'macbuild/build4mac_env.py' for details)| default value\n"
usage += " --------------------------------------------------------------------------------------+---------------\n"
- usage += " [-q|--qt ] : case-insensitive type=['Qt5MacPorts', 'Qt5Brew', 'Qt5Ana3', | %s \n" % myQt56
- usage += " : 'Qt6MacPorts', 'Qt6Brew'] | \n"
- usage += " : Qt5MacPorts: use Qt5 from MacPorts | \n"
- usage += " : Qt5Brew: use Qt5 from Homebrew | \n"
- usage += " : Qt5Ana3: use Qt5 from Anaconda3 | \n"
- usage += " : Qt6MacPorts: use Qt6 from MacPorts (*) | \n"
- usage += " : Qt6Brew: use Qt6 from Homebrew (*) | \n"
- usage += " : (*) migration to Qt6 is ongoing | \n"
- usage += " [-r|--ruby ] : case-insensitive type=['nil', 'Sys', 'MP31', 'HB31', 'Ana3', | %s \n" % myRuby
- usage += " : 'MP32', 'HB32'] | \n"
- usage += " : nil: don't bind Ruby | \n"
- usage += " : Sys: use OS-bundled Ruby [2.0 - 2.6] depending on OS | \n"
- usage += " : MP31: use Ruby 3.1 from MacPorts | \n"
- usage += " : HB31: use Ruby 3.1 from Homebrew | \n"
- usage += " : Ana3: use Ruby 3.1 from Anaconda3 | \n"
- usage += " : MP32: use Ruby 3.2 from MacPorts | \n"
- usage += " : HB32: use Ruby 3.2 from Homebrew | \n"
- usage += " [-p|--python ] : case-insensitive type=['nil', 'Sys', 'MP38', 'HB38', 'Ana3', | %s \n" % myPython
- usage += " : 'MP39', 'HB39', 'HBAuto'] | \n"
- usage += " : nil: don't bind Python | \n"
- usage += " : Sys: use OS-bundled Python 2.7 up to Catalina | \n"
- usage += " : MP38: use Python 3.8 from MacPorts | \n"
- usage += " : HB38: use Python 3.8 from Homebrew | \n"
- usage += " : Ana3: use Python 3.9 from Anaconda3 | \n"
- usage += " : MP39: use Python 3.9 from MacPorts | \n"
- usage += " : HB39: use Python 3.9 from Homebrew | \n"
- usage += " : HBAuto: use the latest Python 3.x auto-detected from Homebrew | \n"
- usage += " [-P|--buildPymod] : build and deploy Pymod (*.whl and *.egg) for LW-*.dmg | disabled\n"
+ usage += " [-q|--qt ] : case-insensitive type=['Qt5MacPorts', 'Qt5Brew', 'Qt5Ana3', | %s\n" % myQt56
+ usage += " : 'Qt6MacPorts', 'Qt6Brew'] |\n"
+ usage += " : Qt5MacPorts: use Qt5 from MacPorts |\n"
+ usage += " : Qt5Brew: use Qt5 from Homebrew |\n"
+ usage += " : Qt5Ana3: use Qt5 from Anaconda3 |\n"
+ usage += " : Qt6MacPorts: use Qt6 from MacPorts (*) |\n"
+ usage += " : Qt6Brew: use Qt6 from Homebrew (*) |\n"
+ usage += " : (*) migration to Qt6 is ongoing |\n"
+ usage += " [-r|--ruby ] : case-insensitive type=['nil', 'Sys', 'MP32', 'HB32', 'Ana3'] | %s\n" % myRuby
+ usage += " : nil: don't bind Ruby |\n"
+ usage += " : Sys: use [Sonoma|Ventura|Monterey]-bundled Ruby 2.6 |\n"
+ usage += " : MP32: use Ruby 3.2 from MacPorts |\n"
+ usage += " : HB32: use Ruby 3.2 from Homebrew |\n"
+ usage += " : Ana3: use Ruby 3.1 from Anaconda3 |\n"
+ usage += " [-p|--python ] : case-insensitive type=['nil', 'MP311', 'HB311', 'Ana3', | %s\n" % myPython
+ usage += " : 'MP39', 'HB39', 'HBAuto'] |\n"
+ usage += " : nil: don't bind Python |\n"
+ usage += " : MP311: use Python 3.11 from MacPorts |\n"
+ usage += " : HB311: use Python 3.11 from Homebrew |\n"
+ usage += " : Ana3: use Python 3.11 from Anaconda3 |\n"
+ usage += " : MP39: use Python 3.9 from MacPorts (+) |\n"
+ usage += " : HB39: use Python 3.9 from Homebrew (+) |\n"
+ usage += " : (+) for the backward compatibility tests |\n"
+ usage += " : HBAuto: use the latest Python 3.x auto-detected from Homebrew |\n"
+ usage += " [-P|--buildPymod] : build and deploy Pymod (*.whl) for LW-*.dmg | disabled\n"
usage += " [-n|--noqtbinding] : don't create Qt bindings for ruby scripts | disabled\n"
usage += " [-u|--noqtuitools] : don't include uitools in Qt binding | disabled\n"
+ usage += " [-g|--nolibgit2] : don't include libgit2 for Git package support | disabled\n"
usage += " [-m|--make ] : option passed to 'make' | '--jobs=4'\n"
usage += " [-d|--debug] : enable debug mode build | disabled\n"
usage += " [-c|--checkcom] : check command-line and exit without building | disabled\n"
usage += " [-y|--deploy] : deploy executables and dylibs, including Qt's Frameworks | disabled\n"
usage += " [-Y|--DEPLOY] : deploy executables and dylibs for those who built KLayout | disabled\n"
- usage += " : from the source code and use the tools in the same machine | \n"
- usage += " : ! After confirmation of the successful build of 'klayout.app', | \n"
- usage += " : rerun this script with BOTH: | \n"
- usage += " : 1) the same options used for building AND | \n"
- usage += " : 2) <-y|--deploy> OR <-Y|--DEPLOY> | \n"
- usage += " : optionally with [-v|--verbose <0-3>] | \n"
+ usage += " : from the source code and use the tools in the same machine |\n"
+ usage += " : ! After confirmation of the successful build of 'klayout.app', |\n"
+ usage += " : rerun this script with BOTH: |\n"
+ usage += " : 1) the same options used for building AND |\n"
+ usage += " : 2) <-y|--deploy> OR <-Y|--DEPLOY> |\n"
+ usage += " : optionally with [-v|--verbose <0-3>] |\n"
usage += " [-v|--verbose <0-3>] : verbose level of `macdeployqt' (effective with -y only) | 1\n"
- usage += " : 0 = no output, 1 = error/warning (default), | \n"
- usage += " : 2 = normal, 3 = debug | \n"
+ usage += " : 0 = no output, 1 = error/warning (default), |\n"
+ usage += " : 2 = normal, 3 = debug |\n"
usage += " [-?|--?] : print this usage and exit; in zsh, quote like '-?' or '--?' | disabled\n"
usage += "-----------------------------------------------------------------------------------------+---------------\n"
return (usage, moduleset)
@@ -113,26 +109,19 @@ def Get_Default_Config():
if not System == "Darwin":
print("")
print( "!!! Sorry. Your system <%s> looks like non-Mac" % System, file=sys.stderr )
- print( GenerateUsage("")[0] )
sys.exit(1)
- release = int( Release.split(".")[0] ) # take the first of ['19', '0', '0']
- if release == 22:
+ release = int( Release.split(".")[0] ) # take the first of ['21', '0', '0']
+ #----------------------------------------------------------------------------
+ # Dropped [ElCapitan - BigSur] (2023-10-24).
+ # See 415b5aa2efca04928f1148a69e77efd5d76f8c1d for the previous states.
+ #----------------------------------------------------------------------------
+ if release == 23:
+ Platform = "Sonoma"
+ elif release == 22:
Platform = "Ventura"
elif release == 21:
Platform = "Monterey"
- elif release == 20:
- Platform = "BigSur"
- elif release == 19:
- Platform = "Catalina"
- elif release == 18:
- Platform = "Mojave"
- elif release == 17:
- Platform = "HighSierra"
- elif release == 16:
- Platform = "Sierra"
- elif release == 15:
- Platform = "ElCapitan"
else:
Platform = ""
print("")
@@ -141,10 +130,11 @@ def Get_Default_Config():
sys.exit(1)
if not Machine == "x86_64":
- if Machine == "arm64" and Platform in ["Ventura", "Monterey", "BigSur"]: # with an Apple Silicon Chip
+ if Machine == "arm64" and Platform in ["Sonoma", "Ventura", "Monterey"]: # with an Apple Silicon Chip
print("")
print( "### Your Mac equips an Apple Silicon Chip ###" )
- print("")
+ print( " Setting QMAKE_APPLE_DEVICE_ARCHS=arm64\n")
+ os.environ['QMAKE_APPLE_DEVICE_ARCHS'] = 'arm64'
else:
print("")
print( "!!! Sorry. Only x86_64/arm64 architecture machine is supported but found <%s>" % Machine, file=sys.stderr )
@@ -158,40 +148,20 @@ def Get_Default_Config():
ToolDebug = list()
# Set the default modules
- if Platform == "Ventura":
+ if Platform == "Sonoma":
ModuleQt = "Qt5Brew"
ModuleRuby = "Ruby32Brew"
- ModulePython = "Python39Brew"
+ ModulePython = "Python311Brew"
+ elif Platform == "Ventura":
+ ModuleQt = "Qt5Brew"
+ ModuleRuby = "Ruby32Brew"
+ ModulePython = "Python311Brew"
elif Platform == "Monterey":
ModuleQt = "Qt5Brew"
ModuleRuby = "Ruby32Brew"
- ModulePython = "Python39Brew"
- elif Platform == "BigSur":
- ModuleQt = "Qt5Brew"
- ModuleRuby = "Ruby32Brew"
- ModulePython = "Python39Brew"
- elif Platform == "Catalina":
- ModuleQt = "Qt5MacPorts"
- ModuleRuby = "RubyCatalina"
- ModulePython = "PythonCatalina"
- elif Platform == "Mojave":
- ModuleQt = "Qt5MacPorts"
- ModuleRuby = "RubyMojave"
- ModulePython = "PythonMojave"
- elif Platform == "HighSierra":
- ModuleQt = "Qt5MacPorts"
- ModuleRuby = "RubyHighSierra"
- ModulePython = "PythonHighSierra"
- elif Platform == "Sierra":
- ModuleQt = "Qt5MacPorts"
- ModuleRuby = "RubySierra"
- ModulePython = "PythonSierra"
- elif Platform == "ElCapitan":
- ModuleQt = "Qt5MacPorts"
- ModuleRuby = "RubyElCapitan"
- ModulePython = "PythonElCapitan"
+ ModulePython = "Python311Brew"
else:
- ModuleQt = "Qt5MacPorts"
+ ModuleQt = "Qt5Brew"
ModuleRuby = "nil"
ModulePython = "nil"
@@ -199,6 +169,7 @@ def Get_Default_Config():
NonOSStdLang = False
NoQtBindings = False
NoQtUiTools = False
+ NoLibGit2 = False
MakeOptions = "--jobs=4"
DebugMode = False
CheckComOnly = False
@@ -207,6 +178,7 @@ def Get_Default_Config():
PackagePrefix = ""
DeployVerbose = 1
Version = GetKLayoutVersionFrom( "./version.sh" )
+ HBPythonIs39 = False # because ModulePython == "Python311Brew" by default
config = dict()
config['ProjectDir'] = ProjectDir # project directory where "build.sh" exists
@@ -220,6 +192,7 @@ def Get_Default_Config():
config['NonOSStdLang'] = NonOSStdLang # True if non-OS-standard language is chosen
config['NoQtBindings'] = NoQtBindings # True if not creating Qt bindings for Ruby scripts
config['NoQtUiTools'] = NoQtUiTools # True if not to include QtUiTools in Qt binding
+ config['NoLibGit2'] = NoLibGit2 # True if not to include libgit2 for Git package support
config['MakeOptions'] = MakeOptions # options passed to `make`
config['DebugMode'] = DebugMode # True if debug mode build
config['CheckComOnly'] = CheckComOnly # True if only for checking the command line parameters to "build.sh"
@@ -230,6 +203,7 @@ def Get_Default_Config():
config['Version'] = Version # KLayout's version
config['ModuleSet'] = ModuleSet # (Qt, Ruby, Python)-tuple
config['ToolDebug'] = ToolDebug # debug level list for this tool
+ config['HBPythonIs39'] = HBPythonIs39 # True if the Homebrew Python version <= 3.9
# auxiliary variables on platform
config['System'] = System # 6-tuple from platform.uname()
config['Node'] = Node # - do -
@@ -239,123 +213,6 @@ def Get_Default_Config():
config['Processor'] = Processor # - do -
return config
-#------------------------------------------------------------------------------
-## To apply a workaround patch to "./src/klayout.pri" to work with Ruby 3.x.
-#
-# @param[in] config dictionary containing the default configuration
-#
-# @return void
-#------------------------------------------------------------------------------
-def ApplyPatch2KLayoutQtPri4Ruby3(config):
- #----------------------------------------------------------------
- # [1] Check if the previous patch exists
- #----------------------------------------------------------------
- priMaster = "./src/klayout.pri"
- priOriginal = "./src/klayout.pri.org"
- if os.path.exists(priOriginal):
- shutil.copy2( priOriginal, priMaster )
- os.remove( priOriginal )
-
- #----------------------------------------------------------------
- # [2] Not using Ruby?
- #----------------------------------------------------------------
- ModuleRuby = config['ModuleRuby']
- if ModuleRuby == 'nil':
- return;
-
- #----------------------------------------------------------------
- # [3] Get the Ruby version code as done in "build.sh"
- #----------------------------------------------------------------
- rubyExe = RubyDictionary[ModuleRuby]['exe']
- oneline = "puts (RbConfig::CONFIG['MAJOR'] || 0).to_i*10000+(RbConfig::CONFIG['MINOR'] || 0).to_i*100+(RbConfig::CONFIG['TEENY'] || 0).to_i"
- command = [ '%s' % rubyExe, '-rrbconfig', '-e', '%s' % oneline ]
- verCode = subprocess.check_output( command, encoding='utf-8' ).strip() # like 3.1.2 => "30102"
- verInt = int(verCode)
- verMajor = verInt // 10000
- verMinor = (verInt - verMajor * 10000) // 100
- verTeeny = (verInt - verMajor * 10000) - (verMinor * 100)
- # print( verMajor, verMinor, verTeeny )
- # quit()
- if verMajor < 3:
- return;
-
- #-----------------------------------------------------------------------------------------------
- # [4] The two buggy Apple compilers below flag errors like:
- #
- # /Applications/anaconda3/include/ruby-3.1.0/ruby/internal/intern/vm.h:383:1: error: \
- # '__declspec' attributes are not enabled; use '-fdeclspec' or '-fms-extensions' to \
- # enable support for __declspec attributes RBIMPL_ATTR_NORETURN()
- #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Problematic in with
- # Apple clang version 12.0.0 (clang-1200.0.32.29)
- # Target: x86_64-apple-darwin19.6.0
- # Thread model: posix
- #
- # Problematic in with
- # Apple clang version 13.0.0 (clang-1300.0.29.30)
- # Target: x86_64-apple-darwin20.6.0
- # Thread model: posix
- #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Non-problematic in with
- # Apple clang version 13.1.6 (clang-1316.0.21.2.5)
- # Target: x86_64-apple-darwin21.6.0
- # Thread model: posix
- #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Refer to https://github.com/nginx/unit/issues/653
- # https://github.com/nginx/unit/issues/653#issuecomment-1062129080
- #
- # Pass "-fdeclspec" option to the QMAKE_CXXFLAGS macro via the "./src/klayout.pri" file like:
- """
- # applied this patch for Mac to work with Ruby 3.x
- mac {
- QMAKE_CXXFLAGS += -fdeclspec
- }
- # applied this patch for Mac to work with Ruby 3.x
- """
- #-----------------------------------------------------------------------------------------------
- #----------------------------------------------------------------
- # (A) Check Platform
- #----------------------------------------------------------------
- Platform = config['Platform']
- if Platform in [ "Ventura", "Monterey" ]:
- return
- elif Platform in [ "BigSur", "Catalina" ]: # take care
- pass
- else:
- return # the results are not tested and unknown
-
- #----------------------------------------------------------------
- # (B) Check ./src/klayout.pri and apply the patch if necessary
- #----------------------------------------------------------------
- keystring = " applied this patch for Mac to work with Ruby 3.x"
- patPatch = r"(^#)([ ]*)(%s)([ ]*$)" % keystring
- regPatch = re.compile(patPatch)
- foundKey1 = False
- foundKey2 = False
-
- with codecs.open( priMaster, "r", "utf-8" ) as file:
- allLines = file.readlines()
- file.close()
- for line in allLines:
- if regPatch.match( line.strip() ):
- if not foundKey1:
- foundKey1 = True
- continue
- elif not foundKey2:
- foundKey2 = True
- break
- if foundKey1 and foundKey2:
- return
-
- shutil.copy2( priMaster, priOriginal )
- with codecs.open( priMaster, "a", "utf-8" ) as file:
- file.write( "# %s\n" % keystring )
- file.write( "mac {\n" )
- file.write( " QMAKE_CXXFLAGS += -fdeclspec\n" )
- file.write( "}\n" )
- file.write( "# %s\n" % keystring )
- return
-
#------------------------------------------------------------------------------
## To parse the command line parameters
#
@@ -378,6 +235,7 @@ def Parse_CLI_Args(config):
NonOSStdLang = config['NonOSStdLang']
NoQtBindings = config['NoQtBindings']
NoQtUiTools = config['NoQtUiTools']
+ NoLibGit2 = config['NoLibGit2']
MakeOptions = config['MakeOptions']
DebugMode = config['DebugMode']
CheckComOnly = config['CheckComOnly']
@@ -387,6 +245,7 @@ def Parse_CLI_Args(config):
DeployVerbose = config['DeployVerbose']
ModuleSet = config['ModuleSet']
ToolDebug = config['ToolDebug']
+ HBPythonIs39 = config['HBPythonIs39']
#-----------------------------------------------------
# [2] Parse the CLI arguments
@@ -398,11 +257,11 @@ def Parse_CLI_Args(config):
p.add_option( '-r', '--ruby',
dest='type_ruby',
- help="Ruby type=['nil', 'Sys', 'MP31', 'HB31', 'Ana3', 'MP32', 'HB32']" )
+ help="Ruby type=['nil', 'Sys', 'MP32', 'HB32', 'Ana3']" )
p.add_option( '-p', '--python',
dest='type_python',
- help="Python type=['nil', 'Sys', 'MP38', 'HB38', 'Ana3', 'MP39', 'HB39', 'HBAuto']" )
+ help="Python type=['nil', 'Sys', 'MP311', 'HB311', 'Ana3', 'MP39', 'HB39', 'HBAuto']" )
p.add_option( '-P', '--buildPymod',
action='store_true',
@@ -422,6 +281,12 @@ def Parse_CLI_Args(config):
default=False,
help="don't include uitools in Qt binding" )
+ p.add_option( '-g', '--nolibgit2',
+ action='store_true',
+ dest='no_libgit2',
+ default=False,
+ help="don't include libgit2 for Git package support" )
+
p.add_option( '-m', '--make',
dest='make_option',
help="options passed to `make`" )
@@ -465,28 +330,14 @@ def Parse_CLI_Args(config):
default=False,
help='check usage' )
- if Platform.upper() in [ "VENTURA", "MONTEREY", "BIGSUR" ]: # with Xcode [13.1 .. ]
+ if Platform.upper() in [ "SONOMA", "VENTURA", "MONTEREY" ]: # with Xcode [13.1 .. ]
p.set_defaults( type_qt = "qt5brew",
type_ruby = "hb32",
- type_python = "hb39",
- build_pymod = False,
- no_qt_binding = False,
- no_qt_uitools = False,
- make_option = "--jobs=4",
- debug_build = False,
- check_command = False,
- deploy_full = False,
- deploy_partial = False,
- deploy_verbose = "1",
- tool_debug = [],
- checkusage = False )
- else: # with Xcode [ .. 12.4]
- p.set_defaults( type_qt = "qt5macports",
- type_ruby = "sys",
- type_python = "sys",
+ type_python = "hb311",
build_pymod = False,
no_qt_binding = False,
no_qt_uitools = False,
+ no_libgit2 = False,
make_option = "--jobs=4",
debug_build = False,
check_command = False,
@@ -495,6 +346,8 @@ def Parse_CLI_Args(config):
deploy_verbose = "1",
tool_debug = [],
checkusage = False )
+ else:
+ raise Exception( "! Too obsolete platform <%s>" % Platform )
opt, args = p.parse_args()
if (opt.checkusage):
@@ -530,18 +383,16 @@ def Parse_CLI_Args(config):
elif ModuleQt == "Qt6Brew":
choiceQt56 = 'qt6Brew'
- # By default, OS-standard (-bundled) script languages (Ruby and Python) are used
+ # Check if non-OS-standard (-bundled) script languages (Ruby and Python) are used
NonOSStdLang = False
# (B) Determine the Ruby type
candidates = dict()
candidates['NIL'] = 'nil'
candidates['SYS'] = 'Sys'
- candidates['MP31'] = 'MP31'
- candidates['HB31'] = 'HB31'
- candidates['ANA3'] = 'Ana3'
candidates['MP32'] = 'MP32'
candidates['HB32'] = 'HB32'
+ candidates['ANA3'] = 'Ana3'
try:
choiceRuby = candidates[ opt.type_ruby.upper() ]
except KeyError:
@@ -553,37 +404,21 @@ def Parse_CLI_Args(config):
ModuleRuby = 'nil'
elif choiceRuby == "Sys":
choiceRuby = "Sys"
- if Platform == "Ventura":
+ if Platform == "Sonoma":
+ ModuleRuby = 'RubySonoma'
+ elif Platform == "Ventura":
ModuleRuby = 'RubyVentura'
elif Platform == "Monterey":
ModuleRuby = 'RubyMonterey'
- elif Platform == "BigSur":
- ModuleRuby = 'RubyBigSur'
- elif Platform == "Catalina":
- ModuleRuby = 'RubyCatalina'
- elif Platform == "Mojave":
- ModuleRuby = 'RubyMojave'
- elif Platform == "HighSierra":
- ModuleRuby = 'RubyHighSierra'
- elif Platform == "Sierra":
- ModuleRuby = 'RubySierra'
- elif Platform == "ElCapitan":
- ModuleRuby = 'RubyElCapitan'
- elif choiceRuby == "MP31":
- ModuleRuby = 'Ruby31MacPorts'
- NonOSStdLang = True
- elif choiceRuby == "HB31":
- ModuleRuby = 'Ruby31Brew'
- NonOSStdLang = True
- elif choiceRuby == "Ana3":
- ModuleRuby = 'RubyAnaconda3'
- NonOSStdLang = True
elif choiceRuby == "MP32":
ModuleRuby = 'Ruby32MacPorts'
NonOSStdLang = True
elif choiceRuby == "HB32":
ModuleRuby = 'Ruby32Brew'
NonOSStdLang = True
+ elif choiceRuby == "Ana3":
+ ModuleRuby = 'RubyAnaconda3'
+ NonOSStdLang = True
if ModuleRuby == '':
print("")
print( "!!! Unknown Ruby type <%s>. Case-insensitive candidates: %s" % \
@@ -594,9 +429,8 @@ def Parse_CLI_Args(config):
# (C) Determine the Python type
candidates = dict()
candidates['NIL'] = 'nil'
- candidates['SYS'] = 'Sys' # has been restored in 0.28.3
- candidates['MP38'] = 'MP38'
- candidates['HB38'] = 'HB38'
+ candidates['MP311'] = 'MP311'
+ candidates['HB311'] = 'HB311'
candidates['ANA3'] = 'Ana3'
candidates['MP39'] = 'MP39'
candidates['HB39'] = 'HB39'
@@ -610,35 +444,30 @@ def Parse_CLI_Args(config):
ModulePython = ''
if choicePython == "nil":
ModulePython = 'nil'
- elif choicePython == "Sys":
- if Platform in [ "Ventura", "Monterey", "BigSur" ]:
- raise Exception( "! Cannot choose the 'sys' Python on <%s>" % Platform )
- elif Platform == "Catalina":
- ModulePython = 'PythonCatalina'
- elif Platform == "Mojave":
- ModulePython = 'PythonMojave'
- elif Platform == "HighSierra":
- ModulePython = 'PythonHighSierra'
- elif Platform == "Sierra":
- ModulePython = 'PythonSierra'
- elif Platform == "ElCapitan":
- ModulePython = 'PythonElCapitan'
- elif choicePython == "MP38":
- ModulePython = 'Python38MacPorts'
+ HBPythonIs39 = None
+ elif choicePython == "MP311":
+ ModulePython = 'Python311MacPorts'
+ HBPythonIs39 = None
NonOSStdLang = True
- elif choicePython == "HB38":
- ModulePython = 'Python38Brew'
+ elif choicePython == "HB311":
+ ModulePython = 'Python311Brew'
+ HBPythonIs39 = False
NonOSStdLang = True
elif choicePython == "Ana3":
ModulePython = 'PythonAnaconda3'
+ HBPythonIs39 = None
NonOSStdLang = True
elif choicePython == "MP39":
ModulePython = 'Python39MacPorts'
+ HBPythonIs39 = None
+ NonOSStdLang = True
elif choicePython == "HB39":
ModulePython = 'Python39Brew'
+ HBPythonIs39 = True
NonOSStdLang = True
elif choicePython == "HBAuto":
ModulePython = 'PythonAutoBrew'
+ HBPythonIs39 = (HBPythonAutoVersion == "3.9")
NonOSStdLang = True
if ModulePython == '':
print("")
@@ -654,6 +483,7 @@ def Parse_CLI_Args(config):
BuildPymod = opt.build_pymod
NoQtBindings = opt.no_qt_binding
NoQtUiTools = opt.no_qt_uitools
+ NoLibGit2 = opt.no_libgit2
MakeOptions = opt.make_option
DebugMode = opt.debug_build
CheckComOnly = opt.check_command
@@ -685,6 +515,7 @@ def Parse_CLI_Args(config):
print("")
print( message % (target, modules, pymodbuild) )
else:
+ okHWdmg = True
message = "### You are going to make "
if DeploymentP:
PackagePrefix = "LW-"
@@ -693,18 +524,24 @@ def Parse_CLI_Args(config):
else:
message += "a lightweight (LW-) package with Pymod excluding Qt5, Ruby, and Python..."
elif DeploymentF:
- if (ModuleRuby in RubySys) and (ModulePython in PythonSys):
+ if (ModuleRuby in RubySys) and (ModulePython in PythonSys): # won't meet this condition any more!
PackagePrefix = "ST-"
message += "a standard (ST-) package including Qt[5|6] and using OS-bundled Ruby and Python..."
- elif ModulePython in ['Python38Brew', 'Python39Brew', 'PythonAutoBrew']:
+ elif ModulePython in ['Python311Brew', 'Python39Brew', 'PythonAutoBrew']:
PackagePrefix = "HW-"
- message += "a heavyweight (HW-) package including Qt[5|6] and Python3.8~ from Homebrew..."
+ message += "a heavyweight (HW-) package including Qt[5|6] and Python3.[11|9] from Homebrew..."
+ okHWdmg = (ModulePython == 'Python311Brew') or \
+ (ModulePython == 'Python39Brew') or \
+ (ModulePython == 'PythonAutoBrew' and HBPythonAutoVersion in ["3.11", "3.9"] )
else:
PackagePrefix = "EX-"
message += "a package with exceptional (EX-) combinations of different modules..."
print( "" )
print( message )
print( "" )
+ if not okHWdmg:
+ print( "!!! HW-dmg package assumes either python@3.11 or python@3.9" )
+ sys.exit(1)
if CheckComOnly:
sys.exit(0)
@@ -720,6 +557,7 @@ def Parse_CLI_Args(config):
config['NonOSStdLang'] = NonOSStdLang
config['NoQtBindings'] = NoQtBindings
config['NoQtUiTools'] = NoQtUiTools
+ config['NoLibGit2'] = NoLibGit2
config['MakeOptions'] = MakeOptions
config['DebugMode'] = DebugMode
config['CheckComOnly'] = CheckComOnly
@@ -729,6 +567,7 @@ def Parse_CLI_Args(config):
config['DeployVerbose'] = DeployVerbose
config['ModuleSet'] = ModuleSet
config['ToolDebug'] = ToolDebug
+ config['HBPythonIs39'] = HBPythonIs39
if CheckComOnly:
pp = pprint.PrettyPrinter( indent=4, width=140 )
@@ -760,6 +599,7 @@ def Get_Build_Parameters(config):
ModuleSet = config['ModuleSet']
NoQtBindings = config['NoQtBindings']
NoQtUiTools = config['NoQtUiTools']
+ NoLibGit2 = config['NoLibGit2']
MakeOptions = config['MakeOptions']
DebugMode = config['DebugMode']
CheckComOnly = config['CheckComOnly']
@@ -833,7 +673,6 @@ def Get_Build_Parameters(config):
# (H) about Ruby
if ModuleRuby != "nil":
- ApplyPatch2KLayoutQtPri4Ruby3( config )
parameters['ruby'] = RubyDictionary[ModuleRuby]['exe']
parameters['rbinc'] = RubyDictionary[ModuleRuby]['inc']
parameters['rblib'] = RubyDictionary[ModuleRuby]['lib']
@@ -858,21 +697,22 @@ def Get_Build_Parameters(config):
# (K) Extra parameters needed for
# will be built if:
# BuildPymod = True
- # Platform = [ 'Monterey', 'BigSur', 'Catalina' ]
- # ModuleRuby = [ 'Ruby31MacPorts', 'Ruby31Brew', 'RubyAnaconda3' ]
- # ModulePython = [ 'Python38MacPorts', 'Python38Brew', 'Python39Brew',
- # 'PythonAnaconda3', 'PythonAutoBrew' ]
+ # Platform = [ 'Sonoma', 'Ventura', 'Monterey']
+ # ModuleRuby = [ 'Ruby32MacPorts', 'Ruby32Brew', 'RubyAnaconda3' ]
+ # ModulePython = [ 'Python311MacPorts', 'Python39MacPorts',
+ # 'Python311Brew', Python39Brew', 'PythonAutoBrew',
+ # 'PythonAnaconda3' ]
parameters['BuildPymod'] = BuildPymod
parameters['Platform'] = Platform
parameters['ModuleRuby'] = ModuleRuby
parameters['ModulePython'] = ModulePython
PymodDistDir = dict()
- if Platform in [ 'Ventura', 'Monterey', 'BigSur', 'Catalina' ]:
- if ModuleRuby in [ 'Ruby31MacPorts', 'Ruby31Brew', 'RubyAnaconda3', 'Ruby32MacPorts', 'Ruby32Brew' ]:
- if ModulePython in [ 'Python38MacPorts', 'Python39MacPorts' ]:
+ if Platform in [ 'Sonoma', 'Ventura', 'Monterey' ]:
+ if ModuleRuby in [ 'Ruby32MacPorts', 'Ruby32Brew', 'RubyAnaconda3' ]:
+ if ModulePython in [ 'Python311MacPorts', 'Python39MacPorts' ]:
PymodDistDir[ModulePython] = 'dist-MP3'
- elif ModulePython in [ 'Python38Brew', 'Python39Brew', 'PythonAutoBrew' ]:
+ elif ModulePython in [ 'Python311Brew', 'Python39Brew', 'PythonAutoBrew' ]:
PymodDistDir[ModulePython] = 'dist-HB3'
elif ModulePython in [ 'PythonAnaconda3' ]:
PymodDistDir[ModulePython] = 'dist-ana3'
@@ -888,27 +728,27 @@ def Get_Build_Parameters(config):
# @return 0 on success; non-zero (1), otherwise
#------------------------------------------------------------------------------
def Build_pymod(parameters):
- #---------------------------------------------------------------------------
+ #-----------------------------------------------------------------------------------------------------------
# [1] will be built if:
# BuildPymod = True
- # Platform = [ 'Ventura', 'Monterey', 'BigSur', 'Catalina' ]
- # ModuleRuby = [ 'Ruby31MacPorts', 'Ruby31Brew', 'RubyAnaconda3',
- # 'Ruby32MacPorts', 'Ruby32Brew' ]
- # ModulePython = [ 'Python38MacPorts', 'Python38Brew', 'PythonAnaconda3',
- # 'Python39MacPorts', 'Python39Brew', 'PythonAutoBrew' ]
- #---------------------------------------------------------------------------
+ # Platform = [ 'Sonoma', 'Ventura', 'Monterey']
+ # ModuleRuby = [ 'Ruby32MacPorts', 'Ruby32Brew', 'RubyAnaconda3' ]
+ # ModulePython = [ 'Python311MacPorts', 'Python39MacPorts',
+ # 'Python311Brew', Python39Brew', 'PythonAutoBrew',
+ # 'PythonAnaconda3' ]
+ #-----------------------------------------------------------------------------------------------------------
BuildPymod = parameters['BuildPymod']
Platform = parameters['Platform']
ModuleRuby = parameters['ModuleRuby']
ModulePython = parameters['ModulePython']
if not BuildPymod:
return 0
- if not Platform in [ 'Ventura', 'Monterey', 'BigSur', 'Catalina' ]:
+ if not Platform in [ 'Sonoma', 'Ventura', 'Monterey' ]:
return 0
- elif not ModuleRuby in [ 'Ruby31MacPorts', 'Ruby31Brew', 'RubyAnaconda3', 'Ruby32MacPorts', 'Ruby32Brew' ]:
+ elif not ModuleRuby in [ 'Ruby32MacPorts', 'Ruby32Brew', 'RubyAnaconda3' ]:
return 0
- elif not ModulePython in [ 'Python38MacPorts', 'Python38Brew', 'PythonAnaconda3', \
- 'Python39MacPorts', 'Python39Brew', 'PythonAutoBrew' ]:
+ elif not ModulePython in [ 'Python311MacPorts', 'Python39MacPorts', 'PythonAnaconda3', \
+ 'Python311Brew', 'Python39Brew', 'PythonAutoBrew' ]:
return 0
#--------------------------------------------------------------------
@@ -927,6 +767,7 @@ def Build_pymod(parameters):
addBinPath = "%s/bin" % DefaultHomebrewRoot # defined in "build4mac_env.py"
addIncPath = "%s/include" % DefaultHomebrewRoot # -- ditto --
addLibPath = "%s/lib" % DefaultHomebrewRoot # -- ditto --
+ # Using Anaconda3
elif PymodDistDir[ModulePython] == 'dist-ana3':
addBinPath = "/Applications/anaconda3/bin"
addIncPath = "/Applications/anaconda3/include"
@@ -1081,16 +922,54 @@ def Build_pymod(parameters):
#------------------------------------------------------------------------------
## To run the main Bash script "build.sh" with appropriate options
#
-# @param[in] parameters dictionary containing the build parameters
+# @param[in] config the build configuration
+# @param[in] parameters the build parameters
#
# @return 0 on success; non-zero (1), otherwise
#------------------------------------------------------------------------------
-def Run_Build_Command(parameters):
- jump2pymod = False # default=False; set True to jump into pymod-build for debugging
+def Run_Build_Command(config, parameters):
+ ModuleQt = config['ModuleQt']
+ NoLibGit2 = config['NoLibGit2']
+ ToolDebug = config['ToolDebug']
+ if 100 not in ToolDebug: # default
+ jump2pymod = False
+ else:
+ jump2pymod = True
+
+ #-----------------------------------------------------
+ # [1] Set two environment variables to use libgit2
+ #-----------------------------------------------------
+ if not NoLibGit2:
+ # Using MacPorts
+ if ModuleQt.upper() in [ 'QT5MACPORTS', 'QT6MACPORTS' ]:
+ addIncPath = "/opt/local/include"
+ addLibPath = "/opt/local/lib"
+ # Using Homebrew
+ elif ModuleQt.upper() in [ 'QT5BREW', 'QT6BREW' ]:
+ addIncPath = "%s/include" % DefaultHomebrewRoot # defined in "build4mac_env.py"
+ addLibPath = "%s/lib" % DefaultHomebrewRoot # -- ditto --
+ # Using Anaconda3
+ elif ModuleQt.upper() in [ 'QT5ANA3' ]:
+ addIncPath = "/Applications/anaconda3/include"
+ addLibPath = "/Applications/anaconda3/lib"
+ else:
+ addIncPath = ""
+ addLibPath = ""
+
+ # These environment variables are expanded on the fly in ../src/klayout.pri.
+ if not addIncPath == "":
+ os.environ['MAC_LIBGIT2_INC'] = "%s" % addIncPath
+ else:
+ os.environ['MAC_LIBGIT2_INC'] = "_invalid_MAC_LIBGIT2_INC_" # compile should fail
+
+ if not addLibPath == "":
+ os.environ['MAC_LIBGIT2_LIB'] = "%s" % addLibPath
+ else:
+ os.environ['MAC_LIBGIT2_LIB'] = "_invalid_MAC_LIBGIT2_LIB_" # link should fail
if not jump2pymod:
#-----------------------------------------------------
- # [1] Set parameters passed to the main Bash script
+ # [2] Set parameters passed to the main Bash script
#-----------------------------------------------------
cmd_args = ""
@@ -1122,11 +1001,15 @@ def Run_Build_Command(parameters):
if parameters['no_qt_uitools']:
cmd_args += " \\\n -without-qt-uitools"
- # (G) options to `make` tool
+ # (G) don't want to use libgit2?
+ if NoLibGit2:
+ cmd_args += " \\\n -libgit2"
+
+ # (H) options to `make` tool
if 'make_options' in parameters:
cmd_args += " \\\n -option %s" % parameters['make_options']
- # (H) about Ruby
+ # (I) about Ruby
if 'ruby' in parameters:
cmd_args += " \\\n -ruby %s" % parameters['ruby']
cmd_args += " \\\n -rbinc %s" % parameters['rbinc']
@@ -1136,7 +1019,7 @@ def Run_Build_Command(parameters):
else:
cmd_args += " \\\n -noruby"
- # (I) about Python
+ # (J) about Python
if 'python' in parameters:
cmd_args += " \\\n -python %s" % parameters['python']
cmd_args += " \\\n -pyinc %s" % parameters['pyinc']
@@ -1145,7 +1028,7 @@ def Run_Build_Command(parameters):
cmd_args += " \\\n -nopython"
#-----------------------------------------------------
- # [2] Make the consolidated command line
+ # [3] Make the consolidated command line
#-----------------------------------------------------
command = "time"
command += " \\\n %s" % parameters['build_cmd']
@@ -1158,7 +1041,7 @@ def Run_Build_Command(parameters):
sys.exit(0)
#-----------------------------------------------------
- # [3] Invoke the main Bash script; takes time:-)
+ # [4] Invoke the main Bash script; takes time:-)
#-----------------------------------------------------
myscript = os.path.basename(__file__)
ret = subprocess.call( command, shell=True )
@@ -1177,7 +1060,7 @@ def Run_Build_Command(parameters):
print( "", file=sys.stderr )
#------------------------------------------------------------------------
- # [4] Prepare "*.macQAT/" directory for the QATest.
+ # [5] Prepare "*.macQAT/" directory for the QATest.
# Binaries under "*.macQAT/" such as *.dylib will be touched later.
#------------------------------------------------------------------------
print( "### Preparing <%s>" % MacBuildDirQAT )
@@ -1209,7 +1092,6 @@ def Run_Build_Command(parameters):
os.remove( tarFile )
os.chdir( "../" )
- shutil.copy2( "macbuild/macQAT.sh", MacBuildDirQAT )
shutil.copy2( "macbuild/macQAT.py", MacBuildDirQAT )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "### <%s>: prepared the initial *.macQAT/" % myscript, file=sys.stderr )
@@ -1217,7 +1099,7 @@ def Run_Build_Command(parameters):
print( "", file=sys.stderr )
#------------------------------------------------------------------------
- # [5] Build for some predetermined environments on demand
+ # [6] Build for some predetermined environments on demand
#------------------------------------------------------------------------
BuildPymod = parameters['BuildPymod']
if BuildPymod:
@@ -1250,6 +1132,7 @@ def Deploy_Binaries_For_Bundle(config, parameters):
ModuleRuby = config['ModuleRuby']
ModulePython = config['ModulePython']
ToolDebug = config['ToolDebug']
+ HBPythonIs39 = config['HBPythonIs39']
BuildPymod = parameters['BuildPymod']
ProjectDir = parameters['project_dir']
@@ -1325,7 +1208,7 @@ def Deploy_Binaries_For_Bundle(config, parameters):
# +-- Frameworks/+
# | +-- '*.framework'
# | +-- '*.dylib'
- # | +-- 'db_plugins' --slink--> ../MacOS/db_plugins/
+ # | +-- 'db_plugins' --sym.link--> ../MacOS/db_plugins/
# +-- MacOS/+
# | +-- 'klayout'
# | +-- db_plugins/
@@ -1336,12 +1219,10 @@ def Deploy_Binaries_For_Bundle(config, parameters):
# | :
# | +-- 'strmxor'
# |
- # +-- pymod-dist/+ (created only if *.whl and *.egg are available)
+ # +-- pymod-dist/+ (created only if *.whl is available)
# +-- klayout-0.27.8-cp38-cp38-macosx_10_9_x86_64.whl (example)(1)
- # +-- klayout-0.27.8-py3.8-macosx-10.9-x86_64.egg (example)(2)
#
- # (1) *.whl is recommended to install with 'pip3'
- # (2) *.egg is for 'easy_install' users
+ # (1) *.whl is install with 'pip3'
#--------------------------------------------------------------------------------------------------------------
targetDir0 = "%s/klayout.app/Contents" % AbsMacPkgDir
targetDirR = targetDir0 + "/Resources"
@@ -1468,7 +1349,7 @@ def Deploy_Binaries_For_Bundle(config, parameters):
# +-- Frameworks/+
# | +-- '*.framework'
# | +-- '*.dylib'
- # | +-- 'db_plugins' --slink--> ../MacOS/db_plugins/
+ # | +-- 'db_plugins' --sym.link--> ../MacOS/db_plugins/
# +-- MacOS/+
# | +-- 'klayout'
# | +-- db_plugins/
@@ -1532,8 +1413,6 @@ def Deploy_Binaries_For_Bundle(config, parameters):
if BuildPymod and not pymodDistDir == "":
for item in glob.glob( pymodDistDir + "/*.whl" ):
shutil.copy2( item, targetDirP )
- for item in glob.glob( pymodDistDir + "/*.egg" ):
- shutil.copy2( item, targetDirP )
print( " [7] Setting and changing the identification names of KLayout's libraries in each executable ..." )
#------------------------------------------------------------------------------------
@@ -1621,16 +1500,16 @@ def Deploy_Binaries_For_Bundle(config, parameters):
# [*] lrwxr-xr-x 1 kazzz-s admin 27 12 16 21:40 Resources -> Versions/Current/Resources/
# drwxr-xr-x 4 kazzz-s admin 128 12 16 21:40 Versions
#-----------------------------------------------------------------------------------------------
- deploymentPython38HB = (ModulePython == 'Python38Brew')
+ deploymentPython311HB = (ModulePython == 'Python311Brew')
deploymentPython39HB = (ModulePython == 'Python39Brew')
deploymentPythonAutoHB = (ModulePython == 'PythonAutoBrew')
- if (deploymentPython38HB or deploymentPython39HB or deploymentPythonAutoHB) and NonOSStdLang:
+ if (deploymentPython311HB or deploymentPython39HB or deploymentPythonAutoHB) and NonOSStdLang:
# from build4mac_util import WalkFrameworkPaths, PerformChanges
# from build4mac_util import Change_Python_LibPath_RelativeToAbsolute, DumpDependencyDic
- if deploymentPython38HB:
- HBPythonFrameworkPath = HBPython38FrameworkPath
- pythonHBVer = "3.8" # 'pinned' to this version as of KLayout version 0.26.7 (2020-09-13)
+ if deploymentPython311HB:
+ HBPythonFrameworkPath = HBPython311FrameworkPath
+ pythonHBVer = "3.11" # 'pinned' to this version as of KLayout version 0.28.12 (2020-10-27)
elif deploymentPython39HB:
HBPythonFrameworkPath = HBPython39FrameworkPath
pythonHBVer = "3.9" # 'pinned' to this version as of KLayout version 0.28.2 (2023-01-02)
@@ -1684,7 +1563,16 @@ def Deploy_Binaries_For_Bundle(config, parameters):
print( msg % command, file=sys.stderr )
sys.exit(1)
- shutil.copy2( sourceDir2 + "/start-console.py", targetDirM )
+ if HBPythonIs39 == None or HBPythonIs39 == True:
+ shutil.copy2( sourceDir2 + "/start-console.py", targetDirM )
+ else:
+ ret = Generate_Start_Console_Py( sourceDir2 + "/template-start-console.py",
+ pythonHBVer,
+ targetDirM + "/start-console.py" )
+ if ret == False:
+ print( "! Generate_Start_Console_Py() failed", file=sys.stderr )
+ return 1
+
shutil.copy2( sourceDir2 + "/klayout_console", targetDirM )
os.chmod( targetDirM + "/start-console.py", 0o0755 )
os.chmod( targetDirM + "/klayout_console", 0o0755 )
@@ -1724,28 +1612,7 @@ def Deploy_Binaries_For_Bundle(config, parameters):
PerformChanges( depdict, replacePairs, bundleExecPathAbs, debug_level=dbglevel )
#---------------------------------------------------------------------------------------------------
- # As of 2023-07-09 (KLayout 0.28.10),
- # python@3.9 (Python 3.9.17) in [ 'Ventura', 'Monterey', 'BigSur' ] depends on openssl@3
- # % brew deps python@3.9
- # ca-certificates
- # gdbm
- # mpdecimal
- # openssl@3 <===
- # readline
- # sqlite
- # xz
- #
- # python@3.9 (Python 3.9.16; already stopped upgrading) in ['Catalina'] depends on openssl@1.1
- # ca-certificates
- # gdbm
- # gettext
- # mpdecimal
- # openssl@1.1 <===
- # readline
- # sqlite
- # xz
- #---------------------------------------------------------------------------------------------------
- # https://formulae.brew.sh/formula/python@3.9#default
+ # https://formulae.brew.sh/formula/python@3.9
# as of 2023-09-22, python@3.9 depends on:
# gdbm 1.23 GNU database manager
# mpdecimal 2.5.1 Library for decimal floating point arithmetic
@@ -1754,46 +1621,32 @@ def Deploy_Binaries_For_Bundle(config, parameters):
# sqlite 3.43.1 Command-line interface for SQLite
# xz 5.4.4 General-purpose data compression with high compression ratio
#---------------------------------------------------------------------------------------------------
- if Platform in ['Catalina']:
- print( " [9.2.4] Patching [openssl@1.1, gdbm, mpdecimal, readline, sqlite, xz]" )
- if 924 in ToolDebug:
- dbglevel = 924
- else:
- dbglevel = 0
- usrLocalPath = '%s/opt/' % DefaultHomebrewRoot
- appUsrLocalPath = '@executable_path/../Frameworks/'
- replacePairs = [ (usrLocalPath, appUsrLocalPath, True) ]
- replacePairs.extend( [ (openssl_version, '@executable_path/../Frameworks/openssl@1.1', True)
- for openssl_version in glob.glob( '%s/Cellar/openssl@1.1/*' % DefaultHomebrewRoot ) ] )
- filterreg = r'\t+%s/(opt|Cellar)' % DefaultHomebrewRoot
- depdict = WalkFrameworkPaths( [pythonFrameworkPath + '/../openssl@1.1',
- pythonFrameworkPath + '/../gdbm',
- pythonFrameworkPath + '/../mpdecimal',
- pythonFrameworkPath + '/../readline',
- pythonFrameworkPath + '/../sqlite',
- pythonFrameworkPath + '/../xz'],
- search_path_filter=filterreg,
- debug_level=dbglevel )
- else: # [ 'Ventura', 'Monterey', 'BigSur' ]
- print( " [9.2.4] Patching [openssl@3, gdbm, mpdecimal, readline, sqlite, xz]" )
- if 924 in ToolDebug:
- dbglevel = 924
- else:
- dbglevel = 0
- usrLocalPath = '%s/opt/' % DefaultHomebrewRoot
- appUsrLocalPath = '@executable_path/../Frameworks/'
- replacePairs = [ (usrLocalPath, appUsrLocalPath, True) ]
- replacePairs.extend( [ (openssl_version, '@executable_path/../Frameworks/openssl@3', True)
- for openssl_version in glob.glob( '%s/Cellar/openssl@3/*' % DefaultHomebrewRoot ) ] )
- filterreg = r'\t+%s/(opt|Cellar)' % DefaultHomebrewRoot
- depdict = WalkFrameworkPaths( [pythonFrameworkPath + '/../openssl@3',
- pythonFrameworkPath + '/../gdbm',
- pythonFrameworkPath + '/../mpdecimal',
- pythonFrameworkPath + '/../readline',
- pythonFrameworkPath + '/../sqlite',
- pythonFrameworkPath + '/../xz'],
- search_path_filter=filterreg,
- debug_level=dbglevel )
+ # https://formulae.brew.sh/formula/python@3.11
+ # as of 2023-10-24, python@3.11 depends on:
+ # mpdecimal 2.5.1 Library for decimal floating point arithmetic
+ # openssl@3 3.1.3 Cryptography and SSL/TLS Toolkit
+ # sqlite 3.43.2 Command-line interface for SQLite
+ # xz 5.4.4 General-purpose data compression with high compression ratio
+ #---------------------------------------------------------------------------------------------------
+ print( " [9.2.4] Patching [mpdecimal, openssl@3, sqlite, xz(, gdbm, readline)]" )
+ if 924 in ToolDebug:
+ dbglevel = 924
+ else:
+ dbglevel = 0
+ usrLocalPath = '%s/opt/' % DefaultHomebrewRoot
+ appUsrLocalPath = '@executable_path/../Frameworks/'
+ replacePairs = [ (usrLocalPath, appUsrLocalPath, True) ]
+ replacePairs.extend( [ (openssl_version, '@executable_path/../Frameworks/openssl@3', True)
+ for openssl_version in glob.glob( '%s/Cellar/openssl@3/*' % DefaultHomebrewRoot ) ] )
+ filterreg = r'\t+%s/(opt|Cellar)' % DefaultHomebrewRoot
+ depdict = WalkFrameworkPaths( [pythonFrameworkPath + '/../mpdecimal',
+ pythonFrameworkPath + '/../openssl@3',
+ pythonFrameworkPath + '/../sqlite',
+ pythonFrameworkPath + '/../xz',
+ pythonFrameworkPath + '/../gdbm',
+ pythonFrameworkPath + '/../readline'],
+ search_path_filter=filterreg,
+ debug_level=dbglevel )
DumpDependencyDic( "[9.2.4]", depdict, debug_level=dbglevel )
PerformChanges( depdict, replacePairs, bundleExecPathAbs, debug_level=dbglevel )
@@ -1819,27 +1672,58 @@ def Deploy_Binaries_For_Bundle(config, parameters):
replacePairs = [ (HBPythonFrameworkPath, appPythonFrameworkPath, False) ]
PerformChanges( depdict, replacePairs, bundleExecPathAbs, debug_level=dbglevel )
- print( " [9.4] Patching site.py, pip/, and distutils/" )
+ print( " [9.4] Patching site.py and pip/" )
if 940 in ToolDebug:
dbglevel = 940
else:
dbglevel = 0
site_module = "%s/Versions/%s/lib/python%s/site.py" % (pythonFrameworkPath, pythonHBVer, pythonHBVer)
+ #-----------------------------------------------------------------------------------------
+ # Rewrite the above file.
+ # :
+ # # Prefixes for site-packages; add additional prefixes like /usr/local here
+ # PREFIXES = [sys.prefix, sys.exec_prefix]
+ # (1) sys.real_prefix = sys.prefix <=== (1) add
+ # # Enable per user site-packages directory
+ # # set it to False to disable the feature or True to force the feature
+ # (2) ENABLE_USER_SITE = False <=== (2) modify
+ # :
+ #
+ # This will fool pip into thinking it's inside a virtual environment
+ # and install new packages to the correct site-packages.
+ #-----------------------------------------------------------------------------------------
+ # It looks like the technique of modifying works when Python<=3.9 as follows.
+ # However, it doesn't when 3.11<=Python.
+ #
+ # In (Linux source code build)
+ # :
+ # # Prefixes for site-packages; add additional prefixes like /usr/local here
+ # PREFIXES = [sys.prefix, sys.exec_prefix]
+ # # Enable per user site-packages directory
+ # # set it to False to disable the feature or True to force the feature
+ # ENABLE_USER_SITE = None
+ # print( "### I have imported the modified <%s>" % __file__ ) <=== (3) added
+ # :
+ #
+ # MyLinux{kazzz-s}(1)$ ./python
+ # ### I have imported the modified ---(3)
+ # Python 3.9.18+ (heads/3.9:43a6e4fa49, Oct 27 2023, 12:51:17)
+ # [GCC 9.4.0] on linux
+ # Type "help", "copyright", "credits" or "license" for more information.
+ # >>>
+ #-----------------------------------------------------------------------------------------
with open(site_module, 'r') as site:
buf = site.readlines()
with open(site_module, 'w') as site:
- import re
for line in buf:
- # This will fool pip into thinking it's inside a virtual environment
- # and install new packages to the correct site-packages
if re.match("^PREFIXES", line) is not None:
- line = line + "sys.real_prefix = sys.prefix\n"
+ line = line + "sys.real_prefix = sys.prefix\n" # --- (1)
# do not allow installation in the user folder.
if re.match("^ENABLE_USER_SITE", line) is not None:
- line = "ENABLE_USER_SITE = False\n"
+ line = "ENABLE_USER_SITE = False\n" # --- (2)
site.write(line)
- #----------------------------------------------------------------------------------
+ #-----------------------------------------------------------------------------------------
# Typical usage of 'pip' after installation of the DMG package
#
# $ cd /Applications/klayout.app/Contents/MacOS/
@@ -1857,29 +1741,61 @@ def Deploy_Binaries_For_Bundle(config, parameters):
# >>> quit()
#
# 'pandas' depends on many modules including 'numpy'. They are also installed.
- #----------------------------------------------------------------------------------
+ #-----------------------------------------------------------------------------------------
pip_module = "%s/Versions/%s/lib/python%s/site-packages/pip/__init__.py" % \
(pythonFrameworkPath, pythonHBVer, pythonHBVer)
with open(pip_module, 'r') as pip:
buf = pip.readlines()
with open(pip_module, 'w') as pip:
- import re
for line in buf:
# this will reject user's configuration of pip, forcing the isolated mode
line = re.sub("return isolated$", "return isolated or True", line)
pip.write(line)
- distutilsconfig = "%s/Versions/%s/lib/python%s/distutils/distutils.cfg" % \
+ #----------------------------------------------------------------------------------------------------
+ # Patch distutils/ in older versions of Python.
+ # However, newer versions of Python deprecate the distutils.cfg file and the distutils module itself.
+ # Ref. https://github.com/Homebrew/homebrew-core/issues/76621
+ #----------------------------------------------------------------------------------------------------
+ if deploymentPython39HB or (HBPythonAutoVersion == "3.9"): # Python == 3.9
+ print( deploymentPython39HB, HBPythonAutoVersion )
+ print( " [9.5.1] Patching distutils/" )
+ if 951 in ToolDebug:
+ dbglevel = 951
+ else:
+ dbglevel = 0
+ distutilsconfig = "%s/Versions/%s/lib/python%s/distutils/distutils.cfg" % \
(pythonFrameworkPath, pythonHBVer, pythonHBVer)
- with open(distutilsconfig, 'r') as file:
- buf = file.readlines()
- with open(distutilsconfig, 'w') as file:
- import re
- for line in buf:
- # This will cause all packages to be installed to sys.prefix
- if re.match('prefix=', line) is not None:
- continue
- file.write(line)
+ #-----------------------------------------------------------------------------------------
+ # Rewrite the above file in Homebrew python@3.9.18.
+ # [install]
+ # prefix=/usr/local <=== remove this line
+ # [build_ext]
+ # include_dirs=/usr/local/include:/usr/local/opt/openssl@3/include:\
+ # /usr/local/opt/sqlite/include
+ # library_dirs=/usr/local/lib:/usr/local/opt/openssl@3/lib:/usr/local/opt/sqlite/lib
+ #
+ # This will cause all packages to be installed to sys.prefix
+ #-----------------------------------------------------------------------------------------
+ with open(distutilsconfig, 'r') as file:
+ buf = file.readlines()
+ with open(distutilsconfig, 'w') as file:
+ for line in buf:
+ if re.match('prefix=', line) is not None:
+ continue
+ file.write(line)
+
+ elif deploymentPython311HB or (HBPythonAutoVersion == "3.11"): # Python == 3.11
+ # The above 'distutils.cfg' file does not exist in the distutils/ directory of Python 3.11.
+ # Use a different technique.
+ print( " [9.5.2] In the Python3.11 environment, use an alternative method of patching distutils/" )
+ print( " See Contents/MacOS/start-console.py in /Applications/klayout.app/" )
+ else: # other than ["3.11", "3.9"]; "3.12" <= Python is yet to be tested
+ print( "!!! HW-dmg package assumes either python@3.11 or python@3.9" )
+ print( "!!! 'distutils' has been deprecated in 3.12 <= Python" )
+ print("")
+ os.chdir(ProjectDir)
+ return 1
#-------------------------------------------------------------
# [10] Special deployment of Ruby3.2 from Homebrew?
@@ -1921,7 +1837,7 @@ def Main():
pp.pprint(parameters)
if not config['DeploymentF'] and not config['DeploymentP']:
- ret = Run_Build_Command(parameters)
+ ret = Run_Build_Command(config, parameters)
pp.pprint(config)
if not ret == 0:
sys.exit(1)
diff --git a/macbuild/build4mac_env.py b/macbuild/build4mac_env.py
index 7eb077891..2074d5c14 100755
--- a/macbuild/build4mac_env.py
+++ b/macbuild/build4mac_env.py
@@ -6,11 +6,12 @@
#
# Here are dictionaries of ...
# different modules for building KLayout (http://www.klayout.de/index.php)
-# version 0.26.1 or later on different Apple Mac OSX platforms.
+# version 0.28.13 or later on different Apple Mac OSX platforms.
#
# This file is imported by 'build4mac.py' script.
#===============================================================================
import os
+import re
import glob
import platform
@@ -30,25 +31,31 @@ if Machine == "arm64": # Apple Silicon!
HomebrewSearchPathFilter1 = '\t+%s/opt' % DefaultHomebrewRoot
HomebrewSearchPathFilter2 = '\t+@loader_path/../../../../../../../../../../opt'
HomebrewSearchPathFilter3 = '@loader_path/../../../../../../../../../../opt' # no leading white space
- # 1: absolute path as in ~python@3.9.17
- # 2: relative path as in python@3.9.18~
+ # 1: absolute path as seen in ~python@3.9.17
+ # 2: relative path as seen in python@3.9.18
else:
DefaultHomebrewRoot = '/usr/local'
HomebrewSearchPathFilter1 = '\t+%s/opt' % DefaultHomebrewRoot
HomebrewSearchPathFilter2 = '\t+@loader_path/../../../../../../../../../../opt'
HomebrewSearchPathFilter3 = '@loader_path/../../../../../../../../../../opt' # no leading white space
- # 1: absolute path as in ~python@3.9.17
+ # 1: absolute path as seen in ~python@3.9.17
# BigSur{kazzz-s} lib-dynload (1)% otool -L _sqlite3.cpython-39-darwin.so
# _sqlite3.cpython-39-darwin.so:
# ===> /usr/local/opt/sqlite/lib/libsqlite3.0.dylib (compatibility version 9.0.0, current version 9.6.0)
# /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.100.5)
#
- # 2: relative path as in python@3.9.18~
+ # 2: relative path as seen in python@3.9.18
# Monterey{kazzz-s} lib-dynload (1)% otool -L _sqlite3.cpython-39-darwin.so
# _sqlite3.cpython-39-darwin.so:
# ===> @loader_path/../../../../../../../../../../opt/sqlite/lib/libsqlite3.0.dylib (compatibility version 9.0.0, current version 9.6.0)
# /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.100.3)
#
+ # 3. absolute path again as seen in python@3.11
+ # Monterey{kazzz-s} lib-dynload (1)% otool -L _sqlite3.cpython-311-darwin.so
+ # _sqlite3.cpython-311-darwin.so:
+ # ===> /usr/local/opt/sqlite/lib/libsqlite3.0.dylib (compatibility version 9.0.0, current version 9.6.0)
+ # /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.100.3)
+ #
# Ref. https://github.com/Homebrew/homebrew-core/issues/140930#issuecomment-1701524467
del System, Node, Release, MacVersion, Machine, Processor
@@ -102,91 +109,21 @@ Qt6Brew = { 'qmake' : '%s/opt/qt@6/bin/qmake' % DefaultHomebrewRoot,
#-----------------------------------------------------
# [2] Ruby
+# * Dropped the followings (2023-10-24).
+# Sys: [ElCapitan - BigSur]
+# Ext: [Ruby31]
+# * See 415b5aa2efca04928f1148a69e77efd5d76f8c1d
+# for the previous states.
#-----------------------------------------------------
RubyNil = [ 'nil' ]
-RubySys = [ 'RubyElCapitan', 'RubySierra', 'RubyHighSierra', 'RubyMojave' ]
-RubySys += [ 'RubyCatalina', 'RubyBigSur', 'RubyMonterey', 'RubyVentura' ]
-RubyExt = [ 'Ruby31MacPorts', 'Ruby32MacPorts', 'Ruby31Brew', 'Ruby32Brew', 'RubyAnaconda3' ]
+RubySys = [ 'RubyMonterey', 'RubyVentura', 'RubySonoma' ]
+RubyExt = [ 'Ruby32MacPorts', 'Ruby32Brew', 'RubyAnaconda3' ]
Rubies = RubyNil + RubySys + RubyExt
#-----------------------------------------------------
# Whereabouts of different components of Ruby
#-----------------------------------------------------
-# Bundled with Yosemite (10.10)
-# !!! Yosemite is no longer supported (KLayout 0.26 ~) but remains here to keep the record of
-# the directory structure of earlier generations.
-# [Key Type Name] = 'Sys'
-RubyYosemite = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby',
- 'inc': '/System/Library/Frameworks/Ruby.framework/Headers',
- 'lib': '/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/libruby.dylib'
- }
-
-# Bundled with El Capitan (10.11)
-# [Key Type Name] = 'Sys'
-RubyElCapitan = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby',
- 'inc': '/System/Library/Frameworks/Ruby.framework/Headers',
- 'lib': '/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/libruby.dylib'
- }
-
-# Bundled with Sierra (10.12)
-# [Key Type Name] = 'Sys'
-RubySierra = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby',
- 'inc': '/System/Library/Frameworks/Ruby.framework/Headers',
- 'lib': '/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/libruby.dylib'
- }
-
-# Bundled with High Sierra (10.13)
-# [Key Type Name] = 'Sys'
-RubyHighSierra = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby',
- 'inc': '/System/Library/Frameworks/Ruby.framework/Headers',
- 'lib': '/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/libruby.dylib'
- }
-
-# Bundled with Mojave (10.14)
-# The missing Ruby header files under "/System/Library/Frameworks/Ruby.framework/" were manually deployed there
-# from "Xcode-10.1-beta2" with the corresponding Ruby version.
-# [Key Type Name] = 'Sys'
-RubyMojave = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby',
- 'inc': '/System/Library/Frameworks/Ruby.framework/Headers',
- 'lib': '/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/libruby.dylib'
- }
-
-# Bundled with Catalina (10.15)
-# !!! 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.
-#
-# 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'
-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',
- 'inc': '%s/System/Library/Frameworks/Ruby.framework/Headers' % CatalinaSDK,
- 'inc2': '%s/System/Library/Frameworks/Ruby.framework/Headers/ruby' % CatalinaSDK,
- 'lib': '%s/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.tbd' % CatalinaSDK
- }
-
-# Bundled with Big Sur (11.x)
-# Refer to the "Catalina" section above
-# [Key Type Name] = 'Sys'
-BigSurSDK = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
-RubyBigSur = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby',
- 'inc': '%s/System/Library/Frameworks/Ruby.framework/Headers' % BigSurSDK,
- 'inc2': '%s/System/Library/Frameworks/Ruby.framework/Headers/ruby' % BigSurSDK,
- 'lib': '%s/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.tbd' % BigSurSDK
- }
-
# Bundled with Monterey (12.x)
-# Refer to the "Catalina" section above
# [Key Type Name] = 'Sys'
MontereySDK = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
RubyMonterey = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby',
@@ -195,8 +132,7 @@ RubyMonterey = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/
'lib': '%s/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.tbd' % MontereySDK
}
-# Bundled with Ventura (14.x)
-# Refer to the "Catalina" section above
+# Bundled with Ventura (13.x)
# [Key Type Name] = 'Sys'
VenturaSDK = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
RubyVentura = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby',
@@ -205,15 +141,16 @@ RubyVentura = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/
'lib': '%s/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.tbd' % VenturaSDK
}
-# Ruby 3.1 from MacPorts (https://www.macports.org/) *+*+*+ EXPERIMENTAL *+*+*+
-# install with 'sudo port install ruby31'
-# [Key Type Name] = 'MP31'
-Ruby31MacPorts = { 'exe': '/opt/local/bin/ruby3.1',
- 'inc': '/opt/local/include/ruby-3.1.3',
- 'lib': '/opt/local/lib/libruby.3.1.dylib'
+# Bundled with Sonoma (14.x)
+# [Key Type Name] = 'Sys'
+SonomaSDK = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
+RubySonoma = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby',
+ 'inc': '%s/System/Library/Frameworks/Ruby.framework/Headers' % SonomaSDK,
+ 'inc2': '%s/System/Library/Frameworks/Ruby.framework/Headers/ruby' % SonomaSDK,
+ 'lib': '%s/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.tbd' % SonomaSDK
}
-# Ruby 3.2 from MacPorts (https://www.macports.org/) *+*+*+ EXPERIMENTAL *+*+*+
+# Ruby 3.2 from MacPorts (https://www.macports.org/)
# install with 'sudo port install ruby32'
# [Key Type Name] = 'MP32'
Ruby32MacPorts = { 'exe': '/opt/local/bin/ruby3.2',
@@ -221,16 +158,7 @@ Ruby32MacPorts = { 'exe': '/opt/local/bin/ruby3.2',
'lib': '/opt/local/lib/libruby.3.2.dylib'
}
-# Ruby 3.1 from Homebrew *+*+*+ EXPERIMENTAL *+*+*+
-# install with 'brew install ruby@3.1'
-# [Key Type Name] = 'HB31'
-HBRuby31Path = '%s/opt/ruby@3.1' % DefaultHomebrewRoot
-Ruby31Brew = { 'exe': '%s/bin/ruby' % HBRuby31Path,
- 'inc': '%s/include/ruby-3.1.0' % HBRuby31Path,
- 'lib': '%s/lib/libruby.3.1.dylib' % HBRuby31Path
- }
-
-# Ruby 3.2 from Homebrew *+*+*+ EXPERIMENTAL *+*+*+
+# Ruby 3.2 from Homebrew
# install with 'brew install ruby@3.2'
# [Key Type Name] = 'HB32'
HBRuby32Path = '%s/opt/ruby@3.2' % DefaultHomebrewRoot
@@ -239,7 +167,7 @@ Ruby32Brew = { 'exe': '%s/bin/ruby' % HBRuby32Path,
'lib': '%s/lib/libruby.3.2.dylib' % HBRuby32Path
}
-# Ruby 3.1 bundled with anaconda3 installed under /Applications/anaconda3/ *+*+*+ EXPERIMENTAL *+*+*+
+# Ruby 3.1 bundled with anaconda3 installed under /Applications/anaconda3/
# The standard installation deploys the tool under $HOME/opt/anaconda3/.
# If so, you need to make a symbolic link: /Applications/anaconda3 ---> $HOME/opt/anaconda3/
# [Key Type Name] = 'Ana3'
@@ -250,157 +178,118 @@ RubyAnaconda3 = { 'exe': '/Applications/anaconda3/bin/ruby',
# Consolidated dictionary kit for Ruby
RubyDictionary = { 'nil' : None,
- 'RubyYosemite' : RubyYosemite,
- 'RubyElCapitan' : RubyElCapitan,
- 'RubySierra' : RubySierra,
- 'RubyHighSierra': RubyHighSierra,
- 'RubyMojave' : RubyMojave,
- 'RubyCatalina' : RubyCatalina,
- 'RubyBigSur' : RubyBigSur,
'RubyMonterey' : RubyMonterey,
'RubyVentura' : RubyVentura,
- 'Ruby31MacPorts': Ruby31MacPorts,
+ 'RubySonoma' : RubySonoma,
'Ruby32MacPorts': Ruby32MacPorts,
- 'Ruby31Brew' : Ruby31Brew,
'Ruby32Brew' : Ruby32Brew,
'RubyAnaconda3' : RubyAnaconda3
}
#-----------------------------------------------------
# [3] Python
+# * Dropped the followings (2023-10-24).
+# Sys: [ElCapitan - Monterey]
+# Ext: [Python38]
+# * See 415b5aa2efca04928f1148a69e77efd5d76f8c1d
+# for the previous states.
#-----------------------------------------------------
PythonNil = [ 'nil' ]
-PythonSys = [ 'PythonElCapitan', 'PythonSierra', 'PythonHighSierra', 'PythonMojave' ]
-PythonSys += [ 'PythonCatalina', 'PythonBigSur', 'PythonMonterey' ]
-PythonExt = [ 'Python38MacPorts', 'Python39MacPorts', 'Python38Brew', 'Python39Brew' ]
+PythonSys = [ ]
+PythonExt = [ 'Python39MacPorts', 'Python39Brew' ]
+PythonExt += [ 'Python311MacPorts', 'Python311Brew' ]
PythonExt += [ 'PythonAnaconda3', 'PythonAutoBrew' ]
Pythons = PythonNil + PythonSys + PythonExt
#-----------------------------------------------------
# Whereabouts of different components of Python
#-----------------------------------------------------
-# Bundled with Yosemite (10.10)
-# !!! Yosemite is no longer supported but remains here to keep the record of the directory structure
-# of earlier generations.
-# [Key Type Name] = 'Sys'
-PythonYosemite = { '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'
- }
-
-# Bundled with El Capitan (10.11)
-# [Key Type Name] = 'Sys'
-PythonElCapitan = { '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'
- }
-
-# Bundled with Sierra (10.12)
-# [Key Type Name] = 'Sys'
-PythonSierra = { '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'
- }
-
-# Bundled with High Sierra (10.13)
-# [Key Type Name] = 'Sys'
-PythonHighSierra= { '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'
- }
-
-# Bundled with Mojave (10.14)
-# [Key Type Name] = 'Sys'
-PythonMojave = { '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'
- }
-
-# Bundled with Catalina (10.15)
-# [Key Type Name] = 'Sys'
-PythonCatalina = { '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'
- }
-
-# Bundled with Big Sur (11.x)
-# ** IMPORTANT NOTES **
-# Xcode [13.1 .. ] does not allow to link the legacy Python 2.7 library not to produce unsupported applications.
-# This code block remains here to keep the parallelism.
-# [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'
- }
-
-# Bundled with Monterey (12.x)
-# ** IMPORTANT NOTES **
-# Xcode [13.1 .. ] does not allow to link the legacy Python 2.7 library not to produce unsupported applications.
-# This code block remains here to keep the parallelism.
-# [Key Type Name] = 'Sys'
-PythonMonterey = { '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 *+*+*+
-# install with 'sudo port install python38'
-# [Key Type Name] = 'MP38'
-Python38MacPorts= { 'exe': '/opt/local/Library/Frameworks/Python.framework/Versions/3.8/bin/python3.8',
- 'inc': '/opt/local/Library/Frameworks/Python.framework/Versions/3.8/include/python3.8',
- 'lib': '/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/libpython3.8.dylib'
- }
-
-# Python 3.9 from MacPorts (https://www.macports.org/) *+*+*+ EXPERIMENTAL *+*+*+
+# Python 3.9 from MacPorts (https://www.macports.org/)
# install with 'sudo port install python39'
-# [Key Type Name] = 'MP38'
-Python39MacPorts= { 'exe': '/opt/local/Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9',
- 'inc': '/opt/local/Library/Frameworks/Python.framework/Versions/3.9/include/python3.9',
- 'lib': '/opt/local/Library/Frameworks/Python.framework/Versions/3.9/lib/libpython3.9.dylib'
- }
+# [Key Type Name] = 'MP39'
+Python39MacPorts = { 'exe': '/opt/local/Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9',
+ 'inc': '/opt/local/Library/Frameworks/Python.framework/Versions/3.9/include/python3.9',
+ 'lib': '/opt/local/Library/Frameworks/Python.framework/Versions/3.9/lib/libpython3.9.dylib'
+ }
-# Python 3.8 from Homebrew *+*+*+ EXPERIMENTAL *+*+*+
-# install with 'brew install python@3.8'
-# [Key Type Name] = 'HB38'
-HBPython38FrameworkPath = '%s/opt/python@3.8/Frameworks/Python.framework' % DefaultHomebrewRoot
-Python38Brew = { 'exe': '%s/Versions/3.8/bin/python3.8' % HBPython38FrameworkPath,
- 'inc': '%s/Versions/3.8/include/python3.8' % HBPython38FrameworkPath,
- 'lib': '%s/Versions/3.8/lib/libpython3.8.dylib' % HBPython38FrameworkPath
- }
+# Python 3.11 from MacPorts (https://www.macports.org/)
+# install with 'sudo port install python311'
+# [Key Type Name] = 'MP311'
+Python311MacPorts = { 'exe': '/opt/local/Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11',
+ 'inc': '/opt/local/Library/Frameworks/Python.framework/Versions/3.11/include/python3.11',
+ 'lib': '/opt/local/Library/Frameworks/Python.framework/Versions/3.11/lib/libpython3.11.dylib'
+ }
-# Python 3.9 from Homebrew *+*+*+ EXPERIMENTAL *+*+*+
+# Python 3.9 from Homebrew
# install with 'brew install python@3.9'
# [Key Type Name] = 'HB39'
HBPython39FrameworkPath = '%s/opt/python@3.9/Frameworks/Python.framework' % DefaultHomebrewRoot
-Python39Brew = { 'exe': '%s/Versions/3.9/bin/python3.9' % HBPython39FrameworkPath,
- 'inc': '%s/Versions/3.9/include/python3.9' % HBPython39FrameworkPath,
- 'lib': '%s/Versions/3.9/lib/libpython3.9.dylib' % HBPython39FrameworkPath
- }
+Python39Brew = { 'exe': '%s/Versions/3.9/bin/python3.9' % HBPython39FrameworkPath,
+ 'inc': '%s/Versions/3.9/include/python3.9' % HBPython39FrameworkPath,
+ 'lib': '%s/Versions/3.9/lib/libpython3.9.dylib' % HBPython39FrameworkPath
+ }
-# Python 3.8 bundled with anaconda3 installed under /Applications/anaconda3/ *+*+*+ EXPERIMENTAL *+*+*+
+# Python 3.11 from Homebrew
+# install with 'brew install python@3.11'
+# [Key Type Name] = 'HB311'
+HBPython311FrameworkPath = '%s/opt/python@3.11/Frameworks/Python.framework' % DefaultHomebrewRoot
+Python311Brew = { 'exe': '%s/Versions/3.11/bin/python3.11' % HBPython311FrameworkPath,
+ 'inc': '%s/Versions/3.11/include/python3.11' % HBPython311FrameworkPath,
+ 'lib': '%s/Versions/3.11/lib/libpython3.11.dylib' % HBPython311FrameworkPath
+ }
+
+# Python 3.11 bundled with anaconda3 installed under /Applications/anaconda3/
# The standard installation deploys the tool under $HOME/opt/anaconda3/.
# If so, you need to make a symbolic link: /Applications/anaconda3 ---> $HOME/opt/anaconda3/
# [Key Type Name] = 'Ana3'
-PythonAnaconda3 = { 'exe': '/Applications/anaconda3/bin/python3.9',
- 'inc': '/Applications/anaconda3/include/python3.9',
- 'lib': '/Applications/anaconda3/lib/libpython3.9.dylib'
+PythonAnaconda3 = { 'exe': '/Applications/anaconda3/bin/python3.11',
+ 'inc': '/Applications/anaconda3/include/python3.11',
+ 'lib': '/Applications/anaconda3/lib/libpython3.11.dylib'
}
-# Latest Python from Homebrew *+*+*+ EXPERIMENTAL *+*+*+
+# Latest Python from Homebrew
# install with 'brew install python'
-# There can be multiple candidates such as: (python, python3, python@3, python@3.8, python@3.9)
+# There can be multiple candidates such as: (python, python3, python@3, python@3.8, python@3.9,
+# python@3.10, python@3.11, python@3.12, python@3.13 )
# 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( "%s/opt/python*/Frameworks/Python.framework" % DefaultHomebrewRoot )[-1]
- # expand 3* into HBPythonAutoVersion, there should be only one, but I am taking no chances.
+ patPF = r"(%s/opt/python)([@]?)(3[.]?)([0-9]*)(/Frameworks/Python[.]framework)" % DefaultHomebrewRoot
+ regPF = re.compile(patPF)
+ dicPy = dict()
+ for item in glob.glob( "%s/opt/python*/Frameworks/Python.framework" % DefaultHomebrewRoot ):
+ if regPF.match(item):
+ pyver = regPF.match(item).groups()[3] # ([0-9]*)
+ if pyver == "":
+ pyver = "0"
+ dicPy[ int(pyver) ] = ( item, "3."+pyver )
+ keys = sorted( dicPy.keys(), reverse=True )
+ HBPythonAutoFrameworkPath = dicPy[keys[0]][0]
+ HBPythonAutoVersion = dicPy[keys[0]][1]
+
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]
}
+ """
+ # when I have [python3, python@3, python@3.8, python@3.9, python@3.10, python@3.11]
+ print(HBPythonAutoFrameworkPath)
+ print(HBAutoFrameworkVersionPath)
+ print(HBPythonAutoVersion)
+ print(PythonAutoBrew)
+ quit()
+
+ /usr/local/opt/python@3.11/Frameworks/Python.framework
+ /usr/local/opt/python@3.11/Frameworks/Python.framework/Versions
+ 3.11
+ { 'exe': '/usr/local/opt/python@3.11/Frameworks/Python.framework/Versions/3.11/bin/python3.11',
+ 'inc': '/usr/local/opt/python@3.11/Frameworks/Python.framework/Versions/3.11/include/python3.11',
+ 'lib': '/usr/local/opt/python@3.11/Frameworks/Python.framework/Versions/3.11/lib/libpython3.11.dylib'
+ }
+ """
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. " )
@@ -409,19 +298,12 @@ else:
_have_Homebrew_Python = True
# Consolidated dictionary kit for Python
-PythonDictionary = { 'nil' : None,
- 'PythonElCapitan' : PythonElCapitan,
- 'PythonSierra' : PythonSierra,
- 'PythonHighSierra': PythonHighSierra,
- 'PythonMojave' : PythonMojave,
- 'PythonCatalina' : PythonCatalina,
- 'PythonBigSur' : PythonBigSur,
- 'PythonMonterey' : PythonMonterey,
- 'Python38MacPorts': Python38MacPorts,
- 'Python39MacPorts': Python39MacPorts,
- 'Python38Brew' : Python38Brew,
- 'Python39Brew' : Python39Brew,
- 'PythonAnaconda3' : PythonAnaconda3
+PythonDictionary = { 'nil' : None,
+ 'Python39MacPorts' : Python39MacPorts,
+ 'Python311MacPorts': Python311MacPorts,
+ 'Python39Brew' : Python39Brew,
+ 'Python311Brew' : Python311Brew,
+ 'PythonAnaconda3' : PythonAnaconda3
}
if _have_Homebrew_Python:
PythonDictionary['PythonAutoBrew'] = PythonAutoBrew
diff --git a/macbuild/build4mac_util.py b/macbuild/build4mac_util.py
index 0cb3969c8..5d12d242f 100755
--- a/macbuild/build4mac_util.py
+++ b/macbuild/build4mac_util.py
@@ -623,18 +623,24 @@ def Patch_Python_In_PythonFramework( pythonFrameworkPath,
#----------------------------------------------------------------------------------------
## To change the Python's relative library paths to the absolute paths
#
-# 1: absolute path as in ~python@3.9.17
+# 1: absolute path as seen in ~python@3.9.17
# BigSur{kazzz-s} lib-dynload (1)% otool -L _sqlite3.cpython-39-darwin.so
# _sqlite3.cpython-39-darwin.so:
# ===> /usr/local/opt/sqlite/lib/libsqlite3.0.dylib (compatibility version 9.0.0, current version 9.6.0)
# /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.100.5)
#
-# 2: relative path as in python@3.9.18~
+# 2: relative path as seen in python@3.9.18
# Monterey{kazzz-s} lib-dynload (1)% otool -L _sqlite3.cpython-39-darwin.so
# _sqlite3.cpython-39-darwin.so:
# ===> @loader_path/../../../../../../../../../../opt/sqlite/lib/libsqlite3.0.dylib (compatibility version 9.0.0, current version 9.6.0)
# /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.100.3)
#
+# 3. absolute path again as seen in python@3.11
+# Monterey{kazzz-s} lib-dynload (1)% otool -L _sqlite3.cpython-311-darwin.so
+# _sqlite3.cpython-311-darwin.so:
+# ===> /usr/local/opt/sqlite/lib/libsqlite3.0.dylib (compatibility version 9.0.0, current version 9.6.0)
+# /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.100.3)
+#
# @param[in] frameworkPath: Python Framework path
# @param[in] debug_level: debug level
#
@@ -650,10 +656,10 @@ def Change_Python_LibPath_RelativeToAbsolute( frameworkPath, debug_level=0 ):
patRel3 = r'(%s)(.+)' % HomebrewSearchPathFilter3 # = '@loader_path/../../../../../../../../../../opt'
regRel3 = re.compile(patRel3)
- #----------------------------------------------------------------------
+ #---------------------------------------------------------------------------------------------------
# (A) Collect *.[so|dylib] that the Python Frameworks depends on
- #----------------------------------------------------------------------
- # Ref. https://formulae.brew.sh/formula/python@3.9#default
+ #---------------------------------------------------------------------------------------------------
+ # Ref. https://formulae.brew.sh/formula/python@3.9
# as of 2023-09-22, python@3.9 depends on:
# gdbm 1.23 GNU database manager
# mpdecimal 2.5.1 Library for decimal floating point arithmetic
@@ -661,6 +667,14 @@ def Change_Python_LibPath_RelativeToAbsolute( frameworkPath, debug_level=0 ):
# readline 8.2.1 Library for command-line editing
# sqlite 3.43.1 Command-line interface for SQLite
# xz 5.4.4 General-purpose data compression with high compression ratio
+ #---------------------------------------------------------------------------------------------------
+ # https://formulae.brew.sh/formula/python@3.11
+ # as of 2023-10-24, python@3.11 depends on:
+ # mpdecimal 2.5.1 Library for decimal floating point arithmetic
+ # openssl@3 3.1.3 Cryptography and SSL/TLS Toolkit
+ # sqlite 3.43.2 Command-line interface for SQLite
+ # xz 5.4.4 General-purpose data compression with high compression ratio
+ #---------------------------------------------------------------------------------------------------
find_grep_results = os.popen( 'find %s -type f | grep -E "%s"' % (frameworkPath, filter_regex) ).read().split('\n')
framework_files = filter( lambda x: x != '', map(lambda x: x.strip(), find_grep_results) )
@@ -745,6 +759,37 @@ def Change_Python_LibPath_RelativeToAbsolute( frameworkPath, debug_level=0 ):
print( " ---> Change_Python_LibPath_RelativeToAbsolute(): Changed the library paths." )
return 0
+#----------------------------------------------------------------------------------------
+## To generate the 'start-console.py' file from the template file
+#
+# @param[in] template: input template file (template-start-console.py)
+# @param[in] pythonver: Python version string such as "3.11"
+# @param[in] target: output target file (start-console.py)
+#
+# @return True on success, False on failure
+#----------------------------------------------------------------------------------------
+def Generate_Start_Console_Py( template, pythonver, target ):
+ try:
+ fd = open( template, "r" )
+ tmpl = fd.read()
+ fd.close()
+ except Exception as e:
+ print( "! Failed to read <%s>" % template, file=sys.stderr )
+ return False
+ else:
+ t = string.Template(tmpl)
+ startpy = t.safe_substitute( PYTHON_VER=pythonver )
+
+ try:
+ fd = open( target, "w" )
+ fd.write(startpy)
+ fd.close()
+ except Exception as e:
+ print( "! Failed to write <%s>" % target, file=sys.stderr )
+ return False
+ else:
+ return True
+
#----------------
# End of File
#----------------
diff --git a/macbuild/macQAT.py b/macbuild/macQAT.py
index 51b8d13f8..6f43ed1c5 100755
--- a/macbuild/macQAT.py
+++ b/macbuild/macQAT.py
@@ -34,6 +34,7 @@ def SetGlobals():
global WorkDir # work directory name
global LogFile # log file name
global Usage # string on usage
+ global DryRun # dry-run mode; print the command line and exit
# auxiliary variables on platform
global System # 6-tuple from platform.uname()
global Node # - do -
@@ -48,16 +49,19 @@ def SetGlobals():
Usage += "<< Usage of 'macQAT.py' >>\n"
Usage += " for running 'ut_runner' after building KLayout.\n"
Usage += "\n"
- Usage += "$ [python] ./macQAT.py \n"
+ Usage += "$ [python] ./macQAT.py\n"
Usage += " option & argument : descriptions | default value\n"
Usage += " -----------------------------------------------------------------+---------------\n"
- Usage += " [-u|--usage] : print usage of 'ut_runner'and exit | disabled \n"
- Usage += " | \n"
- Usage += " <-r|--run> : run this script | disabled \n"
- Usage += " [-s|--stop] : stop on error | disabled \n"
- Usage += " [-x|--exclude ] : exclude test(s) such as 'pymod,pya' | '' \n"
- Usage += " [-a|--args ] : arguments other than '-x' and '-c' | '' \n"
- Usage += " [-?|--?] : print this usage and exit | disabled \n"
+ Usage += " [-u|--usage] : print usage of 'ut_runner'and exit | disabled\n"
+ Usage += " |\n"
+ Usage += " <-r|--run> : run this script | disabled\n"
+ Usage += " [-s|--stop] : stop on error | disabled\n"
+ Usage += " [-x|--exclude ] : exclude test(s) such as 'pymod,pya' | ''\n"
+ Usage += " : you can use this option multiple times |\n"
+ Usage += " [-a|--args ] : arguments other than '-x' and '-c' | ''\n"
+ Usage += " : you can use this option multiple times |\n"
+ Usage += " [--dryrun] : print the command line and exit | disabled\n"
+ Usage += " [-?|--?] : print this usage and exit | disabled\n"
Usage += "--------------------------------------------------------------------+-------------------\n"
ProjectDir = os.getcwd()
@@ -65,11 +69,12 @@ def SetGlobals():
Run = False
ContinueOnError = True
TestsExcluded = list()
- Arguments = ""
+ Arguments = list()
GitSHA1 = GetGitShortSHA1()
TimeStamp = GetTimeStamp()
WorkDir = "QATest_%s_%s__%s" % (GitSHA1, TimeStamp, os.path.basename(ProjectDir) )
LogFile = WorkDir + ".log"
+ DryRun = False
(System, Node, Release, Version, Machine, Processor) = platform.uname()
@@ -103,6 +108,7 @@ def ParseCommandLineArguments():
global ContinueOnError
global TestsExcluded
global Arguments
+ global DryRun
p = optparse.OptionParser( usage=Usage )
p.add_option( '-u', '--usage',
@@ -124,13 +130,21 @@ def ParseCommandLineArguments():
help='stop on error (false)' )
p.add_option( '-x', '--exclude',
+ action='append',
dest='exclude_tests',
help="exclude test(s) such as 'pymod,pya' ('')" )
p.add_option( '-a', '--args',
+ action='append',
dest='arguments',
help="arguments other than '-x' and '-c' ('')" )
+ p.add_option( '--dryrun',
+ action='store_true',
+ dest='dryrun',
+ default=False,
+ help='print the command line and exit (false)' )
+
p.add_option( '-?', '--??',
action='store_true',
dest='checkusage',
@@ -140,8 +154,9 @@ def ParseCommandLineArguments():
p.set_defaults( runner_usage = False,
runme = False,
stop_on_error = False,
- exclude_tests = "",
- arguments = "",
+ exclude_tests = list(),
+ arguments = list(),
+ dryrun = False,
checkusage = False )
opt, args = p.parse_args()
@@ -152,11 +167,15 @@ def ParseCommandLineArguments():
RunnerUsage = opt.runner_usage
Run = opt.runme
ContinueOnError = not opt.stop_on_error
- if not opt.exclude_tests == "":
- TestsExcluded = [ item.strip() for item in opt.exclude_tests.split(',') ]
+ if not len(opt.exclude_tests) == 0:
+ excluded_tests = list()
+ for item in opt.exclude_tests:
+ excluded_tests += [ subitem.strip() for subitem in item.split(',') ]
+ TestsExcluded = sorted(list(set(excluded_tests)))
else:
TestsExcluded = []
Arguments = opt.arguments
+ DryRun = opt.dryrun
#-------------------------------------------------------------------------------
## Hide/Show the private directory
@@ -248,16 +267,20 @@ def Main():
command += " -c"
for item in TestsExcluded:
command += ' -x %s' % item
- if not Arguments == "":
- command += " %s" % Arguments
+ if not len(Arguments) == 0:
+ for arg in Arguments:
+ command += " %s" % arg
print( "" )
print( "### Dumping the log to <%s>" % LogFile )
- print( "------------------------------------------------------------" )
- print( " Git SHA1 = %s" % GitSHA1 )
- print( " Time stamp = %s" % TimeStamp )
- print( "------------------------------------------------------------" )
- sleep( 1.0 )
+ print( "------------------------------------------------------------------------" )
+ print( " Git SHA1 = %s" % GitSHA1 )
+ print( " Time stamp = %s" % TimeStamp )
+ print( " Command line = %s" % command )
+ print( "------------------------------------------------------------------------" )
+ if DryRun:
+ quit()
+ sleep(1.0)
HidePrivateDir()
RunTester( command, logfile=LogFile )
ShowPrivateDir()
diff --git a/macbuild/macQAT.sh b/macbuild/macQAT.sh
index f5e462220..a44d0d6a1 100755
--- a/macbuild/macQAT.sh
+++ b/macbuild/macQAT.sh
@@ -5,7 +5,7 @@
#
# The top Bash script to run "ut_runner" after building KLayout
# (http://www.klayout.de/index.php) version 0.26.1 or later on different Apple
-# ßMac OSX platforms.
+# Mac OSX platforms.
#
# This script must be copied to a "*.macQAT/" directory to run.
#===============================================================================
@@ -68,8 +68,8 @@ if [ $# -eq 1 ]; then
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 " ./macQAT.sh -h: to get the help of 'ut_runner'"
+ echo " ./macQAT.sh -r: to run the tests with '-c' option: continues after an error"
echo ""
exit 0
fi
@@ -79,8 +79,8 @@ else
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 " ./macQAT.sh -h: to get the help of 'ut_runner'"
+ echo " ./macQAT.sh -r: to run the tests with '-c' option: continues after an error"
echo ""
exit 0
fi
diff --git a/macbuild/macQAT2.sh b/macbuild/macQAT2.sh
new file mode 100755
index 000000000..c2fbd5445
--- /dev/null
+++ b/macbuild/macQAT2.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+#===============================================================================
+# File: "macbuild/macQAT2.sh"
+#
+# The top Bash script to run "ut_runner" after building KLayout
+# (http://www.klayout.de/index.php) version 0.26.1 or later on different Apple
+# Mac OSX platforms.
+#
+# This script must be copied to a directory that can be found in $PATH.
+#===============================================================================
+
+prjdir=`pwd`
+
+if [ $# -ge 2 ]; then
+ first_arg=$1
+ shift
+ remaining_args=("$@")
+ echo "#########################"
+ echo "# Starging macQAT2.sh #"
+ echo "#########################"
+ echo " Current Dir: $prjdir"
+ echo " First Arg: $first_arg"
+ echo "Remaining Args: ${remaining_args[@]}"
+ echo ""
+ export TESTSRC=../
+ export TESTTMP=$first_arg
+ export DYLD_LIBRARY_PATH=$prjdir:$prjdir/db_plugins:$prjdir/lay_plugins
+ ./ut_runner ${remaining_args[@]}
+else
+ echo "Usage: -------------------------------------------------"
+ echo " $ macQAT2.sh "
+ echo " ex. $ change directory to a *.macQAT/"
+ echo " $ macQAT2.sh __Homebrew tlGitTests"
+ echo "--------------------------------------------------------"
+fi
+
+#--------------
+# End of File
+#--------------
diff --git a/macbuild/makeDMG4mac.py b/macbuild/makeDMG4mac.py
index 231167cbb..566c9e203 100755
--- a/macbuild/makeDMG4mac.py
+++ b/macbuild/makeDMG4mac.py
@@ -47,7 +47,7 @@ def SetGlobals():
global DefaultBundleName # the default bundle name 'klayout.app'
global BundleName # application bundle name in the DMG
global DMGSerialNum # the DMG serial number
- global PackagePrefix # the package prefix: 'ST-', 'LW-', 'HW-', or 'EX-'
+ global PackagePrefix # the package prefix: LW-', 'HW-', or 'EX-'
global QtIdentification # Qt identification
global RubyPythonID # Ruby- and Python-identification
global KLVersion # KLayout's version
@@ -77,13 +77,13 @@ def SetGlobals():
Usage = "\n"
Usage += "---------------------------------------------------------------------------------------------------------\n"
Usage += "<< Usage of 'makeDMG4mac.py' >>\n"
- Usage += " for making a DMG file of KLayout 0.28.4 or later on different Apple macOS / Mac OSX platforms.\n"
+ Usage += " for making a DMG file of KLayout 0.28.13 or later on different Apple macOS platforms.\n"
Usage += "\n"
Usage += "$ [python] ./makeDMG4mac.py\n"
Usage += " option & argument : descriptions | default value\n"
Usage += " ----------------------------------------------------------------------------------+-----------------\n"
Usage += " <-p|--pkg > : package directory created by `build4mac.py` with [-y|-Y] | ``\n"
- Usage += " : like 'LW-qt5MP.pkg.macos-Catalina-release-Rmp32Pmp39' | \n"
+ Usage += " : like 'LW-qt5MP.pkg.macos-Monterey-release-Rmp32Pmp311' | \n"
Usage += " <-c|--clean> : clean the work directory | disabled\n"
Usage += " <-m|--make> : make a compressed DMG file | disabled\n"
Usage += " : <-c|--clean> and <-m|--make> are mutually exclusive | \n"
@@ -103,9 +103,13 @@ def SetGlobals():
print(Usage)
quit()
- release = int( Release.split(".")[0] ) # take the first of ['19', '0', '0']
+ release = int( Release.split(".")[0] ) # take the first of ['21', '0', '0']
LatestOS = ""
- if release == 22:
+ if release == 23:
+ GenOSName = "macOS"
+ Platform = "Sonoma"
+ LatestOS = Platform
+ elif release == 22:
GenOSName = "macOS"
Platform = "Ventura"
LatestOS = Platform
@@ -113,26 +117,6 @@ def SetGlobals():
GenOSName = "macOS"
Platform = "Monterey"
LatestOS = Platform
- elif release == 20:
- GenOSName = "macOS"
- Platform = "BigSur"
- LatestOS = Platform
- elif release == 19:
- GenOSName = "macOS"
- Platform = "Catalina"
- LatestOS = Platform
- elif release == 18:
- GenOSName = "macOS"
- Platform = "Mojave"
- elif release == 17:
- GenOSName = "macOS"
- Platform = "HighSierra"
- elif release == 16:
- Platform = "Sierra"
- GenOSName = "macOS"
- elif release == 15:
- GenOSName = "MacOSX"
- Platform = "ElCapitan"
else:
Platform = ""
print("")
@@ -141,7 +125,7 @@ def SetGlobals():
sys.exit(1)
if not Machine == "x86_64":
- if Machine == "arm64" and Platform in ["Ventura", "Monterey", "BigSur"]: # with an Apple Silicon Chip
+ if Machine == "arm64" and Platform in ["Sonoma", "Ventura", "Monterey"]: # with an Apple Silicon Chip
print("")
print( "### Your Mac equips an Apple Silicon Chip ###" )
print("")
@@ -207,18 +191,18 @@ def SetGlobals():
## To check the contents of the package directory
#
# The package directory name should look like:
-# * LW-qt5Ana3.pkg.macos-Catalina-release-Rana3Pana3
-# * LW-qt5Brew.pkg.macos-Catalina-release-Rhb32Phb39 --- (1)
-# * LW-qt5MP.pkg.macos-Catalina-release-Rmp32Pmp39
-# * HW-qt5Brew.pkg.macos-Catalina-release-RsysPhb39
+# * LW-qt5Ana3.pkg.macos-Monterey-release-Rana3Pana3
+# * LW-qt5Brew.pkg.macos-Monterey-release-Rhb32Phb311 --- (1)
+# * LW-qt5MP.pkg.macos-Monterey-release-Rmp32Pmp311
+# * HW-qt5Brew.pkg.macos-Monterey-release-RsysPhb311
#
-# * LW-qt6Ana3.pkg.macos-Catalina-release-Rana3Pana3
-# * LW-qt6Brew.pkg.macos-Catalina-release-Rhb32Phb39
-# * LW-qt6MP.pkg.macos-Catalina-release-Rmp32Pmp39
-# * HW-qt6Brew.pkg.macos-Catalina-release-RsysPhb39
+# * LW-qt6Ana3.pkg.macos-Monterey-release-Rana3Pana3
+# * LW-qt6Brew.pkg.macos-Monterey-release-Rhb32Phb311
+# * LW-qt6MP.pkg.macos-Monterey-release-Rmp32Pmp311
+# * HW-qt6Brew.pkg.macos-Monterey-release-RsysPhb311
#
# Generated DMG will be, for example,
-# (1) ---> LW-klayout-0.28.4-macOS-Catalina-1-qt5Brew-Rhb32Phb39.dmg
+# (1) ---> LW-klayout-0.28.13-macOS-Monterey-1-qt5Brew-Rhb32Phb311.dmg
#
# @return on success, positive integer in [MB] that tells approx. occupied disc space;
# on failure, -1
@@ -257,19 +241,18 @@ def CheckPkgDirectory():
#-----------------------------------------------------------------------------------------------
# [2] Identify (Qt, Ruby, Python) from PkgDir
- # * ST-qt5MP.pkg.macos-Catalina-release-RsysPsys # 'ST' has been restored in 0.28.3
- # * LW-qt5Ana3.pkg.macos-Catalina-release-Rana3Pana3
- # * LW-qt5Brew.pkg.macos-Catalina-release-Rhb32Phb39
- # * LW-qt5MP.pkg.macos-Catalina-release-Rmp32Pmp39
- # * HW-qt5Brew.pkg.macos-Catalina-release-RsysPhb39
- # * EX-qt5MP.pkg.macos-Catalina-release-Rhb32Pmp39
+ # * LW-qt5Ana3.pkg.macos-Monterey-release-Rana3Pana3
+ # * LW-qt5Brew.pkg.macos-Monterey-release-Rhb32Phb311
+ # * LW-qt5MP.pkg.macos-Monterey-release-Rmp32Pmp311
+ # * HW-qt5Brew.pkg.macos-Monterey-release-RsysPhb311
+ # * EX-qt5MP.pkg.macos-Monterey-release-Rhb32Pmp311
#
- # * LW-qt6Ana3.pkg.macos-Catalina-release-Rana3Pana3
- # * LW-qt6Brew.pkg.macos-Catalina-release-Rhb32Phb39
- # * LW-qt6MP.pkg.macos-Catalina-release-Rmp32Pmp39
- # * HW-qt6Brew.pkg.macos-Catalina-release-RsysPhb39
+ # * LW-qt6Ana3.pkg.macos-Monterey-release-Rana3Pana3
+ # * LW-qt6Brew.pkg.macos-Monterey-release-Rhb32Phb311
+ # * LW-qt6MP.pkg.macos-Monterey-release-Rmp32Pmp311
+ # * HW-qt6Brew.pkg.macos-Monterey-release-RsysPhb311
#-----------------------------------------------------------------------------------------------
- patQRP = u'(ST|LW|HW|EX)([-])([qt5|qt6][0-9A-Za-z]+)([.]pkg[.])([A-Za-z]+[-][A-Za-z]+[-]release[-])([0-9A-Za-z]+)'
+ patQRP = u'(LW|HW|EX)([-])([qt5|qt6][0-9A-Za-z]+)([.]pkg[.])([A-Za-z]+[-][A-Za-z]+[-]release[-])([0-9A-Za-z]+)'
regQRP = re.compile(patQRP)
if not regQRP.match(PkgDir):
print( "! Cannot identify (Qt, Ruby, Python) from the package directory name" )
@@ -297,14 +280,12 @@ def CheckPkgDirectory():
LatestOSMacPorts = Platform == LatestOS
LatestOSMacPorts &= PackagePrefix == "LW"
LatestOSMacPorts &= QtIdentification in [ "qt5MP", "qt6MP" ]
- LatestOSMacPorts &= RubyPythonID in [ "Rmp31Pmp38", "Rmp31Pmp39", \
- "Rmp32Pmp38", "Rmp32Pmp39" ]
+ LatestOSMacPorts &= RubyPythonID in [ "Rmp32Pmp311", "Rmp32Pmp39" ]
LatestOSHomebrew = Platform == LatestOS
LatestOSHomebrew &= PackagePrefix == "LW"
LatestOSHomebrew &= QtIdentification in [ "qt5Brew", "qt6Brew" ]
- LatestOSHomebrew &= RubyPythonID in [ "Rhb31Phb38", "Rhb31Phb39", "Rhb31Phbauto", \
- "Rhb32Phb38", "Rhb32Phb39", "Rhb32Phbauto" ]
+ LatestOSHomebrew &= RubyPythonID in [ "Rhb32Phb311", "Rhb32Phb39", "Rhb32Phbauto" ]
LatestOSAnaconda3 = Platform == LatestOS
LatestOSAnaconda3 &= PackagePrefix == "LW"
@@ -314,7 +295,7 @@ def CheckPkgDirectory():
LatestOSHomebrewH = Platform == LatestOS
LatestOSHomebrewH &= PackagePrefix == "HW"
LatestOSHomebrewH &= QtIdentification in [ "qt5Brew", "qt6Brew" ]
- LatestOSHomebrewH &= RubyPythonID in [ "RsysPhb39", "RsysPhb39", "RsysPhbauto" ] # Sys-Homebre hybrid
+ LatestOSHomebrewH &= RubyPythonID in [ "RsysPhb311", "RsysPhb39", "RsysPhbauto" ] # Sys-Homebre hybrid
if LatestOSMacPorts:
mydic = DicLightHeavyW["ports"]
diff --git a/macbuild/nightlyBuild.py b/macbuild/nightlyBuild.py
index 959a45e88..5ce1d2c9d 100755
--- a/macbuild/nightlyBuild.py
+++ b/macbuild/nightlyBuild.py
@@ -16,29 +16,19 @@ import subprocess
#
# @return matching platform name on success; "" on failure
#------------------------------------------------------------------------------
-def Test_My_Platform( platforms=[ 'Catalina', 'BigSur', 'Monterey', 'Ventura' ] ):
+def Test_My_Platform( platforms=[ 'Monterey', 'Ventura', 'Sonoma' ] ):
(System, Node, Release, MacVersion, Machine, Processor) = platform.uname()
if not System == "Darwin":
return ""
- release = int( Release.split(".")[0] ) # take the first of ['19', '0', '0']
- if release == 22:
+ release = int( Release.split(".")[0] ) # take the first of ['21', '0', '0']
+ if release == 23:
+ Platform = "Sonoma"
+ elif release == 22:
Platform = "Ventura"
elif release == 21:
Platform = "Monterey"
- elif release == 20:
- Platform = "BigSur"
- elif release == 19:
- Platform = "Catalina"
- elif release == 18:
- Platform = "Mojave"
- elif release == 17:
- Platform = "HighSierra"
- elif release == 16:
- Platform = "Sierra"
- elif release == 15:
- Platform = "ElCapitan"
else:
Platform = ""
@@ -54,7 +44,7 @@ def Test_My_Platform( platforms=[ 'Catalina', 'BigSur', 'Monterey', 'Ventura' ]
#------------------------------------------------------------------------------
def Get_Build_Target_Dict():
buildTargetDic = dict()
- buildTargetDic[0] = 'std' # has been restored in 0.28.3
+ # buildTargetDic[0] = 'std'
buildTargetDic[1] = 'ports'
buildTargetDic[2] = 'brew'
buildTargetDic[3] = 'brewHW'
@@ -88,14 +78,14 @@ def Get_Build_Options( targetDic, platform ):
buildOp["std"] = [ '-q', '%sMacPorts' % qtType, '-r', 'sys', '-p', 'sys' ]
logfile["std"] = "%sMP.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "RsysPsys")
elif target == "ports":
- buildOp["ports"] = [ '-q', '%sMacPorts' % qtType, '-r', 'MP32', '-p', 'MP39' ]
- logfile["ports"] = "%sMP.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "Rmp32Pmp39")
+ buildOp["ports"] = [ '-q', '%sMacPorts' % qtType, '-r', 'MP32', '-p', 'MP311' ]
+ logfile["ports"] = "%sMP.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "Rmp32Pmp311")
elif target == "brew":
- buildOp["brew"] = [ '-q', '%sBrew' % qtType, '-r', 'HB32', '-p', 'HB39' ]
- logfile["brew"] = "%sBrew.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "Rhb32Phb39")
+ buildOp["brew"] = [ '-q', '%sBrew' % qtType, '-r', 'HB32', '-p', 'HB311' ]
+ logfile["brew"] = "%sBrew.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "Rhb32Phb311")
elif target == "brewHW":
- buildOp["brewHW"] = [ '-q', '%sBrew' % qtType, '-r', 'sys', '-p', 'HB39' ]
- logfile["brewHW"] = "%sBrew.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "RsysPhb39")
+ buildOp["brewHW"] = [ '-q', '%sBrew' % qtType, '-r', 'sys', '-p', 'HB311' ]
+ logfile["brewHW"] = "%sBrew.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "RsysPhb311")
elif target == "ana3":
buildOp["ana3"] = [ '-q', '%sAna3' % qtType, '-r', 'Ana3', '-p', 'Ana3' ]
logfile["ana3"] = "%sAna3.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "Rana3Pana3")
@@ -130,14 +120,12 @@ def Get_QAT_Directory( targetDic, platform ):
dirQAT = dict()
for key in targetDic.keys():
target = targetDic[key]
- if target == "std":
- dirQAT["std"] = '%sMP.build.macos-%s-release-RsysPsys.macQAT' % (qtType, platform)
- elif target == "ports":
- dirQAT["ports"] = '%sMP.build.macos-%s-release-Rmp32Pmp39.macQAT' % (qtType, platform)
+ if target == "ports":
+ dirQAT["ports"] = '%sMP.build.macos-%s-release-Rmp32Pmp311.macQAT' % (qtType, platform)
elif target == "brew":
- dirQAT["brew"] = '%sBrew.build.macos-%s-release-Rhb32Phb39.macQAT' % (qtType, platform)
+ dirQAT["brew"] = '%sBrew.build.macos-%s-release-Rhb32Phb311.macQAT' % (qtType, platform)
elif target == "brewHW":
- dirQAT["brewHW"] = '%sBrew.build.macos-%s-release-RsysPhb39.macQAT' % (qtType, platform)
+ dirQAT["brewHW"] = '%sBrew.build.macos-%s-release-RsysPhb311.macQAT' % (qtType, platform)
elif target == "ana3":
dirQAT["ana3"] = '%sAna3.build.macos-%s-release-Rana3Pana3.macQAT' % (qtType, platform)
elif target == "brewA":
@@ -170,17 +158,14 @@ def Get_Package_Options( targetDic, platform, srlDMG, makeflag ):
packOp = dict()
for key in targetDic.keys():
target = targetDic[key]
- if target == "std":
- packOp["std"] = [ '-p', 'ST-%sMP.pkg.macos-%s-release-RsysPsys' % (qtType, platform),
- '-s', '%d' % srlDMG, '%s' % flag ]
- elif target == "ports":
- packOp["ports"] = [ '-p', 'LW-%sMP.pkg.macos-%s-release-Rmp32Pmp39' % (qtType, platform),
+ if target == "ports":
+ packOp["ports"] = [ '-p', 'LW-%sMP.pkg.macos-%s-release-Rmp32Pmp311' % (qtType, platform),
'-s', '%d' % srlDMG, '%s' % flag ]
elif target == "brew":
- packOp["brew"] = [ '-p', 'LW-%sBrew.pkg.macos-%s-release-Rhb32Phb39' % (qtType, platform),
+ packOp["brew"] = [ '-p', 'LW-%sBrew.pkg.macos-%s-release-Rhb32Phb311' % (qtType, platform),
'-s', '%d' % srlDMG, '%s' % flag ]
elif target == "brewHW":
- packOp["brewHW"] = [ '-p', 'HW-%sBrew.pkg.macos-%s-release-RsysPhb39' % (qtType, platform),
+ packOp["brewHW"] = [ '-p', 'HW-%sBrew.pkg.macos-%s-release-RsysPhb311' % (qtType, platform),
'-s', '%d' % srlDMG, '%s' % flag ]
elif target == "ana3":
packOp["ana3"] = [ '-p', 'LW-%sAna3.pkg.macos-%s-release-Rana3Pana3' % (qtType, platform),
@@ -212,23 +197,24 @@ def Parse_CommandLine_Arguments():
global DryRun # True for dry-run
platform = Test_My_Platform()
- if platform in [ "Ventura", "Monterey", "BigSur" ]:
+ if platform in [ "Sonoma", "Ventura", "Monterey" ]:
targetopt = "1,2,3,4"
else:
- targetopt = "0,1,2,3,4"
+ targetopt = "0"
Usage = "\n"
Usage += "----------------------------------------------------------------------------------------------------------\n"
- Usage += " nightlyBuild.py [EXPERIMENTAL] \n"
- Usage += " << To execute the jobs for making KLayout's DMGs for macOS Catalina, Big Sur, Monterey, or Ventura >>\n"
+ Usage += " nightlyBuild.py [EXPERIMENTAL]\n"
+ Usage += " << To execute the jobs for making KLayout's DMGs for\n"
+ Usage += " macOS Monterey, Ventura, or Sonoma >>\n"
Usage += "\n"
Usage += "$ [python] nightlyBuild.py\n"
Usage += " option & argument : comment on option if any | default value\n"
Usage += " ------------------------------------------------------------------------+--------------\n"
Usage += " [--qt ] : 5='qt5', 6='qt6' (migration to Qt6 is ongoing) | 5\n"
- Usage += " [--target ] : 0='std' 1='ports', 2='brew', 3='brewHW', 4='ana3', | '%s'\n" % targetopt
- Usage += " 5='brewA', 6='brewAHW' | \n"
- Usage += " * with --qt=6, use --target='2,3' (4 is ignored) | \n"
+ Usage += " [--target ] : 1='ports', 2='brew', 3='brewHW', 4='ana3', | '%s'\n" % targetopt
+ Usage += " 5='brewA', 6='brewAHW' |\n"
+ Usage += " * with --qt=6, use --target='2,3' (4 is ignored) |\n"
Usage += " [--build] : build and deploy | disabled\n"
Usage += " [--pymod] : build and deploy Pymod, too | disabled\n"
Usage += " [--test] : run the QA Test | disabled\n"
@@ -237,18 +223,18 @@ def Parse_CommandLine_Arguments():
Usage += " [--upload ] : upload DMGs to $HOME/Dropbox/klayout/ | disabled\n"
Usage += " [--dryrun] : dry-run for --build option | disabled\n"
Usage += " [-?|--?] : print this usage and exit | disabled\n"
- Usage += " | \n"
- Usage += " To use this script, make a symbolic link in the project root by: | \n"
- Usage += " $ ln -s ./macbuild/nightlyBuild.py . | \n"
- Usage += " | \n"
- Usage += " Regular sequence for using this script: | \n"
- Usage += " (1) $ ./nightlyBuild.py --build --pymod | \n"
- Usage += " (2) (confirm the build results) | \n"
- Usage += " (3) $ ./nightlyBuild.py --test | \n"
- Usage += " (4) $ ./nightlyBuild.py --check (confirm the QA Test results) | \n"
- Usage += " (5) $ ./nightlyBuild.py --makedmg 1 | \n"
- Usage += " (6) $ ./nightlyBuild.py --upload '0.28.4' | \n"
- Usage += " (7) $ ./nightlyBuild.py --cleandmg 1 | \n"
+ Usage += " |\n"
+ Usage += " To use this script, make a symbolic link in the project root by: |\n"
+ Usage += " $ ln -s ./macbuild/nightlyBuild.py . |\n"
+ Usage += " |\n"
+ Usage += " Regular sequence for using this script: |\n"
+ Usage += " (1) $ ./nightlyBuild.py --build --pymod |\n"
+ Usage += " (2) (confirm the build results) |\n"
+ Usage += " (3) $ ./nightlyBuild.py --test |\n"
+ Usage += " (4) $ ./nightlyBuild.py --check (confirm the QA Test results) |\n"
+ Usage += " (5) $ ./nightlyBuild.py --makedmg 1 |\n"
+ Usage += " (6) $ ./nightlyBuild.py --upload '0.28.12' |\n"
+ Usage += " (7) $ ./nightlyBuild.py --cleandmg 1 |\n"
Usage += "---------------------------------------------------------------------------+------------------------------\n"
p = optparse.OptionParser( usage=Usage )
@@ -325,9 +311,9 @@ def Parse_CommandLine_Arguments():
print(Usage)
quit()
- myPlatform = Test_My_Platform( [ 'Catalina', 'BigSur', 'Monterey', 'Ventura' ] )
+ myPlatform = Test_My_Platform( [ 'Monterey', 'Ventura', 'Sonoma' ] )
if myPlatform == "":
- print( "! Current platform is not [ 'Catalina', 'BigSur', 'Monterey', 'Ventura' ]" )
+ print( "! Current platform is not [ 'Monterey', 'Ventura', 'Sonoma' ]" )
print(Usage)
quit()
@@ -345,7 +331,7 @@ def Parse_CommandLine_Arguments():
targetDic = Get_Build_Target_Dict()
Target = list()
for idx in targetIdx:
- if idx in range(0, 7): # '0' has been restored in 0.28.3
+ if idx in range(1, 7):
Target.append( targetDic[idx] )
Build = opt.build
@@ -394,7 +380,7 @@ def Build_Deploy():
command1 = [ pyBuilder ] + buildOp[key]
- if key in [ "std", "brewHW", "brewAHW" ] :
+ if key in [ "brewHW", "brewAHW" ] :
command2 = "time"
command2 += " \\\n %s" % pyBuilder
for option in buildOp[key]:
diff --git a/macbuild/python3HB.py b/macbuild/python3HB.py
index 882328ec4..118fe13f0 100755
--- a/macbuild/python3HB.py
+++ b/macbuild/python3HB.py
@@ -31,12 +31,13 @@ def SetGlobals():
Usage += "<< Usage of 'python3HB.py' >>\n"
Usage += " to setup the standardized directory structures for Homebrew's Python 3.x on Mac\n"
Usage += "\n"
- Usage += " option & argument : descriptions | default value\n"
- Usage += " -----------------------------------------------------------+---------------\n"
- Usage += " <-v|--version >: in ['3.8', '3.9', '3.10', '3.11'] | ''\n"
- Usage += " [-u|-unlink] : unlink only | disabled\n"
- Usage += " [-?|--?] : print this usage and exit | disabled\n"
- Usage += "--------------------------------------------------------------+----------------------\n"
+ Usage += " option & argument : descriptions | default value\n"
+ Usage += " -------------------------------------------------------------------+----------\n"
+ Usage += " <-v|--version >: in ['3.8', '3.9', '3.10', '3.11', '3.12', | ''\n"
+ Usage += " '3.13'] | ''\n"
+ Usage += " [-u|-unlink] : unlink only | disabled\n"
+ Usage += " [-?|--?] : print this usage and exit | disabled\n"
+ Usage += "----------------------------------------------------------------------+--------------\n"
#------------------------------------------------------------------------------
# Parse the command line arguments
@@ -49,7 +50,7 @@ def Parse_CLI_Args():
p.add_option( '-v', '--version',
dest='version',
- help="python3 version=['3.8', '3.9', '3.10', '3.11']" )
+ help="python3 version=['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']" )
p.add_option( '-u', '--unlink',
action='store_true',
@@ -74,7 +75,7 @@ def Parse_CLI_Args():
Version = opt.version
UnlinkOnly = opt.unlink
- if not Version in [ '3.8', '3.9', '3.10', '3.11' ]:
+ if not Version in [ '3.8', '3.9', '3.10', '3.11', '3.12', '3.13' ]:
print( "! Unsupported Python 3 version <%s>" % Version )
print(Usage)
sys.exit(0)
diff --git a/src/gsi/gsi/gsiExpression.cc b/src/gsi/gsi/gsiExpression.cc
index 9a979e9e7..11045a6df 100644
--- a/src/gsi/gsi/gsiExpression.cc
+++ b/src/gsi/gsi/gsiExpression.cc
@@ -286,6 +286,25 @@ struct test_arg_func
return;
}
+ if (arg.is_list ()) {
+
+ // we may implicitly convert an array into a constructor call of a target object -
+ // for now we only check whether the number of arguments is compatible with the array given.
+
+ int n = int (arg.size ());
+
+ *ret = false;
+ for (gsi::ClassBase::method_iterator c = atype.cls ()->begin_constructors (); c != atype.cls ()->end_constructors (); ++c) {
+ if ((*c)->compatible_with_num_args (n)) {
+ *ret = true;
+ break;
+ }
+ }
+
+ return;
+
+ }
+
if (! arg.is_user ()) {
*ret = false;
return;
@@ -620,6 +639,8 @@ struct writer
}
};
+void push_args (gsi::SerialArgs &arglist, const tl::Variant &args, const gsi::MethodBase *meth, tl::Heap *heap);
+
/**
* @brief Specialization for void
*/
@@ -628,29 +649,67 @@ struct writer
{
void operator() (gsi::SerialArgs *aa, tl::Variant *arg, const gsi::ArgType &atype, tl::Heap *heap)
{
- if (atype.is_ref () || atype.is_cref () || atype.is_ptr () || atype.is_cptr ()) {
+ if (arg->is_nil ()) {
- if (arg->is_nil ()) {
+ if (atype.is_ref () || atype.is_cref ()) {
+ throw tl::Exception (tl::to_string (tr ("Cannot pass nil to reference parameters")));
+ } else if (! atype.is_cptr () && ! atype.is_ptr ()) {
+ throw tl::Exception (tl::to_string (tr ("Cannot pass nil to direct parameters")));
+ }
- if (atype.is_ref () || atype.is_cref ()) {
- throw tl::Exception (tl::to_string (tr ("Cannot pass nil to reference parameters")));
+ aa->write ((void *) 0);
+
+ } else if (arg->is_list ()) {
+
+ // we may implicitly convert an array into a constructor call of a target object -
+ // for now we only check whether the number of arguments is compatible with the array given.
+
+ int n = int (arg->size ());
+ const gsi::MethodBase *meth = 0;
+ for (gsi::ClassBase::method_iterator c = atype.cls ()->begin_constructors (); c != atype.cls ()->end_constructors (); ++c) {
+ if ((*c)->compatible_with_num_args (n)) {
+ meth = *c;
+ break;
}
+ }
- aa->write ((void *) 0);
+ if (!meth) {
+ throw tl::Exception (tl::to_string (tr ("No constructor of %s available that takes %d arguments (implicit call from tuple)")), atype.cls ()->name (), n);
+ }
- } else {
+ // implicit call of constructor
+ gsi::SerialArgs retlist (meth->retsize ());
+ gsi::SerialArgs arglist (meth->argsize ());
- if (! arg->is_user ()) {
- throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unexpected object type (expected argument of class %s)")), atype.cls ()->name ()));
- }
+ push_args (arglist, *arg, meth, heap);
- const tl::VariantUserClassBase *cls = arg->user_cls ();
- if (!cls) {
- throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unexpected object type (expected argument of class %s)")), atype.cls ()->name ()));
- }
- if (cls->is_const () && (atype.is_ref () || atype.is_ptr ())) {
- throw tl::Exception (tl::sprintf (tl::to_string (tr ("Cannot pass a const reference of class %s to a non-const reference or pointer parameter")), atype.cls ()->name ()));
- }
+ meth->call (0, arglist, retlist);
+
+ void *new_obj = retlist.read (*heap);
+ if (new_obj && (atype.is_ptr () || atype.is_cptr () || atype.is_ref () || atype.is_cref ())) {
+ // For pointers or refs, ownership over these objects is not transferred.
+ // Hence we have to keep them on the heap.
+ // TODO: what if the called method takes ownership using keep()?
+ heap->push (new gsi::ObjectHolder (atype.cls (), new_obj));
+ }
+
+ aa->write (new_obj);
+
+ } else {
+
+ if (! arg->is_user ()) {
+ throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unexpected object type (expected argument of class %s)")), atype.cls ()->name ()));
+ }
+
+ const tl::VariantUserClassBase *cls = arg->user_cls ();
+ if (!cls) {
+ throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unexpected object type (expected argument of class %s)")), atype.cls ()->name ()));
+ }
+ if (cls->is_const () && (atype.is_ref () || atype.is_ptr ())) {
+ throw tl::Exception (tl::sprintf (tl::to_string (tr ("Cannot pass a const reference of class %s to a non-const reference or pointer parameter")), atype.cls ()->name ()));
+ }
+
+ if (atype.is_ref () || atype.is_cref () || atype.is_ptr () || atype.is_cptr ()) {
if (cls->gsi_cls ()->is_derived_from (atype.cls ())) {
@@ -673,36 +732,24 @@ struct writer
throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unexpected object type (expected argument of class %s)")), atype.cls ()->name ()));
}
- }
+ } else {
- } else {
+ if (cls->gsi_cls ()->is_derived_from (atype.cls ())) {
- if (! arg->is_user ()) {
- throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unexpected object type (expected argument of class %s)")), atype.cls ()->name ()));
- }
+ if (cls->gsi_cls ()->adapted_type_info ()) {
+ aa->write (cls->gsi_cls ()->create_adapted_from_obj (get_object (*arg)));
+ } else {
+ aa->write ((void *) cls->gsi_cls ()->clone (get_object (*arg)));
+ }
- const tl::VariantUserClassBase *cls = arg->user_cls ();
- if (!cls) {
- throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unexpected object type (expected argument of class %s)")), atype.cls ()->name ()));
- }
- if (cls->is_const () && (atype.is_ref () || atype.is_ptr ())) {
- throw tl::Exception (tl::sprintf (tl::to_string (tr ("Cannot pass a const reference of class %s to a non-const reference or pointer parameter")), atype.cls ()->name ()));
- }
+ } else if (cls->gsi_cls ()->can_convert_to (atype.cls ())) {
- if (cls->gsi_cls ()->is_derived_from (atype.cls ())) {
+ aa->write (atype.cls ()->create_obj_from (cls->gsi_cls (), get_object (*arg)));
- if (cls->gsi_cls ()->adapted_type_info ()) {
- aa->write (cls->gsi_cls ()->create_adapted_from_obj (get_object (*arg)));
} else {
- aa->write ((void *) cls->gsi_cls ()->clone (get_object (*arg)));
+ throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unexpected object type (expected argument of class %s)")), atype.cls ()->name ()));
}
- } else if (cls->gsi_cls ()->can_convert_to (atype.cls ())) {
-
- aa->write (atype.cls ()->create_obj_from (cls->gsi_cls (), get_object (*arg)));
-
- } else {
- throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unexpected object type (expected argument of class %s)")), atype.cls ()->name ()));
}
}
@@ -710,6 +757,23 @@ struct writer
}
};
+void push_args (gsi::SerialArgs &arglist, const tl::Variant &args, const gsi::MethodBase *meth, tl::Heap *heap)
+{
+ int n = int (args.size ());
+ int narg = 0;
+
+ for (gsi::MethodBase::argument_iterator a = meth->begin_arguments (); a != meth->end_arguments () && narg < n; ++a, ++narg) {
+ try {
+ // Note: this const_cast is ugly, but it will basically enable "out" parameters
+ // TODO: clean this up.
+ gsi::do_on_type () (a->type (), &arglist, const_cast ((args.get_list ().begin () + narg).operator-> ()), *a, heap);
+ } catch (tl::Exception &ex) {
+ std::string msg = ex.msg () + tl::sprintf (tl::to_string (tr (" (argument '%s')")), a->spec ()->name ());
+ throw tl::Exception (msg);
+ }
+ }
+}
+
// ---------------------------------------------------------------------
// Reader function for serialization
diff --git a/src/gsi/gsi/gsiSerialisation.cc b/src/gsi/gsi/gsiSerialisation.cc
index 97aa8713e..1744e567c 100644
--- a/src/gsi/gsi/gsiSerialisation.cc
+++ b/src/gsi/gsi/gsiSerialisation.cc
@@ -23,6 +23,7 @@
#include "gsi.h"
#include "gsiSerialisation.h"
+#include "tlLog.h"
namespace gsi
{
@@ -38,7 +39,14 @@ public:
~AdaptorSynchronizer ()
{
- mp_src->copy_to (mp_target, *mp_heap);
+ try {
+ // NOTE: exceptions must not escape destructors as a basic C++ design requirement
+ mp_src->copy_to (mp_target, *mp_heap);
+ } catch (tl::Exception &ex) {
+ tl::error << ex.msg ();
+ } catch (...) {
+ }
+
delete mp_src;
delete mp_target;
mp_src = 0;
diff --git a/src/gsi/gsi_test/gsiTest.cc b/src/gsi/gsi_test/gsiTest.cc
index be3b3921f..370f055f2 100644
--- a/src/gsi/gsi_test/gsiTest.cc
+++ b/src/gsi/gsi_test/gsiTest.cc
@@ -65,6 +65,20 @@ A::A (int nn) {
f = false;
}
+A::A (int n1, int n2) {
+ ++a_count;
+ e = Enum (0);
+ n = n1 + n2;
+ f = false;
+}
+
+A::A (int n1, int n2, double n3) {
+ ++a_count;
+ e = Enum (0);
+ n = (n1 + n2) * n3;
+ f = false;
+}
+
A::A (const A &a)
: gsi::ObjectBase (a)
{
@@ -339,7 +353,17 @@ static A *a_ctor (int i)
return new A (i);
}
-void A::a20 (A *ptr)
+static A *a_ctor2 (int i, int j)
+{
+ return new A (i, j);
+}
+
+static A *a_ctor3 (int i, int j, double f)
+{
+ return new A (i, j, f);
+}
+
+void A::a20 (A *ptr)
{
if (a_inst.get () != ptr) {
a_inst.reset (ptr);
@@ -360,26 +384,26 @@ static int b_count = 0;
B::B ()
{
++b_count;
- av.push_back (A (100));
- av.push_back (A (121));
- av.push_back (A (144));
- avc_nc.push_back (new A_NC (-3100));
- avc_nc.push_back (new A_NC (-3121));
- av_nc.push_back (new A_NC (7100));
- av_nc.push_back (new A_NC (7121));
- av_nc.push_back (new A_NC (7144));
- av_nc.push_back (new A_NC (7169));
+ m_av.push_back (A (100));
+ m_av.push_back (A (121));
+ m_av.push_back (A (144));
+ m_avc_nc.push_back (new A_NC (-3100));
+ m_avc_nc.push_back (new A_NC (-3121));
+ m_av_nc.push_back (new A_NC (7100));
+ m_av_nc.push_back (new A_NC (7121));
+ m_av_nc.push_back (new A_NC (7144));
+ m_av_nc.push_back (new A_NC (7169));
}
B::~B ()
{
- while (! av_nc.empty ()) {
- delete av_nc.back ();
- av_nc.pop_back ();
+ while (! m_av_nc.empty ()) {
+ delete m_av_nc.back ();
+ m_av_nc.pop_back ();
}
- while (! avc_nc.empty ()) {
- delete const_cast (avc_nc.back ());
- avc_nc.pop_back ();
+ while (! m_avc_nc.empty ()) {
+ delete const_cast (m_avc_nc.back ());
+ m_avc_nc.pop_back ();
}
if (b_inst == this) {
b_inst = 0;
@@ -405,22 +429,22 @@ B &B::operator=(const B &d)
}
m = d.m;
- a = d.a;
- bv = d.bv;
- av = d.av;
- while (! av_nc.empty ()) {
- delete av_nc.back ();
- av_nc.pop_back ();
+ m_a = d.m_a;
+ m_bv = d.m_bv;
+ m_av = d.m_av;
+ while (! m_av_nc.empty ()) {
+ delete m_av_nc.back ();
+ m_av_nc.pop_back ();
}
- for (std::vector ::const_iterator i = d.av_nc.begin (); i != d.av_nc.end (); ++i) {
- av_nc.push_back (new A_NC (**i));
+ for (std::vector ::const_iterator i = d.m_av_nc.begin (); i != d.m_av_nc.end (); ++i) {
+ m_av_nc.push_back (new A_NC (**i));
}
- while (! avc_nc.empty ()) {
- delete const_cast (avc_nc.back ());
- avc_nc.pop_back ();
+ while (! m_avc_nc.empty ()) {
+ delete const_cast (m_avc_nc.back ());
+ m_avc_nc.pop_back ();
}
- for (std::vector ::const_iterator i = d.avc_nc.begin (); i != d.avc_nc.end (); ++i) {
- avc_nc.push_back (new A_NC (**i));
+ for (std::vector ::const_iterator i = d.m_avc_nc.begin (); i != d.m_avc_nc.end (); ++i) {
+ m_avc_nc.push_back (new A_NC (**i));
}
m_var = d.m_var;
m_vars = d.m_vars;
@@ -461,7 +485,7 @@ std::string B::addr () const
return c;
}
-static int b3_ext (const B *b, A *aptr)
+static int aptr_to_n_ext (const B *b, A *aptr)
{
return b->b3 (aptr);
}
@@ -1030,6 +1054,8 @@ static gsi::QFlagsClass decl_qflags_enum ("", "Enums");
static gsi::Class decl_a ("", "A",
gsi::constructor ("new_a|new", &a_ctor) +
+ gsi::constructor ("new", &a_ctor2) +
+ gsi::constructor ("new", &a_ctor3) +
gsi::method ("instance_count", &A::instance_count) +
gsi::method ("new_a_by_variant", &A::new_a_by_variant) +
@@ -1146,8 +1172,8 @@ static gsi::Class decl_a ("", "A",
gsi::method ("af?|af", &A::af1) +
gsi::method ("aa", &A::a) +
gsi::method ("aa", &A::a_static) +
- gsi::method ("a1", &A::a1) +
- gsi::method ("a1c", &A::a1c) +
+ gsi::method ("a1|get_n", &A::a1) +
+ gsi::method ("a1c|get_n_const", &A::a1c) +
gsi::method ("a2", &A::a2) +
gsi::method ("a3", &A::a3) +
#if defined(HAVE_QT)
@@ -1262,8 +1288,8 @@ static gsi::Class decl_b ("", "B",
gsi::method ("set_str", &B::set_str) +
gsi::method ("str_ccptr", &B::str_ccptr) +
gsi::method ("set_str_combine", &B::set_str_combine) +
- gsi::method_ext ("b3|aptr_to_n", &b3_ext) +
- gsi::method ("b4|aref_to_s", &B::b4) +
+ gsi::method_ext ("b3|aptr_to_n", &aptr_to_n_ext) +
+ gsi::method ("b4|aref_to_s", &B::aref_to_s) +
gsi::method ("make_a", &B::make_a) +
gsi::method ("set_an", &B::set_an) +
gsi::method ("an", &B::an) +
@@ -1280,18 +1306,23 @@ static gsi::Class decl_b ("", "B",
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) +
- gsi::method ("b16c|av_ref", &B::b16c) +
- gsi::method ("b17a|av_cref=", &B::b17a) +
- gsi::method ("b17b|av_ref=", &B::b17b) +
- gsi::method ("b17c|av=", &B::b17c) +
- gsi::method ("b17d|av_cptr=", &B::b17d) +
- gsi::method ("b17e|av_ptr=", &B::b17e) +
- gsi::iterator ("b18", &B::b18) +
- gsi::iterator ("b18b", &B::b18b) +
- gsi::iterator ("b18c", &B::b18b) +
+ gsi::method ("b15|arg_is_not_nil", &B::arg_is_not_nil) +
+ gsi::method ("b16a|av", &B::av) +
+ gsi::method ("b16b|av_cref", &B::av_cref) +
+ gsi::method ("b16c|av_ref", &B::av_ref) +
+ gsi::method ("push_a", &B::push_a) +
+ gsi::method ("push_a_cref", &B::push_a_cref) +
+ gsi::method ("push_a_cptr", &B::push_a_cptr) +
+ gsi::method ("push_a_ref", &B::push_a_ref) +
+ gsi::method ("push_a_ptr", &B::push_a_ptr) +
+ gsi::method ("b17a|av_cref=", &B::set_av_cref) +
+ gsi::method ("b17b|av_ref=", &B::set_av_ref) +
+ gsi::method ("b17c|av=", &B::set_av) +
+ gsi::method ("b17d|av_cptr=", &B::set_av_cptr) +
+ gsi::method ("b17e|av_ptr=", &B::set_av_ptr) +
+ gsi::iterator ("b18|each_a", &B::b18) +
+ gsi::iterator ("b18b|each_a_ref", &B::b18b) +
+ gsi::iterator ("b18c|each_a_ptr", &B::b18c) +
gsi::method ("b20a|var_is_nil", &B::b20a) +
gsi::method ("b20b|var_is_double", &B::b20b) +
gsi::method ("b20c|var_is_long", &B::b20c) +
diff --git a/src/gsi/gsi_test/gsiTest.h b/src/gsi/gsi_test/gsiTest.h
index 204d4ae82..fe7f47b54 100644
--- a/src/gsi/gsi_test/gsiTest.h
+++ b/src/gsi/gsi_test/gsiTest.h
@@ -73,7 +73,17 @@ struct A
*/
A (int nn);
- /**
+ /**
+ * @brief Parametrized constructor 2
+ */
+ A (int n1, int n2);
+
+ /**
+ * @brief Parametrized constructor 3
+ */
+ A (int n1, int n2, double n3);
+
+ /**
* @brief Copy constructor
*/
A (const A &a);
@@ -640,7 +650,7 @@ struct B
return aptr->n;
}
- std::string b4 (const A &aref) {
+ std::string aref_to_s (const A &aref) {
return tl::sprintf ("b4_result: %d", aref.n);
}
@@ -650,7 +660,7 @@ struct B
void set_an (int n)
{
- a.n = n;
+ m_a.n = n;
}
int an (A a)
@@ -660,7 +670,7 @@ struct B
void set_an_cref (const int &n)
{
- a.n = n;
+ m_a.n = n;
}
const int &an_cref (const A &a)
@@ -670,122 +680,155 @@ struct B
std::vector ::const_iterator b10b () const
{
- return av.begin ();
+ return m_av.begin ();
}
std::vector ::const_iterator b10e () const
{
- return av.end ();
+ return m_av.end ();
}
std::vector ::iterator b10b_nc ()
{
- return av.begin ();
+ return m_av.begin ();
}
std::vector ::iterator b10e_nc ()
{
- return av.end ();
+ return m_av.end ();
}
ValueIter::const_iterator> b11b () const
{
- return ValueIter::const_iterator> (av.begin ());
+ return ValueIter::const_iterator> (m_av.begin ());
}
ValueIter::const_iterator> b11e () const
{
- return ValueIter::const_iterator> (av.end ());
+ return ValueIter::const_iterator> (m_av.end ());
}
std::vector ::const_iterator b12b () const
{
- return av_nc.begin ();
+ return m_av_nc.begin ();
}
std::vector ::const_iterator b12e () const
{
- return av_nc.end ();
+ return m_av_nc.end ();
}
std::vector ::const_iterator b13b () const
{
- return avc_nc.begin ();
+ return m_avc_nc.begin ();
}
std::vector ::const_iterator b13e () const
{
- return avc_nc.end ();
+ return m_avc_nc.end ();
}
- A *amember_or_nil (bool nn) { return nn ? &a : 0; }
- A *amember_ptr () { return &a; }
- A &amember_ref () { return a; }
- const A *amember_cptr () const { return &a; }
- const A &amember_cref () const { return a; }
+ A *amember_or_nil (bool nn) { return nn ? &m_a : 0; }
+ A *amember_ptr () { return &m_a; }
+ A &amember_ref () { return m_a; }
+ const A *amember_cptr () const { return &m_a; }
+ const A &amember_cref () const { return m_a; }
- bool b15 (A *a)
+ bool arg_is_not_nil (A *a)
{
return a != 0;
}
- std::vector b16a () const
+ std::vector av () const
{
- return av;
+ return m_av;
}
- const std::vector &b16b () const
+ const std::vector &av_cref () const
{
- return av;
+ return m_av;
}
- std::vector &b16c ()
+ std::vector &av_ref ()
{
- return av;
+ return m_av;
}
- void b17a (const std::vector &v)
+ void set_av_cref (const std::vector &v)
{
- av = v;
+ m_av = v;
}
- void b17b (std::vector &v)
+ void set_av_ref (std::vector &v)
{
- av = v;
+ m_av = v;
}
- void b17c (std::vector v)
+ void set_av (std::vector v)
{
- av = v;
+ m_av = v;
}
- void b17d (const std::vector *v)
+ void set_av_cptr (const std::vector *v)
{
if (v) {
- av = *v;
+ m_av = *v;
+ } else {
+ m_av.clear ();
}
}
- void b17e (std::vector *v)
+ void set_av_ptr (std::vector *v)
{
if (v) {
- av = *v;
+ m_av = *v;
+ } else {
+ m_av.clear ();
+ }
+ }
+
+ void push_a (A a)
+ {
+ m_av.push_back (a);
+ }
+
+ void push_a_cref (const A &a)
+ {
+ m_av.push_back (a);
+ }
+
+ void push_a_ref (A &a)
+ {
+ m_av.push_back (a);
+ }
+
+ void push_a_cptr (const A *a)
+ {
+ if (a) {
+ m_av.push_back (*a);
+ }
+ }
+
+ void push_a_ptr (A *a)
+ {
+ if (a) {
+ m_av.push_back (*a);
}
}
FreeIter::const_iterator> b18 () const
{
- return FreeIter::const_iterator> (av.begin (), av.end ());
+ return FreeIter::const_iterator> (m_av.begin (), m_av.end ());
}
FreeIterUseRef::const_iterator> b18b () const
{
- return FreeIterUseRef::const_iterator> (av.begin (), av.end ());
+ return FreeIterUseRef::const_iterator> (m_av.begin (), m_av.end ());
}
FreeIterUsePtr::const_iterator> b18c () const
{
- return FreeIterUsePtr::const_iterator> (av.begin (), av.end ());
+ return FreeIterUsePtr::const_iterator> (m_av.begin (), m_av.end ());
}
bool b20a (const tl::Variant &var) const { return var.is_nil (); }
@@ -862,30 +905,30 @@ struct B
FreeIter::const_iterator> each_b_copy () const
{
- return FreeIter::const_iterator> (bv.begin (), bv.end ());
+ return FreeIter::const_iterator> (m_bv.begin (), m_bv.end ());
}
FreeIterUseRef::const_iterator> each_b_cref () const
{
- return FreeIterUseRef::const_iterator> (bv.begin (), bv.end ());
+ return FreeIterUseRef::const_iterator> (m_bv.begin (), m_bv.end ());
}
FreeIterUsePtr::const_iterator> each_b_cptr () const
{
- return FreeIterUsePtr::const_iterator> (bv.begin (), bv.end ());
+ return FreeIterUsePtr::const_iterator> (m_bv.begin (), m_bv.end ());
}
FreeIterUseRef::iterator> each_b_ref ()
{
- return FreeIterUseRef::iterator> (bv.begin (), bv.end ());
+ return FreeIterUseRef::iterator> (m_bv.begin (), m_bv.end ());
}
FreeIterUsePtr::iterator> each_b_ptr ()
{
- return FreeIterUsePtr::iterator> (bv.begin (), bv.end ());
+ return FreeIterUsePtr::iterator> (m_bv.begin (), m_bv.end ());
}
- void push_b (const B &b) { bv.push_back (b); }
+ void push_b (const B &b) { m_bv.push_back (b); }
std::map map_iaptr () { return m_map_iaptr; }
const std::map &map_iaptr_cref () { return m_map_iaptr; }
@@ -996,11 +1039,11 @@ struct B
#endif
std::string m;
- A a;
- std::vector bv;
- std::vector av;
- std::vector av_nc;
- std::vector avc_nc;
+ A m_a;
+ std::vector m_bv;
+ std::vector m_av;
+ std::vector m_av_nc;
+ std::vector m_avc_nc;
tl::Variant m_var;
std::vector m_vars;
std::map m_map1;
diff --git a/src/gsi/unit_tests/gsiExpressionTests.cc b/src/gsi/unit_tests/gsiExpressionTests.cc
index a31717fcf..1bfdf1013 100644
--- a/src/gsi/unit_tests/gsiExpressionTests.cc
+++ b/src/gsi/unit_tests/gsiExpressionTests.cc
@@ -57,14 +57,14 @@ TEST(1)
v = e.parse ("A.aa").execute ();
EXPECT_EQ (v.to_string (), std::string ("static_a"));
- v = e.parse ("A.new.a1").execute ();
+ v = e.parse ("A.new.get_n").execute ();
EXPECT_EQ (v.to_string (), std::string ("17"));
v = e.parse ("var a=A.new").execute ();
- v = e.parse ("a.a5(-5); a.a1").execute ();
+ v = e.parse ("a.a5(-5); a.get_n").execute ();
EXPECT_EQ (v.to_string (), std::string ("-5"));
// mapping of property assignment to method
- v = e.parse ("a.n = -177; a.a1").execute ();
+ v = e.parse ("a.n = -177; a.get_n").execute ();
EXPECT_EQ (v.to_string (), std::string ("-177"));
bool error = false;
try {
@@ -104,9 +104,9 @@ TEST(1)
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 ();
+ v = e.parse ("var a1=A.new; a1.a5(-15); var a2=a1.dup; a2.a5(107); a1.get_n").execute ();
EXPECT_EQ (v.to_string (), std::string ("-15"));
- v = e.parse ("var a1=A.new; a1.a5(-15); var a2=a1.dup; a2.a5(107); a2.a1").execute ();
+ v = e.parse ("var a1=A.new; a1.a5(-15); var a2=a1.dup; a2.a5(107); a2.get_n").execute ();
EXPECT_EQ (v.to_string (), std::string ("107"));
v = e.parse ("var a=A.new; a.get_e.to_s").execute ();
@@ -218,12 +218,22 @@ TEST(2)
EXPECT_EQ (v.to_string (), std::string ("5"));
v = e.parse ("var b=B.new; var a1=A.new(-17); var a2=A.new(42); b.av = [ a1, a2 ]; to_s(b.av)").execute ();
EXPECT_EQ (v.to_string (), std::string ("A: -17,A: 42"));
+ v = e.parse ("var b=B.new; var a1=A.new(-17); var a2=A.new(42); b.av = []; b.push_a(a1); b.push_a(a2); to_s(b.av)").execute ();
+ EXPECT_EQ (v.to_string (), std::string ("A: -17,A: 42"));
+ v = e.parse ("var b=B.new; var a1=A.new(-17); var a2=A.new(42); b.av = []; b.push_a_cref(a1); b.push_a_cptr(a2); to_s(b.av)").execute ();
+ EXPECT_EQ (v.to_string (), std::string ("A: -17,A: 42"));
+ v = e.parse ("var b=B.new; var a1=A.new(-17); var a2=A.new(42); b.av = []; b.push_a_ref(a1); b.push_a_ptr(a2); to_s(b.av)").execute ();
+ EXPECT_EQ (v.to_string (), std::string ("A: -17,A: 42"));
v = e.parse ("var b=B.new; var a1=A.new(-17); var a2=A.new(1); b.av_cref = [ a1, a2 ]; to_s(b.av_cref)").execute ();
EXPECT_EQ (v.to_string (), std::string ("A: -17,A: 1"));
- v = e.parse ("var b=B.new; b.av = [ A.new(-13) ]; b.av_cptr = nil; to_s(b.av)").execute ();
+ v = e.parse ("var b=B.new; b.av_cptr = [ A.new(-13) ]; to_s(b.av)").execute ();
EXPECT_EQ (v.to_string (), std::string ("A: -13"));
- v = e.parse ("var b=B.new; b.av = [ A.new(13) ]; b.av_ptr = nil; to_s(b.av)").execute ();
+ v = e.parse ("var b=B.new; b.av_ptr = [ A.new(13) ]; to_s(b.av)").execute ();
EXPECT_EQ (v.to_string (), std::string ("A: 13"));
+ v = e.parse ("var b=B.new; b.av = [ A.new(-13) ]; b.av_cptr = nil; to_s(b.av)").execute ();
+ EXPECT_EQ (v.to_string (), std::string (""));
+ v = e.parse ("var b=B.new; b.av = [ A.new(13) ]; b.av_ptr = nil; to_s(b.av)").execute ();
+ EXPECT_EQ (v.to_string (), std::string (""));
v = e.parse ("var b=B.new; var a1=A.new(17); b.av_ref = [ a1 ]; to_s(b.av_ref)").execute ();
EXPECT_EQ (v.to_string (), std::string ("A: 17"));
v = e.parse ("var b=B.new; b.arg_is_not_nil(nil)").execute ();
@@ -234,6 +244,21 @@ TEST(2)
EXPECT_EQ (v.to_string (), std::string ("17"));
v = e.parse ("var b=B.new; b.bx(-1)").execute ();
EXPECT_EQ (v.to_string (), std::string ("xz"));
+
+ // List to constructor call
+ v = e.parse ("var b=B.new; b.av = [ [5, 6], [4, 6, 0.5], [42] ]; to_s(b.av)").execute ();
+ EXPECT_EQ (v.to_string (), std::string ("A: 11,A: 5,A: 42"));
+ v = e.parse ("var b=B.new; b.av = []; b.push_a([ 1, 2 ]); b.push_a([ 17 ]); to_s(b.av)").execute ();
+ EXPECT_EQ (v.to_string (), std::string ("A: 3,A: 17"));
+ v = e.parse ("var b=B.new; b.av = []; b.push_a([ 1, 2 ]); b.push_a_cref([ 17 ]); to_s(b.av)").execute ();
+ EXPECT_EQ (v.to_string (), std::string ("A: 3,A: 17"));
+ v = e.parse ("var b=B.new; b.av = []; b.push_a([ 1, 2 ]); b.push_a_cptr([ 17 ]); to_s(b.av)").execute ();
+ EXPECT_EQ (v.to_string (), std::string ("A: 3,A: 17"));
+ v = e.parse ("var b=B.new; b.av = []; b.push_a([ 1, 2 ]); b.push_a_ref([ 17 ]); to_s(b.av)").execute ();
+ EXPECT_EQ (v.to_string (), std::string ("A: 3,A: 17"));
+ v = e.parse ("var b=B.new; b.av = []; b.push_a([ 1, 2 ]); b.push_a_ptr([ 17 ]); to_s(b.av)").execute ();
+ EXPECT_EQ (v.to_string (), std::string ("A: 3,A: 17"));
+
/*
TODO: No detailed type analysis for ambiguity resolution so far:
v = e.parse ("var b=B.new; b.bx('hello', 1)").execute ();
@@ -316,15 +341,15 @@ TEST(2)
EXPECT_EQ (v.to_string (), std::string ("A: 177"));
v = e.parse ("b.amember_or_nil(false)").execute ();
EXPECT_EQ (v.to_string (), std::string ("nil"));
- v = e.parse ("b.amember_ptr.a5(177); b.amember_ref.a1").execute ();
+ v = e.parse ("b.amember_ptr.a5(177); b.amember_ref.get_n").execute ();
EXPECT_EQ (v.to_string (), std::string ("177"));
- v = e.parse ("b.amember_ref.a1c").execute ();
+ v = e.parse ("b.amember_ref.get_n_const").execute ();
EXPECT_EQ (v.to_string (), std::string ("177"));
- v = e.parse ("b.amember_cref.a1c").execute ();
+ v = e.parse ("b.amember_cref.get_n_const").execute ();
EXPECT_EQ (v.to_string (), std::string ("177"));
error = false;
try {
- v = e.parse ("b.amember_cref.a1").execute ();
+ v = e.parse ("b.amember_cref.get_n").execute ();
} catch (...) {
// can't call non-const method on const ref
error = true;
@@ -334,16 +359,16 @@ TEST(2)
// references: storage in variables
v = e.parse ("var aref = b.amember_ptr").execute ();
v = e.parse ("aref.n = 178").execute ();
- v = e.parse ("aref.a1").execute ();
+ v = e.parse ("aref.get_n").execute ();
EXPECT_EQ (v.to_string (), std::string ("178"));
- v = e.parse ("aref.a1 == 178").execute ();
+ v = e.parse ("aref.get_n == 178").execute ();
EXPECT_EQ (v.to_string (), std::string ("true"));
- v = e.parse ("b.amember_ref.a1").execute ();
+ v = e.parse ("b.amember_ref.get_n").execute ();
EXPECT_EQ (v.to_string (), std::string ("178"));
// references: storage in variables
v = e.parse ("var aref = b.amember_cptr").execute ();
- v = e.parse ("aref.a1c").execute ();
+ v = e.parse ("aref.get_n_const").execute ();
EXPECT_EQ (v.to_string (), std::string ("178"));
error = false;
try {
diff --git a/src/klayout.pri b/src/klayout.pri
index 27a7051a0..a370e8490 100644
--- a/src/klayout.pri
+++ b/src/klayout.pri
@@ -104,9 +104,15 @@ equals(HAVE_PTHREADS, "1") {
}
equals(HAVE_GIT2, "1") {
- !isEmpty(BITS_PATH) {
- include($$BITS_PATH/git2/git2.pri)
+ !mac {
+ !isEmpty(BITS_PATH) {
+ include($$BITS_PATH/git2/git2.pri)
+ } else {
+ LIBS += -lgit2
+ }
} else {
+ QMAKE_INCDIR += $$(MAC_LIBGIT2_INC)
+ QMAKE_LFLAGS += -L$$(MAC_LIBGIT2_LIB)
LIBS += -lgit2
}
DEFINES += HAVE_GIT2
diff --git a/src/pya/pya/pya.cc b/src/pya/pya/pya.cc
index 377c7211f..8c617f71d 100644
--- a/src/pya/pya/pya.cc
+++ b/src/pya/pya/pya.cc
@@ -390,6 +390,8 @@ PythonInterpreter::~PythonInterpreter ()
m_stdout = PythonPtr ();
m_stderr = PythonPtr ();
+ sp_interpreter = 0;
+
if (m_embedded) {
Py_Finalize ();
@@ -400,8 +402,6 @@ PythonInterpreter::~PythonInterpreter ()
}
}
-
- sp_interpreter = 0;
}
char *
diff --git a/src/pya/pya/pyaCallables.cc b/src/pya/pya/pyaCallables.cc
index e85010e80..f63f21976 100644
--- a/src/pya/pya/pyaCallables.cc
+++ b/src/pya/pya/pyaCallables.cc
@@ -200,7 +200,8 @@ match_method (int mid, PyObject *self, PyObject *args, bool strict)
tl_assert (cls_decl != 0);
- int argc = args == NULL ? 0 : int (PyTuple_Size (args));
+ bool is_tuple = PyTuple_Check (args);
+ int argc = args == NULL ? 0 : (is_tuple ? int (PyTuple_Size (args)) : int (PyList_Size (args)));
// get number of candidates by argument count
const gsi::MethodBase *meth = 0;
@@ -277,9 +278,10 @@ match_method (int mid, PyObject *self, PyObject *args, bool strict)
int sc = 0;
int i = 0;
for (gsi::MethodBase::argument_iterator a = (*m)->begin_arguments (); is_valid && i < argc && a != (*m)->end_arguments (); ++a, ++i) {
- if (test_arg (*a, PyTuple_GetItem (args, i), false /*strict*/)) {
+ PyObject *arg = is_tuple ? PyTuple_GetItem (args, i) : PyList_GetItem (args, i);
+ if (test_arg (*a, arg, false /*strict*/)) {
++sc;
- } else if (test_arg (*a, PyTuple_GetItem (args, i), true /*loose*/)) {
+ } else if (test_arg (*a, arg, true /*loose*/)) {
// non-scoring match
} else {
is_valid = false;
@@ -326,7 +328,8 @@ match_method (int mid, PyObject *self, PyObject *args, bool strict)
// one candidate, but needs checking whether compatibility is given - this avoid having to route NotImplemented over TypeError exceptions later
int i = 0;
for (gsi::MethodBase::argument_iterator a = meth->begin_arguments (); i < argc && a != meth->end_arguments (); ++a, ++i) {
- if (! test_arg (*a, PyTuple_GetItem (args, i), true /*loose*/)) {
+ PyObject *arg = is_tuple ? PyTuple_GetItem (args, i) : PyList_GetItem (args, i);
+ if (! test_arg (*a, arg, true /*loose*/)) {
return 0;
}
}
@@ -607,16 +610,17 @@ special_method_impl (gsi::MethodBase::special_method_type smt, PyObject *self, P
}
}
-static void
+void
push_args (gsi::SerialArgs &arglist, const gsi::MethodBase *meth, PyObject *args, tl::Heap &heap)
{
+ bool is_tuple = PyTuple_Check (args);
int i = 0;
- int argc = args == NULL ? 0 : int (PyTuple_Size (args));
+ int argc = args == NULL ? 0 : (is_tuple ? int (PyTuple_Size (args)) : int (PyList_Size (args)));
try {
for (gsi::MethodBase::argument_iterator a = meth->begin_arguments (); i < argc && a != meth->end_arguments (); ++a, ++i) {
- push_arg (*a, arglist, PyTuple_GetItem (args, i), heap);
+ push_arg (*a, arglist, is_tuple ? PyTuple_GetItem (args, i) : PyList_GetItem (args, i), heap);
}
} catch (tl::Exception &ex) {
@@ -726,7 +730,7 @@ property_getter_adaptor (int mid, PyObject *self, PyObject *args)
PYA_TRY
- int argc = args == NULL ? 0 : int (PyTuple_Size (args));
+ int argc = args == NULL ? 0 : (PyTuple_Check (args) ? int (PyTuple_Size (args)) : int (PyList_Size (args)));
if (argc != 0) {
throw tl::Exception (tl::to_string (tr ("Property getters must not have an argument")));
}
@@ -747,12 +751,12 @@ property_setter_adaptor (int mid, PyObject *self, PyObject *args)
PYA_TRY
- int argc = args == NULL ? 0 : int (PyTuple_Size (args));
+ int argc = args == NULL ? 0 : (PyTuple_Check (args) ? int (PyTuple_Size (args)) : int (PyList_Size (args)));
if (argc != 1) {
throw tl::Exception (tl::to_string (tr ("Property setter needs exactly one argument")));
}
- PyObject *value = PyTuple_GetItem (args, 0);
+ PyObject *value = PyTuple_Check (args) ? PyTuple_GetItem (args, 0) : PyList_GetItem (args, 0);
if (value) {
ret = property_setter_impl (mid, self, value);
}
@@ -777,7 +781,8 @@ method_init_adaptor (int mid, PyObject *self, PyObject *args)
p->destroy ();
}
- const gsi::MethodBase *meth = match_method (mid, self, args, PyTuple_Size (args) > 0 || ! p->cls_decl ()->can_default_create ());
+ int argc = PyTuple_Check (args) ? int (PyTuple_Size (args)) : int (PyList_Size (args));
+ const gsi::MethodBase *meth = match_method (mid, self, args, argc > 0 || ! p->cls_decl ()->can_default_create ());
if (meth && meth->smt () == gsi::MethodBase::None) {
diff --git a/src/pya/pya/pyaMarshal.cc b/src/pya/pya/pyaMarshal.cc
index 0d1274d6c..38c659e4d 100644
--- a/src/pya/pya/pyaMarshal.cc
+++ b/src/pya/pya/pyaMarshal.cc
@@ -32,6 +32,8 @@
namespace pya
{
+void push_args (gsi::SerialArgs &arglist, const gsi::MethodBase *meth, PyObject *args, tl::Heap &heap);
+
// -------------------------------------------------------------------
// Serialization adaptors for strings, variants, vectors and maps
@@ -43,9 +45,26 @@ class PythonBasedStringAdaptor
{
public:
PythonBasedStringAdaptor (const PythonPtr &string)
- : m_stdstr (python2c (string.get ())), m_string (string)
+ : m_string (string)
{
- // .. nothing yet ..
+#if PY_MAJOR_VERSION < 3
+ if (PyString_Check (string.get ())) {
+ m_stdstr = python2c (string.get ());
+ } else
+#else
+ if (PyBytes_Check (string.get ())) {
+ m_stdstr = python2c (string.get ());
+ } else
+#endif
+ if (PyUnicode_Check (string.get ()) || PyByteArray_Check (string.get ())) {
+ m_stdstr = python2c (string.get ());
+ } else {
+ // use object protocol to get the string through str(...)
+ PythonRef as_str (PyObject_Str (string.get ()));
+ if (as_str) {
+ m_stdstr = python2c (as_str.get ());
+ }
+ }
}
virtual const char *c_str () const
@@ -454,6 +473,8 @@ struct writer
{
void operator() (gsi::SerialArgs *aa, PyObject *arg, const gsi::ArgType &atype, tl::Heap *heap)
{
+ const gsi::ClassBase *acls = atype.cls ();
+
if (arg == Py_None || arg == NULL) {
if (! (atype.is_ptr () || atype.is_cptr ())) {
@@ -465,14 +486,50 @@ struct writer
}
- if (atype.is_ptr () || atype.is_cptr () || atype.is_ref () || atype.is_cref ()) {
+ if (PyTuple_Check (arg) || PyList_Check (arg)) {
+
+ // we may implicitly convert a tuple into a constructor call of a target object -
+ // for now we only check whether the number of arguments is compatible with the list given.
+
+ int n = PyTuple_Check (arg) ? int (PyTuple_Size (arg)) : int (PyList_Size (arg));
+ const gsi::MethodBase *meth = 0;
+ for (gsi::ClassBase::method_iterator c = acls->begin_constructors (); c != acls->end_constructors (); ++c) {
+ if ((*c)->compatible_with_num_args (n)) {
+ meth = *c;
+ break;
+ }
+ }
+
+ if (!meth) {
+ throw tl::Exception (tl::to_string (tr ("No constructor of %s available that takes %d arguments (implicit call from tuple)")), acls->name (), n);
+ }
+
+ // implicit call of constructor
+ gsi::SerialArgs retlist (meth->retsize ());
+ gsi::SerialArgs arglist (meth->argsize ());
+
+ push_args (arglist, meth, arg, *heap);
+
+ meth->call (0, arglist, retlist);
+
+ void *new_obj = retlist.read (*heap);
+ if (new_obj && (atype.is_ptr () || atype.is_cptr () || atype.is_ref () || atype.is_cref ())) {
+ // For pointers or refs, ownership over these objects is not transferred.
+ // Hence we have to keep them on the heap.
+ // TODO: what if the called method takes ownership using keep()?
+ heap->push (new gsi::ObjectHolder (acls, new_obj));
+ }
+
+ aa->write (new_obj);
+
+ } else if (atype.is_ptr () || atype.is_cptr () || atype.is_ref () || atype.is_cref ()) {
const gsi::ClassBase *cls_decl = PythonModule::cls_for_type (Py_TYPE (arg));
if (! cls_decl) {
throw tl::TypeError (tl::sprintf (tl::to_string (tr ("Unexpected object type (expected argument of class %s, got %s)")), atype.cls ()->name (), Py_TYPE (arg)->tp_name));
}
- if (cls_decl->is_derived_from (atype.cls ())) {
+ if (cls_decl->is_derived_from (acls)) {
PYAObjectBase *p = PYAObjectBase::from_pyobject (arg);
@@ -483,14 +540,15 @@ struct writer
aa->write (p->obj ());
}
- } else if (cls_decl->can_convert_to (atype.cls ())) {
+ } else if (cls_decl->can_convert_to (acls)) {
PYAObjectBase *p = PYAObjectBase::from_pyobject (arg);
// We can convert objects for cref and cptr, but ownership over these objects is not transferred.
// Hence we have to keep them on the heap.
- void *new_obj = atype.cls ()->create_obj_from (p->cls_decl (), p->obj ());
- heap->push (new gsi::ObjectHolder (atype.cls (), new_obj));
+ // TODO: what if the called method takes ownership using keep()?
+ void *new_obj = acls->create_obj_from (p->cls_decl (), p->obj ());
+ heap->push (new gsi::ObjectHolder (acls, new_obj));
aa->write (new_obj);
} else {
@@ -504,7 +562,7 @@ struct writer
throw tl::TypeError (tl::sprintf (tl::to_string (tr ("Unexpected object type (expected argument of class %s, got %s)")), atype.cls ()->name (), Py_TYPE (arg)->tp_name));
}
- if (cls_decl->is_derived_from (atype.cls ())) {
+ if (cls_decl->is_derived_from (acls)) {
PYAObjectBase *p = PYAObjectBase::from_pyobject (arg);
@@ -515,7 +573,7 @@ struct writer
aa->write (atype.cls ()->clone (p->obj ()));
}
- } else if (cls_decl->can_convert_to (atype.cls ())) {
+ } else if (cls_decl->can_convert_to (acls)) {
PYAObjectBase *p = PYAObjectBase::from_pyobject (arg);
aa->write (atype.cls ()->create_obj_from (cls_decl, p->obj ()));
@@ -887,8 +945,10 @@ void PythonBasedVectorAdaptor::push (gsi::SerialArgs &r, tl::Heap &heap)
void PythonBasedVectorAdaptor::clear ()
{
- if (PySequence_Check (m_array.get ())) {
- PySequence_DelSlice (m_array.get (), 0, PySequence_Length (m_array.get ()));
+ if (PyList_Check (m_array.get ())) {
+ PyList_SetSlice (m_array.get (), 0, PyList_Size (m_array.get ()), NULL);
+ } else if (PyTuple_Check (m_array.get ())) {
+ throw tl::Exception (tl::to_string (tr ("Tuples cannot be modified and cannot be used as out parameters")));
}
}
@@ -1141,19 +1201,38 @@ struct test_arg_func
{
void operator() (bool *ret, PyObject *arg, const gsi::ArgType &atype, bool loose)
{
+ const gsi::ClassBase *acls = atype.cls ();
+
// for const X * or X *, null is an allowed value
if ((atype.is_cptr () || atype.is_ptr ()) && arg == Py_None) {
*ret = true;
return;
}
+ if (loose && (PyTuple_Check (arg) || PyList_Check (arg))) {
+
+ // we may implicitly convert a tuple into a constructor call of a target object -
+ // for now we only check whether the number of arguments is compatible with the list given.
+
+ int n = PyTuple_Check (arg) ? int (PyTuple_Size (arg)) : int (PyList_Size (arg));
+ *ret = false;
+ for (gsi::ClassBase::method_iterator c = acls->begin_constructors (); c != acls->end_constructors (); ++c) {
+ if ((*c)->compatible_with_num_args (n)) {
+ *ret = true;
+ break;
+ }
+ }
+ return;
+
+ }
+
const gsi::ClassBase *cls_decl = PythonModule::cls_for_type (Py_TYPE (arg));
if (! cls_decl) {
*ret = false;
return;
}
- if (! (cls_decl == atype.cls () || (loose && (cls_decl->is_derived_from (atype.cls ()) || cls_decl->can_convert_to(atype.cls ()))))) {
+ if (! (cls_decl == acls || (loose && (cls_decl->is_derived_from (atype.cls ()) || cls_decl->can_convert_to (atype.cls ()))))) {
*ret = false;
return;
}
diff --git a/src/pya/pya/pyaUtils.cc b/src/pya/pya/pyaUtils.cc
index a279bac18..0bded8e92 100644
--- a/src/pya/pya/pyaUtils.cc
+++ b/src/pya/pya/pyaUtils.cc
@@ -117,8 +117,9 @@ void check_error ()
} else if (PyErr_GivenExceptionMatches (exc_type.get (), PyExc_SystemExit)) {
int status = 0;
- if (exc_value && test_type (exc_value.get (), true)) {
- status = python2c (exc_value.get ());
+ if (exc_value) {
+ tl::Variant st = python2c (exc_value.get ());
+ status = st.to_int ();
}
throw tl::ExitException (status);
diff --git a/src/rba/rba/rba.cc b/src/rba/rba/rba.cc
index 00826361c..7883c78bc 100644
--- a/src/rba/rba/rba.cc
+++ b/src/rba/rba/rba.cc
@@ -943,7 +943,7 @@ static gsi::ArgType create_void_type ()
static gsi::ArgType s_void_type = create_void_type ();
-static void
+void
push_args (gsi::SerialArgs &arglist, const gsi::MethodBase *meth, VALUE *argv, int argc, tl::Heap &heap)
{
int i = 0;
diff --git a/src/rba/rba/rbaMarshal.cc b/src/rba/rba/rbaMarshal.cc
index 7478ecbc2..d7ee41c18 100644
--- a/src/rba/rba/rbaMarshal.cc
+++ b/src/rba/rba/rbaMarshal.cc
@@ -34,6 +34,8 @@
namespace rba
{
+void push_args (gsi::SerialArgs &arglist, const gsi::MethodBase *meth, VALUE *argv, int argc, tl::Heap &heap);
+
// -------------------------------------------------------------------
// Serialization adaptors for strings, variants, vectors and maps
@@ -46,7 +48,7 @@ class RubyBasedStringAdaptor
public:
RubyBasedStringAdaptor (VALUE value)
{
- m_string = rba_safe_string_value (value);
+ m_string = rba_safe_obj_as_string (value);
gc_lock_object (m_string);
}
@@ -497,6 +499,42 @@ struct writer
aa->write ((void *) 0);
}
+ } else if (TYPE (arg) == T_ARRAY) {
+
+ // we may implicitly convert an array into a constructor call of a target object -
+ // for now we only check whether the number of arguments is compatible with the array given.
+
+ int n = RARRAY_LEN (arg);
+ const gsi::MethodBase *meth = 0;
+ for (gsi::ClassBase::method_iterator c = atype.cls ()->begin_constructors (); c != atype.cls ()->end_constructors (); ++c) {
+ if ((*c)->compatible_with_num_args (n)) {
+ meth = *c;
+ break;
+ }
+ }
+
+ if (!meth) {
+ throw tl::Exception (tl::to_string (tr ("No constructor of %s available that takes %d arguments (implicit call from tuple)")), atype.cls ()->name (), n);
+ }
+
+ // implicit call of constructor
+ gsi::SerialArgs retlist (meth->retsize ());
+ gsi::SerialArgs arglist (meth->argsize ());
+
+ push_args (arglist, meth, RARRAY_PTR (arg), n, *heap);
+
+ meth->call (0, arglist, retlist);
+
+ void *new_obj = retlist.read (*heap);
+ if (new_obj && (atype.is_ptr () || atype.is_cptr () || atype.is_ref () || atype.is_cref ())) {
+ // For pointers or refs, ownership over these objects is not transferred.
+ // Hence we have to keep them on the heap.
+ // TODO: what if the called method takes ownership using keep()?
+ heap->push (new gsi::ObjectHolder (atype.cls (), new_obj));
+ }
+
+ aa->write (new_obj);
+
} else {
if (TYPE (arg) != T_DATA) {
@@ -1152,6 +1190,21 @@ struct test_arg_func
// for const X * or X *, nil is an allowed value
*ret = true;
+ } else if (loose && TYPE (arg) == T_ARRAY) {
+
+ // we may implicitly convert an array into a constructor call of a target object -
+ // for now we only check whether the number of arguments is compatible with the array given.
+
+ int n = RARRAY_LEN (arg);
+
+ *ret = false;
+ for (gsi::ClassBase::method_iterator c = atype.cls ()->begin_constructors (); c != atype.cls ()->end_constructors (); ++c) {
+ if ((*c)->compatible_with_num_args (n)) {
+ *ret = true;
+ break;
+ }
+ }
+
} else {
*ret = (TYPE (arg) == T_DATA);
diff --git a/src/tl/tl/tlUnitTest.cc b/src/tl/tl/tlUnitTest.cc
index 473bff366..f6f1ef3d3 100644
--- a/src/tl/tl/tlUnitTest.cc
+++ b/src/tl/tl/tlUnitTest.cc
@@ -265,7 +265,17 @@ bool TestBase::do_test (bool editable, bool slow)
reset_checkpoint ();
- execute (this);
+ try {
+ execute (this);
+ } catch (tl::CancelException &) {
+ throw;
+ } catch (tl::Exception &ex) {
+ raise (std::string ("Exception caught: ") + ex.msg ());
+ } catch (std::runtime_error &ex) {
+ raise (std::string ("std::runtime_error caught: ") + ex.what ());
+ } catch (...) {
+ raise (std::string ("unspecific exception caught: "));
+ }
m_testtmp.clear ();
diff --git a/testdata/klayout_main/main.rb b/testdata/klayout_main/main.rb
index 279c20417..f867f4339 100644
--- a/testdata/klayout_main/main.rb
+++ b/testdata/klayout_main/main.rb
@@ -191,6 +191,18 @@ class KLayoutMain_TestClass < TestBase
end
+ def test_12
+
+ # Application.exit(0) - Python
+ out = `#{self.klayout_bin} -z -r #{File.join(File.dirname(__FILE__), "test12.py")} 2>&1`
+ assert_equal(out, "Before exit()\n")
+
+ # Application.exit(0) - Ruby
+ out = `#{self.klayout_bin} -z -r #{File.join(File.dirname(__FILE__), "test12.rb")} 2>&1`
+ assert_equal(out, "Before exit()\n")
+
+ end
+
end
load("test_epilogue.rb")
diff --git a/testdata/klayout_main/test12.py b/testdata/klayout_main/test12.py
new file mode 100644
index 000000000..b1e545993
--- /dev/null
+++ b/testdata/klayout_main/test12.py
@@ -0,0 +1,4 @@
+
+print("Before exit()")
+pya.Application.instance().exit(0)
+
diff --git a/testdata/klayout_main/test12.rb b/testdata/klayout_main/test12.rb
new file mode 100644
index 000000000..304a4bf6d
--- /dev/null
+++ b/testdata/klayout_main/test12.rb
@@ -0,0 +1,5 @@
+
+$stdout.puts("Before exit()")
+$stdout.flush
+RBA::Application::instance.exit(0)
+
diff --git a/testdata/python/basic.py b/testdata/python/basic.py
index 3c64efbb7..7971416a3 100644
--- a/testdata/python/basic.py
+++ b/testdata/python/basic.py
@@ -26,6 +26,12 @@ import copy
# Set this to True to disable some tests involving exceptions
leak_check = "TEST_LEAK_CHECK" in os.environ
+class ObjectWithStr:
+ def __init__(self, s):
+ self.s = s
+ def __str__(self):
+ return self.s
+
# see test_21
class AEXT(pya.A):
def __init__(self):
@@ -35,7 +41,7 @@ class AEXT(pya.A):
def g(self):
return self.offset
def m(self):
- return self.offset+self.a1()
+ return self.offset+self.get_n()
# Note: there are no protected methods, but this emulates the respective test for RBA
def call_a10_prot(self, f):
a10_prot(f)
@@ -43,7 +49,7 @@ class AEXT(pya.A):
return str(self.offset)
def repr_of_a(self):
- return "a1=" + str(self.a1())
+ return "a1=" + str(self.get_n())
pya.A.__repr__ = repr_of_a
@@ -150,9 +156,9 @@ class BasicTest(unittest.TestCase):
self.assertEqual( pya.A.instance_count(), ic0 + 1 )
a = pya.A()
- self.assertEqual(a.a1(), 17)
+ self.assertEqual(a.get_n(), 17)
a.assign(pya.A(110))
- self.assertEqual(a.a1(), 110)
+ self.assertEqual(a.get_n(), 110)
a = None
self.assertEqual( pya.A.instance_count(), ic0 )
@@ -182,15 +188,16 @@ class BasicTest(unittest.TestCase):
self.assertEqual( pya.A.aa(), "static_a" )
self.assertEqual( a.aa(), "a" )
- self.assertEqual( a.a1(), 17 )
+ self.assertEqual( a.get_n(), 17 )
a.a5(-5)
- self.assertEqual( a.a1(), -5 )
+ self.assertEqual( a.get_n(), -5 )
a.a5(0x7fffffff)
- self.assertEqual( a.a1(), 0x7fffffff )
+ self.assertEqual( a.get_n(), 0x7fffffff )
a.a5(-0x80000000)
- self.assertEqual( a.a1(), -0x80000000 )
+ self.assertEqual( a.get_n(), -0x80000000 )
self.assertEqual( a.a3("a"), 1 )
+ self.assertEqual( a.a3(ObjectWithStr("abcde")), 5 ) # implicitly using to_s for string conversion
self.assertEqual( a.a3("ab"), 2 )
self.assertEqual( a.a3("µ"), 2 ) # two UTF8 bytes
if "a3_qstr" in a.__dict__:
@@ -249,7 +256,7 @@ class BasicTest(unittest.TestCase):
self.assertEqual( pya.A.instance_count(), ic0 )
a = pya.A.new_a( 55 )
self.assertEqual( pya.A.instance_count(), ic0 + 1 )
- self.assertEqual( a.a1(), 55 )
+ self.assertEqual( a.get_n(), 55 )
self.assertEqual( a.a_vp1( a.a_vp2() ), "abc" )
a.destroy()
self.assertEqual( pya.A.instance_count(), ic0 )
@@ -403,9 +410,9 @@ class BasicTest(unittest.TestCase):
a = pya.A.new_a_by_variant()
self.assertEqual(pya.A.instance_count(), ic0 + 1)
- self.assertEqual(a.a1(), 17)
+ self.assertEqual(a.get_n(), 17)
a.a5(-15)
- self.assertEqual(a.a1(), -15)
+ self.assertEqual(a.get_n(), -15)
a = None
self.assertEqual(pya.A.instance_count(), ic0)
@@ -422,6 +429,85 @@ class BasicTest(unittest.TestCase):
b._destroy()
self.assertEqual(pya.B.instance_count(), ic0)
+ def test_11(self):
+
+ # implicitly converting tuples/lists to objects by calling the constructor
+
+ b = pya.B()
+ b.av_cptr = [ pya.A(17), [1,2], [4,6,0.5] ]
+
+ arr = []
+ for a in b.each_a():
+ arr.append(a.get_n_const())
+ self.assertEqual(arr, [17, 3, 5])
+
+ b = pya.B()
+ # NOTE: this gives an error (printed only) that tuples can't be modified as out parameters
+ b.av_ref = ( (1,2), (6,2,0.25), [42] )
+
+ arr = []
+ for a in b.each_a():
+ arr.append(a.get_n_const())
+ self.assertEqual(arr, [3, 2, 42])
+
+ b = pya.B()
+ aa = [ (1,2), (6,2,0.25), [42] ]
+ b.av_ptr = aa
+
+ arr = []
+ for a in b.each_a():
+ arr.append(a.get_n_const())
+ self.assertEqual(arr, [3, 2, 42])
+
+ # NOTE: as we used aa in "av_ptr", it got modified as out parameter and
+ # now holds A object references
+ arr = []
+ for a in aa:
+ arr.append(a.get_n_const())
+ self.assertEqual(arr, [3, 2, 42])
+
+ b.av = ()
+
+ arr = []
+ for a in b.each_a():
+ arr.append(a.get_n_const())
+ self.assertEqual(arr, [])
+
+ b.push_a_ref( (1, 7) )
+
+ arr = []
+ for a in b.each_a():
+ arr.append(a.get_n_const())
+ self.assertEqual(arr, [8])
+
+ b.push_a_ptr( (1, 7, 0.25) )
+
+ arr = []
+ for a in b.each_a():
+ arr.append(a.get_n_const())
+ self.assertEqual(arr, [8, 2])
+
+ b.push_a_cref( [42] )
+
+ arr = []
+ for a in b.each_a():
+ arr.append(a.get_n_const())
+ self.assertEqual(arr, [8, 2, 42])
+
+ b.push_a_cptr( (1, 16) )
+
+ arr = []
+ for a in b.each_a():
+ arr.append(a.get_n_const())
+ self.assertEqual(arr, [8, 2, 42, 17])
+
+ b.push_a( (4, 6, 0.5) )
+
+ arr = []
+ for a in b.each_a():
+ arr.append(a.get_n_const())
+ self.assertEqual(arr, [8, 2, 42, 17, 5])
+
def test_12(self):
a1 = pya.A()
@@ -429,16 +515,16 @@ class BasicTest(unittest.TestCase):
a2 = a1
a3 = a2.dup()
- self.assertEqual( a1.a1(), -15 )
- self.assertEqual( a2.a1(), -15 )
- self.assertEqual( a3.a1(), -15 )
+ self.assertEqual( a1.get_n(), -15 )
+ self.assertEqual( a2.get_n(), -15 )
+ self.assertEqual( a3.get_n(), -15 )
a1.a5( 11 )
a3.a5( -11 )
- self.assertEqual( a1.a1(), 11 )
- self.assertEqual( a2.a1(), 11 )
- self.assertEqual( a3.a1(), -11 )
+ self.assertEqual( a1.get_n(), 11 )
+ self.assertEqual( a2.get_n(), 11 )
+ self.assertEqual( a3.get_n(), -11 )
self.assertEqual( a1.a10_d(5.2), "5.2" )
self.assertEqual( a1.a10_s(0x70000000), "0" )
@@ -651,7 +737,7 @@ class BasicTest(unittest.TestCase):
err_caught = False
try:
- b.amember_cptr().a1() # cannot call non-const method on const reference
+ b.amember_cptr().get_n() # cannot call non-const method on const reference
except:
err_caught = True
self.assertEqual( err_caught, True )
@@ -675,7 +761,7 @@ class BasicTest(unittest.TestCase):
try:
for a in b.b10():
- arr.append(a.a1()) # b10 is a const iterator - cannot call a1 on it
+ arr.append(a.get_n()) # b10 is a const iterator - cannot call a1 on it
except:
err_caught = True
self.assertEqual( err_caught, True )
@@ -687,7 +773,7 @@ class BasicTest(unittest.TestCase):
try:
for a in b.b10p():
- arr.append(a.a1()) # b10p is a const iterator - cannot call a1 on it
+ arr.append(a.get_n()) # b10p is a const iterator - cannot call a1 on it
except:
err_caught = True
self.assertEqual( err_caught, True )
@@ -695,7 +781,7 @@ class BasicTest(unittest.TestCase):
arr = []
for a in b.b10():
- arr.append(a.dup().a1())
+ arr.append(a.dup().get_n())
self.assertEqual(arr, [100, 121, 144])
arr = []
@@ -706,99 +792,99 @@ class BasicTest(unittest.TestCase):
# destroyed too early.
bdup = b.dup()
for a in bdup.b10():
- arr.append(a.dup().a1())
+ arr.append(a.dup().get_n())
self.assertEqual(arr, [100, 121, 144])
return
arr = []
for a in b.b10():
- arr.append(a.a1c())
+ arr.append(a.get_n_const())
self.assertEqual(arr, [100, 121, 144])
arr = []
for a in b.b10p():
- arr.append(a.dup().a1())
+ arr.append(a.dup().get_n())
self.assertEqual(arr, [100, 121, 144])
arr = []
# Ticket #811:
for a in b.dup().b10p():
- arr.append(a.dup().a1())
+ arr.append(a.dup().get_n())
self.assertEqual(arr, [100, 121, 144])
arr = []
bdup = b.dup()
for a in bdup.b10p():
- arr.append(a.dup().a1())
+ arr.append(a.dup().get_n())
self.assertEqual(arr, [100, 121, 144])
arr = []
for a in b.b10p():
- arr.append(a.a1c())
+ arr.append(a.get_n_const())
self.assertEqual(arr, [100, 121, 144])
arr = []
for a in b.b11():
- arr.append(a.a1())
+ arr.append(a.get_n())
self.assertEqual(arr, [100, 121, 144])
arr = []
bdup = b.dup()
for a in bdup.b11():
- arr.append(a.a1())
+ arr.append(a.get_n())
self.assertEqual(arr, [100, 121, 144])
arr = []
for a in b.b12():
- arr.append(a.a1())
+ arr.append(a.get_n())
self.assertEqual(arr, [7100, 7121, 7144, 7169])
arr = []
bdup = b.dup()
for a in bdup.b12():
- arr.append(a.a1())
+ arr.append(a.get_n())
self.assertEqual(arr, [7100, 7121, 7144, 7169])
aarr = b.b16a()
arr = []
for a in aarr:
- arr.append(a.a1())
+ arr.append(a.get_n())
self.assertEqual(arr, [100, 121, 144])
aarr = b.b16b()
arr = []
for a in aarr:
- arr.append(a.a1())
+ arr.append(a.get_n())
self.assertEqual(arr, [100, 121, 144])
aarr = b.b16c()
arr = []
for a in aarr:
- arr.append(a.a1())
+ arr.append(a.get_n())
self.assertEqual(arr, [100, 121, 144])
b.b17a( [ pya.A.new_a( 101 ), pya.A.new_a( -122 ) ] )
arr = []
for a in b.b11():
- arr.append(a.a1())
+ arr.append(a.get_n())
self.assertEqual(arr, [101, -122])
b.b17a( [] )
arr = []
for a in b.b11():
- arr.append(a.a1())
+ arr.append(a.get_n())
self.assertEqual(arr, [])
b.b17b( [ pya.A.new_a( 102 ), pya.A.new_a( -123 ) ] )
arr = []
for a in b.b11():
- arr.append(a.a1())
+ arr.append(a.get_n())
self.assertEqual(arr, [102, -123])
b.b17c( [ pya.A.new_a( 100 ), pya.A.new_a( 121 ), pya.A.new_a( 144 ) ] )
arr = []
for a in b.b11():
- arr.append(a.a1())
+ arr.append(a.get_n())
self.assertEqual(arr, [100, 121, 144])
if not leak_check:
@@ -806,7 +892,7 @@ class BasicTest(unittest.TestCase):
arr = []
try:
for a in b.b13():
- arr.append(a.a1())
+ arr.append(a.get_n())
except:
err_caught = True
self.assertEqual( err_caught, True )
@@ -814,28 +900,28 @@ class BasicTest(unittest.TestCase):
arr = []
for a in b.b13():
- arr.append(a.a1c())
+ arr.append(a.get_n_const())
self.assertEqual(arr, [-3100, -3121])
arr = []
bdup = b.dup()
for a in bdup.b13():
- arr.append(a.a1c())
+ arr.append(a.get_n_const())
self.assertEqual(arr, [-3100, -3121])
arr = []
- for a in b.b18():
- arr.append(a.a1c())
+ for a in b.each_a():
+ arr.append(a.get_n_const())
self.assertEqual(arr, [100, 121, 144])
arr = []
- for a in b.b18():
- arr.append(a.a1())
+ for a in b.each_a():
+ arr.append(a.get_n())
self.assertEqual(arr, [100, 121, 144])
arr = []
- for a in b.b18b():
- arr.append(a.a1c())
+ for a in b.each_a_ref():
+ arr.append(a.get_n_const())
self.assertEqual(arr, [100, 121, 144])
arr = []
@@ -843,8 +929,8 @@ class BasicTest(unittest.TestCase):
# since A is a managed object and is not turned into a copy.
err_caught = False
try:
- for a in b.b18b():
- arr.append(a.a1())
+ for a in b.each_a_ref():
+ arr.append(a.get_n())
except:
err_caught = True
end
@@ -852,17 +938,17 @@ class BasicTest(unittest.TestCase):
self.assertEqual(err_caught, True)
arr = []
- for a in b.b18c():
- arr.append(a.a1c())
+ for a in b.each_a_ptr():
+ arr.append(a.get_n_const())
self.assertEqual(arr, [100, 121, 144])
arr = []
- # this does not work since b18c delivers a "const *" which cannot be used to call a non-const
+ # this does not work since each_a_ptr delivers a "const *" which cannot be used to call a non-const
# method on
err_caught = False
try:
- for a in b.b18c():
- arr.append(a.a1())
+ for a in b.each_a_ptr():
+ arr.append(a.get_n())
except:
err_caught = True
end
@@ -1035,23 +1121,23 @@ class BasicTest(unittest.TestCase):
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( a.get_n(), 1971 );
self.assertEqual( b.an( a ), 1971 );
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( a.get_n(), 1971 );
self.assertEqual( b.an( a ), 1971 );
- self.assertEqual( aa.a1(), -61 );
+ self.assertEqual( aa.get_n(), -61 );
self.assertEqual( b.an( aa ), -61 );
aa.a5(98);
a.a5(100);
- self.assertEqual( a.a1(), 100 );
+ self.assertEqual( a.get_n(), 100 );
self.assertEqual( b.an( a ), 100 );
- self.assertEqual( aa.a1(), 98 );
+ self.assertEqual( aa.get_n(), 98 );
self.assertEqual( b.an( aa ), 98 );
a._destroy()
@@ -1064,10 +1150,10 @@ class BasicTest(unittest.TestCase):
b = pya.B()
b.set_an( 77 )
- self.assertEqual( b.amember_cptr().a1c(), 77 );
+ self.assertEqual( b.amember_cptr().get_n_const(), 77 );
b.set_an_cref( 79 )
- self.assertEqual( b.amember_cptr().a1c(), 79 );
+ self.assertEqual( b.amember_cptr().get_n_const(), 79 );
aref = b.amember_cptr()
err_caught = False
@@ -1075,14 +1161,14 @@ class BasicTest(unittest.TestCase):
if not leak_check:
try:
- x = aref.a1() # cannot call non-const method on const reference (as delivered by amember_cptr)
+ x = aref.get_n() # 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 );
+ self.assertEqual( aref.get_n_const(), 79 );
b.set_an( -1 )
- self.assertEqual( aref.a1c(), -1 );
+ self.assertEqual( aref.get_n_const(), -1 );
def test_19(self):
@@ -1140,11 +1226,11 @@ class BasicTest(unittest.TestCase):
a1 = b.amember_or_nil_alt( True )
a2 = b.amember_ptr_alt()
- self.assertEqual( a1.a1(), 17 )
- self.assertEqual( a2.a1(), 17 )
+ self.assertEqual( a1.get_n(), 17 )
+ self.assertEqual( a2.get_n(), 17 )
a1.a5( 761 )
- self.assertEqual( a1.a1(), 761 )
- self.assertEqual( a2.a1(), 761 )
+ self.assertEqual( a1.get_n(), 761 )
+ self.assertEqual( a2.get_n(), 761 )
a1 = b.amember_or_nil( False )
self.assertEqual( a1, None )
@@ -2279,13 +2365,8 @@ class BasicTest(unittest.TestCase):
self.assertEqual(b.map1_cptr_null() == None, True);
self.assertEqual(b.map1_ptr_null() == None, True);
- try:
- # error converting 1 or True to string
- b.map1 = { 42: 1, -17: True }
- error_caught = False
- except:
- error_caught = True
- self.assertEqual(error_caught, True)
+ b.map1 = { 42: 1, -17: True }
+ self.assertEqual(map2str(b.map1), "{-17: True, 42: 1}")
b.map1 = { 42: "1", -17: "True" }
self.assertEqual(map2str(b.map1), "{-17: True, 42: 1}")
diff --git a/testdata/ruby/basic_testcore.rb b/testdata/ruby/basic_testcore.rb
index 87f2f1e4b..6ca9cdd08 100644
--- a/testdata/ruby/basic_testcore.rb
+++ b/testdata/ruby/basic_testcore.rb
@@ -4,6 +4,19 @@
# safe in multiple inclusions
require File.expand_path('../basic_testcore_defs', __FILE__)
+
+class ObjectWithStr
+
+ def initialize(s)
+ @s = s
+ end
+
+ def to_s
+ @s
+ end
+
+end
+
class Basic_TestClass < TestBase
def test_FIRST
@@ -21,9 +34,9 @@ class Basic_TestClass < TestBase
assert_equal( RBA::A::instance_count, ic0 + 1 )
a = RBA::A.new
- assert_equal(a.a1, 17)
+ assert_equal(a.get_n, 17)
a.assign(RBA::A.new(110))
- assert_equal(a.a1, 110)
+ assert_equal(a.get_n, 110)
a = nil
GC.start
@@ -76,15 +89,16 @@ class Basic_TestClass < TestBase
assert_equal( RBA::A.aa, "static_a" )
assert_equal( a.aa, "a" )
- assert_equal( a.a1, 17 )
+ assert_equal( a.get_n, 17 )
a.a5 -5
- assert_equal( a.a1, -5 )
+ assert_equal( a.get_n, -5 )
a.a5 0x7fffffff
- assert_equal( a.a1, 0x7fffffff )
+ assert_equal( a.get_n, 0x7fffffff )
a.a5 -0x80000000
- assert_equal( a.a1, -0x80000000 )
+ assert_equal( a.get_n, -0x80000000 )
assert_equal( a.a3("a"), 1 )
+ assert_equal( a.a3(ObjectWithStr::new("abcde")), 5 ) # implicitly using to_s for string conversion
assert_equal( a.a3("ab"), 2 )
assert_equal( a.a3("µ"), 2 ) # two UTF8 bytes
if a.respond_to?(:a3_qstr)
@@ -142,7 +156,7 @@ class Basic_TestClass < TestBase
assert_equal( RBA::A::instance_count, ic0 )
a = RBA::A::new_a( 55 )
assert_equal( RBA::A::instance_count, ic0 + 1 )
- assert_equal( a.a1, 55 )
+ assert_equal( a.get_n, 55 )
assert_equal( a.a_vp1( a.a_vp2 ), "abc" )
a.destroy
assert_equal( RBA::A::instance_count, ic0 )
@@ -302,9 +316,9 @@ class Basic_TestClass < TestBase
a = RBA::A.new_a_by_variant
assert_equal(RBA::A::instance_count, ic0 + 1)
- assert_equal(a.a1, 17)
+ assert_equal(a.get_n, 17)
a.a5(-15)
- assert_equal(a.a1, -15)
+ assert_equal(a.get_n, -15)
a = nil
GC.start
@@ -327,6 +341,67 @@ class Basic_TestClass < TestBase
end
+ def test_11
+
+ # implicitly converting tuples/lists to objects by calling the constructor
+
+ b = RBA::B::new()
+ b.av_cptr = [ RBA::A::new(17), [1,2], [4,6,0.5] ]
+
+ arr = b.each_a.collect { |a| a.get_n_const }
+ assert_equal(arr, [17, 3, 5])
+
+ b = RBA::B::new()
+ # NOTE: this gives an error (printed only) that tuples can't be modified as out parameters
+ b.av_ref = [ [1,2], [6,2,0.25], [42] ]
+
+ arr = b.each_a.collect { |a| a.get_n_const }
+ assert_equal(arr, [3, 2, 42])
+
+ b = RBA::B::new()
+ aa = [ [1,2], [6,2,0.25], [42] ]
+ b.av_ptr = aa
+
+ arr = b.each_a.collect { |a| a.get_n_const }
+ assert_equal(arr, [3, 2, 42])
+
+ # NOTE: as we used aa in "av_ptr", it got modified as out parameter and
+ # now holds A object references
+ arr = b.each_a.collect { |a| a.get_n_const }
+ assert_equal(arr, [3, 2, 42])
+
+ b.av = []
+
+ arr = b.each_a.collect { |a| a.get_n_const }
+ assert_equal(arr, [])
+
+ b.push_a_ref([1, 7])
+
+ arr = b.each_a.collect { |a| a.get_n_const }
+ assert_equal(arr, [8])
+
+ b.push_a_ptr([1, 7, 0.25])
+
+ arr = b.each_a.collect { |a| a.get_n_const }
+ assert_equal(arr, [8, 2])
+
+ b.push_a_cref([42])
+
+ arr = b.each_a.collect { |a| a.get_n_const }
+ assert_equal(arr, [8, 2, 42])
+
+ b.push_a_cptr([1, 16])
+
+ arr = b.each_a.collect { |a| a.get_n_const }
+ assert_equal(arr, [8, 2, 42, 17])
+
+ b.push_a([4, 6, 0.5])
+
+ arr = b.each_a.collect { |a| a.get_n_const }
+ assert_equal(arr, [8, 2, 42, 17, 5])
+
+ end
+
def test_12
a1 = RBA::A.new
@@ -334,16 +409,16 @@ class Basic_TestClass < TestBase
a2 = a1
a3 = a2.dup
- assert_equal( a1.a1, -15 )
- assert_equal( a2.a1, -15 )
- assert_equal( a3.a1, -15 )
+ assert_equal( a1.get_n, -15 )
+ assert_equal( a2.get_n, -15 )
+ assert_equal( a3.get_n, -15 )
a1.a5( 11 )
a3.a5( -11 )
- assert_equal( a1.a1, 11 )
- assert_equal( a2.a1, 11 )
- assert_equal( a3.a1, -11 )
+ assert_equal( a1.get_n, 11 )
+ assert_equal( a2.get_n, 11 )
+ assert_equal( a3.get_n, -11 )
assert_equal( a1.a10_s(0x70000000), "0" )
assert_equal( a1.a10_s(0x7fffffff), "-1" )
@@ -564,7 +639,7 @@ class Basic_TestClass < TestBase
err_caught = false
begin
- b.amember_cptr.a1 # cannot call non-const method on const reference
+ b.amember_cptr.get_n # cannot call non-const method on const reference
rescue
err_caught = true
end
@@ -590,7 +665,7 @@ class Basic_TestClass < TestBase
if !$leak_check
begin
- b.b10 { |a| arr.push(a.a1) } # b10 is a const iterator - cannot call a1 on it
+ b.b10 { |a| arr.push(a.get_n) } # b10 is a const iterator - cannot call a1 on it
rescue
err_caught = true
end
@@ -604,7 +679,7 @@ class Basic_TestClass < TestBase
if !$leak_check
begin
- b.b10p { |a| arr.push(a.a1) } # b10p is a const iterator - cannot call a1 on it
+ b.b10p { |a| arr.push(a.get_n) } # b10p is a const iterator - cannot call a1 on it
rescue
err_caught = true
end
@@ -614,85 +689,85 @@ class Basic_TestClass < TestBase
end
arr = []
- b.b10 { |a| arr.push(a.dup.a1) }
+ b.b10 { |a| arr.push(a.dup.get_n) }
assert_equal(arr, [100, 121, 144])
arr = []
- b.dup.b10 { |a| arr.push(a.dup.a1) }
+ b.dup.b10 { |a| arr.push(a.dup.get_n) }
assert_equal(arr, [100, 121, 144])
arr = []
- b.b10 { |a| arr.push(a.a1c) }
+ b.b10 { |a| arr.push(a.get_n_const) }
assert_equal(arr, [100, 121, 144])
arr = []
- b.b10p { |a| arr.push(a.dup.a1) }
+ b.b10p { |a| arr.push(a.dup.get_n) }
assert_equal(arr, [100, 121, 144])
arr = []
- b.dup.b10p { |a| arr.push(a.dup.a1) }
+ b.dup.b10p { |a| arr.push(a.dup.get_n) }
assert_equal(arr, [100, 121, 144])
arr = []
- b.b10p { |a| arr.push(a.a1c) }
+ b.b10p { |a| arr.push(a.get_n_const) }
assert_equal(arr, [100, 121, 144])
arr = []
- b.b11 { |a| arr.push(a.a1) }
+ b.b11 { |a| arr.push(a.get_n) }
assert_equal(arr, [100, 121, 144])
arr = []
- b.dup.b11 { |a| arr.push(a.a1) }
+ b.dup.b11 { |a| arr.push(a.get_n) }
assert_equal(arr, [100, 121, 144])
arr = []
- b.b12 { |a| arr.push(a.a1) }
+ b.b12 { |a| arr.push(a.get_n) }
assert_equal(arr, [7100, 7121, 7144, 7169])
arr = []
- b.dup.b12 { |a| arr.push(a.a1) }
+ b.dup.b12 { |a| arr.push(a.get_n) }
assert_equal(arr, [7100, 7121, 7144, 7169])
aarr = b.b16a
arr = []
- aarr.each { |a| arr.push(a.a1) }
+ aarr.each { |a| arr.push(a.get_n) }
assert_equal(arr, [100, 121, 144])
aarr = b.b16b
arr = []
- aarr.each { |a| arr.push(a.a1) }
+ aarr.each { |a| arr.push(a.get_n) }
assert_equal(arr, [100, 121, 144])
aarr = b.b16c
arr = []
- aarr.each { |a| arr.push(a.a1) }
+ aarr.each { |a| arr.push(a.get_n) }
assert_equal(arr, [100, 121, 144])
b.b17a( [ RBA::A.new_a( 101 ), RBA::A.new_a( -122 ) ] )
arr = []
- b.b11 { |a| arr.push(a.a1) }
+ b.b11 { |a| arr.push(a.get_n) }
assert_equal(arr, [101, -122])
b.b17a( [] )
arr = []
- b.b11 { |a| arr.push(a.a1) }
+ b.b11 { |a| arr.push(a.get_n) }
assert_equal(arr, [])
b.b17b( [ RBA::A.new_a( 102 ), RBA::A.new_a( -123 ) ] )
arr = []
- b.b11 { |a| arr.push(a.a1) }
+ b.b11 { |a| arr.push(a.get_n) }
assert_equal(arr, [102, -123])
b.b17c( [ RBA::A.new_a( 100 ), RBA::A.new_a( 121 ), RBA::A.new_a( 144 ) ] )
arr = []
- b.b11 { |a| arr.push(a.a1) }
+ b.b11 { |a| arr.push(a.get_n) }
assert_equal(arr, [100, 121, 144])
if !$leak_check
arr = []
begin
- b.b13 { |a| arr.push(a.a1) }
+ b.b13 { |a| arr.push(a.get_n) }
rescue
err_caught = true
end
@@ -702,31 +777,31 @@ class Basic_TestClass < TestBase
end
arr = []
- b.b13 { |a| arr.push(a.a1c) }
+ b.b13 { |a| arr.push(a.get_n_const) }
assert_equal(arr, [-3100, -3121])
arr = []
- b.dup.b13 { |a| arr.push(a.a1c) }
+ b.dup.b13 { |a| arr.push(a.get_n_const) }
assert_equal(arr, [-3100, -3121])
arr = []
- b.b18 { |a| arr.push(a.a1c) }
+ b.each_a { |a| arr.push(a.get_n_const) }
assert_equal(arr, [100, 121, 144])
arr = []
- b.b18 { |a| arr.push(a.a1) }
+ b.each_a { |a| arr.push(a.get_n) }
assert_equal(arr, [100, 121, 144])
arr = []
- b.b18b { |a| arr.push(a.a1c) }
+ b.each_a_ref { |a| arr.push(a.get_n_const) }
assert_equal(arr, [100, 121, 144])
arr = []
- # even though b18b returns a "const A &", calling a non-const method does not work
+ # even though each_a_ref returns a "const A &", calling a non-const method does not work
# since A is a managed object and is not turned into a copy.
err_caught = false
begin
- b.b18b { |a| arr.push(a.a1) }
+ b.each_a_ref { |a| arr.push(a.get_n) }
rescue
err_caught = true
end
@@ -734,15 +809,15 @@ class Basic_TestClass < TestBase
assert_equal(err_caught, true)
arr = []
- b.b18c { |a| arr.push(a.a1c) }
+ b.each_a_ptr { |a| arr.push(a.get_n_const) }
assert_equal(arr, [100, 121, 144])
arr = []
- # this does not work since b18c delivers a "const *" which cannot be used to call a non-const
+ # this does not work since each_a_ptr delivers a "const *" which cannot be used to call a non-const
# method on
err_caught = false
begin
- b.b18c { |a| arr.push(a.a1) }
+ b.each_a_ptr { |a| arr.push(a.get_n) }
rescue
err_caught = true
end
@@ -952,23 +1027,23 @@ class Basic_TestClass < TestBase
a = b.make_a( 1971 );
assert_equal( RBA::A.instance_count, a_count + 1 )
- assert_equal( a.a1, 1971 );
+ assert_equal( a.get_n, 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( a.get_n, 1971 );
assert_equal( b.an( a ), 1971 );
- assert_equal( aa.a1, -61 );
+ assert_equal( aa.get_n, -61 );
assert_equal( b.an( aa ), -61 );
aa.a5 98;
a.a5 100;
- assert_equal( a.a1, 100 );
+ assert_equal( a.get_n, 100 );
assert_equal( b.an( a ), 100 );
- assert_equal( aa.a1, 98 );
+ assert_equal( aa.get_n, 98 );
assert_equal( b.an( aa ), 98 );
a._destroy
@@ -984,10 +1059,10 @@ class Basic_TestClass < TestBase
b = RBA::B.new
b.set_an( 77 )
- assert_equal( b.amember_cptr.a1c, 77 );
+ assert_equal( b.amember_cptr.get_n_const, 77 );
b.set_an_cref( 79 )
- assert_equal( b.amember_cptr.a1c, 79 );
+ assert_equal( b.amember_cptr.get_n_const, 79 );
aref = b.amember_cptr
err_caught = false
@@ -995,17 +1070,17 @@ class Basic_TestClass < TestBase
if !$leak_check
begin
- x = aref.a1 # cannot call non-const method on const reference (as delivered by amember_cptr)
+ x = aref.get_n # cannot call non-const method on const reference (as delivered by amember_cptr)
rescue
err_caught = true
end
assert_equal( err_caught, true )
- assert_equal( aref.a1c, 79 );
+ assert_equal( aref.get_n_const, 79 );
end
b.set_an( -1 )
- assert_equal( aref.a1c, -1 );
+ assert_equal( aref.get_n_const, -1 );
end
@@ -1095,11 +1170,11 @@ class Basic_TestClass < TestBase
a1 = b.amember_or_nil( true )
a2 = b.amember_ptr
- assert_equal( a1.a1, 17 )
- assert_equal( a2.a1, 17 )
+ assert_equal( a1.get_n, 17 )
+ assert_equal( a2.get_n, 17 )
a1.a5( 761 )
- assert_equal( a1.a1, 761 )
- assert_equal( a2.a1, 761 )
+ assert_equal( a1.get_n, 761 )
+ assert_equal( a2.get_n, 761 )
a1 = b.amember_or_nil( false )
assert_equal( a1, nil )
@@ -2198,19 +2273,9 @@ class Basic_TestClass < TestBase
assert_equal(b.map1_cptr_null == nil, true);
assert_equal(b.map1_ptr_null == nil, true);
- begin
- b.map1 = { 42 => 1, -17 => true }
- error = nil
- rescue => ex
- error = ex.message.split("\n")[0]
- end
- if error == "can't convert Fixnum into String"
- # Ok
- elsif error == "no implicit conversion of Fixnum into String" || error == "no implicit conversion of Integer into String"
- # Ok
- else
- assert_equal(error, "")
- end
+ b.map1 = { 42 => 1, -17 => true }
+ assert_equal(b.map1.inspect, "{-17=>\"true\", 42=>\"1\"}")
+
b.map1 = { 42 => "1", -17 => "true" }
assert_equal(b.map1.inspect, "{-17=>\"true\", 42=>\"1\"}")
@@ -2985,7 +3050,7 @@ class Basic_TestClass < TestBase
assert_equal(RBA::B::int_to_optional(1, true), 1)
assert_equal(RBA::B::int_to_optional(1, false), nil)
- assert_equal(RBA::B::int_to_optional_a(1, true).a1, 1)
+ assert_equal(RBA::B::int_to_optional_a(1, true).get_n, 1)
assert_equal(RBA::B::int_to_optional_a(1, false), nil)
assert_equal(RBA::B::optional_to_int(1, -1), 1)