fix: le .exe Windows demarrait sans plugin de plateforme Qt

Le hook PySide6 de PyInstaller importe QtCore pour localiser les plugins Qt.
Depuis Qt 6.10, Qt6Core.dll est lie a l'ICU de Windows (icuuc.dll, System32),
que Wine n'implemente pas : l'import echouait, le hook ne collectait aucun
plugin, et le binaire produit refusait de demarrer sous Windows avec
« could not initialize Qt platform plugin "windows" ».

- La build Wine epingle PySide6<6.10 (PYSIDE6_CONSTRAINT pour surcharger).
- Verification avant compilation que PySide6 s'importe reellement.
- Verification apres compilation que qwindows.dll est embarque.
- Reinstallation des dependances declenchee par empreinte de requirements.txt
  et de la contrainte, au lieu de la seule presence de PyInstaller.

Binaire verifie sous Wine : GUI (fenetre a trois onglets) et CLI OK, 45 Mo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-08 22:46:00 +02:00
co-authored by Claude Opus 5
parent 599192fd67
commit 59b6c75942
3 changed files with 59 additions and 7 deletions
+16
View File
@@ -1,5 +1,21 @@
# Changelog
## [Non publié]
### Fixed
- Le binaire Windows produit sous Wine ne démarrait pas (« could not initialize
Qt platform plugin "windows" ») : le hook PySide6 de PyInstaller importe
QtCore pour localiser les plugins Qt, or Qt 6.10+ lie `Qt6Core.dll` à l'ICU
de Windows (`icuuc.dll`), absent de Wine. L'import échouait et aucun plugin
n'était embarqué. La compilation Windows épingle désormais `PySide6<6.10` et
vérifie explicitement l'import de PySide6 puis la présence de `qwindows.dll`.
### Added
- `Makefile` avec aide auto-documentée par catégories (`make help`).
- `packaging/build_windows_wine.sh` : production du `.exe` Windows depuis Linux.
- `README.md`.
- `make publish` : pousse branche et tags vers tous les dépôts Gitea configurés.
## [0.1.2] - 2026-09-04
### Changed
+8 -3
View File
@@ -82,9 +82,14 @@ incrémentaux.
Sur une machine Windows, `packaging/build_windows.bat` fait le même travail
nativement.
> Le `.exe` s'appuie sur l'ICU fourni par le système (`icuuc.dll` dans
> `System32`), présent depuis Windows 10 1703 et Windows Server 2019. Il ne
> peut pas être testé sous Wine, qui ne fournit pas cette bibliothèque.
La build Wine épingle **Qt 6.9** (`PySide6<6.10`) : à partir de Qt 6.10,
`Qt6Core.dll` dépend de l'ICU fourni par Windows (`icuuc.dll` dans `System32`),
que Wine n'implémente pas. PySide6 y devient inimportable — et le hook PySide6
de PyInstaller, qui importe QtCore pour localiser les plugins Qt, échoue alors
*silencieusement* et produit un `.exe` sans plugin de plateforme, qui refuse de
démarrer sous Windows (« could not initialize Qt platform plugin windows »). Le
script vérifie donc, avant compilation, que PySide6 s'importe, et après
compilation, que `qwindows.dll` est bien embarqué.
## Publication
+35 -4
View File
@@ -11,6 +11,13 @@ set -euo pipefail
cd "$(dirname "$0")/.."
PYTHON_VERSION="${PYTHON_VERSION:-3.12.10}"
# Depuis Qt 6.10, Qt6Core.dll est lie a l'ICU fourni par Windows (icuuc.dll dans
# System32, present depuis Win10 1703). Wine ne fournit pas cette DLL : PySide6
# y devient inimportable, et le hook PySide6 de PyInstaller -- qui importe QtCore
# pour localiser les plugins Qt -- echoue alors SILENCIEUSEMENT et produit un
# .exe depourvu de plugin de plateforme ("could not initialize Qt platform
# plugin windows" au lancement). On contraint donc cette build a Qt 6.9.
PYSIDE6_CONSTRAINT="${PYSIDE6_CONSTRAINT:-PySide6<6.10}"
WINEPREFIX="${WINEPREFIX:-$PWD/.build-wine}"
export WINEPREFIX
export WINEARCH=win64
@@ -52,13 +59,30 @@ if [ ! -f "$PY_DIR/Scripts/pip.exe" ]; then
fi
# pip sous Wine est lent (plusieurs minutes pour le wheel PySide6) : on ne
# reinstalle que si le prefixe est neuf. FORCE_DEPS=1 pour forcer une mise a jour.
if [ ! -d "$PY_DIR/Lib/site-packages/PyInstaller" ] || [ "${FORCE_DEPS:-0}" = "1" ]; then
# reinstalle que si requirements.txt ou la contrainte ont change (FORCE_DEPS=1
# pour forcer).
DEPS_STAMP="$PY_DIR/.deps-stamp"
WANT_HASH="$(cat requirements.txt <(echo "$PYSIDE6_CONSTRAINT") | sha256sum | cut -d' ' -f1)"
if [ "${FORCE_DEPS:-0}" = "1" ] || [ "$(cat "$DEPS_STAMP" 2>/dev/null)" != "$WANT_HASH" ]; then
echo ">> Installation des dependances Windows (peut prendre plusieurs minutes)"
printf '%s\n' "$PYSIDE6_CONSTRAINT" > "$PY_DIR/constraints.txt"
# Desinstallation prealable : pip ne retrograde pas toujours un paquet deja
# installe qui viole une contrainte nouvellement ajoutee.
wine "$WPY" -m pip uninstall -q -y PySide6 PySide6-Essentials PySide6-Addons shiboken6 >/dev/null 2>&1 || true
wine "$WPY" -m pip install -q --no-warn-script-location \
-r requirements.txt pyinstaller
-c c:\\python\\constraints.txt -r requirements.txt pyinstaller
echo "$WANT_HASH" > "$DEPS_STAMP"
else
echo ">> Dependances Windows deja presentes (FORCE_DEPS=1 pour les mettre a jour)"
echo ">> Dependances Windows a jour (FORCE_DEPS=1 pour les reinstaller)"
fi
# Garde-fou : si PySide6 ne s'importe pas ici, le hook PyInstaller ne collectera
# aucun plugin Qt et produira un .exe casse sans le signaler. Echouer tot.
echo ">> Verification de PySide6 sous Wine"
if ! wine "$WPY" -c "import PySide6.QtWidgets" 2>&1; then
echo "ERREUR : PySide6 n'est pas importable sous Wine — le .exe produit serait" >&2
echo " depourvu de plugins Qt. Verifiez PYSIDE6_CONSTRAINT." >&2
exit 1
fi
echo ">> Compilation du .exe"
@@ -73,6 +97,13 @@ wine "$WPY" -m PyInstaller \
main.py
wineserver -w
# Garde-fou : sans qwindows.dll, l'application refuse de demarrer sous Windows.
if ! grep -qi 'qwindows.dll' build/windows/JoinDomainGUI/PKG-00.toc; then
echo "ERREUR : le plugin de plateforme qwindows.dll est absent du binaire." >&2
exit 1
fi
echo
echo "Binaire produit : dist/windows/JoinDomainGUI.exe"
echo "Lancement : clic droit -> Executer en tant qu'administrateur"