Produire Qt 4.8.7 sous Debian à partir de Debian 11
Les sources de QT 4.8.7 pour Linux sont accessibles sur Qt Downloads
Si le contexte et mes problèmes initiaux y compris mes états d'âme ne vous intéressent pas, passez directement au message suivant ... que j'écrirais demain, c'est à dire en fait l'année prochaine vu qu'on est le 31 décembre :pastaper:
Contexte
Parler de Qt4 peut sembler iconoclaste alors que Qt5 va lui aussi bientôt cessé d'être maintenu, mais je ne suis peut être pas le seul à avoir jeté l'éponge, fatigué de passer d'une version de QT à la suivante.
Lorsque j'ai commencé le développement de BoUML au début du millénaire en 2007, c'était sous Qt2, puis j'ai dû passé à Qt3, et ensuite à Qt4 (avec support Qt3) dans la douleur, et je me suis arrêté là quelque peu agacé par ces versions incompatibles les unes avec les autres. Même si les choses ne sont pas comparables, j'ai fait en sorte que toutes les versions de BoUML permettent de charger un modèle produit ou modifié avec n'importe qu'elle version antérieure, jusqu'au grand écart permettant à la version 11 faite en 2021 de lire un projet fait avec la version 1 de 2008 ! Et il en est de même au niveau de l'interface avec les plugs-outs, permettant à un vieux plug-out de fonctionner avec un BoUML plus récent.
L'abandon de Qt4 dans les distributions comme par exemple Debian 11 m’empêchait donc de produire BoUML dessus. Cependant il est par contre tout à fait possible d'exécuter sur une Debian 11 ou 12 la version de BoUML faite par exemple pour Debian 10 à partir du moment où on dispose aussi des librairies Qt utilisées, voir Comment utiliser BoUML 7.11 sous Debian à partir de Debian 11 Bullseye (amd64). Cela a aussi participé à ma décision d’arrêter le développement de BoUML, après 15 ans et 382 versions.
BoUML est sorti de ma vie, jusqu'à il y a quelques jours où une professeur de BTS enseignant UML pas très moi de chez moi m'a contacté, et finalement proposé de participer à un de ses cours. Pour ne pas être ridicule après une longue abstinence cumulé à un age de plus en plus avancé, il me parait utile de réutiliser BoUML afin de rafraîchir ma mémoire. Mais depuis plusieurs années ma station de travail est une Raspberry Pi, une Pi5 sous Debian Bookworm depuis peu de temps, et déjà avec ma Pi4 sous Debian Bullseye il était impossible de compiler BoUML.
J'avais bien fait sur une Pi 3 une archive pour utiliser BoUML à partir de Bullseye, mais celle-ci était en 32 bits, alors que ma Pi5 est en 64b.
J'ai donc voulu compiler Qt 4.8.7 sur ma Pi5 Bookworm 64b, en sachant que ce ne serait sans doute pas sans problèmes.
Tentatives
Le début est facile :
Code:
1 2 3 4
| wget https://download.qt.io/archive/qt/4.8/4.8.7/qt-everywhere-opensource-src-4.8.7.tar.gz
tar xf qt-everywhere-opensource-src-4.8.7.tar.gz
cd qt-everywhere-opensource-src-4.8.7
./configure |
Puis bravement make -j3 et après quelque temps et une flopée de warnings, les premières erreurs de compilations assez bénignes dont je reparlerais.
Mais arrivé sous src/gui c'est la bérézina : les sources à compiler utilisent des noms de membres qui ne sont pas ceux présents dans les fichiers header :arf:
Après de vaines recherches :google: je remarque que les headers sont produits par l'outil interne uic, pour avancer je vais sur ma vieille station en multi boot et compile Qt sous Ubuntu 16.04, afin de récupérer les fichiers produits, et il n'y en a pas seulement pour src/gui.
Je passe d'autres problèmes mineurs dont je reparlerais aussi, et j'arrive sous translations sous lequel rien ne va et un autre outil interne râle en disant que le format des fichiers est inconnu. Le but içi est de produire des fichiers qm à partir de fichiers ts.
Rebelote, pour avancer rapidement je récupère les fichiers produits sous Ubuntu.
Arrivé sous src/script il y a des erreurs liées à des définitions dans src/3rdparty/javascriptcore/JavaScriptCore/wtf/TypeTraits.h qui ne sont plus valables depuis C++11. Les résoudre demanderait beaucoup de modifications à différents endroits, et je n'ai pas besoin des scripts, je reconfigure en -no-script (-no-javascript-jit ne suffit pas), et finalement j'arrive à produire Qt :yaisse2:
Après un make install je compile BoUML oh miracle sans problème, et je fais quelque tests d’exécution tout à fait concluants. De toute façon comme disait un ancien collègue : ça compile donc ça marche, n'est ce pas ? :yaisse:
Evidemment récupérer des fichiers produits ailleurs ce n'est pas très glorieux, et ne pas connaître la raison de ces deux problèmes majeurs est loin d'être rassurant. Je décide donc de commencer par le problème de production des fichiers de traduction qui semble plus simple, et je vais entrer dans les détails car c'est intéressant. Je fini par comprendre que le foreach de Qt ne va pas plus loin que le 1er élément, d'où le format inconnu car n'étant pas le 1er de la liste des formats définis. En remplaçant la définition de la boucle par une à moi le problème disparaît et les fichiers qm sont bien produits. Mais je veux comprendre pourquoi le foreach ne marche plus alors qu'il marchait avant.
QT défini foreach ainsi :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| template <typename T>
class QForeachContainer {
public:
inline QForeachContainer(const T& t) : c(t), brk(0), i(c.begin()), e(c.end()) { }
const T c;
int brk;
typename T::const_iterator i, e;
};
#define Q_FOREACH(variable, container) \
for (QForeachContainer<__typeof__(container)> _container_(container); \
!_container_.brk && _container_.i != _container_.e; \
__extension__ ({ ++_container_.brk; ++_container_.i; })) \
for (variable = *_container_.i;; __extension__ ({--_container_.brk; break;}))
#define foreach Q_FOREACH |
que j'avais remplacé par
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| template <typename T, typename TI>
struct ForEachContainer {
T c;
TI it;
TI e;
bool brk;
inline ForEachContainer(const T& t) : c(t), it(c.begin()), e(c.end()), brk(false) {}
};
#define Q_FOREACH(v, l) \
for (ForEachContainer<__typeof__(l), __typeof__((l).begin())> _container_(l); \
_container_.it != _container_.e; \
++_container_.it, _container_.brk = false) \
for (v = *_container_.it; !_container_.brk; _container_.brk = true)
#define foreach Q_FOREACH |
Je ne connaissais pas la possibilité de faire un break en dehors du corps d'un for ou autre via __extension__, et je simplifie ma définition en
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| template <typename T, typename TI>
struct ForEachContainer {
T c;
TI it;
TI e;
inline ForEachContainer(const T& t) : c(t), it(c.begin()), e(c.end()) {}
};
#define Q_FOREACH(v, l) \
for (ForEachContainer<__typeof__(l), __typeof__((l).begin())> _container_(l); \
_container_.it != _container_.e; \
++_container_.it) \
for (v = *_container_.it;; __extension__ ({break;}))
#define foreach Q_FOREACH |
et là patatra j'ai le même comportement qu'avec le foreach de Qt 8O
Pour en voir le cœur net j'utilise le tout petit programme suivant :
Code:
1 2 3 4 5 6 7 8
| #include <iostream>
int main()
{
for (int i = 0; i != 5; ++i)
for (int j = i;; __extension__ ({break;}))
std::cout << j << std::endl;
} |
Sur ma Pi5 cela n'affiche que 0, alors que sur mon Ubuntu 16.04 cela affiche de 0 à 4, et si je remplace le break par un continue sur la Pi 5 j'ai mes 0 à 4 :fou:
Après avoir demandé de l'aide il s'avère que les vieilles versions de gcc étaient buggées et géraient mal un break/continue à cette position, car elles considéraient qu'il s'applique à la boucle interne et non la boucle englobante.
Le foreach de Qt ne marche donc plus à cause de la correction effectuée dans gcc :ptdr:
Je reviens à la définition de Qt en remplaçant le break par un continue et le tour est joué, la génération des fichiers sous translations se fait bien. A noter qu'il est possible de simplifier la définition de Qt, un peu comme j'ai simplifié la mienne, mais pour minimiser les changements dans le code de Qt je ne l'ai pas fait.
Des foreach il y en a évidemment ailleurs, et j'ai modifié un fichier header inclue un peu partout, je relance donc la compilation à partir du haut, et là deuxième effet kiss cool, mon 1er problème avec uic disparaît également :hola:
La suite avec l’ensemble des modifications à faire, et qui finalement sont peu nombreuses, dans le message suivant à venir.