Skip to content

Commit 1e794e5

Browse files
authored
Several fixes and patches (#89)
* minor improvements in code and unit tests * disable warnings for deprecated declarations * add -Wpedantic and even -Werror for src, but relax some warnings * fix undefined behavior * fix memory leaks * use QT_NO_CAST_TO_ASCII to prevent incorrect behavior on non-Latin1 input * Improvements in build and CI: ** add parallel build ** add `make check` support ** fix `debug`/`release` builds ** force C++11 ** introduce UBSan into CI ** fixes for macOS build with clang ** add pkg-config support: if PKGCONFIG is set, skip old-style lookup (useful on Linux and macOS GHA, when `python-config` returns incorrect linkage options with missing `-Ldirs`) ** add macOS GHA CI
1 parent 8336c6f commit 1e794e5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+381
-188
lines changed

.github/workflows/build.yml

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ jobs:
5353
echo ======= SYSTEM INFO ========
5454
uname -a; gcc --version | grep "gcc"; python3 --version; qmake --version
5555
echo ============================
56-
qmake -r PythonQt.pro \
56+
qmake -r PythonQt.pro CONFIG+=release CONFIG+=sanitizer CONFIG+=sanitize_undefined \
5757
PYTHON_VERSION=$(python3 --version | cut -d " " -f 2 | cut -d "." -f1,2) \
5858
PYTHON_DIR=$(which python3 | xargs dirname | xargs dirname)
59-
make
59+
make -j 2 && make check TESTARGS="-platform offscreen"
6060
6161
- name: Generate Wrappers
6262
run: |
@@ -113,10 +113,10 @@ jobs:
113113
echo ======= SYSTEM INFO ========
114114
uname -a; gcc --version | grep "gcc"; python --version; qmake-qt5 --version
115115
echo ============================
116-
qmake-qt5 -r PythonQt.pro \
116+
qmake-qt5 -r PythonQt.pro CONFIG+=release \
117117
PYTHON_VERSION=$(python --version | cut -d " " -f 2 | cut -d "." -f1,2) \
118118
PYTHON_DIR=$(which python | xargs dirname | xargs dirname)
119-
make
119+
make -j 2 && make check TESTARGS="-platform offscreen"
120120
121121
- name: Generate Wrappers
122122
run: |
@@ -131,3 +131,86 @@ jobs:
131131
with:
132132
name: wrappers_centos7
133133
path: generated_cpp
134+
135+
macOS:
136+
strategy:
137+
fail-fast: false
138+
matrix:
139+
macos-version: ['10.15']
140+
python-version: ['2.7']
141+
qt-version: ['5.9.*']
142+
include:
143+
- macos-version: '11'
144+
python-version: '3.6'
145+
qt-version: '5.11.*'
146+
- macos-version: '12'
147+
python-version: '3.10'
148+
qt-version: '5.12.*'
149+
runs-on: macos-${{ matrix.macos-version }}
150+
steps:
151+
- name: Install Qt
152+
uses: jurplel/install-qt-action@v3
153+
with:
154+
aqtversion: '==2.1.*'
155+
version: ${{ matrix.qt-version }}
156+
host: 'mac'
157+
target: 'desktop'
158+
arch: 'clang_64'
159+
modules: 'qtscript'
160+
archives: 'qtmultimedia qtmacextras qtbase qttools'
161+
162+
- name: Setup Python ${{ matrix.python-version }}
163+
uses: actions/setup-python@v4
164+
with:
165+
python-version: '${{ matrix.python-version }}'
166+
167+
- name: Checkout PythonQt
168+
uses: actions/checkout@v3
169+
170+
- name: Detect exact versions
171+
id : versions
172+
run : |
173+
set -eu
174+
PYTHON_VERSION_FULL=$(python --version 2>&1 | cut -f 2 -d ' ')
175+
PYTHON_VERSION_SHORT=$(cut -f 1,2 -d . <<< $PYTHON_VERSION_FULL)
176+
QT_VERSION_FULL=$($Qt5_DIR/bin/qmake -query QT_VERSION)
177+
QT_VERSION_SHORT=$(cut -f 1,2 -d . <<< $QT_VERSION_FULL)
178+
MACOS_VERSION_FULL=$(sw_vers -productVersion)
179+
MACOS_VERSION_SHORT=$(cut -f 1,2 -d . <<< $MACOS_VERSION_FULL)
180+
181+
echo "PYTHON_VERSION_FULL=$PYTHON_VERSION_FULL" | tee -a $GITHUB_OUTPUT
182+
echo "PYTHON_VERSION_SHORT=$PYTHON_VERSION_SHORT" | tee -a $GITHUB_OUTPUT
183+
echo "QT_VERSION_FULL=$QT_VERSION_FULL" | tee -a $GITHUB_OUTPUT
184+
echo "QT_VERSION_SHORT=$QT_VERSION_SHORT" | tee -a $GITHUB_OUTPUT
185+
echo "MACOS_VERSION_FULL=$MACOS_VERSION_FULL" | tee -a $GITHUB_OUTPUT
186+
echo "MACOS_VERSION_SHORT=$MACOS_VERSION_SHORT" | tee -a $GITHUB_OUTPUT
187+
188+
- name: Build PythonQt
189+
run: |
190+
set -ue
191+
echo ======= SYSTEM INFO ========
192+
uname -a; gcc --version | head -n 1; python --version; qmake --version
193+
echo ============================
194+
PYTHON_VERSION_MAJOR=$(cut -d . -f1 <<< ${{ steps.versions.outputs.PYTHON_VERSION_SHORT }})
195+
for i in "python${{ steps.versions.outputs.PYTHON_VERSION_SHORT }}-embed" "python${{ steps.versions.outputs.PYTHON_VERSION_SHORT }}" \
196+
"python${PYTHON_VERSION_MAJOR}-embed" "python${PYTHON_VERSION_MAJOR}"
197+
do if pkg-config --exists "$i"; then PYTHON_PKGCONFIG_NAME="$i"; break; fi; done
198+
qmake CONFIG+=release CONFIG+=sanitizer CONFIG+=sanitize_undefined \
199+
PYTHON_VERSION=${{ steps.versions.outputs.PYTHON_VERSION_SHORT }} \
200+
PYTHON_DIR="$pythonLocation" \
201+
PKGCONFIG+=$PYTHON_PKGCONFIG_NAME \
202+
-r PythonQt.pro
203+
make -j 2 && make check TESTARGS="-platform offscreen"
204+
205+
- name: Generate Wrappers
206+
run: |
207+
cd generator
208+
# workaround to allow to find the Qt include dirs for installed standard qt packages
209+
QTDIR=-UNDEFINED- ./pythonqt_generator --include-paths=$Qt5_DIR/lib
210+
211+
- name: Upload Wrappers
212+
uses: actions/upload-artifact@v3
213+
with:
214+
name: wrappers_macos${{ steps.versions.outputs.MACOS_VERSION_SHORT }}_qt${{ steps.versions.outputs.QT_VERSION_SHORT }}
215+
path: generated_cpp
216+

PythonQt.pro

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
TEMPLATE = subdirs
22

3-
CONFIG += ordered
43
SUBDIRS = generator src extensions tests examples
4+
tests.depends += src extensions
5+
extensions.depends += src
6+
examples.depends += src extensions

build/common.prf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,5 @@ PYTHONQT_GENERATED_PATH = $$PWD/../generated_cpp
7272
VERSION = 3.2.0
7373

7474
win32: CONFIG += skip_target_version_ext
75-
unix: QMAKE_CXXFLAGS += -std=c++11
75+
unix: CONFIG += c++11
76+
gcc: QMAKE_CXXFLAGS += -Wno-deprecated-declarations

build/python.prf

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,27 @@ isEmpty( PYTHON_DIR ) {
1717
PYTHON_DIR=$${PYTHON_DIR}/
1818
}
1919

20-
message(Using Python version $${PYTHON_VERSION})
20+
PYTHON_VERSION_MAJOR=$$section(PYTHON_VERSION, ., 0, 0)
21+
PYTHON_VERSION_MINOR=$$section(PYTHON_VERSION, ., 1, 1)
2122

22-
macx {
23+
!equals(PYTHON_VERSION, $${PYTHON_VERSION_MAJOR}.$${PYTHON_VERSION_MINOR}) {
24+
error("Failed to parse PYTHON_VERSION:\"$$PYTHON_VERSION\"")
25+
} else {
26+
message(Using Python version $${PYTHON_VERSION})
27+
}
28+
29+
30+
# Python 2.x has problems:
31+
# 1) https://wiki.gentoo.org/wiki/Project:Python/Strict_aliasing
32+
# 2) deprecated implicit cast of string literals to char*
33+
equals(PYTHON_VERSION_MAJOR, 2):gcc:QMAKE_CXXFLAGS *= -fno-strict-aliasing -Wno-error=write-strings
34+
contains(PKGCONFIG, "python.*"){
35+
CONFIG += link_pkgconfig
36+
PYTHON_PKGCONFIG = $$member($$unique($$find(PKGCONFIG, "python.*")), 1, 1)
37+
# add rpath
38+
PYTHON_LIBDIR = $$system($$pkgConfigExecutable() --libs-only-L $$PYTHON_PKGCONFIG)
39+
QMAKE_RPATHDIR += $$replace(PYTHON_LIBDIR,-L,)
40+
} else:macx:isEmpty(PYTHON_DIR){
2341
# for macx you need to have the Python development kit installed as framework
2442
INCLUDEPATH += /System/Library/Frameworks/Python.framework/Headers
2543
LIBS += -F/System/Library/Frameworks -framework Python
@@ -52,15 +70,17 @@ macx {
5270
# make sure that you have installed a matching python-dev package.
5371

5472
PYTHON_CONFIG = $${PYTHON_DIR}/bin/python$${PYTHON_VERSION}-config
55-
system($${PYTHON_CONFIG} --embed --libs) {
56-
unix:LIBS += $$system($${PYTHON_CONFIG} --embed --libs)
57-
} else: unix:LIBS += $$system($${PYTHON_CONFIG} --libs)
58-
unix:QMAKE_CXXFLAGS += $$system($${PYTHON_CONFIG} --includes)
73+
PYTHON_CONFIG_OPTIONS_LIBS = --libs
74+
equals(PYTHON_VERSION_MAJOR, 3):!lessThan(PYTHON_VERSION_MINOR, 8) {
75+
# Since 3.8 `--embed` is needed
76+
PYTHON_CONFIG_OPTIONS_LIBS += --embed
77+
}
78+
LIBS += $$system($${PYTHON_CONFIG} $${PYTHON_CONFIG_OPTIONS_LIBS})
79+
QMAKE_CXXFLAGS += $$system($${PYTHON_CONFIG} --includes)
5980
PYTHON_LFLAGS = $$system($${PYTHON_CONFIG} --ldflags)
60-
unix:QMAKE_LFLAGS += $${PYTHON_LFLAGS}
81+
QMAKE_LFLAGS += $${PYTHON_LFLAGS}
6182
# add rpath
6283
PYTHON_LIBDIR = $$find(PYTHON_LFLAGS,-L.*)
63-
RPATH = -Wl,-rpath,
64-
PYTHON_RPATH = $$replace(PYTHON_LIBDIR,-L,$${RPATH})
65-
unix:QMAKE_LFLAGS += $${PYTHON_RPATH}
84+
PYTHON_RPATH = $$replace(PYTHON_LIBDIR,-L,)
85+
QMAKE_RPATHDIR += $$PYTHON_RPATH
6686
}

extensions/PythonQt_QtAll/PythonQt_QtAll.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,5 @@ namespace PythonQt_QtAll
117117
#ifdef PYTHONQT_WITH_UITOOLS
118118
PythonQt_init_QtUiTools(0);
119119
#endif
120-
};
121-
};
122-
123-
120+
}
121+
}

extensions/PythonQt_QtAll/PythonQt_QtAll.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,6 @@ namespace PythonQt_QtAll
4747
{
4848
//! initialize the Qt binding
4949
PYTHONQT_QTALL_EXPORT void init();
50-
};
50+
}
5151

5252
#endif
Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
# get external pythonqtall config or enable all by default
22

3+
isEmpty( PYTHONQTALL_CONFIG ) {
4+
PYTHONQTALL_CONFIG = $$(PYTHONQTALL_CONFIG)
5+
}
6+
37
isEmpty( PYTHONQTALL_CONFIG ) {
48
message("using default PythonQt_QtAll Configuration")
59
CONFIG += PythonQtCore
6-
CONFIG += PythonQtGui
7-
CONFIG += PythonQtSvg
8-
CONFIG += PythonQtSql
9-
CONFIG += PythonQtNetwork
10-
CONFIG += PythonQtOpengl
11-
CONFIG += PythonQtXml
12-
CONFIG += PythonQtXmlpatterns
13-
CONFIG += PythonQtMultimedia
14-
CONFIG += PythonQtQml
15-
CONFIG += PythonQtQuick
16-
CONFIG += PythonQtUiTools
10+
qtHaveModule(gui):qtHaveModule(widgets):CONFIG += PythonQtGui
11+
qtHaveModule(svg):CONFIG += PythonQtSvg
12+
qtHaveModule(sql):CONFIG += PythonQtSql
13+
qtHaveModule(network):CONFIG += PythonQtNetwork
14+
qtHaveModule(opengl):CONFIG += PythonQtOpengl
15+
qtHaveModule(xml):CONFIG += PythonQtXml
16+
qtHaveModule(xmlpatterns):CONFIG += PythonQtXmlpatterns
17+
qtHaveModule(multimedia):CONFIG += PythonQtMultimedia
18+
qtHaveModule(qml):CONFIG += PythonQtQml
19+
qtHaveModule(quick):CONFIG += PythonQtQuick
20+
qtHaveModule(uitools):CONFIG += PythonQtUiTools
1721

1822
qtHaveModule(webkit):CONFIG += PythonQtWebKit
1923
} else {
@@ -36,10 +40,10 @@ CONFIG += dll qt
3640
DEFINES += PYTHONQT_QTALL_EXPORTS
3741

3842
HEADERS += \
39-
PythonQt_QtAll.h
43+
$$PWD/PythonQt_QtAll.h
4044

4145
SOURCES += \
42-
PythonQt_QtAll.cpp
46+
$$PWD/PythonQt_QtAll.cpp
4347

4448
unix {
4549
CONFIG += create_pc create_prl no_install_prl
@@ -60,79 +64,81 @@ headers.path = /include
6064

6165
INSTALLS += target headers
6266

67+
defineTest(Xinclude) {
68+
f=$$PYTHONQT_GENERATED_PATH/$$1/$${1}.pri
69+
exists($$f):include($$f):export(HEADERS):export(SOURCES):export(DEFINES)
70+
71+
}
72+
73+
6374
PythonQtCore {
6475
DEFINES += PYTHONQT_WITH_CORE
65-
include ($$PYTHONQT_GENERATED_PATH/com_trolltech_qt_core/com_trolltech_qt_core.pri)
76+
Xinclude (com_trolltech_qt_core)
6677
}
6778

6879
PythonQtGui {
6980
DEFINES += PYTHONQT_WITH_GUI
70-
include ($$PYTHONQT_GENERATED_PATH/com_trolltech_qt_gui/com_trolltech_qt_gui.pri)
81+
Xinclude (com_trolltech_qt_gui)
7182
QT += gui widgets printsupport
7283
}
7384

7485
PythonQtSvg {
7586
DEFINES += PYTHONQT_WITH_SVG
76-
include ($$PYTHONQT_GENERATED_PATH/com_trolltech_qt_svg/com_trolltech_qt_svg.pri)
87+
Xinclude (com_trolltech_qt_svg)
7788
QT +=svg
7889
}
7990

8091
PythonQtSql {
8192
DEFINES += PYTHONQT_WITH_SQL
82-
include ($$PYTHONQT_GENERATED_PATH/com_trolltech_qt_sql/com_trolltech_qt_sql.pri)
93+
Xinclude (com_trolltech_qt_sql)
8394
QT += sql
8495
}
8596

8697
PythonQtNetwork {
8798
DEFINES += PYTHONQT_WITH_NETWORK
88-
include ($$PYTHONQT_GENERATED_PATH/com_trolltech_qt_network/com_trolltech_qt_network.pri)
99+
Xinclude (com_trolltech_qt_network)
89100
QT += network
90101
}
91102

92103
PythonQtOpengl {
93104
DEFINES += PYTHONQT_WITH_OPENGL
94-
PythonQtCore: include ($$PYTHONQT_GENERATED_PATH/com_trolltech_qt_opengl/com_trolltech_qt_opengl.pri)
95105
QT += opengl
96-
}
97-
98-
PythonQtXml {
99-
DEFINES += PYTHONQT_WITH_XML
100-
include ($$PYTHONQT_GENERATED_PATH/com_trolltech_qt_xml/com_trolltech_qt_xml.pri)
106+
PythonQtCore: Xinclude (com_trolltech_qt_opengl)
101107
QT += xml
102108
}
103109

104110
PythonQtXmlpatterns {
105111
DEFINES += PYTHONQT_WITH_XMLPATTERNS
106-
include ($$PYTHONQT_GENERATED_PATH/com_trolltech_qt_xmlpatterns/com_trolltech_qt_xmlpatterns.pri)
112+
Xinclude (com_trolltech_qt_xmlpatterns)
107113
QT += xmlpatterns
108114
}
109115

110116
PythonQtMultimedia {
111117
DEFINES += PYTHONQT_WITH_MULTIMEDIA
112-
include ($$PYTHONQT_GENERATED_PATH/com_trolltech_qt_multimedia/com_trolltech_qt_multimedia.pri)
113-
QT += multimedia multimediawidgets
118+
Xinclude (com_trolltech_qt_multimedia)
119+
QT += multimedia multimediawidgets
114120
}
115121

116122
PythonQtQml {
117123
DEFINES += PYTHONQT_WITH_QML
118-
include ($$PYTHONQT_GENERATED_PATH/com_trolltech_qt_qml/com_trolltech_qt_qml.pri)
124+
Xinclude (com_trolltech_qt_qml)
119125
QT += qml
120126
}
121127

122128
PythonQtQuick {
123129
DEFINES += PYTHONQT_WITH_QUICK
124-
include ($$PYTHONQT_GENERATED_PATH/com_trolltech_qt_quick/com_trolltech_qt_quick.pri)
130+
Xinclude (com_trolltech_qt_quick)
125131
QT += quick quickwidgets
126132
}
127133

128134
PythonQtUiTools {
129135
DEFINES += PYTHONQT_WITH_UITOOLS
130-
include ($$PYTHONQT_GENERATED_PATH/com_trolltech_qt_uitools/com_trolltech_qt_uitools.pri)
136+
Xinclude (com_trolltech_qt_uitools)
131137
QT += uitools
132138
}
133139

134140
PythonQtWebKit {
135141
DEFINES += PYTHONQT_WITH_WEBKIT
136-
include ($$PYTHONQT_GENERATED_PATH/com_trolltech_qt_webkit/com_trolltech_qt_webkit.pri)
142+
Xinclude (com_trolltech_qt_webkit)
137143
QT += webkit webkitwidgets
138144
}

generator/abstractmetabuilder.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,7 @@ int AbstractMetaBuilder::figureOutEnumValue(const QString &stringValue,
746746
AbstractMetaEnum *meta_enum,
747747
AbstractMetaFunction *meta_function)
748748
{
749+
Q_UNUSED(meta_function)
749750
if (stringValue.isEmpty())
750751
return oldValuevalue;
751752

@@ -1619,12 +1620,15 @@ AbstractMetaFunction *AbstractMetaBuilder::traverseFunction(FunctionModelItem fu
16191620

16201621
// If we where not able to translate the default argument make it
16211622
// reset all default arguments before this one too.
1622-
for (int i=0; i<first_default_argument; ++i)
1623+
for (int i=0; i<first_default_argument; ++i) {
16231624
meta_arguments[i]->setDefaultValueExpression(QString());
1625+
}
16241626

1625-
if (ReportHandler::debugLevel() == ReportHandler::FullDebug)
1626-
foreach(AbstractMetaArgument *arg, meta_arguments)
1627+
if (ReportHandler::debugLevel() == ReportHandler::FullDebug) {
1628+
foreach(AbstractMetaArgument *arg, meta_arguments) {
16271629
ReportHandler::debugFull(" - " + arg->toString());
1630+
}
1631+
}
16281632

16291633
return meta_function;
16301634
}
@@ -1944,6 +1948,7 @@ QString AbstractMetaBuilder::translateDefaultValue(ArgumentModelItem item, Abstr
19441948
AbstractMetaFunction *fnc, AbstractMetaClass *implementing_class,
19451949
int argument_index)
19461950
{
1951+
Q_UNUSED(type)
19471952
QString function_name = fnc->name();
19481953
QString class_name = implementing_class->name();
19491954

0 commit comments

Comments
 (0)