Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
119 changes: 82 additions & 37 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,43 @@ jobs:
with:
key: ${{ runner.os }}-ubuntu-${{ matrix.container_version }}
evict-old-files: 'job'

- name: Build PythonQt

- name: Build PythonQt (generator_only)
run: |
export QT_SELECT=qt5
echo ======= SYSTEM INFO ========
uname -a; gcc --version | grep "gcc"; qmake --version
echo ============================
qmake -r PythonQt.pro CONFIG+=ccache CONFIG+=release CONFIG+=force_debug_info \
CONFIG+=sanitizer CONFIG+=sanitize_undefined CONFIG+=sanitize_address \
CONFIG+=generator_only
make -j $(nproc)

- name: Generate Wrappers
run: |
# workaround to allow to find the Qt include dirs for installed standard qt packages
mkdir /usr/include/qt5; ln -s /usr/include/x86_64-linux-gnu/qt5 /usr/include/qt5/include
export QTDIR=/usr/include/qt5
cd generator
UBSAN_OPTIONS="halt_on_error=1" ASAN_OPTIONS="detect_leaks=0:detect_stack_use_after_return=1:fast_unwind_on_malloc=0" \
./pythonqt_generator

- name: Build PythonQt (exclude_generator)
run: |
export QT_SELECT=qt5
echo ======= SYSTEM INFO ========
uname -a; gcc --version | grep "gcc"; python3 --version; qmake --version
echo ============================
qmake -r PythonQt.pro CONFIG+=ccache CONFIG+=release CONFIG+=force_debug_info \
CONFIG+=sanitizer CONFIG+=sanitize_undefined CONFIG+=sanitize_address \
CONFIG+=exclude_generator \
PYTHON_VERSION=$(python3 --version | cut -d " " -f 2 | cut -d "." -f1,2) \
PYTHON_DIR=$(which python3 | xargs dirname | xargs dirname)
make -j $(nproc)
PYTHONDEVMODE=1 PYTHONASYNCIODEBUG=1 PYTHONWARNINGS=error PYTHONMALLOC=malloc_debug \
UBSAN_OPTIONS="halt_on_error=1" ASAN_OPTIONS="detect_leaks=0:detect_stack_use_after_return=1:fast_unwind_on_malloc=0" \
make check TESTARGS="-platform offscreen"

- name: Run memory tests with sanitizers
run: |
QT_VERSION_FULL=$(qmake -query QT_VERSION)
Expand Down Expand Up @@ -99,15 +120,6 @@ jobs:
PYTHONQT_RUN_ONLY_CLEANUP_TESTS=1 \
PYTHONQT_DISABLE_ASYNCIO=1 \
make check TESTARGS="-platform minimal"

- name: Generate Wrappers
run: |
# workaround to allow to find the Qt include dirs for installed standard qt packages
mkdir /usr/include/qt5; ln -s /usr/include/x86_64-linux-gnu/qt5 /usr/include/qt5/include
export QTDIR=/usr/include/qt5
cd generator
UBSAN_OPTIONS="halt_on_error=1" ASAN_OPTIONS="detect_leaks=0:detect_stack_use_after_return=1:fast_unwind_on_malloc=0" \
./pythonqt_generator

- name: Upload Wrappers
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -144,7 +156,25 @@ jobs:
- name: Checkout PythonQt
uses: actions/checkout@v5

- name: Build PythonQt
- name: Build PythonQt (generator_only)
run: |
export QT_SELECT=qt5
echo ======= SYSTEM INFO ========
uname -a; gcc --version | grep "gcc"; qmake-qt5 --version
echo ============================
qmake-qt5 -r PythonQt.pro CONFIG+=${{ matrix.configuration }} \
CONFIG+=generator_only
make -j $(nproc)

- name: Generate Wrappers
run: |
# workaround to allow to find the Qt include dirs for installed standard qt packages
mkdir /usr/include/qt5ln; ln -s /usr/include/qt5 /usr/include/qt5ln/include
export QTDIR=/usr/include/qt5ln
cd generator
./pythonqt_generator

- name: Build PythonQt (exclude_generator)
run: |
export QT_SELECT=qt5
echo ======= SYSTEM INFO ========
Expand All @@ -157,19 +187,12 @@ jobs:
echo PYTHON_VERSION_SHORT=${PYTHON_VERSION_SHORT}
echo PYTHON_DIR=${PYTHON_DIR}
qmake-qt5 -r PythonQt.pro CONFIG+=${{ matrix.configuration }} \
CONFIG+=exclude_generator \
"PYTHON_VERSION=${PYTHON_VERSION_SHORT}" "PYTHON_DIR=${PYTHON_DIR}"
make -j $(nproc) && \
PYTHONDEVMODE=1 PYTHONASYNCIODEBUG=1 PYTHONWARNINGS=error PYTHONMALLOC=malloc_debug \
make check TESTARGS="-platform offscreen"

- name: Generate Wrappers
run: |
# workaround to allow to find the Qt include dirs for installed standard qt packages
mkdir /usr/include/qt5ln; ln -s /usr/include/qt5 /usr/include/qt5ln/include
export QTDIR=/usr/include/qt5ln
cd generator
./pythonqt_generator

- name: Upload Wrappers
uses: actions/upload-artifact@v4
with:
Expand Down Expand Up @@ -235,7 +258,24 @@ jobs:
echo "MACOS_VERSION_FULL=$MACOS_VERSION_FULL" | tee -a $GITHUB_OUTPUT
echo "MACOS_VERSION_SHORT=$MACOS_VERSION_SHORT" | tee -a $GITHUB_OUTPUT

- name: Build PythonQt
- name: Build PythonQt (generator_only)
run: |
set -ue
echo ======= SYSTEM INFO ========
uname -a; gcc --version | head -n 1; qmake --version
echo ============================
qmake CONFIG+=ccache CONFIG+=${{ matrix.configuration }} CONFIG+=sanitizer CONFIG+=sanitize_undefined CONFIG+=sanitize_address \
CONFIG+=generator_only \
-r PythonQt.pro
make -j $(nproc)

- name: Generate Wrappers
run: |
cd generator
UBSAN_OPTIONS="halt_on_error=1" ASAN_OPTIONS="detect_leaks=0:detect_stack_use_after_return=1:fast_unwind_on_malloc=0" \
./pythonqt_generator

- name: Build PythonQt (exclude_generator)
run: |
set -ue
echo ======= SYSTEM INFO ========
Expand All @@ -246,6 +286,7 @@ jobs:
"python${PYTHON_VERSION_MAJOR}-embed" "python${PYTHON_VERSION_MAJOR}"
do if pkg-config --exists "$i"; then PYTHON_PKGCONFIG_NAME="$i"; break; fi; done
qmake CONFIG+=ccache CONFIG+=${{ matrix.configuration }} CONFIG+=sanitizer CONFIG+=sanitize_undefined CONFIG+=sanitize_address \
CONFIG+=exclude_generator \
PYTHON_VERSION=${{ steps.versions.outputs.PYTHON_VERSION_SHORT }} \
PYTHON_DIR="$pythonLocation" \
PKGCONFIG+=$PYTHON_PKGCONFIG_NAME \
Expand All @@ -255,13 +296,6 @@ jobs:
UBSAN_OPTIONS="halt_on_error=1" ASAN_OPTIONS="detect_leaks=0:detect_stack_use_after_return=1:fast_unwind_on_malloc=0" \
make check TESTARGS="-platform offscreen"

- name: Generate Wrappers
if: ${{ contains(matrix.configuration, 'release') }}
run: |
cd generator
UBSAN_OPTIONS="halt_on_error=1" ASAN_OPTIONS="detect_leaks=0:detect_stack_use_after_return=1:fast_unwind_on_malloc=0" \
./pythonqt_generator

- name: Upload Wrappers
if: ${{ contains(matrix.configuration, 'release') }}
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -351,13 +385,31 @@ jobs:
echo "QT_VERSION_SHORT=$QT_VERSION_SHORT" | tee -a $GITHUB_OUTPUT
echo "PYTHON_VERSION_SHORT=$PYTHON_VERSION_SHORT" | tee -a $GITHUB_OUTPUT

- name: Build PythonQt
- name: Build PythonQt (generator_only)
shell: cmd
run: |
qmake -query
qmake CONFIG+=release CONFIG-=debug_and_release CONFIG-=debug_and_release_target ^
CONFIG+=generator_only ^
PythonQt.pro
mingw32-make -j 2 ^
|| set CL=/MP && nmake

- name: Generate Wrappers
shell: cmd
run: |
cd generator
set QTDIR=%QT_ROOT_DIR%
pythonqt_generator

- name: Build PythonQt (exclude_generator)
shell: cmd
run: |
qmake -query
python --version
set PYTHONQTALL_CONFIG=${{ matrix.pythonqtall-config }}
qmake CONFIG+=release CONFIG-=debug_and_release CONFIG-=debug_and_release_target ^
CONFIG+=exclude_generator ^
"PYTHON_PATH=%pythonLocation%" ^
"PYTHON_VERSION=${{ steps.versions.outputs.PYTHON_VERSION_SHORT }}" ^
PythonQt.pro
Expand All @@ -367,13 +419,6 @@ jobs:
mingw32-make -j 2 && mingw32-make check "TESTARGS=-platform offscreen" ^
|| set CL=/MP && nmake && nmake check "TESTARGS=-platform offscreen"

- name: Generate Wrappers
shell: cmd
run: |
cd generator
set QTDIR=%QT_ROOT_DIR%
pythonqt_generator

- name: Upload Wrappers
if: (matrix.pythonqtall-config || '') == ''
uses: actions/upload-artifact@v4
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/build_latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
fail-fast: false
matrix:
os: ['ubuntu', 'windows']
qt-version: [ '5.12.*', '5.15.*', '6.9.*' ]
qt-version: [ '5.12.*', '5.15.*', '6.10.*' ]
python-version: [ '3.12' ]
runs-on: ${{ matrix.os }}-latest
steps:
Expand Down Expand Up @@ -98,28 +98,30 @@ jobs:
path: generated_cpp
if-no-files-found: error

- name: Build PythonQt Ubuntu
- name: Build PythonQt Ubuntu (exclude_generator)
if: ${{ matrix.os == 'ubuntu' }}
run: |
echo ======= SYSTEM INFO ========
uname -a; gcc --version | grep "gcc"; python3 --version; qmake --version
echo ============================
qmake -r PythonQt.pro CONFIG+=ccache CONFIG+=release CONFIG+=force_debug_info \
CONFIG+=sanitizer CONFIG+=sanitize_undefined CONFIG+=sanitize_address \
CONFIG+=exclude_generator \
PYTHON_VERSION=$(python3 --version | cut -d " " -f 2 | cut -d "." -f1,2) \
PYTHON_DIR=$(which python3 | xargs dirname | xargs dirname)
make -j $(nproc)
PYTHONDEVMODE=1 PYTHONASYNCIODEBUG=1 PYTHONWARNINGS=error PYTHONMALLOC=malloc_debug \
UBSAN_OPTIONS="halt_on_error=1" ASAN_OPTIONS="detect_leaks=0:detect_stack_use_after_return=1:fast_unwind_on_malloc=0" \
make check TESTARGS="-platform offscreen"

- name: Build PythonQt Windows
- name: Build PythonQt Windows (exclude_generator)
shell: cmd
if: ${{ matrix.os == 'windows' }}
run: |
qmake -query
python --version
qmake CONFIG+=release CONFIG-=debug_and_release CONFIG-=debug_and_release_target ^
CONFIG+=exclude_generator ^
"PYTHONQTALL_CONFIG=${{ matrix.pythonqtall-config }}" ^
"PYTHON_PATH=%pythonLocation%" ^
"PYTHON_VERSION=${{ steps.setenv.outputs.PYTHON_VERSION_SHORT }}" ^
Expand Down
20 changes: 19 additions & 1 deletion PythonQt.pro
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
TEMPLATE = subdirs

SUBDIRS = generator src extensions tests examples
# Define the full set of subdirectories, including the generator.
# This list is used as the default build target.
ALL_SUBDIRS = generator src extensions tests examples

tests.depends += src extensions
extensions.depends += src
examples.depends += src extensions

# The 'generator_only' config can be used to override the default.
CONFIG(generator_only) {
# If the generator_only config is set, override the SUBDIRS list
# to only include the generator.
SUBDIRS = generator
} else: CONFIG(exclude_generator) {
# If the 'generator_only' option is not present, but 'exclude_generator' is,
# then remove the generator from the default list.
SUBDIRS = $$ALL_SUBDIRS
SUBDIRS -= generator
} else {
# If neither special option is set, use the default build which includes everything.
SUBDIRS = $$ALL_SUBDIRS
}
63 changes: 33 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ see https://github.com/danmar/simplecpp. It is licensed under the `0BSDL` licens
see the `LICENSE` file in the generator/simplecpp directory.
Copyright (C) 2016-2023 simplecpp team

The generated wrappers are pre-generated and checked-in, so you only
need to build and run the generator when you want to build additional wrappers
or you want to upgrade/downgrade to another Qt version, but this requires
updating the typesystems as well.
Wrappers are **not** shipped pre-generated. You must run the generator to
create wrappers for your Qt version. The repository may keep a
single example tree (e.g., `generated_cpp_515`) only as a reference.

# Building

Expand All @@ -43,12 +42,6 @@ updating the typesystems as well.
Building PythonQt requires a couple of steps.
Follow these instructions in order to get a correctly built PythonQt runtime and Qt bindings.

### Recommendations

It is recommended to build the Qt bindings yourself instead of using the pregenerated ones.
This ensures the bindings are compatible with your Qt version.
Do not build `PythonQt.pro` directly because it will only use the pregenerated bindings!

### Environment

First, you need to set a couple of environment variables, which depend on your Python and Qt installation.
Expand Down Expand Up @@ -76,49 +69,59 @@ First, you need to set a couple of environment variables, which depend on your P

### Binding Generator

1. cd into the `generator` directory
2. Run qmake on `generator.pro`
1. Configure the generator at the top level

`qmake CONFIG+=Release generator.pro`
```bash
qmake CONFIG+=generator_only CONFIG+=Release PythonQt.pro
```

3. Make the generator
2. Build the generator

Use `nmake` for MSVC (Visual Studio; make sure to have the environment variables set for Visual Studio beforehand). Otherwise, use `make`.

4. Generate the bindings
3. Generate the bindings

We use the generator executable from step 3 to generate the bindings.
Use the generator executable from step 2 to generate the bindings.
The location of the generator executable can vary depending on your platform (the subdirectory is named after the current configuration, e.g., `release`).
On Windows, the generator is named `pythonqt_generator.exe`; on all other platforms, it is named `pythonqt_generator`.

`<generator-executable> qtscript_masterinclude.h build_all.txt`
```bash
<generator-executable> qtscript_masterinclude.h build_all.txt
```

### PythonQt Runtime

Next, we need the PythonQt runtime.
**Output location:** by default the generator emits to `../generated_cpp`
(relative to the build). You can override this with:

1. cd into the `src` directory
2. qmake `src.pro`
```bash
qmake PYTHONQT_GENERATED_PATH=/abs/path/to/generated_cpp
```

`qmake CONFIG+=Release src.pro`
#### qmake toggles (optional)

3. Make the runtime
* `CONFIG+=generator_only`: build only the wrapper generator.
* `CONFIG+=exclude_generator`: build everything **except** the generator.

Use `nmake` for MSVC (Visual Studio; make sure to have the environment variables set for Visual Studio beforehand). Otherwise, use `make`.
Use these to (1) build the generator, (2) run it to produce `generated_cpp`, then (3) build the rest without rebuilding the generator.

### Extensions

As a last step, we need to build the extensions.
### PythonQt Runtime

Next, build the runtime (and extensions) without the generator.

1. cd into `extensions`
2. qmake `extensions.pro`
1. Configure at the top level

`qmake CONFIG+=Release extensions.pro`
```
qmake CONFIG+=Release CONFIG+=exclude_generator PythonQt.pro
```

3. Make the extensions
2. Build

Use `nmake` for MSVC (Visual Studio; make sure to have the environment variables set for Visual Studio beforehand). Otherwise, use `make`.

> The build will fail early if wrappers are missing from `../generated_cpp`
> or the path specified via `PYTHONQT_GENERATED_PATH`.

After all these steps, you should now have a fully working PythonQt runtime and Qt bindings for your Python/Qt installation 🎉.

## MinGW
Expand Down
Loading
Loading